@gravity-ui/charts 1.51.7 → 1.52.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 (199) hide show
  1. package/dist/cjs/components/ChartInner/useChartInnerHandlers.d.ts +3 -2
  2. package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +1 -3
  3. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -2
  4. package/dist/cjs/components/ChartInner/useDefaultState.d.ts +3 -2
  5. package/dist/cjs/components/index.d.ts +1 -0
  6. package/dist/cjs/components/index.js +1 -0
  7. package/dist/cjs/core/series/plugin.d.ts +47 -2
  8. package/dist/cjs/core/series/types.d.ts +4 -0
  9. package/dist/cjs/core/shapes/area/prepare-data.js +29 -19
  10. package/dist/cjs/core/shapes/area/renderer.d.ts +0 -5
  11. package/dist/cjs/core/shapes/area/renderer.js +0 -75
  12. package/dist/cjs/core/shapes/area/types.d.ts +2 -8
  13. package/dist/cjs/core/shapes/bar-x/prepare-data.js +18 -7
  14. package/dist/cjs/core/shapes/bar-x/renderer.d.ts +0 -1
  15. package/dist/cjs/core/shapes/bar-x/renderer.js +0 -18
  16. package/dist/cjs/core/shapes/bar-x/types.d.ts +2 -1
  17. package/dist/cjs/core/shapes/bar-y/get-tooltip-data.js +4 -2
  18. package/dist/cjs/core/shapes/bar-y/prepare-data.js +8 -2
  19. package/dist/cjs/core/shapes/funnel/prepare-data.js +121 -68
  20. package/dist/cjs/core/shapes/heatmap/prepare-data.js +11 -2
  21. package/dist/cjs/core/shapes/line/prepare-data.js +27 -17
  22. package/dist/cjs/core/shapes/line/renderer.d.ts +0 -5
  23. package/dist/cjs/core/shapes/line/renderer.js +0 -75
  24. package/dist/cjs/core/shapes/line/types.d.ts +2 -8
  25. package/dist/cjs/core/shapes/marker.d.ts +30 -0
  26. package/dist/cjs/core/shapes/marker.js +68 -0
  27. package/dist/cjs/core/shapes/pie/prepare-data.js +24 -9
  28. package/dist/cjs/core/shapes/radar/prepare-data.js +3 -0
  29. package/dist/cjs/core/shapes/sankey/prepare-data.js +10 -1
  30. package/dist/cjs/core/shapes/scatter/prepare-data.js +8 -1
  31. package/dist/cjs/core/shapes/scatter/renderer.js +3 -2
  32. package/dist/cjs/core/shapes/scatter/types.d.ts +1 -1
  33. package/dist/cjs/core/shapes/treemap/prepare-data.js +9 -1
  34. package/dist/cjs/core/shapes/types.d.ts +35 -0
  35. package/dist/cjs/core/shapes/waterfall/prepare-data.js +5 -2
  36. package/dist/cjs/core/shapes/x-range/prepare-data.js +7 -2
  37. package/dist/cjs/core/types/chart/base.d.ts +22 -2
  38. package/dist/cjs/core/types/chart/funnel.d.ts +25 -1
  39. package/dist/cjs/core/types/chart/tooltip.d.ts +6 -1
  40. package/dist/cjs/core/utils/data-labels.d.ts +34 -0
  41. package/dist/cjs/core/utils/data-labels.js +26 -0
  42. package/dist/cjs/core/utils/get-closest-data.d.ts +2 -2
  43. package/dist/cjs/core/utils/get-closest-data.js +14 -34
  44. package/dist/cjs/core/utils/tooltip-helpers.d.ts +16 -0
  45. package/dist/cjs/core/utils/tooltip-helpers.js +12 -0
  46. package/dist/cjs/hooks/useShapes/AnnotationLayer.d.ts +9 -0
  47. package/dist/cjs/hooks/useShapes/AnnotationLayer.js +17 -0
  48. package/dist/cjs/hooks/useShapes/HoverMarkerLayer.d.ts +10 -0
  49. package/dist/cjs/hooks/useShapes/HoverMarkerLayer.js +22 -0
  50. package/dist/cjs/hooks/useShapes/MarkerLayer.d.ts +7 -0
  51. package/dist/cjs/hooks/useShapes/MarkerLayer.js +12 -0
  52. package/dist/cjs/hooks/useShapes/SeriesShapes.d.ts +18 -0
  53. package/dist/cjs/hooks/useShapes/SeriesShapes.js +32 -0
  54. package/dist/cjs/hooks/useShapes/index.d.ts +5 -18
  55. package/dist/cjs/hooks/useShapes/index.js +39 -229
  56. package/dist/cjs/index.d.ts +0 -1
  57. package/dist/cjs/index.js +0 -1
  58. package/dist/cjs/plugins/area/index.js +42 -0
  59. package/dist/cjs/plugins/bar-x/index.js +42 -0
  60. package/dist/cjs/plugins/bar-y/index.js +26 -0
  61. package/dist/cjs/plugins/funnel/index.js +18 -0
  62. package/dist/cjs/plugins/funnel/prepare.js +17 -12
  63. package/dist/cjs/plugins/heatmap/index.js +23 -0
  64. package/dist/cjs/plugins/line/index.js +28 -0
  65. package/dist/cjs/plugins/pie/index.js +18 -0
  66. package/dist/cjs/plugins/radar/index.js +18 -0
  67. package/dist/cjs/plugins/sankey/index.js +18 -0
  68. package/dist/cjs/plugins/scatter/index.js +26 -0
  69. package/dist/cjs/plugins/treemap/index.js +18 -0
  70. package/dist/cjs/plugins/waterfall/index.js +39 -0
  71. package/dist/cjs/plugins/x-range/index.js +25 -0
  72. package/dist/cjs/setup-jsdom.d.ts +0 -1
  73. package/dist/cjs/setup-jsdom.js +1 -1
  74. package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +3 -2
  75. package/dist/esm/components/ChartInner/useChartInnerHandlers.js +1 -3
  76. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -2
  77. package/dist/esm/components/ChartInner/useDefaultState.d.ts +3 -2
  78. package/dist/esm/components/index.d.ts +1 -0
  79. package/dist/esm/components/index.js +1 -0
  80. package/dist/esm/core/series/plugin.d.ts +47 -2
  81. package/dist/esm/core/series/types.d.ts +4 -0
  82. package/dist/esm/core/shapes/area/prepare-data.js +29 -19
  83. package/dist/esm/core/shapes/area/renderer.d.ts +0 -5
  84. package/dist/esm/core/shapes/area/renderer.js +0 -75
  85. package/dist/esm/core/shapes/area/types.d.ts +2 -8
  86. package/dist/esm/core/shapes/bar-x/prepare-data.js +18 -7
  87. package/dist/esm/core/shapes/bar-x/renderer.d.ts +0 -1
  88. package/dist/esm/core/shapes/bar-x/renderer.js +0 -18
  89. package/dist/esm/core/shapes/bar-x/types.d.ts +2 -1
  90. package/dist/esm/core/shapes/bar-y/get-tooltip-data.js +4 -2
  91. package/dist/esm/core/shapes/bar-y/prepare-data.js +8 -2
  92. package/dist/esm/core/shapes/funnel/prepare-data.js +121 -68
  93. package/dist/esm/core/shapes/heatmap/prepare-data.js +11 -2
  94. package/dist/esm/core/shapes/line/prepare-data.js +27 -17
  95. package/dist/esm/core/shapes/line/renderer.d.ts +0 -5
  96. package/dist/esm/core/shapes/line/renderer.js +0 -75
  97. package/dist/esm/core/shapes/line/types.d.ts +2 -8
  98. package/dist/esm/core/shapes/marker.d.ts +30 -0
  99. package/dist/esm/core/shapes/marker.js +68 -0
  100. package/dist/esm/core/shapes/pie/prepare-data.js +24 -9
  101. package/dist/esm/core/shapes/radar/prepare-data.js +3 -0
  102. package/dist/esm/core/shapes/sankey/prepare-data.js +10 -1
  103. package/dist/esm/core/shapes/scatter/prepare-data.js +8 -1
  104. package/dist/esm/core/shapes/scatter/renderer.js +3 -2
  105. package/dist/esm/core/shapes/scatter/types.d.ts +1 -1
  106. package/dist/esm/core/shapes/treemap/prepare-data.js +9 -1
  107. package/dist/esm/core/shapes/types.d.ts +35 -0
  108. package/dist/esm/core/shapes/waterfall/prepare-data.js +5 -2
  109. package/dist/esm/core/shapes/x-range/prepare-data.js +7 -2
  110. package/dist/esm/core/types/chart/base.d.ts +22 -2
  111. package/dist/esm/core/types/chart/funnel.d.ts +25 -1
  112. package/dist/esm/core/types/chart/tooltip.d.ts +6 -1
  113. package/dist/esm/core/utils/data-labels.d.ts +34 -0
  114. package/dist/esm/core/utils/data-labels.js +26 -0
  115. package/dist/esm/core/utils/get-closest-data.d.ts +2 -2
  116. package/dist/esm/core/utils/get-closest-data.js +14 -34
  117. package/dist/esm/core/utils/tooltip-helpers.d.ts +16 -0
  118. package/dist/esm/core/utils/tooltip-helpers.js +12 -0
  119. package/dist/esm/hooks/useShapes/AnnotationLayer.d.ts +9 -0
  120. package/dist/esm/hooks/useShapes/AnnotationLayer.js +17 -0
  121. package/dist/esm/hooks/useShapes/HoverMarkerLayer.d.ts +10 -0
  122. package/dist/esm/hooks/useShapes/HoverMarkerLayer.js +22 -0
  123. package/dist/esm/hooks/useShapes/MarkerLayer.d.ts +7 -0
  124. package/dist/esm/hooks/useShapes/MarkerLayer.js +12 -0
  125. package/dist/esm/hooks/useShapes/SeriesShapes.d.ts +18 -0
  126. package/dist/esm/hooks/useShapes/SeriesShapes.js +32 -0
  127. package/dist/esm/hooks/useShapes/index.d.ts +5 -18
  128. package/dist/esm/hooks/useShapes/index.js +39 -229
  129. package/dist/esm/index.d.ts +0 -1
  130. package/dist/esm/index.js +0 -1
  131. package/dist/esm/plugins/area/index.js +42 -0
  132. package/dist/esm/plugins/bar-x/index.js +42 -0
  133. package/dist/esm/plugins/bar-y/index.js +26 -0
  134. package/dist/esm/plugins/funnel/index.js +18 -0
  135. package/dist/esm/plugins/funnel/prepare.js +17 -12
  136. package/dist/esm/plugins/heatmap/index.js +23 -0
  137. package/dist/esm/plugins/line/index.js +28 -0
  138. package/dist/esm/plugins/pie/index.js +18 -0
  139. package/dist/esm/plugins/radar/index.js +18 -0
  140. package/dist/esm/plugins/sankey/index.js +18 -0
  141. package/dist/esm/plugins/scatter/index.js +26 -0
  142. package/dist/esm/plugins/treemap/index.js +18 -0
  143. package/dist/esm/plugins/waterfall/index.js +39 -0
  144. package/dist/esm/plugins/x-range/index.js +25 -0
  145. package/dist/esm/setup-jsdom.d.ts +0 -1
  146. package/dist/esm/setup-jsdom.js +1 -1
  147. package/package.json +2 -3
  148. package/dist/cjs/hooks/useShapes/area/index.d.ts +0 -15
  149. package/dist/cjs/hooks/useShapes/area/index.js +0 -52
  150. package/dist/cjs/hooks/useShapes/bar-x/index.d.ts +0 -16
  151. package/dist/cjs/hooks/useShapes/bar-x/index.js +0 -45
  152. package/dist/cjs/hooks/useShapes/bar-y/index.d.ts +0 -13
  153. package/dist/cjs/hooks/useShapes/bar-y/index.js +0 -19
  154. package/dist/cjs/hooks/useShapes/funnel/index.d.ts +0 -13
  155. package/dist/cjs/hooks/useShapes/funnel/index.js +0 -21
  156. package/dist/cjs/hooks/useShapes/heatmap/index.d.ts +0 -13
  157. package/dist/cjs/hooks/useShapes/heatmap/index.js +0 -20
  158. package/dist/cjs/hooks/useShapes/line/index.d.ts +0 -15
  159. package/dist/cjs/hooks/useShapes/line/index.js +0 -38
  160. package/dist/cjs/hooks/useShapes/pie/index.d.ts +0 -12
  161. package/dist/cjs/hooks/useShapes/pie/index.js +0 -20
  162. package/dist/cjs/hooks/useShapes/radar/index.d.ts +0 -12
  163. package/dist/cjs/hooks/useShapes/radar/index.js +0 -19
  164. package/dist/cjs/hooks/useShapes/sankey/index.d.ts +0 -12
  165. package/dist/cjs/hooks/useShapes/sankey/index.js +0 -18
  166. package/dist/cjs/hooks/useShapes/scatter/index.d.ts +0 -13
  167. package/dist/cjs/hooks/useShapes/scatter/index.js +0 -22
  168. package/dist/cjs/hooks/useShapes/treemap/index.d.ts +0 -12
  169. package/dist/cjs/hooks/useShapes/treemap/index.js +0 -18
  170. package/dist/cjs/hooks/useShapes/waterfall/index.d.ts +0 -14
  171. package/dist/cjs/hooks/useShapes/waterfall/index.js +0 -31
  172. package/dist/cjs/hooks/useShapes/x-range/index.d.ts +0 -14
  173. package/dist/cjs/hooks/useShapes/x-range/index.js +0 -20
  174. package/dist/esm/hooks/useShapes/area/index.d.ts +0 -15
  175. package/dist/esm/hooks/useShapes/area/index.js +0 -52
  176. package/dist/esm/hooks/useShapes/bar-x/index.d.ts +0 -16
  177. package/dist/esm/hooks/useShapes/bar-x/index.js +0 -45
  178. package/dist/esm/hooks/useShapes/bar-y/index.d.ts +0 -13
  179. package/dist/esm/hooks/useShapes/bar-y/index.js +0 -19
  180. package/dist/esm/hooks/useShapes/funnel/index.d.ts +0 -13
  181. package/dist/esm/hooks/useShapes/funnel/index.js +0 -21
  182. package/dist/esm/hooks/useShapes/heatmap/index.d.ts +0 -13
  183. package/dist/esm/hooks/useShapes/heatmap/index.js +0 -20
  184. package/dist/esm/hooks/useShapes/line/index.d.ts +0 -15
  185. package/dist/esm/hooks/useShapes/line/index.js +0 -38
  186. package/dist/esm/hooks/useShapes/pie/index.d.ts +0 -12
  187. package/dist/esm/hooks/useShapes/pie/index.js +0 -20
  188. package/dist/esm/hooks/useShapes/radar/index.d.ts +0 -12
  189. package/dist/esm/hooks/useShapes/radar/index.js +0 -19
  190. package/dist/esm/hooks/useShapes/sankey/index.d.ts +0 -12
  191. package/dist/esm/hooks/useShapes/sankey/index.js +0 -18
  192. package/dist/esm/hooks/useShapes/scatter/index.d.ts +0 -13
  193. package/dist/esm/hooks/useShapes/scatter/index.js +0 -22
  194. package/dist/esm/hooks/useShapes/treemap/index.d.ts +0 -12
  195. package/dist/esm/hooks/useShapes/treemap/index.js +0 -18
  196. package/dist/esm/hooks/useShapes/waterfall/index.d.ts +0 -14
  197. package/dist/esm/hooks/useShapes/waterfall/index.js +0 -31
  198. package/dist/esm/hooks/useShapes/x-range/index.d.ts +0 -14
  199. package/dist/esm/hooks/useShapes/x-range/index.js +0 -20
