@gravity-ui/chartkit 4.6.0 → 4.7.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 (99) hide show
  1. package/build/plugins/d3/examples/bar-x/Basic.d.ts +4 -0
  2. package/build/plugins/d3/examples/bar-x/Basic.js +78 -0
  3. package/build/plugins/d3/examples/bar-x/GroupedColumns.d.ts +2 -0
  4. package/build/plugins/d3/examples/bar-x/GroupedColumns.js +44 -0
  5. package/build/plugins/d3/examples/bar-x/StackedColumns.d.ts +2 -0
  6. package/build/plugins/d3/examples/bar-x/StackedColumns.js +45 -0
  7. package/build/plugins/d3/examples/nintendoGames.d.ts +62 -0
  8. package/build/plugins/d3/examples/nintendoGames.js +12037 -0
  9. package/build/plugins/d3/examples/pie/Basic.d.ts +2 -0
  10. package/build/plugins/d3/examples/pie/Basic.js +30 -0
  11. package/build/plugins/d3/examples/pie/Donut.d.ts +2 -0
  12. package/build/plugins/d3/examples/pie/Donut.js +31 -0
  13. package/build/plugins/d3/examples/scatter/Basic.d.ts +2 -0
  14. package/build/plugins/d3/examples/scatter/Basic.js +66 -0
  15. package/build/plugins/d3/renderer/D3Widget.js +11 -1
  16. package/build/plugins/d3/renderer/components/AxisX.d.ts +1 -2
  17. package/build/plugins/d3/renderer/components/AxisX.js +8 -21
  18. package/build/plugins/d3/renderer/components/AxisY.js +50 -18
  19. package/build/plugins/d3/renderer/components/Chart.js +25 -17
  20. package/build/plugins/d3/renderer/components/Legend.js +20 -22
  21. package/build/plugins/d3/renderer/components/Title.js +1 -1
  22. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.d.ts +2 -2
  23. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +8 -0
  24. package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.d.ts +14 -0
  25. package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.js +70 -0
  26. package/build/plugins/d3/renderer/components/Tooltip/index.d.ts +5 -3
  27. package/build/plugins/d3/renderer/components/Tooltip/index.js +4 -2
  28. package/build/plugins/d3/renderer/components/styles.css +3 -0
  29. package/build/plugins/d3/renderer/constants/defaults/axis.d.ts +9 -0
  30. package/build/plugins/d3/renderer/constants/defaults/axis.js +6 -0
  31. package/build/plugins/d3/renderer/constants/defaults/index.d.ts +1 -0
  32. package/build/plugins/d3/renderer/constants/defaults/index.js +1 -0
  33. package/build/plugins/d3/renderer/constants/defaults/series-options.d.ts +11 -0
  34. package/build/plugins/d3/renderer/constants/defaults/series-options.js +41 -0
  35. package/build/plugins/d3/renderer/constants/index.d.ts +0 -1
  36. package/build/plugins/d3/renderer/constants/index.js +0 -1
  37. package/build/plugins/d3/renderer/d3-dispatcher.d.ts +1 -0
  38. package/build/plugins/d3/renderer/d3-dispatcher.js +4 -0
  39. package/build/plugins/d3/renderer/hooks/index.d.ts +0 -1
  40. package/build/plugins/d3/renderer/hooks/index.js +0 -1
  41. package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +6 -5
  42. package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +2 -1
  43. package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +8 -41
  44. package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.d.ts +3 -0
  45. package/build/plugins/d3/renderer/hooks/useChartDimensions/utils.js +17 -4
  46. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.d.ts +2 -4
  47. package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +4 -23
  48. package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +1 -1
  49. package/build/plugins/d3/renderer/hooks/useChartOptions/index.js +2 -10
  50. package/build/plugins/d3/renderer/hooks/useChartOptions/title.d.ts +1 -1
  51. package/build/plugins/d3/renderer/hooks/useChartOptions/title.js +1 -0
  52. package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +8 -5
  53. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.d.ts +5 -3
  54. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +61 -6
  55. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +1 -1
  56. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +20 -12
  57. package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +1 -0
  58. package/build/plugins/d3/renderer/hooks/useSeries/index.js +8 -2
  59. package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.js +8 -3
  60. package/build/plugins/d3/renderer/hooks/useSeries/prepare-options.d.ts +3 -0
  61. package/build/plugins/d3/renderer/hooks/useSeries/prepare-options.js +5 -0
  62. package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +6 -3
  63. package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +5 -1
  64. package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.d.ts +12 -0
  65. package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.js +91 -0
  66. package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.d.ts +19 -0
  67. package/build/plugins/d3/renderer/hooks/useShapes/{bar-x.js → bar-x/prepare-data.js} +9 -88
  68. package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +13 -10
  69. package/build/plugins/d3/renderer/hooks/useShapes/index.js +28 -13
  70. package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +6 -4
  71. package/build/plugins/d3/renderer/hooks/useShapes/pie.js +98 -20
  72. package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.d.ts +15 -0
  73. package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +89 -0
  74. package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.d.ts +19 -0
  75. package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +55 -0
  76. package/build/plugins/d3/renderer/hooks/useShapes/styles.css +1 -9
  77. package/build/plugins/d3/renderer/hooks/useTooltip/index.d.ts +6 -6
  78. package/build/plugins/d3/renderer/hooks/useTooltip/index.js +15 -17
  79. package/build/plugins/d3/renderer/hooks/useTooltip/types.d.ts +0 -6
  80. package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +3 -1
  81. package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +77 -38
  82. package/build/plugins/d3/renderer/utils/axis.js +0 -6
  83. package/build/plugins/d3/renderer/utils/index.d.ts +5 -0
  84. package/build/plugins/d3/renderer/utils/index.js +13 -8
  85. package/build/plugins/d3/renderer/utils/math.d.ts +2 -0
  86. package/build/plugins/d3/renderer/utils/math.js +8 -0
  87. package/build/plugins/d3/renderer/utils/text.d.ts +6 -6
  88. package/build/plugins/d3/renderer/utils/text.js +25 -15
  89. package/build/types/widget-data/axis.d.ts +10 -0
  90. package/build/types/widget-data/series.d.ts +51 -0
  91. package/build/types/widget-data/tooltip.d.ts +18 -7
  92. package/package.json +2 -2
  93. package/build/plugins/d3/renderer/hooks/useChartEvents/index.d.ts +0 -5
  94. package/build/plugins/d3/renderer/hooks/useChartEvents/index.js +0 -15
  95. package/build/plugins/d3/renderer/hooks/useShapes/bar-x.d.ts +0 -21
  96. package/build/plugins/d3/renderer/hooks/useShapes/defaults.d.ts +0 -5
  97. package/build/plugins/d3/renderer/hooks/useShapes/defaults.js +0 -5
  98. package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +0 -19
  99. package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +0 -89
