@gravity-ui/chartkit 4.8.0 → 4.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/build/components/ChartKit.d.ts +1 -1
  2. package/build/components/ChartKit.js +1 -1
  3. package/build/components/Loader/Loader.d.ts +5 -2
  4. package/build/components/Loader/Loader.js +8 -1
  5. package/build/plugins/d3/examples/bar-x/GroupedColumns.js +4 -2
  6. package/build/plugins/d3/examples/bar-y/Basic.d.ts +2 -0
  7. package/build/plugins/d3/examples/bar-y/Basic.js +43 -0
  8. package/build/plugins/d3/examples/bar-y/GroupedColumns.d.ts +2 -0
  9. package/build/plugins/d3/examples/bar-y/GroupedColumns.js +48 -0
  10. package/build/plugins/d3/examples/bar-y/StackedColumns.d.ts +2 -0
  11. package/build/plugins/d3/examples/bar-y/StackedColumns.js +47 -0
  12. package/build/plugins/d3/examples/combined/LineAndBarX.d.ts +2 -0
  13. package/build/plugins/d3/examples/combined/LineAndBarX.js +61 -0
  14. package/build/plugins/d3/examples/line/Basic.d.ts +2 -0
  15. package/build/plugins/d3/examples/line/Basic.js +66 -0
  16. package/build/plugins/d3/examples/nintendoGames.d.ts +40 -10
  17. package/build/plugins/d3/examples/nintendoGames.js +2416 -2189
  18. package/build/plugins/d3/renderer/D3Widget.d.ts +1 -1
  19. package/build/plugins/d3/renderer/D3Widget.js +27 -11
  20. package/build/plugins/d3/renderer/components/Chart.d.ts +0 -2
  21. package/build/plugins/d3/renderer/components/Chart.js +4 -6
  22. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.d.ts +2 -2
  23. package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +42 -35
  24. package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.d.ts +0 -2
  25. package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.js +118 -48
  26. package/build/plugins/d3/renderer/components/Tooltip/index.d.ts +1 -0
  27. package/build/plugins/d3/renderer/components/Tooltip/index.js +5 -4
  28. package/build/plugins/d3/renderer/components/styles.css +1 -0
  29. package/build/plugins/d3/renderer/constants/defaults/series-options.d.ts +9 -2
  30. package/build/plugins/d3/renderer/constants/defaults/series-options.js +27 -0
  31. package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +15 -1
  32. package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +3 -3
  33. package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +3 -3
  34. package/build/plugins/d3/renderer/hooks/useSeries/constants.d.ts +3 -0
  35. package/build/plugins/d3/renderer/hooks/useSeries/constants.js +5 -0
  36. package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +1 -1
  37. package/build/plugins/d3/renderer/hooks/useSeries/index.js +2 -1
  38. package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.d.ts +10 -0
  39. package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.js +38 -0
  40. package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.d.ts +10 -0
  41. package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.js +50 -0
  42. package/build/plugins/d3/renderer/hooks/useSeries/prepare-line-series.d.ts +11 -0
  43. package/build/plugins/d3/renderer/hooks/useSeries/prepare-line-series.js +32 -0
  44. package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +2 -1
  45. package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +21 -60
  46. package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +24 -2
  47. package/build/plugins/d3/renderer/hooks/useSeries/utils.d.ts +3 -1
  48. package/build/plugins/d3/renderer/hooks/useSeries/utils.js +13 -0
  49. package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +4 -6
  50. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.d.ts +11 -0
  51. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.js +87 -0
  52. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.d.ts +12 -0
  53. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +114 -0
  54. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.d.ts +10 -0
  55. package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.js +1 -0
  56. package/build/plugins/d3/renderer/hooks/useShapes/constants.d.ts +3 -0
  57. package/build/plugins/d3/renderer/hooks/useShapes/constants.js +3 -0
  58. package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +4 -4
  59. package/build/plugins/d3/renderer/hooks/useShapes/index.js +35 -5
  60. package/build/plugins/d3/renderer/hooks/useShapes/line/index.d.ts +11 -0
  61. package/build/plugins/d3/renderer/hooks/useShapes/line/index.js +98 -0
  62. package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.d.ts +11 -0
  63. package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +21 -0
  64. package/build/plugins/d3/renderer/hooks/useShapes/line/types.d.ts +16 -0
  65. package/build/plugins/d3/renderer/hooks/useShapes/line/types.js +1 -0
  66. package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +0 -2
  67. package/build/plugins/d3/renderer/hooks/useShapes/pie.js +3 -3
  68. package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.d.ts +0 -2
  69. package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +6 -6
  70. package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.d.ts +1 -1
  71. package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +3 -34
  72. package/build/plugins/d3/renderer/hooks/useShapes/styles.css +6 -0
  73. package/build/plugins/d3/renderer/hooks/useShapes/utils.d.ts +17 -0
  74. package/build/plugins/d3/renderer/hooks/useShapes/utils.js +25 -0
  75. package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +3 -3
  76. package/build/plugins/d3/renderer/utils/text.d.ts +5 -7
  77. package/build/plugins/d3/renderer/utils/text.js +4 -15
  78. package/build/plugins/highcharts/renderer/HighchartsWidget.d.ts +1 -1
  79. package/build/plugins/indicator/renderer/IndicatorWidget.d.ts +1 -1
  80. package/build/plugins/yagr/renderer/YagrWidget.d.ts +1 -1
  81. package/build/types/index.d.ts +2 -1
  82. package/build/types/widget-data/bar-y.d.ts +55 -0
  83. package/build/types/widget-data/bar-y.js +1 -0
  84. package/build/types/widget-data/base.d.ts +4 -0
  85. package/build/types/widget-data/index.d.ts +2 -0
  86. package/build/types/widget-data/index.js +2 -0
  87. package/build/types/widget-data/line.d.ts +37 -0
  88. package/build/types/widget-data/line.js +1 -0
  89. package/build/types/widget-data/series.d.ts +53 -3
  90. package/build/types/widget-data/tooltip.d.ts +15 -1
  91. package/build/utils/index.d.ts +1 -1
  92. package/build/utils/index.js +1 -1
  93. package/build/utils/performance.d.ts +3 -0
  94. package/build/utils/performance.js +8 -0
  95. package/package.json +3 -2