@@ -1,5 +1,6 @@
1
1
  import { prepareAnnotation } from '../../series/prepare-annotation';
2
2
  import { filterOverlappingLabels, preparePointDataLabels } from '../../utils';
3
+ import { buildHoverMarkerGetter } from '../marker';
3
4
  import { getXValue, getYValue, markHiddenPointsOutOfYRange } from '../utils';
4
5
  export const prepareLineData = async (args) => {
5
6
  var _a, _b, _c, _d, _e, _f;
@@ -58,44 +59,53 @@ export const prepareLineData = async (args) => {
58
59
  svgLabels = filterOverlappingLabels(svgLabels, otherLayers.map((l) => l.svgLabels).flat());
59
60
  htmlElements = filterOverlappingLabels(htmlElements, otherLayers.map((l) => l.htmlLabels).flat());
60
61
  }
61
- let markers = [];
62
+ markHiddenPointsOutOfYRange({
63
+ points,
64
+ yScale: seriesYScale,
65
+ yAxisTop,
66
+ axisMin: seriesYAxis.min,
67
+ axisMax: seriesYAxis.max,
68
+ getDataY: (p) => p.data.y,
69
+ });
70
+ const normalState = s.marker.states.normal;
62
71
  const hasPerPointNormalMarkers = s.data.some((d) => { var _a, _b, _c; return (_c = (_b = (_a = d.marker) === null || _a === void 0 ? void 0 : _a.states) === null || _b === void 0 ? void 0 : _b.normal) === null || _c === void 0 ? void 0 : _c.enabled; });
63
- if (s.marker.states.normal.enabled || hasPerPointNormalMarkers) {
64
- markers = points.reduce((result, p) => {
65
- var _a, _b, _c, _d;
66
- if (p.y === null || p.x === null) {
72
+ const markers = s.marker.states.normal.enabled || hasPerPointNormalMarkers
73
+ ? points.reduce((result, p) => {
74
+ var _a, _b, _c, _d, _e;
75
+ if (p.y === null || p.x === null || p.hiddenInLine) {
67
76
  return result;
68
77
  }
69
78
  const pointNormalEnabled = (_d = (_c = (_b = (_a = p.data.marker) === null || _a === void 0 ? void 0 : _a.states) === null || _b === void 0 ? void 0 : _b.normal) === null || _c === void 0 ? void 0 : _c.enabled) !== null && _d !== void 0 ? _d : false;
70
79
  if (s.marker.states.normal.enabled || pointNormalEnabled) {
71
80
  result.push({
72
- point: p,
81
+ cx: p.x,
82
+ cy: p.y,
83
+ radius: normalState.radius,
84
+ symbolType: normalState.symbol,
85
+ fill: (_e = p.color) !== null && _e !== void 0 ? _e : s.color,
86
+ stroke: normalState.borderColor,
87
+ strokeWidth: normalState.borderWidth,
88
+ opacity: 1,
73
89
  active: true,
74
- hovered: false,
75
90
  clipped: isOutsideBounds(p.x, p.y),
91
+ series: { id: s.id },
92
+ data: p.data,
76
93
  });
77
94
  }
78
95
  return result;
79
- }, []);
80
- }
96
+ }, [])
97
+ : [];
81
98
  const annotations = points.reduce((result, p) => {
82
99
  if (p.annotation && p.x !== null && p.y !== null) {
83
100
  result.push({ annotation: p.annotation, x: p.x, y: p.y });
84
101
  }
85
102
  return result;
86
103
  }, []);
87
- markHiddenPointsOutOfYRange({
88
- points,
89
- yScale: seriesYScale,
90
- yAxisTop,
91
- axisMin: seriesYAxis.min,
92
- axisMax: seriesYAxis.max,
93
- getDataY: (p) => p.data.y,
94
- });
95
104
  const result = {
96
105
  annotations,
97
106
  points,
98
107
  markers,
108
+ getHoverMarkers: buildHoverMarkerGetter(points, s),
99
109
  svgLabels: svgLabels,
100
110
  series: s,
101
111
  hovered: false,
@@ -3,9 +3,4 @@ import type { PreparedSeriesOptions } from '../../series/types';
3
3
  import type { PreparedLineData } from './types';
4
4
  export declare function renderLine(elements: {
5
5
  plot: SVGGElement;
6
- markers: SVGGElement;
7
- hoverMarkers: SVGGElement;
8
- annotations: SVGGElement;
9
- boundsWidth: number;
10
- boundsHeight: number;
11
6
  }, preparedData: PreparedLineData[], seriesOptions: PreparedSeriesOptions, dispatcher?: Dispatch<object>): () => void;
@@ -4,17 +4,12 @@ import { line as lineGenerator } from 'd3-shape';
4
4
  import get from 'lodash/get';
5
5
  import { block } from '../../../utils';
6
6
  import { getLineDashArray } from '../../utils';
7
- import { renderAnnotations } from '../annotation';
8
7
  import { renderDataLabels } from '../data-labels';
9
- import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
10
8
  import { setActiveState } from '../utils';
11
9
  const b = block('line');
12
10
  export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
13
11
  var _a, _b;
14
12
  const plotSvgElement = select(elements.plot);
15
- const markersSvgElement = select(elements.markers);
16
- const hoverMarkersSvgElement = select(elements.hoverMarkers);
17
- const annotationsSvgElement = select(elements.annotations);
18
13
  const hoverOptions = get(seriesOptions, 'line.states.hover');
19
14
  const inactiveOptions = get(seriesOptions, 'line.states.inactive');
20
15
  const line = lineGenerator()
@@ -22,7 +17,6 @@ export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
22
17
  .x((d) => d.x)
23
18
  .y((d) => d.y);
24
19
  plotSvgElement.selectAll('*').remove();
25
- markersSvgElement.selectAll('*').remove();
26
20
  const lineSelection = plotSvgElement
27
21
  .selectAll('path')
28
22
  .data(preparedData)
@@ -44,23 +38,10 @@ export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
44
38
  data: dataLabels,
45
39
  className: b('label'),
46
40
  });
47
- const markers = preparedData.reduce((acc, d) => acc.concat(d.markers), []);
48
- const markerSelection = markersSvgElement
49
- .selectAll('marker')
50
- .data(markers)
51
- .join('g')
52
- .call(renderMarker);
53
- renderAnnotations({
54
- anchors: preparedData.flatMap((d) => d.annotations),
55
- container: annotationsSvgElement,
56
- plotHeight: elements.boundsHeight,
57
- plotWidth: elements.boundsWidth,
58
- });
59
41
  const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
60
42
  const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
61
43
  function handleShapeHover(data) {
62
44
  const selected = (data === null || data === void 0 ? void 0 : data.filter((d) => d.series.type === 'line')) || [];
63
- const selectedDataItems = selected.map((d) => d.data);
64
45
  const selectedSeriesIds = selected.map((d) => { var _a; return (_a = d.series) === null || _a === void 0 ? void 0 : _a.id; });
65
46
  lineSelection.datum((d, index, list) => {
66
47
  const elementSelection = select(list[index]);
@@ -96,62 +77,6 @@ export function renderLine(elements, preparedData, seriesOptions, dispatcher) {
96
77
  datum: d,
97
78
  });
98
79
  });
99
- markerSelection.datum((d, index, list) => {
100
- const elementSelection = select(list[index]);
101
- const hovered = Boolean(hoverEnabled && selectedDataItems.includes(d.point.data));
102
- if (d.hovered !== hovered) {
103
- d.hovered = hovered;
104
- elementSelection.attr('visibility', getMarkerVisibility(d));
105
- selectMarkerHalo(elementSelection).attr('visibility', getMarkerHaloVisibility);
106
- selectMarkerSymbol(elementSelection).call(setMarker, hovered ? 'hover' : 'normal');
107
- }
108
- if (d.point.series.marker.states.normal.enabled) {
109
- const isActive = Boolean(!inactiveEnabled ||
110
- !selectedSeriesIds.length ||
111
- selectedSeriesIds.includes(d.point.series.id));
112
- setActiveState({
113
- element: list[index],
114
- state: inactiveOptions,
115
- active: isActive,
116
- datum: d,
117
- });
118
- }
119
- return d;
120
- });
121
- hoverMarkersSvgElement.selectAll('*').remove();
122
- if (hoverEnabled && selected.length > 0) {
123
- const hoverOnlyMarkers = [];
124
- for (const chunk of selected) {
125
- const seriesData = preparedData.find((pd) => pd.id === chunk.series.id);
126
- if (!seriesData) {
127
- continue;
128
- }
129
- const { series } = seriesData;
130
- if (series.marker.states.normal.enabled || !series.marker.states.hover.enabled) {
131
- continue;
132
- }
133
- const point = seriesData.points.find((p) => p.data === chunk.data);
134
- if (!point || point.x === null || point.y === null) {
135
- continue;
136
- }
137
- hoverOnlyMarkers.push({
138
- point: point,
139
- active: true,
140
- hovered: true,
141
- clipped: false,
142
- });
143
- }
144
- if (hoverOnlyMarkers.length > 0) {
145
- hoverMarkersSvgElement
146
- .selectAll('g')
147
- .data(hoverOnlyMarkers)
148
- .join('g')
149
- .call(renderMarker)
150
- .each((_d, i, nodes) => {
151
- selectMarkerSymbol(select(nodes[i])).call(setMarker, 'hover');
152
- });
153
- }
154
- }
155
80
  }