@@ -1,5 +1,5 @@
1
1
  import get from 'lodash/get';
2
- import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
2
+ import { axisLabelsDefaults, DEFAULT_AXIS_LABEL_FONT_SIZE, yAxisTitleDefaults, } from '../../constants';
3
3
  import { getHorisontalSvgTextHeight, formatAxisTickLabel, getClosestPointsRange, getScaleTicks, getLabelsMaxWidth, } from '../../utils';
4
4
  import { createYScale } from '../useAxisScales';
5
5
  const getAxisLabelMaxWidth = (args) => {
@@ -18,39 +18,45 @@ const getAxisLabelMaxWidth = (args) => {
18
18
  }));
19
19
  return getLabelsMaxWidth({
20
20
  labels,
21
- style: axis.labels.style,
21
+ style: {
22
+ 'font-size': axis.labels.style.fontSize,
23
+ 'font-weight': axis.labels.style.fontWeight || '',
24
+ },
25
+ rotation: axis.labels.rotation,
22
26
  });
23
27
  };
24
- const applyLabelsMaxWidth = (args) => {
25
- const { series, preparedYAxis } = args;
26
- preparedYAxis.labels.maxWidth = getAxisLabelMaxWidth({ axis: preparedYAxis, series });
27
- };
28
28
  export const getPreparedYAxis = ({ series, yAxis, }) => {
29
29
  // FIXME: add support for n axises
30
30
  const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
31
+ const labelsEnabled = get(yAxis1, 'labels.enabled', true);
31
32
  const y1LabelsStyle = {
32
33
  fontSize: get(yAxis1, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE),
33
34
  };
34
35
  const y1TitleText = get(yAxis1, 'title.text', '');
35
36
  const y1TitleStyle = {
36
- fontSize: get(yAxis1, 'title.style.fontSize', DEFAULT_AXIS_TITLE_FONT_SIZE),
37
+ fontSize: get(yAxis1, 'title.style.fontSize', yAxisTitleDefaults.fontSize),
37
38
  };
38
39
  const preparedY1Axis = {
39
40
  type: get(yAxis1, 'type', 'linear'),
40
41
  labels: {
41
- enabled: get(yAxis1, 'labels.enabled', true),
42
- margin: get(yAxis1, 'labels.margin', axisLabelsDefaults.margin),
43
- padding: get(yAxis1, 'labels.padding', axisLabelsDefaults.padding),
44
- autoRotation: get(yAxis1, 'labels.autoRotation', false),
42
+ enabled: labelsEnabled,
43
+ margin: labelsEnabled ? get(yAxis1, 'labels.margin', axisLabelsDefaults.margin) : 0,
44
+ padding: labelsEnabled ? get(yAxis1, 'labels.padding', axisLabelsDefaults.padding) : 0,
45
45
  dateFormat: get(yAxis1, 'labels.dateFormat'),
46
46
  numberFormat: get(yAxis1, 'labels.numberFormat'),
47
47
  style: y1LabelsStyle,
48
+ rotation: get(yAxis1, 'labels.rotation', 0),
49
+ width: 0,
50
+ height: 0,
51
+ lineHeight: getHorisontalSvgTextHeight({ text: 'TmpLabel', style: y1LabelsStyle }),
52
+ maxWidth: get(yAxis1, 'labels.maxWidth', axisLabelsDefaults.maxWidth),
48
53
  },
49
54
  lineColor: get(yAxis1, 'lineColor'),
50
55
  categories: get(yAxis1, 'categories'),
51
56
  timestamps: get(yAxis1, 'timestamps'),
52
57
  title: {
53
58
  text: y1TitleText,
59
+ margin: get(yAxis1, 'title.margin', yAxisTitleDefaults.margin),
54
60
  style: y1TitleStyle,
55
61
  height: y1TitleText
56
62
  ? getHorisontalSvgTextHeight({ text: y1TitleText, style: y1TitleStyle })
@@ -65,6 +71,8 @@ export const getPreparedYAxis = ({ series, yAxis, }) => {
65
71
  pixelInterval: get(yAxis1, 'ticks.pixelInterval'),
66
72
  },
67
73
  };
68
- applyLabelsMaxWidth({ series, preparedYAxis: preparedY1Axis });
74
+ if (labelsEnabled) {
75
+ preparedY1Axis.labels.width = getAxisLabelMaxWidth({ axis: preparedY1Axis, series });
76
+ }
69
77
  return [preparedY1Axis];
70
78
  };
@@ -23,6 +23,7 @@ export declare const useSeries: (args: Args) => {
23
23
  };
24
24
  preparedLegend: import("./types").PreparedLegend;
25
25
  preparedSeries: PreparedSeries[];
26
+ preparedSeriesOptions: import("../../constants").SeriesOptionsDefaults;
26
27
  handleLegendItemClick: OnLegendItemClick;
27
28
  };