@@ -5,13 +5,13 @@ import type { ChartScale } from '../useAxisScales';
5
5
  import type { PreparedSeries, PreparedSeriesOptions } from '../';
6
6
  import type { PreparedBarXData } from './bar-x';
7
7
  import type { PreparedScatterData } from './scatter';
8
- import './styles.css';
8
+ import type { PreparedLineData } from './line/types';
9
+ import type { PreparedBarYData } from './bar-y/types';
9
10
  export type { PreparedBarXData } from './bar-x';
10
11
  export type { PreparedScatterData } from './scatter';
11
- export type ShapeData = PreparedBarXData | PreparedScatterData;
12
+ import './styles.css';
13
+ export type ShapeData = PreparedBarXData | PreparedBarYData | PreparedScatterData | PreparedLineData;
12
14
  type Args = {
13
- top: number;
14
- left: number;
15
15
  boundsWidth: number;
16
16
  boundsHeight: number;
17
17
  dispatcher: Dispatch<object>;
@@ -4,9 +4,12 @@ import { getOnlyVisibleSeries } from '../../utils';
4
4
  import { BarXSeriesShapes, prepareBarXData } from './bar-x';
5
5
  import { ScatterSeriesShape, prepareScatterData } from './scatter';
6
6
  import { PieSeriesComponent } from './pie';
7
+ import { prepareLineData } from './line/prepare-data';
8
+ import { LineSeriesShapes } from './line';
9
+ import { BarYSeriesShapes, prepareBarYData } from './bar-y';
7
10
  import './styles.css';
8
11
  export const useShapes = (args) => {
9
- const { top, left, boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, svgContainer, } = args;
12
+ const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, svgContainer, } = args;
10
13
  const shapesComponents = React.useMemo(() => {
11
14
  const visibleSeries = getOnlyVisibleSeries(series);
12
15
  const groupedSeries = group(visibleSeries, (item) => item.type);
@@ -29,6 +32,35 @@ export const useShapes = (args) => {
29
32
  }
30
33
  break;
31
34
  }
35
+ case 'bar-y': {
36
+ if (xScale && yScale) {
37
+ const preparedData = prepareBarYData({
38
+ series: chartSeries,
39
+ seriesOptions,
40
+ xAxis,
41
+ xScale,
42
+ yAxis,
43
+ yScale,
44
+ });
45
+ acc.push(React.createElement(BarYSeriesShapes, { key: "bar-y", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
46
+ shapesData.push(...preparedData);
47
+ }
48
+ break;
49
+ }
50
+ case 'line': {
51
+ if (xScale && yScale) {
52
+ const preparedData = prepareLineData({
53
+ series: chartSeries,
54
+ xAxis,
55
+ xScale,
56
+ yAxis,
57
+ yScale,
58
+ });
59
+ acc.push(React.createElement(LineSeriesShapes, { key: "line", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
60
+ shapesData.push(...preparedData);
61
+ }
62
+ break;
63
+ }
32
64
  case 'scatter': {
33
65
  if (xScale && yScale) {
34
66
  const preparedData = prepareScatterData({
@@ -38,14 +70,14 @@ export const useShapes = (args) => {
38
70
  yAxis: yAxis[0],
39
71
  yScale,
40
72
  });
41
- acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, top: top, left: left, preparedData: preparedData, seriesOptions: seriesOptions, svgContainer: svgContainer }));
73
+ acc.push(React.createElement(ScatterSeriesShape, { key: "scatter", dispatcher: dispatcher, preparedData: preparedData, seriesOptions: seriesOptions, svgContainer: svgContainer }));
42
74
  }
43
75
  break;
44
76
  }
45
77
  case 'pie': {
46
78
  const groupedPieSeries = group(chartSeries, (pieSeries) => pieSeries.stackId);
47
79
  acc.push(...Array.from(groupedPieSeries).map(([key, pieSeries]) => {
48
- return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, dispatcher: dispatcher, top: top, left: left, series: pieSeries, seriesOptions: seriesOptions, svgContainer: svgContainer }));
80
+ return (React.createElement(PieSeriesComponent, { key: `pie-${key}`, boundsWidth: boundsWidth, boundsHeight: boundsHeight, dispatcher: dispatcher, series: pieSeries, seriesOptions: seriesOptions, svgContainer: svgContainer }));
49
81
  }));
50
82
  }
51
83
  }
@@ -63,8 +95,6 @@ export const useShapes = (args) => {
63
95
  yAxis,
64
96
  yScale,
65
97
  svgContainer,
66
- left,
67
- top,
68
98
  ]);
69
99
  return { shapes: shapesComponents.shapes, shapesData: shapesComponents.shapesData };
70
100
  };
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import type { Dispatch } from 'd3';
3
+ import type { PreparedSeriesOptions } from '../../useSeries/types';
4
+ import { PreparedLineData } from './types';
5
+ type Args = {
6
+ dispatcher: Dispatch<object>;
7
+ preparedData: PreparedLineData[];
8
+ seriesOptions: PreparedSeriesOptions;
9
+ };
10
+ export declare const LineSeriesShapes: (args: Args) => React.JSX.Element;
11
+ export {};
@@ -0,0 +1,98 @@
1
+ import React from 'react';
2
+ import { select, line as lineGenerator, color } from 'd3';
3
+ import get from 'lodash/get';
4
+ import { block } from '../../../../../../utils/cn';
5
+ import { shapeKey } from '../utils';
6
+ const b = block('d3-line');
7
+ export const LineSeriesShapes = (args) => {
8
+ const { dispatcher, preparedData, seriesOptions } = args;
9
+ const ref = React.useRef(null);
10
+ React.useEffect(() => {
11
+ if (!ref.current) {
12
+ return () => { };
13
+ }
14
+ const svgElement = select(ref.current);
15
+ const hoverOptions = get(seriesOptions, 'line.states.hover');
16
+ const inactiveOptions = get(seriesOptions, 'line.states.inactive');
17
+ const line = lineGenerator()
18
+ .x((d) => d.x)
19
+ .y((d) => d.y);
20
+ svgElement.selectAll('*').remove();
21
+ const selection = svgElement
22
+ .selectAll('path')
23
+ .data(preparedData, shapeKey)
24
+ .join('path')
25
+ .attr('d', (d) => line(d.points))
26
+ .attr('fill', 'none')
27
+ .attr('stroke', (d) => d.color)
28
+ .attr('stroke-width', (d) => d.width)
29
+ .attr('stroke-linejoin', 'round')
30
+ .attr('stroke-linecap', 'round');
31
+ const dataLabels = preparedData.reduce((acc, d) => {
32
+ if (d.series.dataLabels.enabled) {
33
+ acc.push(...d.points.map((p) => ({
34
+ x: p.x,
35
+ y: p.y,
36
+ data: p.data,
37
+ series: d.series,
38
+ })));
39
+ }
40
+ return acc;
41
+ }, []);
42
+ svgElement
43
+ .selectAll('allLabels')
44
+ .data(dataLabels)
45
+ .join('text')
46
+ .text((d) => String(d.data.label || d.data.y))
47
+ .attr('class', b('label'))
48
+ .attr('x', (d) => d.x)
49
+ .attr('y', (d) => {
50
+ return d.y - d.series.dataLabels.padding;
51
+ })
52
+ .attr('text-anchor', 'middle')
53
+ .style('font-size', (d) => d.series.dataLabels.style.fontSize)
54
+ .style('font-weight', (d) => d.series.dataLabels.style.fontWeight || null)
55
+ .style('fill', (d) => d.series.dataLabels.style.fontColor || null);
56
+ const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
57
+ const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
58
+ dispatcher.on('hover-shape.line', (data) => {
59
+ var _a, _b;
60
+ const selectedSeriesId = (_b = (_a = data === null || data === void 0 ? void 0 : data.find((d) => d.series.type === 'line')) === null || _a === void 0 ? void 0 : _a.series) === null || _b === void 0 ? void 0 : _b.id;
61
+ const updates = [];
62
+ preparedData.forEach((p) => {
63
+ const hovered = Boolean(hoverEnabled && p.id === selectedSeriesId);
64
+ if (p.hovered !== hovered) {
65
+ p.hovered = hovered;
66
+ updates.push(p);
67
+ }
68
+ const active = Boolean(!inactiveEnabled || !selectedSeriesId || selectedSeriesId === p.id);
69
+ if (p.active !== active) {
70
+ p.active = active;
71
+ updates.push(p);
72
+ }
73
+ });
74
+ selection.data(updates, shapeKey).join('shape', (update) => {
75
+ update
76
+ .attr('stroke', (d) => {
77
+ var _a;
78
+ const initialColor = d.color || '';
79
+ if (d.hovered) {
80
+ return (((_a = color(initialColor)) === null || _a === void 0 ? void 0 : _a.brighter(hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.brightness).toString()) || initialColor);
81
+ }
82
+ return initialColor;
83
+ })
84
+ .attr('opacity', function (d) {
85
+ if (!d.active) {
86
+ return (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
87
+ }
88
+ return null;
89
+ });
90
+ return update;
91
+ }, (exit) => exit);
92
+ });
93
+ return () => {
94
+ dispatcher.on('hover-shape.line', null);
95
+ };
96
+ }, [dispatcher, preparedData, seriesOptions]);
97
+ return React.createElement("g", { ref: ref, className: b() });
98
+ };
@@ -0,0 +1,11 @@
1
+ import { PreparedLineSeries } from '../../useSeries/types';
2
+ import { PreparedAxis } from '../../useChartOptions/types';
3
+ import { ChartScale } from '../../useAxisScales';
4
+ import { PreparedLineData } from './types';
5
+ export declare const prepareLineData: (args: {
6
+ series: PreparedLineSeries[];
7
+ xAxis: PreparedAxis;
8
+ xScale: ChartScale;
9
+ yAxis: PreparedAxis[];
10
+ yScale: ChartScale;
11
+ }) => PreparedLineData[];
@@ -0,0 +1,21 @@
1
+ import { getXValue, getYValue } from '../utils';
2
+ export const prepareLineData = (args) => {
3
+ const { series, xAxis, xScale, yScale } = args;
4
+ const yAxis = args.yAxis[0];
5
+ return series.reduce((acc, s) => {
6
+ acc.push({
7
+ points: s.data.map((d) => ({
8
+ x: getXValue({ point: d, xAxis, xScale }),
9
+ y: getYValue({ point: d, yAxis, yScale }),
10
+ data: d,
11
+ })),
12
+ color: s.color,
13
+ width: s.lineWidth,
14
+ series: s,
15
+ hovered: false,
16
+ active: true,
17
+ id: s.id,
18
+ });
19
+ return acc;
20
+ }, []);
21
+ };
@@ -0,0 +1,16 @@
1
+ import { PreparedLineSeries } from '../../useSeries/types';
2
+ import { LineSeriesData } from '../../../../../../types';
3
+ export type PointData = {
4
+ x: number;
5
+ y: number;
6
+ data: LineSeriesData;
7
+ };
8
+ export type PreparedLineData = {
9
+ id: string;
10
+ points: PointData[];
11
+ color: string;
12
+ width: number;
13
+ series: PreparedLineSeries;
14
+ hovered: boolean;
15
+ active: boolean;
16
+ };
@@ -5,8 +5,6 @@ type PreparePieSeriesArgs = {
5
5
  boundsWidth: number;
6
6
  boundsHeight: number;
7
7
  dispatcher: Dispatch<object>;
8
- top: number;
9
- left: number;
10
8
  series: PreparedPieSeries[];
11
9
  seriesOptions: PreparedSeriesOptions;
12
10
  svgContainer: SVGSVGElement | null;
@@ -32,7 +32,7 @@ const isNodeContainsPieData = (node) => {
32
32
  };
33
33
  export function PieSeriesComponent(args) {
34
34
  var _a;
35
- const { boundsWidth, boundsHeight, dispatcher, top, left, series, seriesOptions, svgContainer } = args;
35
+ const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, svgContainer } = args;
36
36
  const ref = React.useRef(null);
37
37
  const [x, y] = getCenter(boundsWidth, boundsHeight, (_a = series[0]) === null || _a === void 0 ? void 0 : _a.center);
38
38
  React.useEffect(() => {
@@ -154,7 +154,7 @@ export function PieSeriesComponent(args) {
154
154
  }
155
155
  const [pointerX, pointerY] = pointer(e, svgContainer);
156
156
  const segmentData = extractD3DataFromNode(segment).data;
157
- dispatcher.call('hover-shape', {}, [segmentData], [pointerX - left, pointerY - top]);
157
+ dispatcher.call('hover-shape', {}, [segmentData], [pointerX, pointerY]);
158
158
  })
159
159
  .on('mouseleave', () => {
160
160
  dispatcher.call('hover-shape', {}, undefined);
@@ -199,6 +199,6 @@ export function PieSeriesComponent(args) {
199
199
  return () => {
200
200
  dispatcher.on(eventName, null);
201
201
  };
202
- }, [boundsWidth, boundsHeight, dispatcher, top, left, series, seriesOptions, svgContainer]);
202
+ }, [boundsWidth, boundsHeight, dispatcher, series, seriesOptions, svgContainer]);
203
203
  return React.createElement("g", { ref: ref, className: b(), transform: `translate(${x}, ${y})` });
204
204
  }
