@gravity-ui/chartkit 4.4.1 → 4.6.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 (61) hide show
  1. package/build/plugins/d3/renderer/components/AxisX.d.ts +2 -1
  2. package/build/plugins/d3/renderer/components/AxisX.js +51 -49
  3. package/build/plugins/d3/renderer/components/AxisY.js +28 -31
  4. package/build/plugins/d3/renderer/components/Chart.js +19 -7
  5. package/build/plugins/d3/renderer/components/Legend.d.ts +5 -6
  6. package/build/plugins/d3/renderer/components/Legend.js +139 -84
  7. package/build/plugins/d3/renderer/components/styles.css +27 -0
  8. package/build/plugins/d3/renderer/constants/defaults/axis.d.ts +5 -0
  9. package/build/plugins/d3/renderer/constants/defaults/axis.js +5 -0
  10. package/build/plugins/d3/renderer/constants/defaults/index.d.ts +2 -0
  11. package/build/plugins/d3/renderer/constants/defaults/index.js +2 -0
  12. package/build/plugins/d3/renderer/constants/defaults/legend.d.ts +4 -0
  13. package/build/plugins/d3/renderer/constants/defaults/legend.js +8 -0
  14. package/build/plugins/d3/renderer/{constants.d.ts → constants/index.d.ts} +1 -1
  15. package/build/plugins/d3/renderer/{constants.js → constants/index.js} +1 -1
  16. package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +3 -1
  17. package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +64 -59
  18. package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +7 -4
  19. package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +65 -7
  20. package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.d.ts +6 -0
  21. package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.js +7 -0
  22. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.d.ts +1 -3
  23. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +12 -75
  24. package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -1
  25. package/build/plugins/d3/renderer/hooks/useChartOptions/index.js +3 -8
  26. package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +3 -6
  27. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +4 -2
  28. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +3 -2
  29. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +31 -4
  30. package/build/plugins/d3/renderer/hooks/useSeries/constants.d.ts +1 -1
  31. package/build/plugins/d3/renderer/hooks/useSeries/constants.js +1 -1
  32. package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +19 -7
  33. package/build/plugins/d3/renderer/hooks/useSeries/index.js +26 -8
  34. package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.d.ts +27 -0
  35. package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.js +92 -0
  36. package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +1 -2
  37. package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +26 -1
  38. package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +21 -0
  39. package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +75 -0
  40. package/build/plugins/d3/renderer/utils/axis-generators/index.d.ts +1 -0
  41. package/build/plugins/d3/renderer/utils/axis-generators/index.js +1 -0
  42. package/build/plugins/d3/renderer/utils/axis.d.ts +22 -0
  43. package/build/plugins/d3/renderer/utils/axis.js +49 -0
  44. package/build/plugins/d3/renderer/utils/index.d.ts +8 -4
  45. package/build/plugins/d3/renderer/utils/index.js +17 -6
  46. package/build/plugins/d3/renderer/utils/text.d.ts +20 -0
  47. package/build/plugins/d3/renderer/utils/text.js +62 -0
  48. package/build/plugins/d3/renderer/utils/time.d.ts +3 -0
  49. package/build/plugins/d3/renderer/utils/time.js +34 -0
  50. package/build/plugins/highcharts/renderer/components/HighchartsComponent.js +3 -3
  51. package/build/plugins/shared/format-number/format-number.d.ts +1 -0
  52. package/build/plugins/shared/format-number/format-number.js +19 -20
  53. package/build/types/widget-data/axis.d.ts +13 -1
  54. package/build/types/widget-data/legend.d.ts +24 -7
  55. package/build/utils/common.d.ts +1 -0
  56. package/build/utils/common.js +1 -1
  57. package/build/utils/index.d.ts +1 -1
  58. package/build/utils/index.js +1 -1
  59. package/package.json +2 -2
  60. package/build/plugins/d3/renderer/hooks/useChartOptions/legend.d.ts +0 -6
  61. package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +0 -12
@@ -1,5 +1,5 @@
1
1
  import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
2
- import type { ChartOptions } from '../useChartOptions/types';
2
+ import type { ChartOptions, PreparedAxis } from '../useChartOptions/types';
3
3
  import { PreparedSeries } from '../useSeries/types';
4
4
  export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
