@gravity-ui/chartkit 3.1.3 → 3.2.0-beta.2

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 (132) hide show
  1. package/build/plugins/d3/index.d.ts +7 -0
  2. package/build/plugins/d3/index.js +10 -0
  3. package/build/plugins/d3/renderer/D3Widget.d.ts +15 -0
  4. package/build/plugins/d3/renderer/D3Widget.js +40 -0
  5. package/build/plugins/d3/renderer/components/AxisX.d.ts +10 -0
  6. package/build/plugins/d3/renderer/components/AxisX.js +68 -0
  7. package/build/plugins/d3/renderer/components/AxisY.d.ts +10 -0
  8. package/build/plugins/d3/renderer/components/AxisY.js +73 -0
  9. package/build/plugins/d3/renderer/components/Chart.d.ts +10 -0
  10. package/build/plugins/d3/renderer/components/Chart.js +64 -0
  11. package/build/plugins/d3/renderer/components/Legend.d.ts +12 -0
  12. package/build/plugins/d3/renderer/components/Legend.js +66 -0
  13. package/build/plugins/d3/renderer/components/Title.d.ts +7 -0
  14. package/build/plugins/d3/renderer/components/Title.js +8 -0
  15. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.d.ts +10 -0
  16. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +21 -0
  17. package/build/plugins/d3/renderer/components/Tooltip/index.d.ts +12 -0
  18. package/build/plugins/d3/renderer/components/Tooltip/index.js +53 -0
  19. package/build/plugins/d3/renderer/components/index.d.ts +1 -0
  20. package/build/plugins/d3/renderer/components/index.js +1 -0
  21. package/build/plugins/d3/renderer/components/styles.css +61 -0
  22. package/build/plugins/d3/renderer/constants.d.ts +1 -0
  23. package/build/plugins/d3/renderer/constants.js +22 -0
  24. package/build/plugins/d3/renderer/hooks/index.d.ts +10 -0
  25. package/build/plugins/d3/renderer/hooks/index.js +10 -0
  26. package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +17 -0
  27. package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +13 -0
  28. package/build/plugins/d3/renderer/hooks/useChartEvents/index.d.ts +5 -0
  29. package/build/plugins/d3/renderer/hooks/useChartEvents/index.js +15 -0
  30. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.d.ts +8 -0
  31. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +60 -0
  32. package/build/plugins/d3/renderer/hooks/useChartOptions/constants.d.ts +3 -0
  33. package/build/plugins/d3/renderer/hooks/useChartOptions/constants.js +3 -0
  34. package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -0
  35. package/build/plugins/d3/renderer/hooks/useChartOptions/index.js +32 -0
  36. package/build/plugins/d3/renderer/hooks/useChartOptions/legend.d.ts +6 -0
  37. package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +7 -0
  38. package/build/plugins/d3/renderer/hooks/useChartOptions/title.d.ts +5 -0
  39. package/build/plugins/d3/renderer/hooks/useChartOptions/title.js +17 -0
  40. package/build/plugins/d3/renderer/hooks/useChartOptions/tooltip.d.ts +5 -0
  41. package/build/plugins/d3/renderer/hooks/useChartOptions/tooltip.js +5 -0
  42. package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +33 -0
  43. package/build/plugins/d3/renderer/hooks/useChartOptions/utils.d.ts +5 -0
  44. package/build/plugins/d3/renderer/hooks/useChartOptions/utils.js +18 -0
  45. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.d.ts +5 -0
  46. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +29 -0
  47. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +5 -0
  48. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +35 -0
  49. package/build/plugins/d3/renderer/hooks/useLegend/index.d.ts +13 -0
  50. package/build/plugins/d3/renderer/hooks/useLegend/index.js +28 -0
  51. package/build/plugins/d3/renderer/hooks/useScales/index.d.ts +17 -0
  52. package/build/plugins/d3/renderer/hooks/useScales/index.js +106 -0
  53. package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +14 -0
  54. package/build/plugins/d3/renderer/hooks/useSeries/index.js +23 -0
  55. package/build/plugins/d3/renderer/hooks/useShapes/bar.d.ts +16 -0
  56. package/build/plugins/d3/renderer/hooks/useShapes/bar.js +75 -0
  57. package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +19 -0
  58. package/build/plugins/d3/renderer/hooks/useShapes/index.js +44 -0
  59. package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +18 -0
  60. package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +62 -0
  61. package/build/plugins/d3/renderer/hooks/useTooltip/index.d.ts +13 -0
  62. package/build/plugins/d3/renderer/hooks/useTooltip/index.js +19 -0
  63. package/build/plugins/d3/renderer/hooks/useTooltip/types.d.ts +7 -0
  64. package/build/plugins/d3/renderer/utils/index.d.ts +18 -0
  65. package/build/plugins/d3/renderer/utils/index.js +71 -0
  66. package/build/plugins/d3/types.d.ts +4 -0
  67. package/build/types/widget-data/axis.d.ts +24 -0
  68. package/build/types/widget-data/bar.d.ts +31 -0
  69. package/build/types/widget-data/base.d.ts +15 -0
  70. package/build/types/widget-data/base.js +1 -0
  71. package/build/types/widget-data/chart.d.ts +9 -0
  72. package/build/types/widget-data/chart.js +1 -0
  73. package/build/types/widget-data/index.d.ts +28 -0
  74. package/build/types/widget-data/index.js +10 -0
  75. package/build/types/widget-data/legend.d.ts +3 -0
  76. package/build/types/widget-data/legend.js +1 -0
  77. package/build/types/widget-data/pie.d.ts +10 -0
  78. package/build/types/widget-data/pie.js +1 -0
  79. package/build/types/widget-data/scatter.d.ts +20 -0
  80. package/build/types/widget-data/scatter.js +1 -0
  81. package/build/types/widget-data/series.d.ts +18 -0
  82. package/build/types/widget-data/series.js +1 -0
  83. package/build/types/widget-data/title.d.ts +5 -0
  84. package/build/types/widget-data/title.js +1 -0
  85. package/build/types/widget-data/tooltip.d.ts +12 -0
  86. package/build/types/widget-data/tooltip.js +1 -0
  87. package/build/types/widget.d.ts +5 -0
  88. package/package.json +10 -3
  89. package/build/libs/chartkit-error/__tests__/chartkit-error.js +0 -27
  90. package/build/libs/settings/__tests__/settings.test.js +0 -17
  91. package/build/plugins/highcharts/__stories__/Line.stories.d.ts +0 -3
  92. package/build/plugins/highcharts/__stories__/Line.stories.js +0 -12
  93. package/build/plugins/highcharts/__stories__/Pie.stories.d.ts +0 -3
  94. package/build/plugins/highcharts/__stories__/Pie.stories.js +0 -12
  95. package/build/plugins/highcharts/__stories__/area/Range.stories.d.ts +0 -3
  96. package/build/plugins/highcharts/__stories__/area/Range.stories.js +0 -12
  97. package/build/plugins/highcharts/__stories__/area/Stacked.stories.d.ts +0 -3
  98. package/build/plugins/highcharts/__stories__/area/Stacked.stories.js +0 -12
  99. package/build/plugins/highcharts/__stories__/column/HorizontalStacked.stories.d.ts +0 -3
  100. package/build/plugins/highcharts/__stories__/column/HorizontalStacked.stories.js +0 -12
  101. package/build/plugins/highcharts/__stories__/column/Vertical.stories.d.ts +0 -3
  102. package/build/plugins/highcharts/__stories__/column/Vertical.stories.js +0 -12
  103. package/build/plugins/highcharts/__stories__/column/VerticalStacked.stories.d.ts +0 -3
  104. package/build/plugins/highcharts/__stories__/column/VerticalStacked.stories.js +0 -12
  105. package/build/plugins/highcharts/__stories__/combined/ComboChartWithSameLegendValues.stories.d.ts +0 -3
  106. package/build/plugins/highcharts/__stories__/combined/ComboChartWithSameLegendValues.stories.js +0 -12
  107. package/build/plugins/highcharts/__stories__/complex/TwoAxis.stories.d.ts +0 -3
  108. package/build/plugins/highcharts/__stories__/complex/TwoAxis.stories.js +0 -12
  109. package/build/plugins/highcharts/__stories__/components/ChartStory.d.ts +0 -12
  110. package/build/plugins/highcharts/__stories__/components/ChartStory.js +0 -28
  111. package/build/plugins/highcharts/__stories__/constants/story-settings.d.ts +0 -42
  112. package/build/plugins/highcharts/__stories__/constants/story-settings.js +0 -42
  113. package/build/plugins/highcharts/__stories__/custom-error-render/custom-error-render.stories.d.ts +0 -3
  114. package/build/plugins/highcharts/__stories__/custom-error-render/custom-error-render.stories.js +0 -41
  115. package/build/plugins/highcharts/__stories__/no-data/no-data.stories.d.ts +0 -3
  116. package/build/plugins/highcharts/__stories__/no-data/no-data.stories.js +0 -20
  117. package/build/plugins/highcharts/__stories__/pie/WithTotals.stories.d.ts +0 -3
  118. package/build/plugins/highcharts/__stories__/pie/WithTotals.stories.js +0 -12
  119. package/build/plugins/highcharts/__tests__/prepare-data.test.js +0 -13
  120. package/build/plugins/indicator/__stories__/Indicator.stories.d.ts +0 -4
  121. package/build/plugins/indicator/__stories__/Indicator.stories.js +0 -45
  122. package/build/plugins/yagr/__stories__/Yagr.stories.d.ts +0 -6
  123. package/build/plugins/yagr/__stories__/Yagr.stories.js +0 -90
  124. package/build/plugins/yagr/__stories__/mocks/line10.d.ts +0 -53
  125. package/build/plugins/yagr/__stories__/mocks/line10.js +0 -78
  126. package/build/plugins/yagr/__tests__/utils.test.js +0 -26
  127. package/build/utils/__tests__/common.test.js +0 -9
  128. /package/build/{libs/chartkit-error/__tests__/chartkit-error.d.ts → plugins/d3/renderer/hooks/useChartOptions/types.js} +0 -0
  129. /package/build/{libs/settings/__tests__/settings.test.d.ts → plugins/d3/renderer/hooks/useTooltip/types.js} +0 -0
  130. /package/build/plugins/{highcharts/__tests__/prepare-data.test.d.ts → d3/types.js} +0 -0
  131. /package/build/{plugins/yagr/__tests__/utils.test.d.ts → types/widget-data/axis.js} +0 -0
  132. /package/build/{utils/__tests__/common.test.d.ts → types/widget-data/bar.js} +0 -0
