@oliasoft-open-source/charts-library 0.0.2-beta-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.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/index.js +13 -0
  4. package/package.json +100 -0
  5. package/release-notes.md +178 -0
  6. package/src/assets/icons/line-and-point.svg +1 -0
  7. package/src/assets/icons/line-only.svg +1 -0
  8. package/src/assets/icons/list-hide.svg +1 -0
  9. package/src/assets/icons/point-only.svg +1 -0
  10. package/src/components/bar-chart/bar-chart-prop-types.js +188 -0
  11. package/src/components/bar-chart/bar-chart.interface.ts +84 -0
  12. package/src/components/bar-chart/bar-chart.jsx +243 -0
  13. package/src/components/bar-chart/bar-chart.module.less +61 -0
  14. package/src/components/bar-chart/get-bar-chart-data-labels.js +42 -0
  15. package/src/components/bar-chart/get-bar-chart-scales.js +123 -0
  16. package/src/components/bar-chart/get-bar-chart-tooltips.js +100 -0
  17. package/src/components/controls/axes-options/axes-options-form-state.js +95 -0
  18. package/src/components/controls/axes-options/axes-options.jsx +166 -0
  19. package/src/components/controls/controls.jsx +104 -0
  20. package/src/components/controls/controls.module.less +12 -0
  21. package/src/components/controls/drag-options.jsx +77 -0
  22. package/src/components/controls/legend-options.jsx +25 -0
  23. package/src/components/controls/line-options.jsx +54 -0
  24. package/src/components/line-chart/axis-scales/axis-scales.js +165 -0
  25. package/src/components/line-chart/datalabels-alignment/get-alignment-condition.js +13 -0
  26. package/src/components/line-chart/datalabels-alignment/get-alignment-data.js +20 -0
  27. package/src/components/line-chart/datalabels-alignment/get-datalabels-position.js +25 -0
  28. package/src/components/line-chart/get-axes-ranges-from-chart.js +10 -0
  29. package/src/components/line-chart/get-line-chart-data-labels.js +21 -0
  30. package/src/components/line-chart/get-line-chart-scales.js +120 -0
  31. package/src/components/line-chart/get-line-chart-tooltips.js +91 -0
  32. package/src/components/line-chart/line-chart-consts.js +7 -0
  33. package/src/components/line-chart/line-chart-prop-types.js +212 -0
  34. package/src/components/line-chart/line-chart-utils.js +192 -0
  35. package/src/components/line-chart/line-chart.interface.ts +107 -0
  36. package/src/components/line-chart/line-chart.jsx +531 -0
  37. package/src/components/line-chart/line-chart.minor-gridlines-plugin.js +88 -0
  38. package/src/components/line-chart/line-chart.module.less +77 -0
  39. package/src/components/line-chart/state/action-types.js +11 -0
  40. package/src/components/line-chart/state/initial-state.js +69 -0
  41. package/src/components/line-chart/state/line-chart-reducer.js +101 -0
  42. package/src/components/pie-chart/pie-chart-prop-types.js +111 -0
  43. package/src/components/pie-chart/pie-chart-utils.js +32 -0
  44. package/src/components/pie-chart/pie-chart.interface.ts +61 -0
  45. package/src/components/pie-chart/pie-chart.jsx +450 -0
  46. package/src/components/pie-chart/pie-chart.module.less +61 -0
  47. package/src/components/scatter-chart/scatter-chart.intefrace.ts +33 -0
  48. package/src/components/scatter-chart/scatter-chart.jsx +21 -0
  49. package/src/components/scatter-chart/scatter-chart.module.less +4 -0
  50. package/src/helpers/chart-border-plugin.js +19 -0
  51. package/src/helpers/chart-consts.js +62 -0
  52. package/src/helpers/chart-interface.ts +76 -0
  53. package/src/helpers/chart-utils.js +183 -0
  54. package/src/helpers/container.jsx +60 -0
  55. package/src/helpers/disabled-context.js +8 -0
  56. package/src/helpers/enums.js +87 -0
  57. package/src/helpers/get-chart-annotation.js +143 -0
  58. package/src/helpers/get-custom-legend-plugin-example.js +80 -0
  59. package/src/helpers/numbers/numbers.js +44 -0
  60. package/src/helpers/range/estimate-data-series-have-close-values.js +54 -0
  61. package/src/helpers/range/range.js +95 -0
  62. package/src/helpers/styles.js +68 -0
  63. package/src/helpers/text.js +6 -0
  64. package/src/style/external.less +4 -0
  65. package/src/style/fonts/lato/Lato-Bold.woff2 +0 -0
  66. package/src/style/fonts/lato/Lato-BoldItalic.woff2 +0 -0
  67. package/src/style/fonts/lato/Lato-Italic.woff2 +0 -0
  68. package/src/style/fonts/lato/Lato-Regular.woff2 +0 -0
  69. package/src/style/fonts.less +27 -0
  70. package/src/style/global.less +43 -0
  71. package/src/style/reset/reset.less +28 -0
  72. package/src/style/shared.less +24 -0
  73. package/src/style/variables.less +91 -0
