@gravity-ui/chartkit 5.11.0 → 5.11.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -84,11 +84,14 @@ export const Chart = (props) => {
84
84
  const boundsOffsetTop = chart.margin.top;
85
85
  // We only need to consider the width of the first left axis
86
86
  const boundsOffsetLeft = chart.margin.left + getYAxisWidth(yAxis[0]);
87
+ const isOutsideBounds = React.useCallback((x, y) => {
88
+ return x < 0 || x > boundsWidth || y < 0 || y > boundsHeight;
89
+ }, [boundsHeight, boundsWidth]);
87
90
  const handleMouseMove = (event) => {
88
91
  const [pointerX, pointerY] = pointer(event, svgRef.current);
89
92
  const x = pointerX - boundsOffsetLeft;
90
93
  const y = pointerY - boundsOffsetTop;
91
- if (x < 0 || x > boundsWidth || y < 0 || y > boundsHeight) {
94
+ if (isOutsideBounds(x, y)) {
92
95
  dispatcher.call('hover-shape', {}, undefined);
93
96
  return;
94
97
  }
@@ -103,8 +106,25 @@ export const Chart = (props) => {
103
106
  throttledHandleMouseMove.cancel();
104
107
  dispatcher.call('hover-shape', {}, undefined);
105
108
  };
109
+ const handleChartClick = React.useCallback((event) => {
110
+ const [pointerX, pointerY] = pointer(event, svgRef.current);
111
+ const x = pointerX - boundsOffsetLeft;
112
+ const y = pointerY - boundsOffsetTop;
113
+ if (isOutsideBounds(x, y)) {
114
+ return;
115
+ }
116
+ const items = getClosestPoints({
117
+ position: [x, y],
118
+ shapesData,
119
+ });
120
+ const selected = items === null || items === void 0 ? void 0 : items.find((item) => item.closest);
121
+ if (!selected) {
122
+ return;
123
+ }
124
+ dispatcher.call('click-chart', undefined, { point: selected.data, series: selected.series }, event);
125
+ }, [boundsOffsetLeft, boundsOffsetTop, dispatcher, isOutsideBounds, shapesData]);
106
126
  return (React.createElement(React.Fragment, null,
107
- React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height, onMouseMove: throttledHandleMouseMove, onMouseLeave: handleMouseLeave },
127
+ React.createElement("svg", { ref: svgRef, className: b(), width: width, height: height, onMouseMove: throttledHandleMouseMove, onMouseLeave: handleMouseLeave, onClick: handleChartClick },
108
128
  title && React.createElement(Title, Object.assign({}, title, { chartWidth: width })),
109
129
  React.createElement("g", { transform: `translate(0, ${boundsOffsetTop})` }, preparedSplit.plots.map((plot, index) => {
110
130
  return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
@@ -116,23 +116,9 @@ export function PieSeriesShapes(args) {
116
116
  nodes[index].append(customShape);
117
117
  }
118
118
  });
119
- const getSelectedSegment = (element) => {
120
- const datum = select(element).datum();
121
- const seriesId = get(datum, 'data.series.id', get(datum, 'series.id'));
122
- return preparedData.reduce((result, pie) => {
123
- var _a;
124
- return result || ((_a = pie.segments.find((s) => s.data.series.id === seriesId)) === null || _a === void 0 ? void 0 : _a.data);
125
- }, undefined);
126
- };
127
119
  const eventName = `hover-shape.pie`;
128
120
  const hoverOptions = get(seriesOptions, 'pie.states.hover');
129
121
  const inactiveOptions = get(seriesOptions, 'pie.states.inactive');
130
- svgElement.on('click', (e) => {
131
- const selectedSegment = getSelectedSegment(e.target);
132
- if (selectedSegment) {
133
- dispatcher.call('click-chart', undefined, { point: selectedSegment.series.data, series: selectedSegment.series }, e);
134
- }
135
- });
136
122
  dispatcher.on(eventName, (data) => {
137
123
  var _a, _b;
138
124
  const selectedSeriesId = (_b = (_a = data === null || data === void 0 ? void 0 : data[0]) === null || _a === void 0 ? void 0 : _a.series) === null || _b === void 0 ? void 0 : _b.id;
@@ -25,15 +25,6 @@ export function ScatterSeriesShape(props) {
25
25
  .attr('fill', (d) => d.point.data.color || d.point.series.color || '')
26
26
  .attr('opacity', (d) => d.point.opacity)
27
27
  .attr('cursor', (d) => d.point.series.cursor);
28
- const getSelectedPoint = (element) => {
29
- return select(element).datum();
30
- };
31
- svgElement.on('click', (e) => {
32
- const datum = getSelectedPoint(e.target);
33
- if (datum) {
34
- dispatcher.call('click-chart', undefined, { point: datum.point.data, series: datum.point.series }, e);
35
- }
36
- });
37
28
  const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
38
29
  const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
39
30
  dispatcher.on('hover-shape.scatter', (data) => {
@@ -45,17 +45,9 @@ export const TreemapSeriesShape = (props) => {
45
45
  .style('font-weight', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontWeight) || null; })
46
46
  .style('fill', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontColor) || null; })
47
47
  .call(setEllipsisForOverflowTexts, (d) => d.width);
48
- const getSelectedPart = (node) => {
49
- const hoveredRect = select(node);
50
- return hoveredRect.datum();
51
- };
52
48
  const eventName = `hover-shape.treemap`;
53
49
  const hoverOptions = get(seriesOptions, 'treemap.states.hover');
54
50
  const inactiveOptions = get(seriesOptions, 'treemap.states.inactive');
55
- svgElement.on('click', (e) => {
56
- const datum = getSelectedPart(e.target);
57
- dispatcher.call('click-chart', undefined, { point: datum.data, series }, e);
58
- });
59
51
  dispatcher.on(eventName, (data) => {
60
52
  var _a;
61
53
  const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
@@ -2,7 +2,7 @@ import { Delaunay, bisector, sort } from 'd3';
2
2
  import get from 'lodash/get';
3
3
  import groupBy from 'lodash/groupBy';
4
4
  function getClosestPointsByXValue(x, y, points) {
5
- var _a, _b;
5
+ var _a, _b, _c, _d;
6
6
  const sorted = sort(points, (p) => p.x);
7
7
  const closestXIndex = bisector((p) => p.x).center(sorted, x);
8
8
  if (closestXIndex === -1) {
@@ -19,6 +19,11 @@ function getClosestPointsByXValue(x, y, points) {
19
19
  }
20
20
  else {
21
21
  closestYIndex = closestPoints.findIndex((p) => y > p.y0 && y < p.y1);
22
+ if (closestYIndex === -1) {
23
+ const sortedY = sort(closestPoints.map((p, index) => ({ index, y: p.y1 + (p.y0 - p.y1) / 2 })), (p) => p.y);
24
+ const sortedYIndex = bisector((p) => p.y).center(sortedY, y);
25
+ closestYIndex = (_d = (_c = sortedY[sortedYIndex]) === null || _c === void 0 ? void 0 : _c.index) !== null && _d !== void 0 ? _d : -1;
26
+ }
22
27
  }
23
28
  return closestPoints.map((p, i) => ({
24
29
  data: p.data,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/chartkit",
3
- "version": "5.11.0",
3
+ "version": "5.11.2",
4
4
  "description": "React component used to render charts based on any sources you need",
5
5
  "license": "MIT",
6
6
  "repository": "git@github.com:gravity-ui/ChartKit.git",