5
5
  type Args = {
@@ -13,6 +13,8 @@ type ReturnValue = {
13
13
  xScale?: ChartScale;
14
14
  yScale?: ChartScale;
15
15
  };
16
+ export declare function createYScale(axis: PreparedAxis, series: PreparedSeries[], boundsHeight: number): ScaleLinear<number, number, never> | ScaleBand<string> | ScaleTime<number, number, never>;
17
+ export declare function createXScale(axis: PreparedAxis, series: PreparedSeries[], boundsWidth: number): ScaleLinear<number, number, never> | ScaleBand<string> | ScaleTime<number, number, never>;
16
18
  /**
17
19
  * Uses to create scales for axis related series
18
20
  */
@@ -17,105 +17,110 @@ const filterCategoriesByVisibleSeries = (args) => {
17
17
  });
18
18
  return categories.filter((c) => visibleCategories.has(c));
19
19
  };
20
- const createScales = (args) => {
21
- const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
22
- const xMin = get(xAxis, 'min');
23
- const xType = get(xAxis, 'type', 'linear');
24
- const xCategories = get(xAxis, 'categories');
25
- const xTimestamps = get(xAxis, 'timestamps');
26
- const yType = get(yAxis[0], 'type', 'linear');
27
- const yMin = get(yAxis[0], 'min');
28
- const yCategories = get(yAxis[0], 'categories');
29
- const yTimestamps = get(xAxis, 'timestamps');
30
- let visibleSeries = getOnlyVisibleSeries(series);
31
- // Reassign to all series in case of all series unselected,
32
- // otherwise we will get an empty space without grid
33
- visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
34
- let xScale;
35
- let yScale;
36
- switch (xType) {
20
+ export function createYScale(axis, series, boundsHeight) {
21
+ const yType = get(axis, 'type', 'linear');
22
+ const yMin = get(axis, 'min');
23
+ const yCategories = get(axis, 'categories');
24
+ const yTimestamps = get(axis, 'timestamps');
25
+ switch (yType) {
37
26
  case 'linear': {
38
- const domain = getDomainDataXBySeries(visibleSeries);
39
- const range = [0, boundsWidth - boundsWidth * xAxis.maxPadding];
27
+ const domain = getDomainDataYBySeries(series);
28
+ const range = [boundsHeight, boundsHeight * axis.maxPadding];
40
29
  if (isNumericalArrayData(domain)) {
41
- const [domainXMin, xMax] = extent(domain);
42
- const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
43
- xScale = scaleLinear().domain([xMinValue, xMax]).range(range).nice();
30
+ const [domainYMin, yMax] = extent(domain);
31
+ const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
32
+ return scaleLinear().domain([yMinValue, yMax]).range(range).nice();
44
33
  }
45
34
  break;
46
35
  }
47
36
  case 'category': {
48
- if (xCategories) {
37
+ if (yCategories) {
49
38
  const filteredCategories = filterCategoriesByVisibleSeries({
50
- axisDirection: 'x',
51
- categories: xCategories,
52
- series: visibleSeries,
39
+ axisDirection: 'y',
40
+ categories: yCategories,
41
+ series: series,
53
42
  });
54
- xScale = scaleBand().domain(filteredCategories).range([0, boundsWidth]);
43
+ return scaleBand().domain(filteredCategories).range([boundsHeight, 0]);
55
44
  }
56
45
  break;
57
46
  }
58
47
  case 'datetime': {
59
- const range = [0, boundsWidth - boundsWidth * xAxis.maxPadding];
60
- if (xTimestamps) {
61
- const [xMin, xMax] = extent(xTimestamps);
62
- xScale = scaleUtc().domain([xMin, xMax]).range(range).nice();
48
+ const range = [boundsHeight, boundsHeight * axis.maxPadding];
49
+ if (yTimestamps) {
50
+ const [yMin, yMax] = extent(yTimestamps);
51
+ return scaleUtc().domain([yMin, yMax]).range(range).nice();
63
52
  }
64
53
  else {
65
- const domain = getDomainDataXBySeries(visibleSeries);
54
+ const domain = getDomainDataYBySeries(series);
66
55
  if (isNumericalArrayData(domain)) {
67
- const [xMin, xMax] = extent(domain);
68
- xScale = scaleUtc().domain([xMin, xMax]).range(range).nice();
56
+ const [yMin, yMax] = extent(domain);
57
+ return scaleUtc().domain([yMin, yMax]).range(range).nice();
69
58
  }
70
59
  }
71
60
  break;
72
61
  }
73
62
  }
74
- if (!xScale) {
75
- throw new Error('Failed to create xScale');
76
- }
77
- switch (yType) {
63
+ throw new Error('Failed to create yScale');
64
+ }
65
+ export function createXScale(axis, series, boundsWidth) {
66
+ const xMin = get(axis, 'min');
67
+ const xType = get(axis, 'type', 'linear');
68
+ const xCategories = get(axis, 'categories');
69
+ const xTimestamps = get(axis, 'timestamps');
70
+ const xAxisMinPadding = boundsWidth * axis.maxPadding;
71
+ const xRange = [0, boundsWidth - xAxisMinPadding];
72
+ switch (xType) {
78
73
  case 'linear': {
79
- const domain = getDomainDataYBySeries(visibleSeries);
80
- const range = [boundsHeight, boundsHeight * yAxis[0].maxPadding];
74
+ const domain = getDomainDataXBySeries(series);
81
75
  if (isNumericalArrayData(domain)) {
82
- const [domainYMin, yMax] = extent(domain);
83
- const yMinValue = typeof yMin === 'number' ? yMin : domainYMin;
84
- yScale = scaleLinear().domain([yMinValue, yMax]).range(range).nice();
76
+ const [domainXMin, xMax] = extent(domain);
77
+ const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
78
+ return scaleLinear().domain([xMinValue, xMax]).range(xRange).nice();
85
79
  }
86
80
  break;
87
81
  }
88
82
  case 'category': {
89
- if (yCategories) {
83
+ if (xCategories) {
90
84
  const filteredCategories = filterCategoriesByVisibleSeries({
91
- axisDirection: 'y',
92
- categories: yCategories,
93
- series: visibleSeries,
85
+ axisDirection: 'x',
86
+ categories: xCategories,
87
+ series: series,
94
88
  });
95
- yScale = scaleBand().domain(filteredCategories).range([boundsHeight, 0]);
89
+ const xScale = scaleBand().domain(filteredCategories).range([0, boundsWidth]);
90
+ if (xScale.step() / 2 < xAxisMinPadding) {
91
+ xScale.range(xRange);
92
+ }
93
+ return xScale;
96
94
  }
97
95
  break;
98
96
  }
99
97
  case 'datetime': {
100
- const range = [boundsHeight, boundsHeight * yAxis[0].maxPadding];
101
- if (yTimestamps) {
102
- const [yMin, yMax] = extent(yTimestamps);
103
- yScale = scaleUtc().domain([yMin, yMax]).range(range).nice();
98
+ if (xTimestamps) {
99
+ const [xMin, xMax] = extent(xTimestamps);
100
+ return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
104
101
  }
105
102
  else {
106
- const domain = getDomainDataYBySeries(visibleSeries);
103
+ const domain = getDomainDataXBySeries(series);
107
104
  if (isNumericalArrayData(domain)) {
108
- const [yMin, yMax] = extent(domain);
109
- yScale = scaleUtc().domain([yMin, yMax]).range(range).nice();
105
+ const [xMin, xMax] = extent(domain);
106
+ return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
110
107
  }
111
108
  }
112
109
  break;
113
110
  }
114
111
  }
115
- if (!yScale) {
116
- throw new Error('Failed to create yScale');
117
- }
118
- return { xScale, yScale };
112
+ throw new Error('Failed to create xScale');
113
+ }
114
+ const createScales = (args) => {
115
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis } = args;
116
+ let visibleSeries = getOnlyVisibleSeries(series);
117
+ // Reassign to all series in case of all series unselected,
118
+ // otherwise we will get an empty space without grid
119
+ visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
120
+ return {
121
+ xScale: createXScale(xAxis, visibleSeries, boundsWidth),
122
+ yScale: createYScale(yAxis[0], visibleSeries, boundsHeight),
123
+ };
119
124
  };
120
125
  /**
121
126
  * Uses to create scales for axis related series
@@ -1,13 +1,16 @@
1
- import type { ChartMargin } from '../../../../../types/widget-data';
2
- import type { PreparedAxis } from '../useChartOptions/types';
1
+ import type { ChartMargin } from '../../../../../types';
2
+ import type { PreparedAxis, PreparedLegend, PreparedSeries } from '../../hooks';
3
+ export { getBoundsWidth } from './utils';
3
4
  type Args = {
4
5
  width: number;
5
6
  height: number;
6
7
  margin: ChartMargin;
7
- yAxis?: PreparedAxis[];
8
+ preparedLegend: PreparedLegend;
9
+ preparedXAxis: PreparedAxis;
10
+ preparedYAxis: PreparedAxis[];
11
+ preparedSeries: PreparedSeries[];
8
12
  };
9
13
  export declare const useChartDimensions: (args: Args) => {
10
14
  boundsWidth: number;
11
15
  boundsHeight: number;
12
16
  };
13
- export {};
@@ -1,9 +1,67 @@
1
+ import React from 'react';
2
+ import { createXScale } from '../../hooks';
3
+ import { formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsMaxHeight, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, isAxisRelatedSeries, } from '../../utils';
4
+ import { getBoundsWidth } from './utils';
5
+ export { getBoundsWidth } from './utils';
6
+ const getHeightOccupiedByXAxis = ({ preparedXAxis, preparedSeries, width, }) => {
7
+ let height = preparedXAxis.title.height;
8
+ if (preparedXAxis.labels.enabled) {
9
+ const scale = createXScale(preparedXAxis, preparedSeries, width);
10
+ const tickCount = getTicksCount({ axis: preparedXAxis, range: width });
11
+ const ticks = getXAxisItems({
12
+ scale: scale,
13
+ count: tickCount,
14
+ maxCount: getMaxTickCount({ width, axis: preparedXAxis }),
15
+ });
16
+ const step = getClosestPointsRange(preparedXAxis, ticks);
17
+ const labels = ticks.map((value) => {
18
+ return formatAxisTickLabel({
19
+ axis: preparedXAxis,
20
+ value,
21
+ step,
22
+ });
23
+ });
24
+ const overlapping = hasOverlappingLabels({
25
+ width,
26
+ labels,
27
+ padding: preparedXAxis.labels.padding,
28
+ style: preparedXAxis.labels.style,
29
+ });
30
+ const labelsHeight = overlapping
31
+ ? getLabelsMaxHeight({
32
+ labels,
33
+ style: preparedXAxis.labels.style,
34
+ transform: 'rotate(-45)',
35
+ })
36
+ : getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedXAxis.labels.style });
37
+ height += preparedXAxis.labels.margin + labelsHeight;
38
+ }
39
+ return height;
40
+ };
41
+ const getBottomOffset = (args) => {
42
+ const { hasAxisRelatedSeries, preparedLegend, preparedXAxis, preparedSeries, width } = args;
43
+ let result = 0;
44
+ if (preparedLegend.enabled) {
45
+ result += preparedLegend.height + preparedLegend.margin;
46
+ }
47
+ if (hasAxisRelatedSeries) {
48
+ result += getHeightOccupiedByXAxis({ preparedXAxis, preparedSeries, width });
49
+ }
50
+ return result;
51
+ };
1
52
  export const useChartDimensions = (args) => {
2
- const { margin, width, height, yAxis } = args;
3
- const yAxisTitleHeight = (yAxis === null || yAxis === void 0 ? void 0 : yAxis.reduce((acc, axis) => {
4
- return acc + (axis.title.height || 0);
5
- }, 0)) || 0;
6
- const boundsWidth = width - margin.right - margin.left - yAxisTitleHeight;
7
- const boundsHeight = height - margin.top - margin.bottom;
8
- return { boundsWidth, boundsHeight };
53
+ const { margin, width, height, preparedLegend, preparedXAxis, preparedYAxis, preparedSeries } = args;
54
+ return React.useMemo(() => {
55
+ const hasAxisRelatedSeries = preparedSeries.some(isAxisRelatedSeries);
56
+ const boundsWidth = getBoundsWidth({ chartWidth: width, chartMargin: margin, preparedYAxis });
57
+ const bottomOffset = getBottomOffset({
58
+ hasAxisRelatedSeries,
59
+ preparedLegend,
60
+ preparedXAxis,
61
+ preparedSeries,
62
+ width: boundsWidth,
63
+ });
64
+ const boundsHeight = height - margin.top - margin.bottom - bottomOffset;
65
+ return { boundsWidth, boundsHeight };
66
+ }, [margin, width, height, preparedLegend, preparedXAxis, preparedYAxis, preparedSeries]);
9
67
  };
@@ -0,0 +1,6 @@
1
+ import type { PreparedAxis, PreparedChart } from '../../hooks';
2
+ export declare const getBoundsWidth: (args: {
3
+ chartWidth: number;
4
+ chartMargin: PreparedChart['margin'];
5
+ preparedYAxis: PreparedAxis[];
6
+ }) => number;
@@ -0,0 +1,7 @@
1
+ export const getBoundsWidth = (args) => {
2
+ const { chartWidth, chartMargin, preparedYAxis } = args;
3
+ const yAxisTitleHeight = preparedYAxis.reduce((acc, axis) => {
4
+ return acc + (axis.title.height || 0);
5
+ }, 0) || 0;
6
+ return chartWidth - chartMargin.right - chartMargin.left - yAxisTitleHeight;
7
+ };
@@ -1,10 +1,8 @@
1
1
  import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
- import type { PreparedAxis, PreparedChart, PreparedTitle, PreparedLegend } from './types';
2
+ import type { PreparedAxis, PreparedChart, PreparedTitle } from './types';
3
3
  export declare const getPreparedChart: (args: {
4
4
  chart: ChartKitWidgetData['chart'];
5
5
  series: ChartKitWidgetData['series'];
6
- preparedLegend: PreparedLegend;
7
- preparedXAxis: PreparedAxis;
8
6
  preparedY1Axis: PreparedAxis;
9
7
  preparedTitle?: PreparedTitle;
10
8
  }) => PreparedChart;
@@ -1,47 +1,6 @@
1
- import { select, max } from 'd3';
2
1
  import get from 'lodash/get';
3
- import { formatAxisTickLabel, getDomainDataYBySeries, getHorisontalSvgTextHeight, isAxisRelatedSeries, } from '../../utils';
4
- const AXIS_WIDTH = 1;
5
- const getAxisLabelMaxWidth = (args) => {
6
- const { axis, series } = args;
7
- let maxDomainValue;
8
- let width = 0;
9
- switch (axis.type) {
10
- case 'category': {
11
- const yCategories = get(axis, 'categories', []);
12
- maxDomainValue = [...yCategories].sort((c1, c2) => c2.length - c1.length)[0];
13
- break;
14
- }
15
- case 'datetime': {
16
- const yTimestamps = get(axis, 'timestamps');
17
- const domain = yTimestamps || getDomainDataYBySeries(series);
18
- maxDomainValue = max(domain);
19
- break;
20
- }
21
- case 'linear': {
22
- const domain = getDomainDataYBySeries(series);
23
- maxDomainValue = max(domain);
24
- }
25
- }
26
- let formattedValue = '';
27
- if (axis.labels.enabled) {
28
- formattedValue = formatAxisTickLabel({
29
- axisType: axis.type,
30
- value: maxDomainValue,
31
- dateFormat: axis.labels['dateFormat'],
32
- numberFormat: axis.labels['numberFormat'],
33
- });
34
- }
35
- select(document.body)
36
- .append('text')
37
- .style('font-size', axis.labels.style.fontSize)
38
- .text(formattedValue)
39
- .each(function () {
40
- width = this.getBoundingClientRect().width;
41
- })
42
- .remove();
43
- return width;
44
- };
2
+ import { isAxisRelatedSeries, getHorisontalSvgTextHeight } from '../../utils';
3
+ const AXIS_LINE_WIDTH = 1;
45
4
  const getMarginTop = (args) => {
46
5
  const { chart, hasAxisRelatedSeries, preparedY1Axis, preparedTitle } = args;
47
6
  let marginTop = get(chart, 'margin.top', 0);
@@ -54,51 +13,29 @@ const getMarginTop = (args) => {
54
13
  }
55
14
  return marginTop;
56
15
  };
57
- const getMarginBottom = (args) => {
58
- const { chart, hasAxisRelatedSeries, preparedLegend, preparedXAxis } = args;
59
- let marginBottom = get(chart, 'margin.bottom', 0) + preparedLegend.height;
60
- if (hasAxisRelatedSeries) {
61
- marginBottom +=
62
- preparedXAxis.title.height +
63
- getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedXAxis.labels.style });
64
- if (preparedXAxis.labels.enabled) {
65
- marginBottom += preparedXAxis.labels.padding;
66
- }
67
- }
68
- return marginBottom;
69
- };
70
16
  const getMarginLeft = (args) => {
71
- const { chart, hasAxisRelatedSeries, series, preparedY1Axis } = args;
17
+ const { chart, hasAxisRelatedSeries, preparedY1Axis } = args;
72
18
  let marginLeft = get(chart, 'margin.left', 0);
73
19
  if (hasAxisRelatedSeries) {
74
20
  marginLeft +=
75
- AXIS_WIDTH +
76
- preparedY1Axis.labels.padding +
77
- getAxisLabelMaxWidth({ axis: preparedY1Axis, series: series.data }) +
21
+ AXIS_LINE_WIDTH +
22
+ preparedY1Axis.labels.margin +
23
+ (preparedY1Axis.labels.maxWidth || 0) +
78
24
  preparedY1Axis.title.height;
79
25
  }
80
26
  return marginLeft;
81
27
  };
82
28
  const getMarginRight = (args) => {
83
- const { chart, hasAxisRelatedSeries, series, preparedXAxis } = args;
84
- let marginRight = get(chart, 'margin.right', 0);
85
- if (hasAxisRelatedSeries) {
86
- marginRight += getAxisLabelMaxWidth({ axis: preparedXAxis, series: series.data }) / 2;
87
- }
88
- return marginRight;
29
+ const { chart } = args;
30
+ return get(chart, 'margin.right', 0);
89
31
  };
90
32
  export const getPreparedChart = (args) => {
91
- const { chart, series, preparedLegend, preparedXAxis, preparedY1Axis, preparedTitle } = args;
33
+ const { chart, series, preparedY1Axis, preparedTitle } = args;
92
34
  const hasAxisRelatedSeries = series.data.some(isAxisRelatedSeries);
93
35
  const marginTop = getMarginTop({ chart, hasAxisRelatedSeries, preparedY1Axis, preparedTitle });
94
- const marginBottom = getMarginBottom({
95
- chart,
96
- hasAxisRelatedSeries,
97
- preparedLegend,
98
- preparedXAxis,
99
- });
100
- const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, series, preparedY1Axis });
101
- const marginRight = getMarginRight({ chart, hasAxisRelatedSeries, series, preparedXAxis });
36
+ const marginBottom = get(chart, 'margin.bottom', 0);
37
+ const marginLeft = getMarginLeft({ chart, hasAxisRelatedSeries, preparedY1Axis });
38
+ const marginRight = getMarginRight({ chart });
102
39
  return {
103
40
  margin: {
104
41
  top: marginTop,
@@ -1,5 +1,7 @@
1
1
  import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
2
  import type { ChartOptions } from './types';
3
- type Args = ChartKitWidgetData;
3
+ type Args = {
4
+ data: ChartKitWidgetData;
5
+ };
4
6
  export declare const useChartOptions: (args: Args) => ChartOptions;
5
7
  export {};
@@ -1,34 +1,29 @@
1
1
  import React from 'react';
2
2
  import { getPreparedChart } from './chart';
3
- import { getPreparedLegend } from './legend';
4
3
  import { getPreparedTitle } from './title';
5
4
  import { getPreparedTooltip } from './tooltip';
6
5
  import { getPreparedXAxis } from './x-axis';
7
6
  import { getPreparedYAxis } from './y-axis';
8
7
  export const useChartOptions = (args) => {
9
- const { chart, series, legend, title, tooltip, xAxis, yAxis } = args;
8
+ const { data: { chart, series, title, tooltip, xAxis, yAxis }, } = args;
10
9
  const options = React.useMemo(() => {
11
10
  const preparedTitle = getPreparedTitle({ title });
12
11
  const preparedTooltip = getPreparedTooltip({ tooltip });
13
- const preparedLegend = getPreparedLegend({ legend, series });
14
- const preparedYAxis = getPreparedYAxis({ yAxis });
12
+ const preparedYAxis = getPreparedYAxis({ series: series.data, yAxis });
15
13
  const preparedXAxis = getPreparedXAxis({ xAxis });
16
14
  const preparedChart = getPreparedChart({
17
15
  chart,
18
16
  series,
19
17
  preparedTitle,
20
- preparedLegend,
21
- preparedXAxis,
22
18
  preparedY1Axis: preparedYAxis[0],
23
19
  });
24
20
  return {
25
21
  chart: preparedChart,
26
- legend: preparedLegend,
27
22
  title: preparedTitle,
28
23
  tooltip: preparedTooltip,
29
24
  xAxis: preparedXAxis,
30
25
  yAxis: preparedYAxis,
31
26
  };
32
- }, [chart, legend, title, tooltip, series, xAxis, yAxis]);
27
+ }, [chart, title, tooltip, series, xAxis, yAxis]);
33
28
  return options;
34
29
  };
@@ -1,13 +1,11 @@
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'>> & {
1
+ import type { BaseTextStyle, ChartKitWidgetData, ChartKitWidgetAxis, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels, ChartMargin } from '../../../../../types/widget-data';
2
+ type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'style'> & Required<Pick<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'margin'>> & {
3
3
  style: BaseTextStyle;
4
+ maxWidth?: number;
4
5
  };
5
6
  export type PreparedChart = {
6
7
  margin: ChartMargin;
7
8
  };
8
- export type PreparedLegend = Required<ChartKitWidgetLegend> & {
9
- height: number;
10
- };
11
9
  export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
12
10
  type: ChartKitWidgetAxisType;
13
11
  labels: PreparedAxisLabels;
@@ -33,7 +31,6 @@ export type PreparedTooltip = ChartKitWidgetData['tooltip'] & {
33
31
  };
34
32
  export type ChartOptions = {
35
33
  chart: PreparedChart;
36
- legend: PreparedLegend;
37
34
  tooltip: PreparedTooltip;
38
35
  xAxis: PreparedAxis;
39
36
  yAxis: PreparedAxis[];
@@ -1,5 +1,5 @@
1
1
  import get from 'lodash/get';
2
- import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
2
+ import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
3
3
  import { getHorisontalSvgTextHeight } from '../../utils';
4
4
  export const getPreparedXAxis = ({ xAxis }) => {
5
5
  const titleText = get(xAxis, 'title.text', '');
@@ -10,9 +10,11 @@ export const getPreparedXAxis = ({ xAxis }) => {
10
10
  type: get(xAxis, 'type', 'linear'),
11
11
  labels: {
12
12
  enabled: get(xAxis, 'labels.enabled', true),
13
- padding: get(xAxis, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
13
+ margin: get(xAxis, 'labels.margin', axisLabelsDefaults.margin),
14
+ padding: get(xAxis, 'labels.padding', axisLabelsDefaults.padding),
14
15
  dateFormat: get(xAxis, 'labels.dateFormat'),
15
16
  numberFormat: get(xAxis, 'labels.numberFormat'),
17
+ autoRotation: get(xAxis, 'labels.autoRotation', true),
16
18
  style: { fontSize: get(xAxis, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE) },
17
19
  },
18
20
  lineColor: get(xAxis, 'lineColor'),
@@ -1,5 +1,6 @@
1
- import type { ChartKitWidgetData } from '../../../../../types/widget-data';
1
+ import type { ChartKitWidgetData, ChartKitWidgetSeries } from '../../../../../types/widget-data';
2
2
  import type { PreparedAxis } from './types';
3
- export declare const getPreparedYAxis: ({ yAxis }: {
3
+ export declare const getPreparedYAxis: ({ series, yAxis, }: {
4
+ series: ChartKitWidgetSeries[];
4
5
  yAxis: ChartKitWidgetData['yAxis'];
5
6
  }) => PreparedAxis[];
@@ -1,7 +1,31 @@
1
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 { getHorisontalSvgTextHeight } from '../../utils';
4
- export const getPreparedYAxis = ({ yAxis }) => {
2
+ import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
3
+ import { getHorisontalSvgTextHeight, formatAxisTickLabel, getClosestPointsRange, getScaleTicks, getLabelsMaxWidth, } from '../../utils';
4
+ import { createYScale } from '../useAxisScales';
5
+ const getAxisLabelMaxWidth = (args) => {
6
+ const { axis, series } = args;
7
+ if (!axis.labels.enabled) {
8
+ return 0;
9
+ }
10
+ const scale = createYScale(axis, series, 1);
11
+ const ticks = getScaleTicks(scale);
12
+ // FIXME: it is necessary to filter data, since we do not draw overlapping ticks
13
+ const step = getClosestPointsRange(axis, ticks);
14
+ const labels = ticks.map((tick) => formatAxisTickLabel({
15
+ axis,
16
+ value: tick,
17
+ step,
18
+ }));
19
+ return getLabelsMaxWidth({
20
+ labels,
21
+ style: axis.labels.style,
22
+ });
23
+ };
24
+ const applyLabelsMaxWidth = (args) => {
25
+ const { series, preparedYAxis } = args;
26
+ preparedYAxis.labels.maxWidth = getAxisLabelMaxWidth({ axis: preparedYAxis, series });
27
+ };
28
+ export const getPreparedYAxis = ({ series, yAxis, }) => {
5
29
  // FIXME: add support for n axises
6
30
  const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
7
31
  const y1LabelsStyle = {
@@ -15,7 +39,9 @@ export const getPreparedYAxis = ({ yAxis }) => {
15
39
  type: get(yAxis1, 'type', 'linear'),
16
40
  labels: {
17
41
  enabled: get(yAxis1, 'labels.enabled', true),
18
- padding: get(yAxis1, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
42
+ margin: get(yAxis1, 'labels.margin', axisLabelsDefaults.margin),
43
+ padding: get(yAxis1, 'labels.padding', axisLabelsDefaults.padding),
44
+ autoRotation: get(yAxis1, 'labels.autoRotation', false),
19
45
  dateFormat: get(yAxis1, 'labels.dateFormat'),
20
46
  numberFormat: get(yAxis1, 'labels.numberFormat'),
21
47
  style: y1LabelsStyle,
@@ -39,5 +65,6 @@ export const getPreparedYAxis = ({ yAxis }) => {
39
65
  pixelInterval: get(yAxis1, 'ticks.pixelInterval'),
40
66
  },
41
67
  };
68
+ applyLabelsMaxWidth({ series, preparedYAxis: preparedY1Axis });
42
69
  return [preparedY1Axis];
43
70
  };
@@ -1 +1 @@
1
- export declare const DEFAULT_LEGEND_SYMBOL_SIZE = 10;
1
+ export declare const DEFAULT_LEGEND_SYMBOL_SIZE = 8;
@@ -1 +1 @@
1
- export const DEFAULT_LEGEND_SYMBOL_SIZE = 10;
1
+ export const DEFAULT_LEGEND_SYMBOL_SIZE = 8;
@@ -1,15 +1,27 @@
1
1
  import type { ChartKitWidgetData } from '../../../../../types/widget-data';
2
- import { PreparedLegend } from '../useChartOptions/types';
3
- import { PreparedSeries } from './types';
4
- export type OnLegendItemClick = (data: {
5
- name: string;
6
- metaKey: boolean;
7
- }) => void;
2
+ import type { PreparedAxis, PreparedChart } from '../useChartOptions/types';
3
+ import type { PreparedSeries, OnLegendItemClick } from './types';
8
4
  type Args = {
9
- legend: PreparedLegend;
5
+ chartWidth: number;
6
+ chartHeight: number;
7
+ chartMargin: PreparedChart['margin'];
8
+ legend: ChartKitWidgetData['legend'];
10
9
  series: ChartKitWidgetData['series'];
10
+ preparedYAxis: PreparedAxis[];
11
11
  };
12
12
  export declare const useSeries: (args: Args) => {
13
+ legendItems: import("./types").LegendItem[][];
14
+ legendConfig: {
15
+ offset: {
16
+ left: number;
17
+ top: number;
18
+ };
19
+ pagination: {
20
+ limit: number;
21
+ maxPage: number;
22
+ } | undefined;
23
+ };
24
+ preparedLegend: import("./types").PreparedLegend;
13
25
  preparedSeries: PreparedSeries[];
14
26
  handleLegendItemClick: OnLegendItemClick;
15
27
  };