@@ -0,0 +1,54 @@
1
+ import { isEqualWithTolerance } from '../numbers/numbers';
2
+
3
+ /**
4
+ * Estimates whether any of the data series has values that are all close together
5
+ * - checks only the first and last values in each series (i.e. assumes they are ordered)
6
+ * - uses an equality check with tolerance for decimal precision noise
7
+ * - this is just an inexpensive "guesstimate" (full min/max detection can be used afterwards)
8
+ *
9
+ * @param {Array} generatedDatasets chart dataset series with x, y points
10
+ * @return {boolean} - at least one series has values that seem close together
11
+ */
12
+ export const estimateDataSeriesHaveCloseValues = (generatedDatasets) => {
13
+ if (!Array.isArray(generatedDatasets) || !generatedDatasets.length) {
14
+ return false;
15
+ }
16
+ const axesFirstLast = generatedDatasets.reduce((acc, dataset) => {
17
+ const xAxisId = dataset?.xAxisID ?? 'defaultX';
18
+ const yAxisId = dataset?.yAxisID ?? 'defaultY';
19
+ const data = dataset?.data;
20
+ if (data && data.length) {
21
+ const { x: xFirstCurrent, y: yFirstCurrent } = data?.[0] ?? {};
22
+ const { x: xLastCurrent, y: yLastCurrent } = data.at(-1) ?? {};
23
+ const xFirstAcc = acc?.[xAxisId]?.xFirst ?? xFirstCurrent;
24
+ const xLastAcc = acc?.[xAxisId]?.xLast ?? xLastCurrent;
25
+ const yFirstAcc = acc?.[yAxisId]?.yFirst ?? yFirstCurrent;
26
+ const yLastAcc = acc?.[yAxisId]?.yLast ?? yLastCurrent;
27
+ const xFirst = Math.min(xFirstCurrent, xFirstAcc);
28
+ const xLast = Math.max(xLastCurrent, xLastAcc);
29
+ const yFirst = Math.min(yFirstCurrent, yFirstAcc);
30
+ const yLast = Math.max(yLastCurrent, yLastAcc);
31
+ acc = {
32
+ ...acc,
33
+ [xAxisId]: {
34
+ ...acc[xAxisId],
35
+ xFirst,
36
+ xLast,
37
+ },
38
+ [yAxisId]: {
39
+ yFirst,
40
+ yLast,
41
+ },
42
+ };
43
+ }
44
+ return acc;
45
+ }, {});
46
+ return Object.values(axesFirstLast).some(
47
+ ({ xFirst, xLast, yFirst, yLast }) => {
48
+ return (
49
+ isEqualWithTolerance(xFirst, xLast) ||
50
+ isEqualWithTolerance(yFirst, yLast)
51
+ );
52
+ },
53
+ );
54
+ };
@@ -0,0 +1,95 @@
1
+ import { isEqualWithTolerance, round } from '../numbers/numbers';
2
+
3
+ const whiteSpacePercentage = 0.05; // relative amount of white space on each "side" of the data points
4
+
5
+ const defaultRange = { min: -1, max: 1 };
6
+
7
+ /**
8
+ * Overrides the default chart.js axis range for some edge-cases:
9
+ * - when no data -> default range
10
+ * - when all values are close to zero -> default range
11
+ * - when all values are close to each other -> custom 5% padding
12
+ * - when autoAxisPadding is set -> custom 5% padding
13
+ * - all other cases fall back to chart.js default behaviour
14
+ *
15
+ * `autoAxisPadding` feature requirements:
16
+ * - specified by Truls and ported by Mark+Oleg
17
+ * - numbers that are equal (within tolerance) shall be presented as a straight line
18
+ * - all other data series shall use 90% of width of axis (5% padding each side)
19
+ * - the padding on each side shall be symmetric
20
+ *
21
+ * @param {object} args
22
+ * @param {array<number|null>} args.data
23
+ * @param {boolean} [args.beginAtZero]
24
+ * @param {boolean>} [args.autoAxisPadding]
25
+ * @returns {object} returns {min, max} pair
26
+ */
27
+ export const getSuggestedAxisRange = ({
28
+ data,
29
+ beginAtZero = false,
30
+ autoAxisPadding = false,
31
+ }) => {
32
+ const dataMin = Math.min(
33
+ ...data.filter((v) => v !== null && v !== undefined && !isNaN(v)),
34
+ );
35
+ const dataMax = Math.max(
36
+ ...data.filter((v) => v !== null && v !== undefined && !isNaN(v)),
37
+ );
38
+ const isNegative = Math.sign(dataMin) === -1 || Math.sign(dataMax) === -1;
39
+ const isCloseToZeroWithTolerance =
40
+ isEqualWithTolerance(dataMin, 0) && isEqualWithTolerance(dataMax, 0);
41
+
42
+ /*
43
+ Use default range upon no data or when all values are close to 0
44
+ */
45
+ if (!data.length || isCloseToZeroWithTolerance) {
46
+ return defaultRange;
47
+ }
48
+
49
+ /*
50
+ When all values are close to the same, always add some padding OW-4327
51
+ */
52
+ if (isEqualWithTolerance(dataMin, dataMax)) {
53
+ const point = dataMax;
54
+ const padding = point * whiteSpacePercentage;
55
+ const minAxisValue = beginAtZero && !isNegative ? 0 : point - padding;
56
+ const maxAxisValue = beginAtZero && isNegative ? 0 : point + padding;
57
+ return {
58
+ min: round(minAxisValue),
59
+ max: round(maxAxisValue),
60
+ };
61
+ }
62
+
63
+ /*
64
+ Else fall back to native chart.js implementation when autoAxisPadding is off
65
+ */
66
+ if (!autoAxisPadding) {
67
+ return {
68
+ min: undefined,
69
+ max: undefined,
70
+ };
71
+ }
72
+
73
+ /*
74
+ Else use custom auto scaling with 5% padding (only when autoAxisPadding is set)
75
+ */
76
+ const rangeBeginAtZero = dataMin === 0 || dataMax === 0 || beginAtZero;
77
+ const positiveAndNegative =
78
+ Math.sign(dataMin) === -1 && Math.sign(dataMax) === 1;
79
+
80
+ const range = Math.abs(dataMax - dataMin);
81
+ const padding = autoAxisPadding ? range * whiteSpacePercentage : 0;
82
+ const minAxisValue =
83
+ !positiveAndNegative && rangeBeginAtZero && beginAtZero && !isNegative
84
+ ? 0
85
+ : dataMin - padding;
86
+ const maxAxisValue =
87
+ !positiveAndNegative && rangeBeginAtZero && beginAtZero && isNegative
88
+ ? 0
89
+ : dataMax + padding;
90
+
91
+ return {
92
+ min: round(minAxisValue),
93
+ max: round(maxAxisValue),
94
+ };
95
+ };
@@ -0,0 +1,68 @@
1
+ /*
2
+ This helper allows us to export simple LESS variables as JavaScript objects.
3
+ The intention is for keeping code DRY by allowing primary colour palettes etc
4
+ to be defined in one place only (LESS).
5
+
6
+ These simple variables should be defined in a files called `shared.less` that
7
+ can exist in one of two place:
8
+
9
+ - in `override.less` in the root of the parent project
10
+ (to allow overriding of the default values set in this project)
11
+ - in `src/style/shared.less in this project (default values)
12
+
13
+ The parent and local definitions are merged, with the parent taking
14
+ precedence.
15
+
16
+ The implementation uses Webpack raw-loader to load the shared LESS variables
17
+ file, and a 3rd party package (less-vars-to-js) to parse it, so they can be
18
+ exported for use in JavaScript.
19
+
20
+ When we upgrade to Webpack 5, we'll have to refactor this to use asset modules
21
+ instead.
22
+ */
23
+
24
+ import lessToJs from 'less-vars-to-js';
25
+
26
+ // eslint-disable-next-line import/no-unresolved,import/no-webpack-loader-syntax
27
+ import lessVariables from '../style/shared.less?raw';
28
+
29
+ /*
30
+ We need to import the `shared.less` file from the root of the parent project
31
+ conditionally (it may not exist). Would love to use ES6 imports here, but they
32
+ don't allow optional files without throwing an error when the file doesn't
33
+ exist. ES6 dynamic imports would require `async` when we use this helper
34
+ (prefer to avoid that). So falling back to CommonJS require here.
35
+
36
+ Hopefully this will get better once we have Webpack 5 asset modules.
37
+ */
38
+ let lessParentVariables = '{}';
39
+ try {
40
+ const parentPath = '../../../../override.less?raw';
41
+ // eslint-disable-next-line import/no-unresolved,global-require,import/no-webpack-loader-syntax,import/no-dynamic-require
42
+ lessParentVariables = require(`${parentPath}`).default;
43
+ } catch (e) {
44
+ //do nothing (we fallback to the local definition anyway)
45
+ }
46
+
47
+ const load = () => {
48
+ /*
49
+ Merge the parent project shared.less with the local shared.less
50
+ (since less-vars-to-js doesn't handle import statements for us)
51
+
52
+ The parent definition takes precedence over the local definition
53
+ */
54
+ const parent = lessToJs(lessParentVariables, {
55
+ resolveVariables: true,
56
+ stripPrefix: true,
57
+ });
58
+ const local = lessToJs(lessVariables, {
59
+ resolveVariables: true,
60
+ stripPrefix: true,
61
+ });
62
+ return {
63
+ ...local,
64
+ ...parent,
65
+ };
66
+ };
67
+
68
+ export const styleVariables = load();
@@ -0,0 +1,6 @@
1
+ export const getTextWidth = (text, font) => {
2
+ const element = document.createElement('canvas');
3
+ const context = element.getContext('2d');
4
+ context.font = font;
5
+ return context.measureText(text).width;
6
+ };
@@ -0,0 +1,4 @@
1
+ @import './fonts.less';
2
+ @import './reset/reset.less';
3
+
4
+ @import '../components/button/button.module.less';
@@ -0,0 +1,27 @@
1
+ @font-face {
2
+ font-family: 'Lato';
3
+ font-weight: normal;
4
+ font-style: normal;
5
+ src: url('./fonts/lato/Lato-Regular.woff2') format('woff2');
6
+ }
7
+
8
+ @font-face {
9
+ font-family: 'Lato';
10
+ font-weight: bold;
11
+ font-style: normal;
12
+ src: url('./fonts/lato/Lato-Bold.woff2') format('woff2');
13
+ }
14
+
15
+ @font-face {
16
+ font-family: 'Lato';
17
+ font-weight: normal;
18
+ font-style: italic;
19
+ src: url('./fonts/lato/Lato-Italic.woff2') format('woff2');
20
+ }
21
+
22
+ @font-face {
23
+ font-family: 'Lato';
24
+ font-weight: bold;
25
+ font-style: italic;
26
+ src: url('./fonts/lato/Lato-BoldItalic.woff2') format('woff2');
27
+ }
@@ -0,0 +1,43 @@
1
+ @import './variables.less';
2
+ @import './fonts.less';
3
+ @import './reset/reset.less';
4
+
5
+ html {
6
+ font-size: 14px;
7
+ }
8
+
9
+ body {
10
+ color: rgba(0, 0, 0, 0.87);
11
+ line-height: 1.4285em;
12
+ font-family: @default_font;
13
+ font-size: 14px;
14
+ }
15
+
16
+ h1,
17
+ h2,
18
+ h3,
19
+ h4,
20
+ h5 {
21
+ line-height: 1.285714em;
22
+ margin: 0 0 1rem;
23
+ }
24
+
25
+ p,
26
+ ul,
27
+ ol {
28
+ margin: 0 0 1rem;
29
+ line-height: 1.4285em;
30
+
31
+ &:last-child {
32
+ margin-bottom: 0;
33
+ }
34
+ }
35
+
36
+ ul,
37
+ ol {
38
+ padding-left: 1.5em;
39
+ }
40
+
41
+ a {
42
+ text-decoration: none;
43
+ }
@@ -0,0 +1,28 @@
1
+ @import '~normalize.css/normalize.css';
2
+
3
+ /* Border-Box */
4
+ *,
5
+ *:before,
6
+ *:after {
7
+ box-sizing: inherit;
8
+ }
9
+ html {
10
+ box-sizing: border-box;
11
+ }
12
+
13
+ /* iPad Input Shadows */
14
+ input[type='text'],
15
+ input[type='email'],
16
+ input[type='search'],
17
+ input[type='password'] {
18
+ -webkit-appearance: none;
19
+ -moz-appearance: none; /* mobile firefox too! */
20
+ }
21
+
22
+ /* FF dotted border outlines */
23
+ :focus {
24
+ outline: none !important;
25
+ }
26
+ ::-moz-focus-inner {
27
+ border: 0 !important;
28
+ }
@@ -0,0 +1,24 @@
1
+ /*
2
+ This file has shared variables that are re-used:
3
+ - in other LESS files/modules
4
+ - in JavaScript, via https://www.npmjs.com/package/less-vars-to-js
5
+
6
+ Only use simple variables in this file
7
+ */
8
+
9
+ // Brand guidelines
10
+ @colorPrimary: #eb6429;
11
+ @colorError: #e14c4c;
12
+ @colorWarning: #e2bd27;
13
+ @colorSuccess: #3bbb3b;
14
+ @colorInfo: #29a7eb;
15
+
16
+ /*
17
+ Allow the parent project to optionally override the primary colour palette
18
+ by having an `override.less` file in its root directory
19
+ */
20
+ @import (optional) '../../../../override.less';
21
+
22
+ /*
23
+ Other shared variables
24
+ */
@@ -0,0 +1,91 @@
1
+ @import './shared.less';
2
+
3
+ @default_font: 'Lato', sans-serif;
4
+
5
+ /*
6
+ LAYOUT
7
+ */
8
+
9
+ @topbar_height: 60px;
10
+ @sidebar_width: 300px;
11
+ @sidebar_width_collapsed: 70px;
12
+
13
+ /*
14
+ CARDS
15
+ */
16
+
17
+ @card_border_radius: 4px;
18
+ @card_border_color: #d5d7d9;
19
+ @card_header_bg_color: #f7f7f7;
20
+ @card_padding_x: 15px;
21
+ @card_padding_y: 10px;
22
+
23
+ /*
24
+ INPUTS
25
+ */
26
+
27
+ @input_height: 38px;
28
+ @input_height_small: 24px;
29
+ @input_font_size_small: 12px;
30
+ @input_padding_x: 14px;
31
+ @input_padding_y: 9.5px;
32
+ @input_padding_small_x: 7px;
33
+ @input_padding_small_y: 3.5px;
34
+ @input_border_radius: 4px;
35
+
36
+ /*
37
+ COLOR
38
+ */
39
+
40
+ // Text
41
+ @colorTextDefault: rgba(0, 0, 0, 0.87);
42
+ @colorTextMuted: #7d7b7a;
43
+ @colorTextFaint: #acabab;
44
+ @colorTextError: hsl(hue(@colorError), 40%, 50%);
45
+ @colorTextWarning: hsl(hue(@colorWarning), 40%, 50%);
46
+ @colorTextSuccess: hsl(hue(@colorSuccess), 40%, 50%);
47
+ @colorTextPrimary: @colorPrimary;
48
+
49
+ :root {
50
+ --color-text-default: @colorTextDefault;
51
+ --color-text-muted: @colorTextMuted;
52
+ --color-text-faint: @colorTextFaint;
53
+ --color-text-error: @colorTextError;
54
+ --color-text-warning: @colorTextWarning;
55
+ --color-text-success: @colorTextSuccess;
56
+ --color-text-primary: @colorTextPrimary;
57
+ }
58
+
59
+ // Buttons
60
+ @col_btn_default: white;
61
+ @col_btn_primary: @colorPrimary;
62
+ @col_btn_danger: @colorError;
63
+ @col_btn_success: @colorSuccess;
64
+
65
+ // Inputs
66
+ @input_border_color: rgba(34, 36, 38, 0.15);
67
+ @input_border_color_hover: rgba(34, 36, 38, 0.35);
68
+ @input_border_color_focus: hsl(hue(@colorInfo), 40%, 60%);
69
+ @input_background_error: hsl(hue(@colorError), 40%, 97%);
70
+ @input_border_color_error: hsl(hue(@colorError), 40%, 70%);
71
+ @input_color_error: @colorTextError;
72
+ @input_background_warning: hsl(hue(@colorWarning), 40%, 97%);
73
+ @input_border_color_warning: hsl(hue(@colorWarning), 40%, 70%);
74
+ @input_color_warning: @colorTextWarning;
75
+ @input_color_placeholder: #c0c0c0;
76
+ @input_background_disabled: #ecedef;
77
+
78
+ /*
79
+ Z-INDEX
80
+ */
81
+
82
+ @zindex_topbar_alert: 98;
83
+ @zindex_drawer: 99;
84
+ @zindex_topbar: 101;
85
+ @zindex_dimmer: 1000;
86
+ @zindex_modal: 2000;
87
+ //We need react-laag layers to appear above modals
88
+ //Tooltips need to be above dropdown layers
89
+ @zindex_popover: 2001;
90
+ @zindex_dropdown: 2002;
91
+ @zindex_tooltip: 2003;