28
29
  export {};
@@ -4,9 +4,10 @@ import { DEFAULT_PALETTE } from '../../constants';
4
4
  import { getSeriesNames } from '../../utils';
5
5
  import { getActiveLegendItems, getAllLegendItems } from './utils';
6
6
  import { getPreparedLegend, getLegendComponents } from './prepare-legend';
7
+ import { getPreparedOptions } from './prepare-options';
7
8
  import { prepareSeries } from './prepareSeries';
8
9
  export const useSeries = (args) => {
9
- const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series }, } = args;
10
+ const { chartWidth, chartHeight, chartMargin, legend, preparedYAxis, series: { data: series, options: seriesOptions }, } = args;
10
11
  const preparedLegend = React.useMemo(() => getPreparedLegend({ legend, series }), [legend, series]);
11
12
  const preparedSeries = React.useMemo(() => {
12
13
  const seriesNames = getSeriesNames(series);
@@ -22,9 +23,13 @@ export const useSeries = (args) => {
22
23
  return acc;
23
24
  }, []);
24
25
  }, [series, preparedLegend]);
26
+ const preparedSeriesOptions = React.useMemo(() => {
27
+ return getPreparedOptions(seriesOptions);
28
+ }, [seriesOptions]);
25
29
  const [activeLegendItems, setActiveLegendItems] = React.useState(getActiveLegendItems(preparedSeries));