@@ -6,8 +6,6 @@ export { prepareScatterData } from './prepare-data';
6
6
  export type { PreparedScatterData } from './prepare-data';
7
7
  type ScatterSeriesShapeProps = {
8
8
  dispatcher: Dispatch<object>;
9
- top: number;
10
- left: number;
11
9
  preparedData: PreparedScatterData[];
12
10
  seriesOptions: PreparedSeriesOptions;
13
11
  svgContainer: SVGSVGElement | null;
@@ -3,16 +3,16 @@ import get from 'lodash/get';
3
3
  import { color, pointer, select } from 'd3';
4
4
  import { block } from '../../../../../../utils/cn';
5
5
  import { extractD3DataFromNode, isNodeContainsD3Data } from '../../../utils';
6
+ import { shapeKey } from '../utils';
6
7
  export { prepareScatterData } from './prepare-data';
7
8
  const b = block('d3-scatter');
8
9
  const DEFAULT_SCATTER_POINT_RADIUS = 4;
9
10
  const EMPTY_SELECTION = null;
10
- const key = (d) => d.id || -1;
11
11
  const isNodeContainsScatterData = (node) => {
12
12
  return isNodeContainsD3Data(node);
13
13
  };
14
14
  export function ScatterSeriesShape(props) {
15
- const { dispatcher, top, left, preparedData, seriesOptions, svgContainer } = props;
15
+ const { dispatcher, preparedData, seriesOptions, svgContainer } = props;
16
16
  const ref = React.useRef(null);
17
17
  React.useEffect(() => {
18
18
  if (!ref.current) {
@@ -23,7 +23,7 @@ export function ScatterSeriesShape(props) {
23
23
  const inactiveOptions = get(seriesOptions, 'scatter.states.inactive');
24
24
  const selection = svgElement
25
25
  .selectAll(`circle`)
26
- .data(preparedData, key)
26
+ .data(preparedData, shapeKey)
27
27
  .join((enter) => enter.append('circle').attr('class', b('point')), (update) => update, (exit) => exit.remove())
28
28
  .attr('fill', (d) => d.data.color || d.series.color || '')
29
29
  .attr('r', (d) => d.data.radius || DEFAULT_SCATTER_POINT_RADIUS)
@@ -37,7 +37,7 @@ export function ScatterSeriesShape(props) {
37
37
  }
38
38
  const [pointerX, pointerY] = pointer(e, svgContainer);
39
39
  const segmentData = extractD3DataFromNode(point);
40
- dispatcher.call('hover-shape', {}, [segmentData], [pointerX - left, pointerY - top]);
40
+ dispatcher.call('hover-shape', {}, [segmentData], [pointerX, pointerY]);
41
41
  })
42
42
  .on('mouseleave', () => {
43
43
  dispatcher.call('hover-shape', {}, undefined);
@@ -62,7 +62,7 @@ export function ScatterSeriesShape(props) {
62
62
  updates.push(p);
63
63
  }
64
64
  });
65
- selection.data(updates, key).join(() => EMPTY_SELECTION, (update) => {
65
+ selection.data(updates, shapeKey).join(() => EMPTY_SELECTION, (update) => {
66
66
  update
67
67
  .attr('fill', (d) => {
68
68
  var _a;
@@ -84,6 +84,6 @@ export function ScatterSeriesShape(props) {
84
84
  return () => {
85
85
  dispatcher.on('hover-shape.scatter', null);
86
86
  };
87
- }, [dispatcher, top, left, preparedData, seriesOptions, svgContainer]);
87
+ }, [dispatcher, preparedData, seriesOptions, svgContainer]);
88
88
  return React.createElement("g", { ref: ref, className: b() });
89
89
  }
@@ -1,4 +1,4 @@
1
- import type { TooltipDataChunkScatter } from '../../../../../../types/widget-data';
1
+ import type { TooltipDataChunkScatter } from '../../../../../../types';
2
2
  import type { ChartScale } from '../../useAxisScales';
3
3
  import type { PreparedAxis } from '../../useChartOptions/types';
4
4
  import { PreparedScatterSeries } from '../../useSeries/types';
@@ -1,35 +1,4 @@
1
- import get from 'lodash/get';
2
- import { getDataCategoryValue } from '../../../utils';
3
- const getCxAttr = (args) => {
4
- const { point, xAxis, xScale } = args;
5
- let cx;
6
- if (xAxis.type === 'category') {
7
- const xBandScale = xScale;
8
- const categories = get(xAxis, 'categories', []);
9
- const dataCategory = getDataCategoryValue({ axisDirection: 'x', categories, data: point });
10
- cx = (xBandScale(dataCategory) || 0) + xBandScale.step() / 2;
11
- }
12
- else {
13
- const xLinearScale = xScale;
14
- cx = xLinearScale(point.x);
15
- }
16
- return cx;
17
- };
18
- const getCyAttr = (args) => {
19
- const { point, yAxis, yScale } = args;
20
- let cy;
21
- if (yAxis.type === 'category') {
22
- const yBandScale = yScale;
23
- const categories = get(yAxis, 'categories', []);
24
- const dataCategory = getDataCategoryValue({ axisDirection: 'y', categories, data: point });
25
- cy = (yBandScale(dataCategory) || 0) + yBandScale.step() / 2;
26
- }
27
- else {
28
- const yLinearScale = yScale;
29
- cy = yLinearScale(point.y);
30
- }
31
- return cy;
32
- };
1
+ import { getXValue, getYValue } from '../utils';
33
2
  const getFilteredLinearScatterData = (data) => {
34
3
  return data.filter((d) => typeof d.x === 'number' && typeof d.y === 'number');
35
4
  };
@@ -43,8 +12,8 @@ export const prepareScatterData = (args) => {
43
12
  acc.push({
44
13
  data: d,
45
14
  series: s,
46
- cx: getCxAttr({ point: d, xAxis, xScale }),
47
- cy: getCyAttr({ point: d, yAxis, yScale }),
15
+ cx: getXValue({ point: d, xAxis, xScale }),
16
+ cy: getYValue({ point: d, yAxis, yScale }),
48
17
  hovered: false,
49
18
  active: true,
50
19
  id: acc.length - 1,
@@ -15,4 +15,10 @@
15
15
  .chartkit-d3-bar-x__label {
16
16
  fill: var(--g-color-text-complementary);
17
17
  user-select: none;
18
+ }
19
+
20
+ .chartkit-d3-bar-y__label {
21
+ fill: var(--g-color-text-complementary);
22
+ user-select: none;
23
+ alignment-baseline: after-edge;
18
24
  }
@@ -0,0 +1,17 @@
1
+ import { PreparedAxis } from '../useChartOptions/types';
2
+ import { ChartScale } from '../useAxisScales';
3
+ export declare function getXValue(args: {
4
+ point: {
5
+ x?: number | string;
6
+ };
7
+ xAxis: PreparedAxis;
8
+ xScale: ChartScale;
9
+ }): number;
10
+ export declare function getYValue(args: {
11
+ point: {
12
+ y?: number | string;
13
+ };
14
+ yAxis: PreparedAxis;
15
+ yScale: ChartScale;
16
+ }): number;
17
+ export declare const shapeKey: (d: unknown) => string | number;
@@ -0,0 +1,25 @@
1
+ import get from 'lodash/get';
2
+ import { getDataCategoryValue } from '../../utils';
3
+ export function getXValue(args) {
4
+ const { point, xAxis, xScale } = args;
5
+ if (xAxis.type === 'category') {
6
+ const xBandScale = xScale;
7
+ const categories = get(xAxis, 'categories', []);
8
+ const dataCategory = getDataCategoryValue({ axisDirection: 'x', categories, data: point });
9
+ return (xBandScale(dataCategory) || 0) + xBandScale.step() / 2;
10
+ }
11
+ const xLinearScale = xScale;
12
+ return xLinearScale(point.x);
13
+ }
14
+ export function getYValue(args) {
15
+ const { point, yAxis, yScale } = args;
16
+ if (yAxis.type === 'category') {
17
+ const yBandScale = yScale;
18
+ const categories = get(yAxis, 'categories', []);
19
+ const dataCategory = getDataCategoryValue({ axisDirection: 'y', categories, data: point });
20
+ return (yBandScale(dataCategory) || 0) + yBandScale.step() / 2;
21
+ }
22
+ const yLinearScale = yScale;
23
+ return yLinearScale(point.y);
24
+ }
25
+ export const shapeKey = (d) => d.id || -1;
@@ -1,6 +1,6 @@
1
1
  import { select } from 'd3';
2
2
  import { getXAxisItems, getXAxisOffset, getXTickPosition } from '../axis';
3
- import { getLabelsMaxHeight, setEllipsisForOverflowText } from '../text';
3
+ import { getLabelsSize, setEllipsisForOverflowText } from '../text';
4
4
  import { calculateCos, calculateSin } from '../math';
5
5
  function addDomain(selection, options) {
6
6
  const { size, color } = options;
@@ -18,10 +18,10 @@ export function axisBottom(args) {
18
18
  const offset = getXAxisOffset();
19
19
  const position = getXTickPosition({ scale, offset });
20
20
  const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
21
- const labelHeight = getLabelsMaxHeight({
21
+ const labelHeight = getLabelsSize({
22
22
  labels: values,
23
23
  style: { 'font-size': (labelsStyle === null || labelsStyle === void 0 ? void 0 : labelsStyle.fontSize) || '' },
24
- });
24
+ }).maxHeight;
25
25
  return function (selection) {
26
26
  var _a, _b;
27
27
  const x = ((_b = (_a = selection.node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.x) || 0;
@@ -8,13 +8,11 @@ export declare function hasOverlappingLabels({ width, labels, padding, style, }:
8
8
  style?: BaseTextStyle;
9
9
  padding?: number;
10
10
  }): boolean;
11
- export declare function getLabelsMaxWidth({ labels, style, rotation, }: {
11
+ export declare function getLabelsSize({ labels, style, rotation, }: {
12
12
  labels: string[];
13
13
  style?: Record<string, string>;
14
14
  rotation?: number;
15
- }): number;
16
- export declare function getLabelsMaxHeight({ labels, style, rotation, }: {
17
- labels: string[];
18
- style?: Record<string, string>;
19
- rotation?: number;
20
- }): number;
15
+ }): {
16
+ maxHeight: number;
17
+ maxWidth: number;
18
+ };
@@ -46,19 +46,8 @@ function renderLabels(selection, { labels, style = {}, attrs = {}, }) {
46
46
  .text((d) => d);
47
47
  return text;
48
48
  }
49
- export function getLabelsMaxWidth({ labels, style, rotation, }) {
50
- var _a, _b;
51
- const svg = select(document.body).append('svg');
52
- const textSelection = renderLabels(svg, { labels, style });
53
- if (rotation) {
54
- textSelection.attr('text-anchor', 'end').style('transform', `rotate(${rotation}deg)`);
55
- }
56
- const maxWidth = ((_b = (_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.width) || 0;
57
- svg.remove();
58
- return maxWidth;
59
- }
60
- export function getLabelsMaxHeight({ labels, style, rotation, }) {
61
- var _a, _b;
49
+ export function getLabelsSize({ labels, style, rotation, }) {
50
+ var _a;
62
51
  const svg = select(document.body).append('svg');
63
52
  const textSelection = renderLabels(svg, { labels, style });
64
53
  if (rotation) {
@@ -66,7 +55,7 @@ export function getLabelsMaxHeight({ labels, style, rotation, }) {
66
55
  .attr('text-anchor', rotation > 0 ? 'start' : 'end')
67
56
  .style('transform', `rotate(${rotation}deg)`);
68
57
  }
69
- const maxHeight = ((_b = (_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) === null || _b === void 0 ? void 0 : _b.height) || 0;
58
+ const { height = 0, width = 0 } = ((_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {};
70
59
  svg.remove();
71
- return maxHeight;
60
+ return { maxHeight: height, maxWidth: width };
72
61
  }
@@ -10,7 +10,7 @@ declare const HighchartsWidget: React.ForwardRefExoticComponent<{
10
10
  onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"highcharts">) => void) | undefined;
11
11
  onError?: import("../../../types").ChartKitOnError | undefined;
12
12
  renderError?: import("../../../types").RenderError | undefined;
13
- renderPluginLoader?: (() => React.ReactNode) | undefined;
13
+ renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
14
14
  } & {
15
15
  hoistConfigError?: boolean | undefined;
16
16
  nonBodyScroll?: boolean | undefined;
@@ -11,7 +11,7 @@ declare const IndicatorWidget: React.ForwardRefExoticComponent<{
11
11
  onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"indicator">) => void) | undefined;
12
12
  onError?: import("../../../types").ChartKitOnError | undefined;
13
13
  renderError?: import("../../../types").RenderError | undefined;
14
- renderPluginLoader?: (() => React.ReactNode) | undefined;
14
+ renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
15
15
  } & {
16
16
  formatNumber?: (<T = any>(value: number, options?: T | undefined) => string) | undefined;
17
17
  } & React.RefAttributes<ChartKitWidgetRef | undefined>>;
@@ -13,7 +13,7 @@ declare const YagrWidget: React.ForwardRefExoticComponent<{
13
13
  onChartLoad?: ((data: import("../../../types").ChartKitOnChartLoad<"yagr">) => void) | undefined;
14
14
  onError?: import("../../../types").ChartKitOnError | undefined;
15
15
  renderError?: import("../../../types").RenderError | undefined;
16
- renderPluginLoader?: (() => React.ReactNode) | undefined;
16
+ renderPluginLoader?: import("../../../types").ChartKitRenderPluginLoader | undefined;
17
17
  } & {
18
18
  tooltip?: (<T extends import("../types").CustomTooltipProps = import("../types").CustomTooltipProps>(props: T) => React.ReactNode) | undefined;
19
19
  } & {
@@ -24,6 +24,7 @@ export type ChartKitOnChartLoad<T extends ChartKitType> = {
24
24
  export type ChartKitOnError = (data: {
25
25
  error: any;
26
26
  }) => void;
27
+ export type ChartKitRenderPluginLoader = () => React.ReactNode;
27
28
  export type ChartKitProps<T extends ChartKitType> = {
28
29
  type: T;
29
30
  data: ChartKitWidget[T]['data'];
@@ -39,7 +40,7 @@ export type ChartKitProps<T extends ChartKitType> = {
39
40
  /** Used to render user's error component */
40
41
  renderError?: RenderError;
41
42
  /** Used to render user's plugin loader component */
42
- renderPluginLoader?: () => React.ReactNode;
43
+ renderPluginLoader?: ChartKitRenderPluginLoader;
43
44
  } & {
44
45
  [key in keyof Omit<ChartKitWidget[T], 'data' | 'widget'>]: ChartKitWidget[T][key];
45
46
  };
@@ -0,0 +1,55 @@
1
+ import type { BaseSeries, BaseSeriesData } from './base';
2
+ import type { ChartKitWidgetSeriesOptions } from './series';
3
+ import { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
4
+ export type BarYSeriesData<T = any> = BaseSeriesData<T> & {
5
+ /**
6
+ * The `x` value of the bar. Depending on the context , it may represents:
7
+ * - numeric value (for `linear` x axis)
8
+ * - timestamp value (for `datetime` x axis)
9
+ * - x axis category value (for `category` x axis). If the type is a string, then it is a category value itself. If the type is a number, then it is the index of an element in the array of categories described in `xAxis.categories`
10
+ */
11
+ x?: string | number;
12
+ /**
13
+ * The `y` value of the bar. Depending on the context , it may represents:
14
+ * - numeric value (for `linear` y axis)
15
+ * - timestamp value (for `datetime` y axis)
16
+ * - y axis category value (for `category` y axis). If the type is a string, then it is a category value itself. If the type is a number, then it is the index of an element in the array of categories described in `yAxis[0].categories`
17
+ */
18
+ y?: string | number;
19
+ /** Data label value of the bar. If not specified, the x value is used. */
20
+ label?: string | number;
21
+ };
22
+ export type BarYSeries<T = any> = BaseSeries & {
23
+ type: 'bar-y';
24
+ data: BarYSeriesData<T>[];
25
+ /** The name of the series (used in legend, tooltip etc) */
26
+ name: string;
27
+ /** The main color of the series (hex, rgba) */
28
+ color?: string;
29
+ /** Whether to stack the values of each series on top of each other.
30
+ * Possible values are undefined to disable, "normal" to stack by value or "percent"
31
+ *
32
+ * @default undefined
33
+ * */
34
+ stacking?: 'normal' | 'percent';
35
+ /** This option allows grouping series in a stacked chart */
36
+ stackId?: string;
37
+ /** Whether to group non-stacked columns or to let them render independent of each other.
38
+ * When false columns will be laid out individually and overlap each other.
39
+ *
40
+ * @default true
41
+ * */
42
+ grouping?: boolean;
43
+ dataLabels?: ChartKitWidgetSeriesOptions['dataLabels'] & {
44
+ /**
45
+ * Whether to align the data label inside or outside the box
46
+ *
47
+ * @default false
48
+ * */
49
+ inside?: boolean;
50
+ };
51
+ /** Individual series legend options. Has higher priority than legend options in widget data */
52
+ legend?: ChartKitWidgetLegend & {
53
+ symbol?: RectLegendSymbolOptions;
54
+ };
55
+ };