@@ -0,0 +1,13 @@
1
+ const LEGEND_LINE_HEIGHT = 15;
2
+ export const useChartDimensions = (args) => {
3
+ const { margin, legend, title, width, height, xAxis, yAxis } = args;
4
+ const legendHeight = legend.enabled ? LEGEND_LINE_HEIGHT : 0;
5
+ const titleHeight = (title === null || title === void 0 ? void 0 : title.height) || 0;
6
+ const xAxisTitleHeight = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.title.height) || 0;
7
+ const yAxisTitleHeight = (yAxis === null || yAxis === void 0 ? void 0 : yAxis.reduce((acc, axis) => {
8
+ return acc + (axis.title.height || 0);
9
+ }, 0)) || 0;
10
+ const boundsWidth = width - margin.right - margin.left - yAxisTitleHeight;
11
+ const boundsHeight = height - margin.top - margin.bottom - legendHeight - titleHeight - xAxisTitleHeight;
12
+ return { boundsWidth, boundsHeight, legendHeight };
13
+ };
@@ -0,0 +1,5 @@
1
+ export declare const useChartEvents: () => {
2
+ chartHovered: boolean;
3
+ handleMouseEnter: () => void;
4
+ handleMouseLeave: () => void;
5
+ };
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ export const useChartEvents = () => {
3
+ const [chartHovered, setChartHovered] = React.useState(false);
4
+ const handleMouseEnter = React.useCallback(() => {
5
+ setChartHovered(true);
6
+ }, []);
7
+ const handleMouseLeave = React.useCallback(() => {
8
+ setChartHovered(false);
9
+ }, []);
10
+ return {
11
+ chartHovered,
12
+ handleMouseEnter,
13
+ handleMouseLeave,
14
+ };
15
+ };
@@ -0,0 +1,8 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedAxis, PreparedChart } from './types';
3
+ export declare const getPreparedChart: (args: {
4
+ chart: ChartKitWidgetData['chart'];
5
+ series: ChartKitWidgetData['series'];
6
+ preparedXAxis: PreparedAxis;
7
+ preparedY1Axis: PreparedAxis;
8
+ }) => PreparedChart;
@@ -0,0 +1,60 @@
1
+ import { select, max } from 'd3';
2
+ import get from 'lodash/get';
3
+ import { formatAxisTickLabel, getDomainDataYBySeries } from '../../utils';
4
+ import { getHorisontalSvgTextDimensions } from './utils';
5
+ const AXIS_WIDTH = 1;
6
+ const getAxisLabelMaxWidth = (args) => {
7
+ const { axis, series } = args;
8
+ let maxDomainValue;
9
+ let width = 0;
10
+ switch (axis.type) {
11
+ case 'category': {
12
+ const yCatigories = get(axis, 'categories', []);
13
+ maxDomainValue = [...yCatigories].sort((c1, c2) => c2.length - c1.length)[0];
14
+ break;
15
+ }
16
+ case 'datetime': {
17
+ const yTimestamps = get(axis, 'timestamps');
18
+ const domain = yTimestamps || getDomainDataYBySeries(series);
19
+ maxDomainValue = max(domain);
20
+ break;
21
+ }
22
+ case 'linear': {
23
+ const domain = getDomainDataYBySeries(series);
24
+ maxDomainValue = max(domain);
25
+ }
26
+ }
27
+ const formattedValue = formatAxisTickLabel({
28
+ axisType: axis.type,
29
+ value: maxDomainValue,
30
+ dateFormat: axis.labels.dateFormat,
31
+ numberFormat: axis.labels.numberFormat,
32
+ });
33
+ select(document.body)
34
+ .append('text')
35
+ .style('font-size', axis.labels.style.fontSize)
36
+ .text(formattedValue)
37
+ .each(function () {
38
+ width = this.getBoundingClientRect().width;
39
+ })
40
+ .remove();
41
+ return width;
42
+ };
43
+ export const getPreparedChart = (args) => {
44
+ const { chart, series, preparedXAxis, preparedY1Axis } = args;
45
+ const marginBottom = get(chart, 'margin.bottom', 0) +
46
+ preparedXAxis.labels.padding +
47
+ getHorisontalSvgTextDimensions({ text: 'Tmp', style: preparedXAxis.labels.style });
48
+ const marginLeft = get(chart, 'margin.left', AXIS_WIDTH) +
49
+ preparedY1Axis.labels.padding +
50
+ getAxisLabelMaxWidth({ axis: preparedY1Axis, series: series.data }) +
51
+ (preparedY1Axis.title.height || 0);
52
+ return {
53
+ margin: {
54
+ top: get(chart, 'margin.top', 0),
55
+ right: get(chart, 'margin.right', 0),
56
+ bottom: marginBottom,
57
+ left: marginLeft,
58
+ },
59
+ };
60
+ };
@@ -0,0 +1,3 @@
1
+ export declare const DEFAULT_AXIS_LABEL_FONT_SIZE = "11px";
2
+ export declare const DEFAULT_AXIS_LABEL_PADDING = 10;
3
+ export declare const DEFAULT_AXIS_TITLE_FONT_SIZE = "14px";
@@ -0,0 +1,3 @@
1
+ export const DEFAULT_AXIS_LABEL_FONT_SIZE = '11px';
2
+ export const DEFAULT_AXIS_LABEL_PADDING = 10;
3
+ export const DEFAULT_AXIS_TITLE_FONT_SIZE = '14px';
@@ -0,0 +1,3 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { ChartOptions } from './types';
3
+ export declare const useChartOptions: (args: ChartKitWidgetData) => ChartOptions;
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import { getPreparedChart } from './chart';
3
+ import { getPreparedLegend } from './legend';
4
+ import { getPreparedTitle } from './title';
5
+ import { getPreparedTooltip } from './tooltip';
6
+ import { getPreparedXAxis } from './x-axis';
7
+ import { getPreparedYAxis } from './y-axis';
8
+ export const useChartOptions = (args) => {
9
+ const { chart, series, legend, title, tooltip, xAxis, yAxis } = args;
10
+ const options = React.useMemo(() => {
11
+ const preparedTitle = getPreparedTitle({ title });
12
+ const preparedTooltip = getPreparedTooltip({ tooltip });
13
+ const preparedLegend = getPreparedLegend({ legend, series });
14
+ const preparedYAxis = getPreparedYAxis({ yAxis });
15
+ const preparedXAxis = getPreparedXAxis({ xAxis });
16
+ const preparedChart = getPreparedChart({
17
+ chart,
18
+ series,
19
+ preparedXAxis,
20
+ preparedY1Axis: preparedYAxis[0],
21
+ });
22
+ return {
23
+ chart: preparedChart,
24
+ legend: preparedLegend,
25
+ title: preparedTitle,
26
+ tooltip: preparedTooltip,
27
+ xAxis: preparedXAxis,
28
+ yAxis: preparedYAxis,
29
+ };
30
+ }, [chart, legend, title, tooltip, series, xAxis, yAxis]);
31
+ return options;
32
+ };
@@ -0,0 +1,6 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedLegend } from './types';
3
+ export declare const getPreparedLegend: (args: {
4
+ legend: ChartKitWidgetData['legend'];
5
+ series: ChartKitWidgetData['series'];
6
+ }) => PreparedLegend;
@@ -0,0 +1,7 @@
1
+ export const getPreparedLegend = (args) => {
2
+ const { legend, series } = args;
3
+ const enabled = legend === null || legend === void 0 ? void 0 : legend.enabled;
4
+ return {
5
+ enabled: typeof enabled === 'boolean' ? enabled : series.data.length > 1,
6
+ };
7
+ };
@@ -0,0 +1,5 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedTitle } from './types';
3
+ export declare const getPreparedTitle: ({ title, }: {
4
+ title: ChartKitWidgetData['title'];
5
+ }) => PreparedTitle | undefined;
@@ -0,0 +1,17 @@
1
+ import get from 'lodash/get';
2
+ import { getHorisontalSvgTextDimensions } from './utils';
3
+ const DEFAULT_TITLE_FONT_SIZE = '15px';
4
+ const TITLE_PADDINGS = 8 * 2;
5
+ export const getPreparedTitle = ({ title, }) => {
6
+ const titleText = get(title, 'text');
7
+ const titleStyle = {
8
+ fontSize: get(title, 'style.fontSize', DEFAULT_TITLE_FONT_SIZE),
9
+ };
10
+ const titleHeight = titleText
11
+ ? getHorisontalSvgTextDimensions({ text: titleText, style: titleStyle }) + TITLE_PADDINGS
12
+ : 0;
13
+ const preparedTitle = titleText
14
+ ? { text: titleText, style: titleStyle, height: titleHeight }
15
+ : undefined;
16
+ return preparedTitle;
17
+ };
@@ -0,0 +1,5 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedTooltip } from './types';
3
+ export declare const getPreparedTooltip: (args: {
4
+ tooltip: ChartKitWidgetData['tooltip'];
5
+ }) => PreparedTooltip;
@@ -0,0 +1,5 @@
1
+ import get from 'lodash/get';
2
+ export const getPreparedTooltip = (args) => {
3
+ const { tooltip } = args;
4
+ return Object.assign(Object.assign({}, tooltip), { enabled: get(tooltip, 'enabled', true) });
5
+ };
@@ -0,0 +1,33 @@
1
+ import type { BaseTextStyle, ChartKitWidgetData, ChartKitWidgetAxis, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels, ChartKitWidgetLegend, ChartMargin } from '../../../../../types/widget-data';
2
+ type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'style'> & Required<Pick<ChartKitWidgetAxisLabels, 'enabled' | 'padding'>> & {
3
+ style: BaseTextStyle;
4
+ };
5
+ export type PreparedChart = {
6
+ margin: ChartMargin;
7
+ };
8
+ export type PreparedLegend = Required<ChartKitWidgetLegend>;
9
+ export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
10
+ type: ChartKitWidgetAxisType;
11
+ labels: PreparedAxisLabels;
12
+ title: {
13
+ height: number;
14
+ text: string;
15
+ style: BaseTextStyle;
16
+ };
17
+ min?: number;
18
+ };
19
+ export type PreparedTitle = ChartKitWidgetData['title'] & {
20
+ height: number;
21
+ };
22
+ export type PreparedTooltip = ChartKitWidgetData['tooltip'] & {
23
+ enabled: boolean;
24
+ };
25
+ export type ChartOptions = {
26
+ chart: PreparedChart;
27
+ legend: PreparedLegend;
28
+ tooltip: PreparedTooltip;
29
+ xAxis: PreparedAxis;
30
+ yAxis: PreparedAxis[];
31
+ title?: PreparedTitle;
32
+ };
33
+ export {};
@@ -0,0 +1,5 @@
1
+ import type { BaseTextStyle } from '../../../../../types/widget-data';
2
+ export declare const getHorisontalSvgTextDimensions: (args: {
3
+ text: string;
4
+ style?: Partial<BaseTextStyle>;
5
+ }) => number;
@@ -0,0 +1,18 @@
1
+ import { select } from 'd3';
2
+ import get from 'lodash/get';
3
+ import { DEFAULT_AXIS_LABEL_FONT_SIZE } from './constants';
4
+ export const getHorisontalSvgTextDimensions = (args) => {
5
+ const { text, style } = args;
6
+ const textSelection = select(document.body).append('text').text(text);
7
+ const fontSize = get(style, 'fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE);
8
+ let height = 0;
9
+ if (fontSize) {
10
+ textSelection.style('font-size', fontSize);
11
+ }
12
+ textSelection
13
+ .each(function () {
14
+ height = this.getBoundingClientRect().height;
15
+ })
16
+ .remove();
17
+ return height;
18
+ };
@@ -0,0 +1,5 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedAxis } from './types';
3
+ export declare const getPreparedXAxis: ({ xAxis }: {
4
+ xAxis: ChartKitWidgetData['xAxis'];
5
+ }) => PreparedAxis;
@@ -0,0 +1,29 @@
1
+ import get from 'lodash/get';
2
+ import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from './constants';
3
+ import { getHorisontalSvgTextDimensions } from './utils';
4
+ export const getPreparedXAxis = ({ xAxis }) => {
5
+ const titleText = get(xAxis, 'title.text', '');
6
+ const titleStyle = {
7
+ fontSize: get(xAxis, 'title.style.fontSize', DEFAULT_AXIS_TITLE_FONT_SIZE),
8
+ };
9
+ const preparedXAxis = {
10
+ type: get(xAxis, 'type', 'linear'),
11
+ labels: {
12
+ enabled: get(xAxis, 'labels.enabled', true),
13
+ padding: get(xAxis, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
14
+ dateFormat: get(xAxis, 'labels.dateFormat'),
15
+ numberFormat: get(xAxis, 'labels.numberFormat'),
16
+ style: { fontSize: get(xAxis, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE) },
17
+ },
18
+ categories: get(xAxis, 'categories'),
19
+ timestamps: get(xAxis, 'timestamps'),
20
+ title: {
21
+ text: titleText,
22
+ style: titleStyle,
23
+ height: titleText
24
+ ? getHorisontalSvgTextDimensions({ text: titleText, style: titleStyle })
25
+ : 0,
26
+ },
27
+ };
28
+ return preparedXAxis;
29
+ };
@@ -0,0 +1,5 @@
1
+ import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
+ import type { PreparedAxis } from './types';
3
+ export declare const getPreparedYAxis: ({ yAxis }: {
4
+ yAxis: ChartKitWidgetData['yAxis'];
5
+ }) => PreparedAxis[];
@@ -0,0 +1,35 @@
1
+ import get from 'lodash/get';
2
+ import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from './constants';
3
+ import { getHorisontalSvgTextDimensions } from './utils';
4
+ export const getPreparedYAxis = ({ yAxis }) => {
5
+ // FIXME: add support for n axises
6
+ const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
7
+ const y1LabelsStyle = {
8
+ fontSize: get(yAxis1, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE),
9
+ };
10
+ const y1TitleText = get(yAxis1, 'title.text', '');
11
+ const y1TitleStyle = {
12
+ fontSize: get(yAxis1, 'title.style.fontSize', DEFAULT_AXIS_TITLE_FONT_SIZE),
13
+ };
14
+ const preparedY1Axis = {
15
+ type: get(yAxis1, 'type', 'linear'),
16
+ labels: {
17
+ enabled: get(yAxis1, 'labels.enabled', true),
18
+ padding: get(yAxis1, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
19
+ dateFormat: get(yAxis1, 'labels.dateFormat'),
20
+ numberFormat: get(yAxis1, 'labels.numberFormat'),
21
+ style: y1LabelsStyle,
22
+ },
23
+ categories: get(yAxis1, 'categories'),
24
+ timestamps: get(yAxis1, 'timestamps'),
25
+ title: {
26
+ text: y1TitleText,
27
+ style: y1TitleStyle,
28
+ height: y1TitleText
29
+ ? getHorisontalSvgTextDimensions({ text: y1TitleText, style: y1TitleStyle })
30
+ : 0,
31
+ },
32
+ min: get(yAxis1, 'min'),
33
+ };
34
+ return [preparedY1Axis];
35
+ };
@@ -0,0 +1,13 @@
1
+ import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
2
+ export type OnLegendItemClick = (data: {
3
+ name: string;
4
+ metaKey: boolean;
5
+ }) => void;
6
+ type Args = {
7
+ series: ChartKitWidgetSeries[];
8
+ };
9
+ export declare const useLegend: (args: Args) => {
10
+ activeLegendItems: string[];
11
+ handleLegendItemClick: OnLegendItemClick;
12
+ };
13
+ export {};
@@ -0,0 +1,28 @@
1
+ import React from 'react';
2
+ import { getVisibleSeriesNames } from '../../utils';
3
+ export const useLegend = (args) => {
4
+ const { series } = args;
5
+ const [activeLegendItems, setActiveLegendItems] = React.useState(getVisibleSeriesNames(series));
6
+ const handleLegendItemClick = React.useCallback(({ name, metaKey }) => {
7
+ const onlyItemSelected = activeLegendItems.length === 1 && activeLegendItems.includes(name);
8
+ let nextActiveLegendItems;
9
+ if (metaKey && activeLegendItems.includes(name)) {
10
+ nextActiveLegendItems = activeLegendItems.filter((item) => item !== name);
11
+ }
12
+ else if (metaKey && !activeLegendItems.includes(name)) {
13
+ nextActiveLegendItems = activeLegendItems.concat(name);
14
+ }
15
+ else if (onlyItemSelected) {
16
+ nextActiveLegendItems = getVisibleSeriesNames(series);
17
+ }
18
+ else {
19
+ nextActiveLegendItems = [name];
20
+ }
21
+ setActiveLegendItems(nextActiveLegendItems);
22
+ }, [series, activeLegendItems]);
23
+ // FIXME: remove effect. It initiates extra rerender
24
+ React.useEffect(() => {
25
+ setActiveLegendItems(getVisibleSeriesNames(series));
26
+ }, [series]);
27
+ return { activeLegendItems, handleLegendItemClick };
28
+ };
@@ -0,0 +1,17 @@
1
+ import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
2
+ import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
3
+ import type { ChartOptions } from '../useChartOptions/types';
4
+ export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
5
+ type Args = {
6
+ boundsWidth: number;
7
+ boundsHeight: number;
8
+ series: ChartKitWidgetSeries[];
9
+ xAxis: ChartOptions['xAxis'];
10
+ yAxis: ChartOptions['yAxis'];
11
+ };
12
+ type ReturnValue = {
13
+ xScale: ChartScale;
14
+ yScale: ChartScale;
15
+ };
16
+ export declare const useScales: (args: Args) => ReturnValue;
17
+ export {};
@@ -0,0 +1,106 @@
1
+ import React from 'react';
2
+ import { scaleBand, scaleLinear, scaleUtc, extent } from 'd3';
3
+ import get from 'lodash/get';
4
+ import { getOnlyVisibleSeries, getDomainDataXBySeries, getDomainDataYBySeries } from '../../utils';
5
+ const isNumericalArrayData = (data) => {
6
+ return data.every((d) => typeof d === 'number' || d === null);
7
+ };
8
+ const filterCategoriesByVisibleSeries = (categories, series) => {
9
+ return categories.filter((category) => {
10
+ return series.some((s) => {
11
+ return s.data.some((d) => 'category' in d && d.category === category);
12
+ });
13
+ });
14
+ };
15
+ export const useScales = (args) => {
16
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
17
+ const scales = React.useMemo(() => {
18
+ const xType = get(xAxis, 'type', 'linear');
19
+ const xCategories = get(xAxis, 'categories');
20
+ const xTimestamps = get(xAxis, 'timestamps');
21
+ const yType = get(yAxis[0], 'type', 'linear');
22
+ const yMin = get(yAxis[0], 'min');
23
+ const yCategories = get(yAxis[0], 'categories');
24
+ const yTimestamps = get(xAxis, 'timestamps');
25
+ let visibleSeries = getOnlyVisibleSeries(series);
26
+ // Reassign to all series in case of all series unselected,
27
+ // otherwise we will get an empty space without grid
28
+ visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
29
+ let xScale;
30
+ let yScale;
31
+ switch (xType) {
32
+ case 'linear': {
33
+ const domain = getDomainDataXBySeries(visibleSeries);
34
+ if (isNumericalArrayData(domain)) {
35
+ const [xMin, xMax] = extent(domain);
36
+ xScale = scaleLinear().domain([xMin, xMax]).range([0, boundsWidth]).nice();
37
+ }
38
+ break;
39
+ }
40
+ case 'category': {
41
+ if (xCategories) {
42
+ const filteredCategories = filterCategoriesByVisibleSeries(xCategories, visibleSeries);
43
+ xScale = scaleBand().domain(filteredCategories).range([0, boundsWidth]);
44
+ }
45
+ break;
46
+ }
47
+ case 'datetime': {
48
+ if (xTimestamps) {
49
+ const [xMin, xMax] = extent(xTimestamps);
50
+ xScale = scaleUtc().domain([xMin, xMax]).range([0, boundsWidth]).nice();
51
+ }
52
+ else {
53
+ const domain = getDomainDataXBySeries(visibleSeries);
54
+ if (isNumericalArrayData(domain)) {
55
+ const [xMin, xMax] = extent(domain);
56
+ xScale = scaleUtc().domain([xMin, xMax]).range([0, boundsWidth]).nice();
57
+ }
58
+ }
59
+ break;
60
+ }
61
+ }
62
+ if (!xScale) {
63
+ throw new Error('Failed to create xScale');
64
+ }
65
+ switch (yType) {
66
+ case 'linear': {
67
+ const domain = getDomainDataYBySeries(visibleSeries);
68
+ if (isNumericalArrayData(domain)) {
69
+ const [domainYMin, yMax] = extent(domain);
70
+ const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
71
+ yScale = scaleLinear()
72
+ .domain([yMinValue, yMax])
73
+ .range([boundsHeight, 0])
74
+ .nice();
75
+ }
76
+ break;
77
+ }
78
+ case 'category': {
79
+ if (yCategories) {
80
+ const filteredCategories = filterCategoriesByVisibleSeries(yCategories, visibleSeries);
81
+ yScale = scaleBand().domain(filteredCategories).range([boundsHeight, 0]);
82
+ }
83
+ break;
84
+ }
85
+ case 'datetime': {
86
+ if (yTimestamps) {
87
+ const [yMin, yMax] = extent(yTimestamps);
88
+ yScale = scaleUtc().domain([yMin, yMax]).range([boundsHeight, 0]).nice();
89
+ }
90
+ else {
91
+ const domain = getDomainDataYBySeries(visibleSeries);
92
+ if (isNumericalArrayData(domain)) {
93
+ const [yMin, yMax] = extent(domain);
94
+ yScale = scaleUtc().domain([yMin, yMax]).range([boundsHeight, 0]).nice();
95
+ }
96
+ }
97
+ break;
98
+ }
99
+ }
100
+ if (!yScale) {
101
+ throw new Error('Failed to create yScale');
102
+ }
103
+ return { xScale, yScale };
104
+ }, [boundsWidth, boundsHeight, series, xAxis, yAxis]);
105
+ return scales;
106
+ };
@@ -0,0 +1,14 @@
1
+ import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
2
+ export type ChartSeries = ChartKitWidgetSeries & {
3
+ color: string;
4
+ name: string;
5
+ visible: boolean;
6
+ };
7
+ type Args = {
8
+ activeLegendItems: string[];
9
+ series: ChartKitWidgetSeries[];
10
+ };
11
+ export declare const useSeries: (args: Args) => {
12
+ chartSeries: ChartSeries[];
13
+ };
14
+ export {};
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import clone from 'lodash/clone';
3
+ import { scaleOrdinal } from 'd3';
4
+ import { DEFAULT_PALETTE } from '../../constants';
5
+ import { getSeriesNames } from '../../utils';
6
+ export const useSeries = (args) => {
7
+ const { activeLegendItems, series } = args;
8
+ // FIXME: handle case with one pie chart series
9
+ const chartSeries = React.useMemo(() => {
10
+ const seriesNames = getSeriesNames(series);
11
+ const colorScale = scaleOrdinal(seriesNames, DEFAULT_PALETTE);
12
+ return series.map((s) => {
13
+ const preparedSeries = clone(s);
14
+ const name = 'name' in s ? s.name : '';
15
+ const color = 'color' in s && s.color ? s.color : colorScale(name);
16
+ preparedSeries.color = color;
17
+ preparedSeries.name = name;
18
+ preparedSeries.visible = activeLegendItems.includes(name);
19
+ return preparedSeries;
20
+ });
21
+ }, [activeLegendItems, series]);
22
+ return { chartSeries };
23
+ };
@@ -0,0 +1,16 @@
1
+ import React from 'react';
2
+ import { ChartOptions } from '../useChartOptions/types';
3
+ import { ChartScale } from '../useScales';
4
+ import { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
5
+ import { BarSeries } from '../../../../../types/widget-data';
6
+ type Args = {
7
+ series: BarSeries[];
8
+ xAxis: ChartOptions['xAxis'];
9
+ xScale: ChartScale;
10
+ yAxis: ChartOptions['yAxis'];
11
+ yScale: ChartScale;
12
+ onSeriesMouseMove?: OnSeriesMouseMove;
13
+ onSeriesMouseLeave?: OnSeriesMouseLeave;
14
+ };
15
+ export declare function prepareBarSeries(args: Args): React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
16
+ export {};
@@ -0,0 +1,75 @@
1
+ import React from 'react';
2
+ import block from 'bem-cn-lite';
3
+ const DEFAULT_BAR_RECT_WIDTH = 50;
4
+ const DEFAULT_LINEAR_BAR_RECT_WIDTH = 20;
5
+ const MIN_RECT_GAP = 1;
6
+ const b = block('chartkit-d3-bar');
7
+ const getRectProperties = (args) => {
8
+ const { point, xAxis, xScale, yAxis, yScale, minPointDistance } = args;
9
+ let cx;
10
+ let cy;
11
+ let width;
12
+ let height;
13
+ if (xAxis.type === 'category') {
14
+ const xBandScale = xScale;
15
+ const maxWidth = xBandScale.bandwidth() - MIN_RECT_GAP;
16
+ width = Math.min(maxWidth, DEFAULT_BAR_RECT_WIDTH);
17
+ cx = (xBandScale(point.category) || 0) + xBandScale.step() / 2 - width / 2;
18
+ }
19
+ else {
20
+ const xLinearScale = xScale;
21
+ const [min, max] = xLinearScale.domain();
22
+ const range = xLinearScale.range();
23
+ const maxWidth = ((range[1] - range[0]) * minPointDistance) / (Number(max) - Number(min)) - MIN_RECT_GAP;
24
+ width = Math.min(Math.max(maxWidth, 1), DEFAULT_LINEAR_BAR_RECT_WIDTH);
25
+ cx = xLinearScale(point.x) - width / 2;
26
+ }
27
+ if (yAxis[0].type === 'linear') {
28
+ const yLinearScale = yScale;
29
+ cy = yLinearScale(point.y);
30
+ height = yLinearScale(yLinearScale.domain()[0]) - cy;
31
+ }
32
+ else {
33
+ throw Error(`The "${yAxis[0].type}" type for the Y axis is not supported`);
34
+ }
35
+ return { x: cx, y: cy, width, height };
36
+ };
37
+ function minDiff(arr) {
38
+ let result = Infinity;
39
+ for (let i = 0; i < arr.length - 1; i++) {
40
+ for (let j = i + 1; j < arr.length; j++) {
41
+ const diff = Math.abs(arr[i] - arr[j]);
42
+ if (diff < result) {
43
+ result = diff;
44
+ }
45
+ }
46
+ }
47
+ return result;
48
+ }
49
+ export function prepareBarSeries(args) {
50
+ const { series, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave } = args;
51
+ const seriesData = series.map(({ data }) => data).flat(2);
52
+ const minPointDistance = minDiff(seriesData.map((item) => Number(item.x)));
53
+ return series.reduce((result, item) => {
54
+ const randomKey = Math.random().toString();
55
+ item.data.forEach((point, i) => {
56
+ const rectProps = getRectProperties({
57
+ point,
58
+ xAxis,
59
+ xScale,
60
+ yAxis,
61
+ yScale,
62
+ minPointDistance,
63
+ });
64
+ result.push(React.createElement("rect", Object.assign({ key: `${i}-${randomKey}`, className: b('rect'), fill: item.color }, rectProps, { onMouseMove: function () {
65
+ onSeriesMouseMove === null || onSeriesMouseMove === void 0 ? void 0 : onSeriesMouseMove({
66
+ hovered: {
67
+ data: point,
68
+ series: item,
69
+ },
70
+ });
71
+ }, onMouseLeave: onSeriesMouseLeave })));
72
+ });
73
+ return result;
74
+ }, []);
75
+ }