26
30
  const chartSeries = React.useMemo(() => {
27
- return preparedSeries.map((singleSeries) => {
31
+ return preparedSeries.map((singleSeries, i) => {
32
+ singleSeries.id = `Series ${i + 1}`;
28
33
  if (singleSeries.legend.enabled) {
29
34
  return Object.assign(Object.assign({}, singleSeries), { visible: activeLegendItems.includes(singleSeries.name) });
30
35
  }
@@ -67,6 +72,7 @@ export const useSeries = (args) => {
67
72
  legendConfig,
68
73
  preparedLegend,
69
74
  preparedSeries: chartSeries,
75
+ preparedSeriesOptions,
70
76
  handleLegendItemClick,
71
77
  };
72
78
  };
@@ -5,6 +5,7 @@ import { select } from 'd3';
5
5
  import { legendDefaults } from '../../constants';
6
6
  import { getHorisontalSvgTextHeight } from '../../utils';
7
7
  import { getBoundsWidth } from '../useChartDimensions';
8
+ import { getWidthOccupiedByYAxis } from '../useChartDimensions/utils';
8
9
  export const getPreparedLegend = (args) => {
9
10
  const { legend, series } = args;
10
11
  const enabled = typeof (legend === null || legend === void 0 ? void 0 : legend.enabled) === 'boolean' ? legend === null || legend === void 0 ? void 0 : legend.enabled : series.length > 1;
@@ -80,13 +81,17 @@ export const getLegendComponents = (args) => {
80
81
  let legendHeight = preparedLegend.lineHeight * items.length;
81
82
  let pagination;
82
83
  if (maxLegendHeight < legendHeight) {
83
- const limit = Math.floor(maxLegendHeight / preparedLegend.lineHeight);
84
+ // extra line for paginator
85
+ const limit = Math.floor(maxLegendHeight / preparedLegend.lineHeight) - 1;
84
86
  const maxPage = Math.ceil(items.length / limit);
85
87
  pagination = { limit, maxPage };
86
88
  legendHeight = maxLegendHeight;
87
89
  }
88
90
  preparedLegend.height = legendHeight;
89
- const top = chartHeight - chartMargin.bottom - preparedLegend.height + preparedLegend.lineHeight / 2;
90
- const offset = { left: chartMargin.left, top };
91
+ const top = chartHeight - chartMargin.bottom - preparedLegend.height;
92
+ const offset = {
93
+ left: chartMargin.left + getWidthOccupiedByYAxis({ preparedAxis: preparedYAxis }),
94
+ top,
95
+ };
91
96
  return { legendConfig: { offset, pagination }, legendItems: items };
92
97
  };
@@ -0,0 +1,3 @@
1
+ import type { ChartKitWidgetSeriesOptions } from '../../../../../types/widget-data';
2
+ import type { PreparedSeriesOptions } from './types';
3
+ export declare const getPreparedOptions: (options?: ChartKitWidgetSeriesOptions) => PreparedSeriesOptions;
@@ -0,0 +1,5 @@
1
+ import merge from 'lodash/merge';
2
+ import { seriesOptionsDefaults } from '../../constants';
3
+ export const getPreparedOptions = (options) => {
4
+ return merge({}, seriesOptionsDefaults, options);
5
+ };
@@ -1,9 +1,9 @@
1
- import { scaleOrdinal } from 'd3';
2
1
  import cloneDeep from 'lodash/cloneDeep';
3
2
  import get from 'lodash/get';
3
+ import { scaleOrdinal } from 'd3';
4
+ import { getRandomCKId } from '../../../../../utils';
4
5
  import { DEFAULT_PALETTE } from '../../constants';
5
6
  import { DEFAULT_LEGEND_SYMBOL_SIZE } from './constants';
6
- import { getRandomCKId } from '../../../../../utils';
7
7
  const DEFAULT_DATALABELS_STYLE = {
8
8
  fontSize: '11px',
9
9
  fontWeight: 'bold',
@@ -53,6 +53,7 @@ function prepareBarXSeries(args) {
53
53
  type: series.type,
54
54
  color: color,
55
55
  name: name,
56
+ id: '',
56
57
  visible: get(series, 'visible', true),
57
58
  legend: {
58
59
  enabled: get(series, 'legend.enabled', legend.enabled),
@@ -80,13 +81,15 @@ function preparePieSeries(args) {
80
81
  var _a, _b;
81
82
  const result = {
82
83
  type: 'pie',
83
- data: dataItem.value,
84
+ data: dataItem,
84
85
  dataLabels: {
85
86
  enabled: get(series, 'dataLabels.enabled', true),
86
87
  },
87
88
  label: dataItem.label,
89
+ value: dataItem.value,
88
90
  visible: typeof dataItem.visible === 'boolean' ? dataItem.visible : true,
89
91
  name: dataItem.name,
92
+ id: '',
90
93
  color: dataItem.color || colorScale(dataItem.name),
91
94
  legend: {
92
95
  enabled: get(series, 'legend.enabled', legend.enabled),
@@ -1,4 +1,5 @@
1
1
  import { BarXSeries, BarXSeriesData, BaseTextStyle, ChartKitWidgetLegend, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData } from '../../../../../types/widget-data';
2
+ import type { SeriesOptionsDefaults } from '../../constants';
2
3
  export type RectLegendSymbol = {
3
4
  shape: 'rect';
4
5
  } & Required<RectLegendSymbolOptions>;
@@ -31,6 +32,7 @@ export type LegendConfig = {
31
32
  type BasePreparedSeries = {
32
33
  color: string;
33
34
  name: string;
35
+ id: string;
34
36
  visible: boolean;
35
37
  legend: {
36
38
  enabled: boolean;
@@ -52,9 +54,11 @@ export type PreparedBarXSeries = {
52
54
  };
53
55
  } & BasePreparedSeries;
54
56
  export type PreparedPieSeries = BasePreparedSeries & Required<Omit<PieSeries, 'data'>> & {
55
- data: PieSeriesData['value'];
57
+ data: PieSeriesData;
58
+ value: PieSeriesData['value'];
56
59
  stackId: string;
57
60
  label?: PieSeriesData['label'];
58
61
  };
59
62
  export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedPieSeries;
63
+ export type PreparedSeriesOptions = SeriesOptionsDefaults;
60
64
  export {};
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import type { Dispatch } from 'd3';
3
+ import type { PreparedSeriesOptions } from '../../useSeries/types';
4
+ import type { PreparedBarXData } from './prepare-data';
5
+ export { prepareBarXData } from './prepare-data';
6
+ export type { PreparedBarXData } from './prepare-data';
7
+ type Args = {
8
+ dispatcher: Dispatch<object>;
9
+ preparedData: PreparedBarXData[];
10
+ seriesOptions: PreparedSeriesOptions;
11
+ };
12
+ export declare const BarXSeriesShapes: (args: Args) => React.JSX.Element;
@@ -0,0 +1,91 @@
1
+ import React from 'react';
2
+ import get from 'lodash/get';
3
+ import { color, select } from 'd3';
4
+ import { block } from '../../../../../../utils/cn';
5
+ export { prepareBarXData } from './prepare-data';
6
+ const DEFAULT_LABEL_PADDING = 7;
7
+ const b = block('d3-bar-x');
8
+ export const BarXSeriesShapes = (args) => {
9
+ const { dispatcher, preparedData, seriesOptions } = args;
10
+ const ref = React.useRef(null);
11
+ React.useEffect(() => {
12
+ if (!ref.current) {
13
+ return () => { };
14
+ }
15
+ const svgElement = select(ref.current);
16
+ const hoverOptions = get(seriesOptions, 'bar-x.states.hover');
17
+ const inactiveOptions = get(seriesOptions, 'bar-x.states.inactive');
18
+ svgElement.selectAll('*').remove();
19
+ const rectSelection = svgElement
20
+ .selectAll('allRects')
21
+ .data(preparedData)
22
+ .join('rect')
23
+ .attr('class', b('segment'))
24
+ .attr('x', (d) => d.x)
25
+ .attr('y', (d) => d.y)
26
+ .attr('height', (d) => d.height)
27
+ .attr('width', (d) => d.width)
28
+ .attr('fill', (d) => d.data.color || d.series.color);
29
+ const dataLabels = preparedData.filter((d) => d.series.dataLabels.enabled);
30
+ const labelSelection = svgElement
31
+ .selectAll('allLabels')
32
+ .data(dataLabels)
33
+ .join('text')
34
+ .text((d) => String(d.data.label || d.data.y))
35
+ .attr('class', b('label'))
36
+ .attr('x', (d) => d.x + d.width / 2)
37
+ .attr('y', (d) => {
38
+ if (d.series.dataLabels.inside) {
39
+ return d.y + d.height / 2;
40
+ }
41
+ return d.y - DEFAULT_LABEL_PADDING;
42
+ })
43
+ .attr('text-anchor', 'middle')
44
+ .style('font-size', (d) => d.series.dataLabels.style.fontSize)
45
+ .style('font-weight', (d) => d.series.dataLabels.style.fontWeight || null)
46
+ .style('fill', (d) => d.series.dataLabels.style.fontColor || null);
47
+ dispatcher.on('hover-shape.bar-x', (data) => {
48
+ const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
49
+ const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
50
+ if (!data) {
51
+ if (hoverEnabled) {
52
+ rectSelection.attr('fill', (d) => d.data.color || d.series.color);
53
+ }
54
+ if (inactiveEnabled) {
55
+ rectSelection.attr('opacity', null);
56
+ labelSelection.attr('opacity', null);
57
+ }
58
+ return;
59
+ }
60
+ if (hoverEnabled) {
61
+ const hoveredValues = data.map((d) => d.data.x);
62
+ rectSelection.attr('fill', (d) => {
63
+ var _a;
64
+ const fillColor = d.data.color || d.series.color;
65
+ if (hoveredValues.includes(d.data.x)) {
66
+ return (((_a = color(fillColor)) === null || _a === void 0 ? void 0 : _a.brighter(hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.brightness).toString()) ||
67
+ fillColor);
68
+ }
69
+ return fillColor;
70
+ });
71
+ }
72
+ if (inactiveEnabled) {
73
+ const hoveredSeries = data.map((d) => d.series.id);
74
+ rectSelection.attr('opacity', (d) => {
75
+ return hoveredSeries.includes(d.series.id)
76
+ ? null
77
+ : (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
78
+ });
79
+ labelSelection.attr('opacity', (d) => {
80
+ return hoveredSeries.includes(d.series.id)
81
+ ? null
82
+ : (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
83
+ });
84
+ }
85
+ });
86
+ return () => {
87
+ dispatcher.on('hover-shape.bar-x', null);
88
+ };
89
+ }, [dispatcher, preparedData, seriesOptions]);
90
+ return React.createElement("g", { ref: ref, className: b() });
91
+ };
@@ -0,0 +1,19 @@
1
+ import type { TooltipDataChunkBarX } from '../../../../../../types';
2
+ import type { ChartScale } from '../../useAxisScales';
3
+ import type { PreparedAxis } from '../../useChartOptions/types';
4
+ import type { PreparedBarXSeries, PreparedSeriesOptions } from '../../useSeries/types';
5
+ export type PreparedBarXData = Omit<TooltipDataChunkBarX, 'series'> & {
6
+ x: number;
7
+ y: number;
8
+ width: number;
9
+ height: number;
10
+ series: PreparedBarXSeries;
11
+ };
12
+ export declare const prepareBarXData: (args: {
13
+ series: PreparedBarXSeries[];
14
+ seriesOptions: PreparedSeriesOptions;
15
+ xAxis: PreparedAxis;
16
+ xScale: ChartScale;
17
+ yAxis: PreparedAxis[];
18
+ yScale: ChartScale;
19
+ }) => PreparedBarXData[];
@@ -1,20 +1,15 @@
1
- import { ascending, descending, max, pointer, select, sort } from 'd3';
2
- import React from 'react';
1
+ import { ascending, descending, max, sort } from 'd3';
3
2
  import get from 'lodash/get';
4
- import { block } from '../../../../../utils/cn';
5
- import { getDataCategoryValue } from '../../utils';
6
- import { DEFAULT_BAR_X_SERIES_OPTIONS } from './defaults';
3
+ import { getDataCategoryValue } from '../../../utils';
4
+ const MIN_RECT_WIDTH = 1;
7
5
  const MIN_RECT_GAP = 1;
8
6
  const MIN_GROUP_GAP = 1;
9
- const DEFAULT_LABEL_PADDING = 7;
10
- const b = block('d3-bar-x');
11
- function prepareData(args) {
7
+ export const prepareBarXData = (args) => {
12
8
  const { series, seriesOptions, xAxis, xScale, yScale } = args;
13
9
  const categories = get(xAxis, 'categories', []);
14
- const { barMaxWidth: defaultBarMaxWidth, barPadding: defaultBarPadding, groupPadding: defaultGroupPadding, } = DEFAULT_BAR_X_SERIES_OPTIONS;
15
- const barMaxWidth = get(seriesOptions, 'bar-x.barMaxWidth', defaultBarMaxWidth);
16
- const barPadding = get(seriesOptions, 'bar-x.barPadding', defaultBarPadding);
17
- const groupPadding = get(seriesOptions, 'bar-x.groupPadding', defaultGroupPadding);
10
+ const barMaxWidth = get(seriesOptions, 'bar-x.barMaxWidth');
11
+ const barPadding = get(seriesOptions, 'bar-x.barPadding');
12
+ const groupPadding = get(seriesOptions, 'bar-x.groupPadding');
18
13
  const sortingOptions = get(seriesOptions, 'bar-x.dataSorting');
19
14
  const comparator = (sortingOptions === null || sortingOptions === void 0 ? void 0 : sortingOptions.direction) === 'desc' ? descending : ascending;
20
15
  const sortKey = (() => {
@@ -72,7 +67,7 @@ function prepareData(args) {
72
67
  const groupGap = Math.max(bandWidth * groupPadding, MIN_GROUP_GAP);
73
68
  const groupWidth = bandWidth - groupGap;
74
69
  const rectGap = Math.max(bandWidth * barPadding, MIN_RECT_GAP);
75
- const rectWidth = Math.min(groupWidth / maxGroupSize - rectGap, barMaxWidth);
70
+ const rectWidth = Math.max(MIN_RECT_WIDTH, Math.min(groupWidth / maxGroupSize - rectGap, barMaxWidth));
76
71
  const result = [];
77
72
  Object.entries(data).forEach(([xValue, val]) => {
78
73
  const stacks = Object.values(val);
@@ -109,78 +104,4 @@ function prepareData(args) {
109
104
  });
110
105
  });
111
106
  return result;
112
- }
113
- export function BarXSeriesShapes(args) {
114
- const { top, left, series, seriesOptions, xAxis, xScale, yAxis, yScale, onSeriesMouseMove, onSeriesMouseLeave, svgContainer, } = args;
115
- const ref = React.useRef(null);
116
- React.useEffect(() => {
117
- if (!ref.current) {
118
- return;
119
- }
120
- const svgElement = select(ref.current);
121
- svgElement.selectAll('*').remove();
122
- const shapes = prepareData({
123
- series,
124
- seriesOptions,
125
- xAxis,
126
- xScale,
127
- yAxis,
128
- yScale,
129
- });
130
- svgElement
131
- .selectAll('allRects')
132
- .data(shapes)
133
- .join('rect')
134
- .attr('class', b('segment'))
135
- .attr('x', (d) => d.x)
136
- .attr('y', (d) => d.y)
137
- .attr('height', (d) => d.height)
138
- .attr('width', (d) => d.width)
139
- .attr('fill', (d) => d.data.color || d.series.color)
140
- .on('mousemove', (e, d) => {
141
- const [x, y] = pointer(e, svgContainer);
142
- onSeriesMouseMove === null || onSeriesMouseMove === void 0 ? void 0 : onSeriesMouseMove({
143
- hovered: {
144
- data: d.data,
145
- series: d.series,
146
- },
147
- pointerPosition: [x - left, y - top],
148
- });
149
- })
150
- .on('mouseleave', () => {
151
- if (onSeriesMouseLeave) {
152
- onSeriesMouseLeave();
153
- }
154
- });
155
- const dataLabels = shapes.filter((s) => s.series.dataLabels.enabled);
156
- svgElement
157
- .selectAll('allLabels')
158
- .data(dataLabels)
159
- .join('text')
160
- .text((d) => String(d.data.label || d.data.y))
161
- .attr('class', b('label'))
162
- .attr('x', (d) => d.x + d.width / 2)
163
- .attr('y', (d) => {
164
- if (d.series.dataLabels.inside) {
165
- return d.y + d.height / 2;
166
- }
167
- return d.y - DEFAULT_LABEL_PADDING;
168
- })
169
- .attr('text-anchor', 'middle')
170
- .style('font-size', (d) => d.series.dataLabels.style.fontSize)
171
- .style('font-weight', (d) => d.series.dataLabels.style.fontWeight || null)
172
- .style('fill', (d) => d.series.dataLabels.style.fontColor || null);
173
- }, [
174
- onSeriesMouseMove,
175
- onSeriesMouseLeave,
176
- svgContainer,
177
- xAxis,
178
- xScale,
179
- yAxis,
180
- yScale,
181
- series,
182
- left,
183
- top,
184
- ]);
185
- return React.createElement("g", { ref: ref, className: b() });
186
- }
107
+ };
@@ -1,26 +1,29 @@
1
1
  import React from 'react';
2
- import type { ChartKitWidgetSeriesOptions } from '../../../../../types';
3
- import type { ChartOptions } from '../useChartOptions/types';
2
+ import { Dispatch } from 'd3';
3
+ import type { PreparedAxis } from '../useChartOptions/types';
4
4
  import type { ChartScale } from '../useAxisScales';
5
- import type { PreparedSeries } from '../';
6
- import type { OnSeriesMouseMove, OnSeriesMouseLeave } from '../useTooltip/types';
5
+ import type { PreparedSeries, PreparedSeriesOptions } from '../';
6
+ import type { PreparedBarXData } from './bar-x';
7
+ import type { PreparedScatterData } from './scatter';
7
8
  import './styles.css';
9
+ export type { PreparedBarXData } from './bar-x';
10
+ export type { PreparedScatterData } from './scatter';
11
+ export type ShapeData = PreparedBarXData | PreparedScatterData;
8
12
  type Args = {
9
13
  top: number;
10
14
  left: number;
11
15
  boundsWidth: number;
12
16
  boundsHeight: number;
17
+ dispatcher: Dispatch<object>;
13
18
  series: PreparedSeries[];
14
- seriesOptions?: ChartKitWidgetSeriesOptions;
15
- xAxis: ChartOptions['xAxis'];
16
- yAxis: ChartOptions['yAxis'];
19
+ seriesOptions: PreparedSeriesOptions;
20
+ xAxis: PreparedAxis;
21
+ yAxis: PreparedAxis[];
17
22
  svgContainer: SVGSVGElement | null;
18
- onSeriesMouseMove?: OnSeriesMouseMove;
19
- onSeriesMouseLeave?: OnSeriesMouseLeave;
20
23
  xScale?: ChartScale;
21
24
  yScale?: ChartScale;
22
25
  };
23
26
  export declare const useShapes: (args: Args) => {
24
27
  shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
28
+ shapesData: ShapeData[];
25
29
  };
26
- export {};
@@ -1,46 +1,63 @@
1
1
  import React from 'react';
2
2
  import { group } from 'd3';
3
3
  import { getOnlyVisibleSeries } from '../../utils';
4
- import { BarXSeriesShapes } from './bar-x';
5
- import { ScatterSeriesShape } from './scatter';
4
+ import { BarXSeriesShapes, prepareBarXData } from './bar-x';
5
+ import { ScatterSeriesShape, prepareScatterData } from './scatter';
6
6
  import { PieSeriesComponent } from './pie';
7
7
  import './styles.css';
8
8
  export const useShapes = (args) => {
9
- const { top, left, boundsWidth, boundsHeight, series, seriesOptions, xAxis, xScale, yAxis, yScale, svgContainer, onSeriesMouseMove, onSeriesMouseLeave, } = args;
10
- const shapes = React.useMemo(() => {
9
+ const { top, left, boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, svgContainer, } = args;
10
+ const shapesComponents = React.useMemo(() => {
11
11
  const visibleSeries = getOnlyVisibleSeries(series);
12
12
  const groupedSeries = group(visibleSeries, (item) => item.type);
13
- return Array.from(groupedSeries).reduce((acc, item) => {
13
+ const shapesData = [];
14
+ const shapes = Array.from(groupedSeries).reduce((acc, item) => {
14
15
  const [seriesType, chartSeries] = item;
15
16
  switch (seriesType) {
16
17
  case 'bar-x': {
17
18
  if (xScale && yScale) {
18
- acc.push(React.createElement(BarXSeriesShapes, { key: "bar-x", series: chartSeries, seriesOptions: seriesOptions, xAxis: xAxis, xScale: xScale, yAxis: yAxis, yScale: yScale, top: top, left: left, svgContainer: svgContainer, onSeriesMouseMove: onSeriesMouseMove, onSeriesMouseLeave: onSeriesMouseLeave }));
19
+ const preparedData = prepareBarXData({
20
+ series: chartSeries,
21
+ seriesOptions,
22
+ xAxis,
23
+ xScale,
24
+ yAxis,
25
+ yScale,
26
+ });
27
+ acc.push(React.createElement(BarXSeriesShapes, { key: "bar-x", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
28
+ shapesData.push(...preparedData);
19
29
  }
20
30
  break;
21
31
  }
22
32
  case 'scatter': {
23
33
  if (xScale && yScale) {
24
- const scatterShapes = chartSeries.map((scatterSeries, i) => {
25
- return (React.createElement(ScatterSeriesShape, { key: i, top: top, left: left, series: scatterSeries, xAxis: xAxis, xScale: xScale, yAxis: yAxis, yScale: yScale, onSeriesMouseMove: onSeriesMouseMove, onSeriesMouseLeave: onSeriesMouseLeave, svgContainer: svgContainer }));
34
+ const preparedData = prepareScatterData({
35
+ series: chartSeries,
36
+ xAxis,
37
+ xScale,
38
+ yAxis: yAxis[0],
39
+ yScale,
26
40
  });
27
- acc.push(...scatterShapes);
41
+ acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, top: top, left: left, preparedData: preparedData, seriesOptions: seriesOptions, svgContainer: svgContainer }));
28
42
  }
29
43
  break;
30
44
  }
31
45
  case 'pie': {
32
46
  const groupedPieSeries = group(chartSeries, (pieSeries) => pieSeries.stackId);
33
47
  acc.push(...Array.from(groupedPieSeries).map(([key, pieSeries]) => {
34
- return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, series: pieSeries, onSeriesMouseMove: onSeriesMouseMove, onSeriesMouseLeave: onSeriesMouseLeave, svgContainer: svgContainer }));
48
+ return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, dispatcher: dispatcher, top: top, left: left, series: pieSeries, seriesOptions: seriesOptions, svgContainer: svgContainer }));
35
49
  }));
36
50
  }
37
51
  }
38
52
  return acc;
39
53
  }, []);
54
+ return { shapes, shapesData };
40
55
  }, [
41
56
  boundsWidth,
42
57
  boundsHeight,
58
+ dispatcher,
43
59
  series,
60
+ seriesOptions,
44
61
  xAxis,
45
62
  xScale,
46
63
  yAxis,
@@ -48,8 +65,6 @@ export const useShapes = (args) => {
48
65
  svgContainer,
49
66
  left,
50
67
  top,
51
- onSeriesMouseMove,
52
- onSeriesMouseLeave,
53
68
  ]);
54
- return { shapes };
69
+ return { shapes: shapesComponents.shapes, shapesData: shapesComponents.shapesData };
55
70
  };
@@ -1,13 +1,15 @@
1
1
  import React from 'react';
2
- import type { OnSeriesMouseLeave, OnSeriesMouseMove } from '../useTooltip/types';
3
- import { PreparedPieSeries } from '../useSeries/types';
2
+ import type { Dispatch } from 'd3';
3
+ import { PreparedPieSeries, PreparedSeriesOptions } from '../useSeries/types';
4
4
  type PreparePieSeriesArgs = {
5
5
  boundsWidth: number;
6
6
  boundsHeight: number;
7
+ dispatcher: Dispatch<object>;
8
+ top: number;
9
+ left: number;
7
10
  series: PreparedPieSeries[];
11
+ seriesOptions: PreparedSeriesOptions;
8
12
  svgContainer: SVGSVGElement | null;
9
- onSeriesMouseMove?: OnSeriesMouseMove;
10
- onSeriesMouseLeave?: OnSeriesMouseLeave;
11
13
  };
12
14
  export declare function PieSeriesComponent(args: PreparePieSeriesArgs): React.JSX.Element;
13
15
  export {};