156
81
  const eventName = `hover-shape.line-${(_b = (_a = preparedData[0]) === null || _a === void 0 ? void 0 : _a.id) !== null && _b !== void 0 ? _b : 'unknown'}`;
157
82
  dispatcher === null || dispatcher === void 0 ? void 0 : dispatcher.on(eventName, handleShapeHover);
@@ -1,7 +1,7 @@
1
1
  import type { LabelData, LineSeriesData, LineSeriesLineBaseStyle } from '../../../types';
2
2
  import type { DashStyle, LineCap, LineJoin } from '../../constants';
3
3
  import type { AnnotationAnchor, PreparedAnnotation, PreparedLineSeries } from '../../series/types';
4
- import type { SeriesShapeData } from '../types';
4
+ import type { MarkerItem, SeriesShapeData } from '../types';
5
5
  export type PointData = {
6
6
  annotation?: PreparedAnnotation;
7
7
  color?: string;
@@ -15,17 +15,11 @@ export type MarkerPointData = PointData & {
15
15
  y: number;
16
16
  x: number;
17
17
  };
18
- export type MarkerData = {
19
- point: MarkerPointData;
20
- active: boolean;
21
- hovered: boolean;
22
- clipped: boolean;
23
- };
24
18
  export type PreparedLineData = {
25
19
  annotations: AnnotationAnchor[];
26
20
  id: string;
27
21
  points: PointData[];
28
- markers: MarkerData[];
22
+ markers: MarkerItem[];
29
23
  series: PreparedLineSeries;
30
24
  hovered: boolean;
31
25
  active: boolean;
@@ -1,5 +1,6 @@
1
1
  import type { BaseType, Selection } from 'd3-selection';
2
2
  import { SymbolType } from '../constants';
3
+ import type { MarkerItem } from './types';
3
4
  export interface BaseMarkerData {
4
5
  point: {
5
6
  x: number;
@@ -43,3 +44,32 @@ export declare function setMarker<T extends BaseType, D extends BaseMarkerData>(
43
44
  export declare function getMarkerSymbol(type: `${SymbolType}` | undefined, radius: number): string | null;
44
45
  export declare function selectMarkerHalo<T>(parentSelection: Selection<BaseType, T, null, undefined>): Selection<BaseType, T, null, undefined>;
45
46
  export declare function selectMarkerSymbol<T>(parentSelection: Selection<BaseType, T, null, undefined>): Selection<BaseType, T, null, undefined>;
47
+ export declare function renderMarkers(container: Selection<SVGGElement, unknown, null, undefined>, markers: MarkerItem[]): void;
48
+ export declare function renderHoverMarkers(container: Selection<SVGGElement, unknown, null, undefined>, hoverMarkers: MarkerItem[]): void;
49
+ interface HoverMarkerPoint {
50
+ data: unknown;
51
+ x: number | null;
52
+ y: number | null;
53
+ hiddenInLine?: boolean;
54
+ color?: string;
55
+ }
56
+ interface HoverMarkerSeries {
57
+ id: string;
58
+ color: string;
59
+ marker: {
60
+ states: {
61
+ normal: {
62
+ enabled: boolean;
63
+ symbol: `${SymbolType}`;
64
+ };
65
+ hover: {
66
+ enabled: boolean;
67
+ radius: number;
68
+ borderColor: string;
69
+ borderWidth: number;
70
+ };
71
+ };
72
+ };
73
+ }
74
+ export declare function buildHoverMarkerGetter(points: HoverMarkerPoint[], series: HoverMarkerSeries): (hoveredData: unknown[]) => MarkerItem[];
75
+ export {};
@@ -80,3 +80,71 @@ export function selectMarkerHalo(parentSelection) {
80
80
  export function selectMarkerSymbol(parentSelection) {
81
81
  return parentSelection.select(`.${symbolClassName}`);
82
82
  }
83
+ export function renderMarkers(container, markers) {
84
+ container.selectAll('*').remove();
85
+ const selection = container
86
+ .selectAll('g')
87
+ .data(markers)
88
+ .join('g')
89
+ .attr('class', b('wrapper'))
90
+ .attr('transform', (d) => `translate(${d.cx},${d.cy})`);
91
+ selection
92
+ .append('path')
93
+ .attr('class', b('symbol'))
94
+ .attr('d', (d) => d.clipped ? null : getMarkerSymbol(d.symbolType, d.radius + d.strokeWidth))
95
+ .attr('fill', (d) => d.fill)
96
+ .attr('stroke', (d) => d.stroke)
97
+ .attr('stroke-width', (d) => d.strokeWidth);
98
+ }
99
+ export function renderHoverMarkers(container, hoverMarkers) {
100
+ container.selectAll('*').remove();
101
+ if (hoverMarkers.length === 0)
102
+ return;
103
+ container
104
+ .selectAll('g')
105
+ .data(hoverMarkers)
106
+ .join('g')
107
+ .attr('class', b('wrapper'))
108
+ .attr('transform', (d) => `translate(${d.cx},${d.cy})`)
109
+ .append('path')
110
+ .attr('class', b('symbol'))
111
+ .attr('d', (d) => getMarkerSymbol(d.symbolType, d.radius + d.strokeWidth))
112
+ .attr('fill', (d) => d.fill)
113
+ .attr('stroke', (d) => d.stroke)
114
+ .attr('stroke-width', (d) => d.strokeWidth);
115
+ }
116
+ export function buildHoverMarkerGetter(points, series) {
117
+ const { normal: normalState, hover: hoverState } = series.marker.states;
118
+ if (normalState.enabled || !hoverState.enabled)
119
+ return () => [];
120
+ const pointByData = new Map();
121
+ for (const p of points) {
122
+ if (p.x !== null && p.y !== null && !p.hiddenInLine) {
123
+ pointByData.set(p.data, p);
124
+ }
125
+ }
126
+ return (hoveredData) => {
127
+ var _a;
128
+ const items = [];
129
+ for (const rawData of hoveredData) {
130
+ const point = pointByData.get(rawData);
131
+ if (!point || point.x === null || point.y === null)
132
+ continue;
133
+ items.push({
134
+ cx: point.x,
135
+ cy: point.y,
136
+ radius: hoverState.radius,
137
+ symbolType: normalState.symbol,
138
+ fill: (_a = point.color) !== null && _a !== void 0 ? _a : series.color,
139
+ stroke: hoverState.borderColor,
140
+ strokeWidth: hoverState.borderWidth,
141
+ opacity: 1,
142
+ active: true,
143
+ clipped: false,
144
+ series: { id: series.id },
145
+ data: rawData,
146
+ });
147
+ }
148
+ return items;
149
+ };
150
+ }
@@ -2,7 +2,7 @@ import { group, max } from 'd3-array';
2
2
  import { arc, line as lineGenerator } from 'd3-shape';
3
3
  import merge from 'lodash/merge';
4
4
  import { DEFAULT_DATALABELS_STYLE } from '../../constants';
5
- import { calculateNumericProperty, getLabelsSize, getLeftPosition, getTextSizeFn, isLabelsOverlapping, } from '../../utils';
5
+ import { calculateNumericProperty, getLabelsSize, getLeftPosition, getTextSizeFn, isLabelsOverlapping, isPointDataLabelEnabled, shouldPrepareSeriesDataLabels, } from '../../utils';
6
6
  import { getFormattedValue } from '../../utils/format';
7
7
  import { getCurveFactory, getInscribedAngle, pieGenerator } from './utils';
8
8
  const FULL_CIRCLE = Math.PI * 2;
@@ -32,7 +32,7 @@ export function preparePieData(args) {
32
32
  const minRadius = typeof propsMinRadius === 'number' ? propsMinRadius : maxRadius * 0.3;
33
33
  const groupedPieSeries = group(preparedSeries, (pieSeries) => pieSeries.stackId);
34
34
  const dataLabelsStyle = merge({}, DEFAULT_DATALABELS_STYLE, (_b = (_a = preparedSeries[0]) === null || _a === void 0 ? void 0 : _a.dataLabels) === null || _b === void 0 ? void 0 : _b.style);
35
- const prepareItem = ({ stackId, items, labels, }) => {
35
+ const prepareItem = ({ stackId, items, labels, hasDataLabels, }) => {
36
36
  var _a;
37
37
  const series = items[0];
38
38
  const { center, borderWidth, borderColor, borderRadius, dataLabels } = series;
@@ -54,6 +54,9 @@ export function preparePieData(args) {
54
54
  opacity: series.states.hover.halo.opacity,
55
55
  size: series.states.hover.halo.size,
56
56
  },
57
+ markers: [],
58
+ getHoverMarkers: () => [],
59
+ annotations: [],
57
60
  };
58
61
  const labelMaxHeight = (_a = max(Object.values(labels).map((l) => { var _a, _b; return (_b = (_a = l.size) === null || _a === void 0 ? void 0 : _a.height) !== null && _b !== void 0 ? _b : 0; }))) !== null && _a !== void 0 ? _a : 0;
59
62
  const segments = items.reduce((acc, item) => {
@@ -62,7 +65,7 @@ export function preparePieData(args) {
62
65
  return acc;
63
66
  }
64
67
  let maxSegmentRadius = maxRadius;
65
- if (dataLabels.enabled) {
68
+ if (hasDataLabels) {
66
69
  maxSegmentRadius -=
67
70
  dataLabels.distance + dataLabels.connectorPadding + labelMaxHeight;
68
71
  }
@@ -82,16 +85,19 @@ export function preparePieData(args) {
82
85
  data.segments = pieGenerator(segments);
83
86
  return data;
84
87
  };
85
- const getLabels = async ({ series }) => {
88
+ const getLabels = async ({ series, hasDataLabels, }) => {
86
89
  var _a;
87
90
  const { dataLabels } = series[0];
88
- if (!dataLabels.enabled) {
91
+ if (!hasDataLabels) {
89
92
  return {};
90
93
  }
91
94
  const getTextSize = getTextSizeFn({ style: dataLabelsStyle });
92
95
  const acc = {};
93
96
  for (let i = 0; i < series.length; i++) {
94
97
  const d = series[i];
98
+ if (!isPointDataLabelEnabled({ data: d.data, series: d })) {
99
+ continue;
100
+ }
95
101
  const text = getFormattedValue(Object.assign({ value: (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.value }, d.dataLabels));
96
102
  let labelWidth = 0;
97
103
  let labelHeight = 0;
@@ -120,12 +126,12 @@ export function preparePieData(args) {
120
126
  return acc;
121
127
  };
122
128
  const prepareLabels = (prepareLabelsArgs) => {
123
- const { data, series, labels: labelsData, allowOverlow = true } = prepareLabelsArgs;
129
+ const { data, series, labels: labelsData, hasDataLabels, allowOverlow = true, } = prepareLabelsArgs;
124
130
  const { dataLabels } = series[0];
125
131
  const labels = [];
126
132
  const htmlLabels = [];
127
133
  const connectors = [];
128
- if (!dataLabels.enabled) {
134
+ if (!hasDataLabels) {
129
135
  return { labels, htmlLabels, connectors };
130
136
  }
131
137
  const shouldUseHtml = dataLabels.html;
@@ -150,6 +156,9 @@ export function preparePieData(args) {
150
156
  let shouldStopLabelPlacement = false;
151
157
  series.forEach((d, index) => {
152
158
  var _a, _b;
159
+ if (!isPointDataLabelEnabled({ data: d.data, series: d })) {
160
+ return;
161
+ }
153
162
  const prevLabel = labels[labels.length - 1];
154
163
  const { text = '', size: labelSize } = labelsData[d.id];
155
164
  const labelWidth = (_a = labelSize === null || labelSize === void 0 ? void 0 : labelSize.width) !== null && _a !== void 0 ? _a : 0;
@@ -287,12 +296,17 @@ export function preparePieData(args) {
287
296
  };
288
297
  return Promise.all(Array.from(groupedPieSeries).map(async ([stackId, items]) => {
289
298
  var _a;
290
- const seriesLabels = await getLabels({ series: items });
291
- const data = prepareItem({ stackId, items, labels: seriesLabels });
299
+ const hasDataLabels = shouldPrepareSeriesDataLabels({
300
+ dataLabels: items[0].dataLabels,
301
+ data: items.map((it) => it.data),
302
+ });
303
+ const seriesLabels = await getLabels({ series: items, hasDataLabels });
304
+ const data = prepareItem({ stackId, items, labels: seriesLabels, hasDataLabels });
292
305
  const preparedLabels = prepareLabels({
293
306
  data,
294
307
  labels: seriesLabels,
295
308
  series: items,
309
+ hasDataLabels,
296
310
  });
297
311
  let maxLeftRightFreeSpace = Infinity;
298
312
  let labelsOverflow = 0;
@@ -370,6 +384,7 @@ export function preparePieData(args) {
370
384
  data,
371
385
  series: items,
372
386
  labels: seriesLabels,
387
+ hasDataLabels,
373
388
  allowOverlow: false,
374
389
  });
375
390
  if (typeof ((_a = items[0]) === null || _a === void 0 ? void 0 : _a.innerRadius) !== 'undefined') {
@@ -26,6 +26,9 @@ export async function prepareRadarData(args) {
26
26
  htmlLabels: [],
27
27
  grid: [],
28
28
  cursor: preparedSeries[0].cursor,
29
+ markers: [],
30
+ getHoverMarkers: () => [],
31
+ annotations: [],
29
32
  };
30
33
  const categories = preparedSeries[0].categories;
31
34
  const axisStrokeColor = 'var(--g-color-line-generic)';
@@ -70,5 +70,14 @@ export function prepareSankeyData(args) {
70
70
  });
71
71
  dataLabels.push(...labels);
72
72
  }
73
- return { series, nodes: sankeyNodes, links: sankeyLinks, htmlLabels, labels: dataLabels };
73
+ return {
74
+ series,
75
+ nodes: sankeyNodes,
76
+ links: sankeyLinks,
77
+ htmlLabels,
78
+ labels: dataLabels,
79
+ markers: [],
80
+ getHoverMarkers: () => [],
81
+ annotations: [],
82
+ };
74
83
  }
@@ -112,5 +112,12 @@ export async function prepareScatterData(args) {
112
112
  }
113
113
  }
114
114
  }
115
- return { markers, svgLabels: allSvgLabels, htmlLabels: allHtmlLabels };
115
+ return {
116
+ scatterData: markers,
117
+ svgLabels: allSvgLabels,
118
+ htmlLabels: allHtmlLabels,
119
+ markers: [],
120
+ getHoverMarkers: () => [],
121
+ annotations: [],
122
+ };
116
123
  }
@@ -6,20 +6,21 @@ import { setActiveState, shapeKey } from '../../shapes/utils';
6
6
  import { renderDataLabels } from '../data-labels';
7
7
  const b = block('scatter');
8
8
  export function renderScatter(elements, preparedData, seriesOptions, dispatcher) {
9
+ var _a;
9
10
  const svgElement = select(elements.plot);
10
11
  const hoverOptions = get(seriesOptions, 'scatter.states.hover');
11
12
  const inactiveOptions = get(seriesOptions, 'scatter.states.inactive');
12
13
  svgElement.selectAll('*').remove();
13
14
  const selection = svgElement
14
15
  .selectAll('path')
15
- .data(preparedData.markers, shapeKey)
16
+ .data(preparedData.scatterData, shapeKey)
16
17
  .join('g')
17
18
  .call(renderMarker)
18
19
  .attr('opacity', (d) => d.point.opacity)
19
20
  .attr('cursor', (d) => d.point.series.cursor);
20
21
  renderDataLabels({
21
22
  container: svgElement,
22
- data: preparedData.svgLabels,
23
+ data: (_a = preparedData.svgLabels) !== null && _a !== void 0 ? _a : [],
23
24
  className: b('label'),
24
25
  });
25
26
  const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
@@ -18,7 +18,7 @@ export type MarkerData = {
18
18
  };
19
19
  export type PreparedScatterData = MarkerData;
20
20
  export type PreparedScatterShapeData = {
21
- markers: PreparedScatterData[];
21
+ scatterData: PreparedScatterData[];
22
22
  svgLabels: LabelData[];
23
23
  } & SeriesShapeData;
24
24
  export {};
@@ -160,5 +160,13 @@ export async function prepareTreemapData(args) {
160
160
  labelData = labels;
161
161
  }
162
162
  }
163
- return { labelData, leaves, series, htmlLabels };
163
+ return {
164
+ labelData,
165
+ leaves,
166
+ series,
167
+ htmlLabels,
168
+ markers: [],
169
+ getHoverMarkers: () => [],
170
+ annotations: [],
171
+ };
164
172
  }
@@ -1,4 +1,39 @@
1
1
  import type { HtmlItem } from '../../types';
2
+ import type { SymbolType } from '../constants';
3
+ import type { AnnotationAnchor } from '../series/types';
4
+ export interface MarkerItem {
5
+ cx: number;
6
+ cy: number;
7
+ radius: number;
8
+ symbolType: `${SymbolType}`;
9
+ fill: string;
10
+ stroke: string;
11
+ strokeWidth: number;
12
+ opacity: number;
13
+ active: boolean;
14
+ clipped: boolean;
15
+ series: {
16
+ id: string;
17
+ };
18
+ data: unknown;
19
+ }
2
20
  export interface SeriesShapeData {
3
21
  htmlLabels: HtmlItem[];
22
+ markers: MarkerItem[];
23
+ annotations: AnnotationAnchor[];
24
+ getHoverMarkers(hoveredData: unknown[]): MarkerItem[];
25
+ }
26
+ export interface TooltipItemData {
27
+ type?: string;
28
+ series?: {
29
+ type?: string;
30
+ tooltip?: {
31
+ enabled?: boolean;
32
+ };
33
+ };
34
+ point?: {
35
+ series?: {
36
+ type?: string;
37
+ };
38
+ };
4
39
  }
@@ -2,11 +2,11 @@ import get from 'lodash/get';
2
2
  import sortBy from 'lodash/sortBy';
3
3
  import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '../../shapes/bar-constants';
4
4
  import { getXValue, getYValue } from '../../shapes/utils';
5
- import { getLabelsSize } from '../../utils';
5
+ import { getLabelsSize, isPointDataLabelEnabled } from '../../utils';
6
6
  import { getFormattedValue } from '../../utils/format';
7
7
  async function getLabelData(d, plotHeight) {
8
8
  var _a, _b;
9
- if (!d.series.dataLabels.enabled) {
9
+ if (!isPointDataLabelEnabled({ data: d.data, series: d.series })) {
10
10
  return undefined;
11
11
  }
12
12
  const labelValue = (_b = (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.y) !== null && _b !== void 0 ? _b : d.subTotal;
@@ -145,6 +145,9 @@ export const prepareWaterfallData = async (args) => {
145
145
  series: item.series,
146
146
  subTotal: totalValue,
147
147
  htmlLabels: [],
148
+ markers: [],
149
+ getHoverMarkers: () => [],
150
+ annotations: [],
148
151
  };
149
152
  preparedData.label = await getLabelData(preparedData, plotHeight);
150
153
  result.push(preparedData);
@@ -1,6 +1,6 @@
1
1
  import get from 'lodash/get';
2
2
  import { MIN_BAR_WIDTH } from '../../shapes/bar-constants';
3
- import { getDataCategoryValue, getLabelsSize, getTextSizeFn, getTextWithElipsis } from '../../utils';
3
+ import { getDataCategoryValue, getLabelsSize, getTextSizeFn, getTextWithElipsis, isPointDataLabelEnabled, } from '../../utils';
4
4
  import { getBandSize } from '../../utils/band-size';
5
5
  import { getFormattedValue } from '../../utils/format';
6
6
  const DEFAULT_BAR_PADDING = 0.2;
@@ -84,6 +84,9 @@ export async function prepareXRangeData(args) {
84
84
  series: s,
85
85
  htmlLabels: [],
86
86
  svgLabels: [],
87
+ markers: [],
88
+ getHoverMarkers: () => [],
89
+ annotations: [],
87
90
  });
88
91
  });
89
92
  });
@@ -91,7 +94,9 @@ export async function prepareXRangeData(args) {
91
94
  for (let i = 0; i < result.length; i++) {
92
95
  const item = result[i];
93
96
  const { dataLabels } = item.series;
94
- if (!dataLabels.enabled || item.data.label === null || isRangeSlider) {
97
+ if (isRangeSlider ||
98
+ item.data.label === null ||
99
+ !isPointDataLabelEnabled({ data: item.data, series: item.series })) {
95
100
  continue;
96
101
  }
97
102
  const content = getFormattedValue(Object.assign({ value: item.data.label }, dataLabels));