@gravity-ui/charts 1.39.0 → 1.40.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 (31) hide show
  1. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +2 -38
  2. package/dist/cjs/components/ChartInner/utils/axis.d.ts +1 -37
  3. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +6 -0
  4. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +41 -0
  5. package/dist/cjs/components/Tooltip/index.js +2 -0
  6. package/dist/cjs/hooks/useAxis/index.d.ts +1 -37
  7. package/dist/cjs/hooks/useAxis/types.d.ts +6 -4
  8. package/dist/cjs/hooks/useAxisScales/index.d.ts +2 -2
  9. package/dist/cjs/hooks/useCrosshair/index.js +21 -15
  10. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +1 -1
  11. package/dist/cjs/hooks/useTooltip/index.d.ts +4 -1
  12. package/dist/cjs/hooks/useTooltip/index.js +12 -5
  13. package/dist/cjs/types/chart/axis.d.ts +2 -1
  14. package/dist/cjs/types/chart/tooltip.d.ts +20 -0
  15. package/dist/cjs/utils/chart/zoom.js +2 -2
  16. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +2 -38
  17. package/dist/esm/components/ChartInner/utils/axis.d.ts +1 -37
  18. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +6 -0
  19. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +41 -0
  20. package/dist/esm/components/Tooltip/index.js +2 -0
  21. package/dist/esm/hooks/useAxis/index.d.ts +1 -37
  22. package/dist/esm/hooks/useAxis/types.d.ts +6 -4
  23. package/dist/esm/hooks/useAxisScales/index.d.ts +2 -2
  24. package/dist/esm/hooks/useCrosshair/index.js +21 -15
  25. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +1 -1
  26. package/dist/esm/hooks/useTooltip/index.d.ts +4 -1
  27. package/dist/esm/hooks/useTooltip/index.js +12 -5
  28. package/dist/esm/types/chart/axis.d.ts +2 -1
  29. package/dist/esm/types/chart/tooltip.d.ts +20 -0
  30. package/dist/esm/utils/chart/zoom.js +2 -2
  31. package/package.json +1 -1
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Dispatch } from 'd3';
3
- import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
3
+ import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, PreparedYAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
4
4
  import type { PreparedChart } from '../../hooks/types';
5
5
  import type { LegendConfig } from '../../types';
6
6
  import type { ChartInnerProps } from './types';
@@ -21,43 +21,7 @@ export declare function useChartInnerProps(props: Props): {
21
21
  boundsHeight: number;
22
22
  boundsWidth: number;
23
23
  xAxis: PreparedXAxis | null;
24
- yAxis: (Omit<import("../../types").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
25
- type: import("../../types").ChartAxisType;
26
- labels: Omit<import("../../types").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../types").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
27
- style: import("../../types").BaseTextStyle;
28
- rotation: number;
29
- height: number;
30
- width: number;
31
- lineHeight: number;
32
- maxWidth: number;
33
- };
34
- title: {
35
- height: number;
36
- width: number;
37
- text: string;
38
- margin: number;
39
- style: import("../../types").BaseTextStyle;
40
- align: import("../../types").ChartAxisTitleAlignment;
41
- maxRowCount: number;
42
- rotation: number;
43
- maxWidth: number;
44
- html: boolean;
45
- };
46
- min?: number;
47
- grid: {
48
- enabled: boolean;
49
- };
50
- maxPadding: number;
51
- ticks: {
52
- pixelInterval?: number;
53
- };
54
- tickMarks: import("../../hooks").PreparedAxisTickMarks;
55
- position: "left" | "right" | "top" | "bottom";
56
- plotIndex: number;
57
- plotLines: import("../../hooks").PreparedAxisPlotLine[];
58
- plotBands: import("../../hooks").PreparedAxisPlotBand[];
59
- crosshair: Required<import("../../types").AxisCrosshair>;
60
- })[];
24
+ yAxis: PreparedYAxis[];
61
25
  shapesData: ShapeData[];
62
26
  shapesReady: boolean;
63
27
  handleLegendItemClick: OnLegendItemClick;
@@ -5,40 +5,4 @@ export declare function recalculateYAxisLabelsWidth(props: {
5
5
  seriesData: PreparedSeries[];
6
6
  yAxis: PreparedYAxis[];
7
7
  yScale?: (ChartScale | undefined)[];
8
- }): Promise<(Omit<import("../../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
9
- type: import("../../..").ChartAxisType;
10
- labels: Omit<import("../../..").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../..").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
11
- style: import("../../..").BaseTextStyle;
12
- rotation: number;
13
- height: number;
14
- width: number;
15
- lineHeight: number;
16
- maxWidth: number;
17
- };
18
- title: {
19
- height: number;
20
- width: number;
21
- text: string;
22
- margin: number;
23
- style: import("../../..").BaseTextStyle;
24
- align: import("../../..").ChartAxisTitleAlignment;
25
- maxRowCount: number;
26
- rotation: number;
27
- maxWidth: number;
28
- html: boolean;
29
- };
30
- min?: number;
31
- grid: {
32
- enabled: boolean;
33
- };
34
- maxPadding: number;
35
- ticks: {
36
- pixelInterval?: number;
37
- };
38
- tickMarks: import("../../../hooks").PreparedAxisTickMarks;
39
- position: "left" | "right" | "top" | "bottom";
40
- plotIndex: number;
41
- plotLines: import("../../../hooks").PreparedAxisPlotLine[];
42
- plotBands: import("../../../hooks").PreparedAxisPlotBand[];
43
- crosshair: Required<import("../../..").AxisCrosshair>;
44
- })[]>;
8
+ }): Promise<PreparedYAxis[]>;
@@ -35,6 +35,12 @@ export declare function getPreparedAggregation(args: {
35
35
  xAxis?: ChartXAxis | null;
36
36
  yAxis?: ChartYAxis;
37
37
  }): ChartTooltipTotalsBuiltInAggregation | (() => ChartTooltipTotalsAggregationValue);
38
+ export declare function getSortedHovered(args: {
39
+ hovered: TooltipDataChunk[];
40
+ sorting?: ChartTooltip['sorting'];
41
+ xAxis?: ChartXAxis | null;
42
+ yAxis?: ChartYAxis;
43
+ }): TooltipDataChunk[];
38
44
  export declare function getTooltipRowColorSymbol({ series, color, height, width, }: {
39
45
  color?: string;
40
46
  series?: TooltipDataChunk['series'];
@@ -130,6 +130,47 @@ export function getPreparedAggregation(args) {
130
130
  }
131
131
  return 'sum';
132
132
  }
133
+ export function getSortedHovered(args) {
134
+ var _a;
135
+ const { hovered, sorting, xAxis, yAxis } = args;
136
+ if (!sorting) {
137
+ return hovered;
138
+ }
139
+ if (typeof sorting === 'function') {
140
+ return [...hovered].sort(sorting);
141
+ }
142
+ switch (sorting.key) {
143
+ case 'value': {
144
+ const values = getHoveredValues({ hovered, xAxis, yAxis });
145
+ const direction = (_a = sorting.direction) !== null && _a !== void 0 ? _a : 'asc';
146
+ const compareValue = (a, b) => {
147
+ const aNil = a === null || a === undefined;
148
+ const bNil = b === null || b === undefined;
149
+ if (aNil && bNil) {
150
+ return 0;
151
+ }
152
+ if (aNil) {
153
+ return -1;
154
+ }
155
+ if (bNil) {
156
+ return 1;
157
+ }
158
+ if (typeof a === 'number' && typeof b === 'number') {
159
+ return a - b;
160
+ }
161
+ return String(a).localeCompare(String(b));
162
+ };
163
+ const indices = hovered.map((_, i) => i);
164
+ indices.sort((i, j) => direction === 'asc'
165
+ ? compareValue(values[i], values[j])
166
+ : compareValue(values[j], values[i]));
167
+ return indices.map((i) => hovered[i]);
168
+ }
169
+ default: {
170
+ return hovered;
171
+ }
172
+ }
173
+ }
133
174
  export function getTooltipRowColorSymbol({ series, color, height = 8, width = 16, }) {
134
175
  if ((series === null || series === void 0 ? void 0 : series.type) === 'line') {
135
176
  const colorSymbol = create('svg').attr('height', height).attr('width', width);
@@ -10,6 +10,8 @@ export const Tooltip = (props) => {
10
10
  const { hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition } = useTooltip({
11
11
  dispatcher,
12
12
  tooltip,
13
+ xAxis,
14
+ yAxis,
13
15
  });
14
16
  const containerRect = (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) || { left: 0, top: 0 };
15
17
  const left = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) || 0) + containerRect.left;
@@ -16,43 +16,7 @@ interface UseAxesProps {
16
16
  }
17
17
  export declare function getAxes(props: UseAxesProps): Promise<{
18
18
  xAxis: import("./types").PreparedXAxis | null;
19
- yAxis: (Omit<import("../../types").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
20
- type: import("../../types").ChartAxisType;
21
- labels: Omit<import("../../types").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../types").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
22
- style: import("../../types").BaseTextStyle;
23
- rotation: number;
24
- height: number;
25
- width: number;
26
- lineHeight: number;
27
- maxWidth: number;
28
- };
29
- title: {
30
- height: number;
31
- width: number;
32
- text: string;
33
- margin: number;
34
- style: import("../../types").BaseTextStyle;
35
- align: import("../../types").ChartAxisTitleAlignment;
36
- maxRowCount: number;
37
- rotation: number;
38
- maxWidth: number;
39
- html: boolean;
40
- };
41
- min?: number;
42
- grid: {
43
- enabled: boolean;
44
- };
45
- maxPadding: number;
46
- ticks: {
47
- pixelInterval?: number;
48
- };
49
- tickMarks: import("./types").PreparedAxisTickMarks;
50
- position: "left" | "right" | "top" | "bottom";
51
- plotIndex: number;
52
- plotLines: import("./types").PreparedAxisPlotLine[];
53
- plotBands: import("./types").PreparedAxisPlotBand[];
54
- crosshair: Required<import("../../types").AxisCrosshair>;
55
- })[];
19
+ yAxis: import("./types").PreparedYAxis[];
56
20
  }>;
57
21
  export declare function useAxis(props: UseAxesProps): AxesState;
58
22
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { DashStyle } from '../../constants';
2
- import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
2
+ import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
3
3
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation' | 'html'>> & {
4
4
  style: BaseTextStyle;
5
5
  rotation: number;
@@ -51,7 +51,7 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
51
51
  style: BaseTextStyle;
52
52
  align: ChartAxisTitleAlignment;
53
53
  maxRowCount: number;
54
- rotation: number;
54
+ rotation: ChartAxisTitleRotation;
55
55
  maxWidth: number;
56
56
  html: boolean;
57
57
  };
@@ -64,7 +64,6 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
64
64
  pixelInterval?: number;
65
65
  };
66
66
  tickMarks: PreparedAxisTickMarks;
67
- position: 'left' | 'right' | 'top' | 'bottom';
68
67
  plotIndex: number;
69
68
  plotLines: PreparedAxisPlotLine[];
70
69
  plotBands: PreparedAxisPlotBand[];
@@ -72,8 +71,11 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
72
71
  };
73
72
  export type PreparedXAxis = PreparedBaseAxis & {
74
73
  rangeSlider: PreparedRangeSlider;
74
+ position: 'bottom';
75
+ };
76
+ export type PreparedYAxis = PreparedBaseAxis & {
77
+ position: 'left' | 'right';
75
78
  };
76
- export type PreparedYAxis = PreparedBaseAxis;
77
79
  export type PreparedAxis = PreparedXAxis | PreparedYAxis;
78
80
  export type AxesState = {
79
81
  xAxis: PreparedXAxis | null;
@@ -1,4 +1,4 @@
1
- import type { PreparedAxis, PreparedSeries, PreparedSplit, RangeSliderState, ZoomState } from '../../hooks';
1
+ import type { PreparedAxis, PreparedSeries, PreparedSplit, PreparedYAxis, RangeSliderState, ZoomState } from '../../hooks';
2
2
  import type { ChartScale } from './types';
3
3
  export { createXScale } from './x-scale';
4
4
  export { createYScale } from './y-scale';
@@ -7,7 +7,7 @@ type Args = {
7
7
  boundsHeight: number;
8
8
  series: PreparedSeries[];
9
9
  xAxis: PreparedAxis | null;
10
- yAxis: PreparedAxis[];
10
+ yAxis: PreparedYAxis[];
11
11
  split: PreparedSplit;
12
12
  isRangeSlider?: boolean;
13
13
  rangeSliderState?: RangeSliderState;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { line, select } from 'd3';
3
3
  import { getAxisPlotsPosition, getLineDashArray } from '../../utils';
4
+ import { getXValue, getYValue } from '../useShapes/utils';
4
5
  import { useCrosshairHover } from './useCrosshairHover';
5
6
  export const useCrosshair = (props) => {
6
7
  var _a, _b;
@@ -29,15 +30,18 @@ export const useCrosshair = (props) => {
29
30
  crosshairSelection
30
31
  .append('path')
31
32
  .attr('d', (hoveredElement) => {
32
- var _a, _b, _c;
33
33
  let lineValue = 0;
34
- if (xAxis.crosshair.snap) {
35
- const offset = ((_b = (_a = xAxisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(xAxisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
36
- if (typeof hoveredElement.data === 'object' && 'x' in hoveredElement.data) {
37
- lineValue = Number(xAxisScale((_c = hoveredElement.data.x) !== null && _c !== void 0 ? _c : 0)) + offset;
38
- }
34
+ if (xAxis.crosshair.snap &&
35
+ typeof hoveredElement.data === 'object' &&
36
+ 'x' in hoveredElement.data) {
37
+ const xVal = getXValue({
38
+ point: hoveredElement.data,
39
+ xAxis,
40
+ xScale: xAxisScale,
41
+ });
42
+ lineValue = xVal !== null && !Number.isNaN(xVal) ? xVal : lineValue;
39
43
  }
40
- else {
44
+ else if (!xAxis.crosshair.snap) {
41
45
  lineValue = pointerXPos - boundsOffsetLeft;
42
46
  }
43
47
  const points = [
@@ -89,16 +93,18 @@ export const useCrosshair = (props) => {
89
93
  crosshairSelection
90
94
  .append('path')
91
95
  .attr('d', (hoveredElement) => {
92
- var _a, _b, _c;
93
96
  let lineValue = 0;
94
- if (yAxis.crosshair.snap) {
95
- const offset = ((_b = (_a = yAxisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(yAxisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
96
- if (typeof hoveredElement.data === 'object' &&
97
- 'y' in hoveredElement.data) {
98
- lineValue = Number(yAxisScale((_c = hoveredElement.data.y) !== null && _c !== void 0 ? _c : 0)) + offset;
99
- }
97
+ if (yAxis.crosshair.snap &&
98
+ typeof hoveredElement.data === 'object' &&
99
+ 'y' in hoveredElement.data) {
100
+ const yVal = getYValue({
101
+ point: hoveredElement.data,
102
+ yAxis,
103
+ yScale: yAxisScale,
104
+ });
105
+ lineValue = yVal !== null && !Number.isNaN(yVal) ? yVal : lineValue;
100
106
  }
101
- else {
107
+ else if (!yAxis.crosshair.snap) {
102
108
  lineValue = pointerYPos - boundsOffsetTop;
103
109
  }
104
110
  const points = [
@@ -178,7 +178,7 @@ export const prepareBarXData = async (args) => {
178
178
  }
179
179
  if (series.some((s) => s.stacking === 'percent')) {
180
180
  let acc = 0;
181
- const ratio = plotHeight / (positiveStackHeight - stackItems.length);
181
+ const ratio = plotHeight / (positiveStackHeight - (stackItems.length - 1) * stackGap);
182
182
  stackItems.forEach((item) => {
183
183
  item.height = item.height * ratio;
184
184
  item.y = plotHeight - item.height - acc;
@@ -1,11 +1,14 @@
1
1
  import type { Dispatch } from 'd3';
2
2
  import type { AxisPlotBand, AxisPlotLine, PointPosition, TooltipDataChunk } from '../../types';
3
3
  import type { PreparedTooltip } from '../types';
4
+ import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
4
5
  type Args = {
5
6
  dispatcher: Dispatch<object>;
6
7
  tooltip: PreparedTooltip;
8
+ xAxis?: PreparedXAxis | null;
9
+ yAxis?: PreparedYAxis;
7
10
  };
8
- export declare const useTooltip: ({ dispatcher, tooltip }: Args) => {
11
+ export declare const useTooltip: ({ dispatcher, tooltip, xAxis, yAxis }: Args) => {
9
12
  hovered: TooltipDataChunk[] | undefined;
10
13
  hoveredPlotLines: AxisPlotLine[] | undefined;
11
14
  hoveredPlotBands: AxisPlotBand[] | undefined;
@@ -1,21 +1,28 @@
1
1
  import React from 'react';
2
2
  import isEqual from 'lodash/isEqual';
3
- export const useTooltip = ({ dispatcher, tooltip }) => {
3
+ import { getSortedHovered } from '../../components/Tooltip/DefaultTooltipContent/utils';
4
+ export const useTooltip = ({ dispatcher, tooltip, xAxis, yAxis }) => {
4
5
  const [{ hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition }, setTooltipState] = React.useState({});
5
6
  const prevHovered = React.useRef(hovered);
6
7
  React.useEffect(() => {
7
8
  if (tooltip === null || tooltip === void 0 ? void 0 : tooltip.enabled) {
8
9
  dispatcher.on('hover-shape.tooltip', (nextHovered, nextPointerPosition, nextHoveredPlots) => {
9
10
  const filteredNextHovered = nextHovered === null || nextHovered === void 0 ? void 0 : nextHovered.filter((item) => 'y' in item.data ? item.data.y !== null : true);
10
- const isHoveredChanged = !isEqual(prevHovered.current, filteredNextHovered);
11
+ const sortedHovered = getSortedHovered({
12
+ hovered: filteredNextHovered !== null && filteredNextHovered !== void 0 ? filteredNextHovered : [],
13
+ sorting: tooltip === null || tooltip === void 0 ? void 0 : tooltip.sorting,
14
+ xAxis,
15
+ yAxis,
16
+ });
17
+ const isHoveredChanged = !isEqual(prevHovered.current, sortedHovered);
11
18
  const newTooltipState = {
12
- hovered: isHoveredChanged ? filteredNextHovered : prevHovered.current,
19
+ hovered: isHoveredChanged ? sortedHovered : prevHovered.current,
13
20
  hoveredPlotLines: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.lines,
14
21
  hoveredPlotBands: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.bands,
15
22
  pointerPosition: nextPointerPosition,
16
23
  };
17
24
  if (isHoveredChanged) {
18
- prevHovered.current = filteredNextHovered;
25
+ prevHovered.current = sortedHovered;
19
26
  }
20
27
  setTooltipState(newTooltipState);
21
28
  });
@@ -25,7 +32,7 @@ export const useTooltip = ({ dispatcher, tooltip }) => {
25
32
  dispatcher.on('hover-shape.tooltip', null);
26
33
  }
27
34
  };
28
- }, [dispatcher, tooltip]);
35
+ }, [dispatcher, tooltip, xAxis, yAxis]);
29
36
  return {
30
37
  hovered,
31
38
  hoveredPlotLines,
@@ -6,6 +6,7 @@ import type { BaseTextStyle } from './base';
6
6
  import type { ChartBrush } from './brush';
7
7
  export type ChartAxisType = (typeof AXIS_TYPE)[keyof typeof AXIS_TYPE];
8
8
  export type ChartAxisTitleAlignment = 'left' | 'center' | 'right';
9
+ export type ChartAxisTitleRotation = 0 | 90 | -90;
9
10
  export interface ChartAxisLabels {
10
11
  /** Enable or disable the axis labels. */
11
12
  enabled?: boolean;
@@ -314,7 +315,7 @@ export interface ChartYAxisTitle extends ChartAxisTitle {
314
315
  *
315
316
  * The default values are -90 for the left axis and 90 for the right.
316
317
  */
317
- rotation?: 0 | 90 | -90;
318
+ rotation?: ChartAxisTitleRotation;
318
319
  /**
319
320
  * Interval of the tick marks(absolute or relative to the chart area).
320
321
  *
@@ -115,6 +115,7 @@ export type ChartTooltipRowRendererArgs = {
115
115
  hovered?: TooltipDataChunk<unknown>[];
116
116
  className?: string;
117
117
  };
118
+ export type ChartTooltipSortComparator<T = MeaningfulAny> = (a: TooltipDataChunk<T>, b: TooltipDataChunk<T>) => number;
118
119
  export interface ChartTooltip<T = MeaningfulAny> {
119
120
  enabled?: boolean;
120
121
  /** Specifies the renderer for the tooltip. If returned null default tooltip renderer will be used. */
@@ -158,4 +159,23 @@ export interface ChartTooltip<T = MeaningfulAny> {
158
159
  * It is assigned as a data-qa attribute to an element.
159
160
  */
160
161
  qa?: string;
162
+ /**
163
+ * Controls the order of tooltip rows. Applied to `hovered` before rendering.
164
+ * Use a custom comparator `(a, b) => number` for arbitrary ordering.
165
+ */
166
+ sorting?: {
167
+ /**
168
+ * Determines what data should be used to sort by.
169
+ * `'value'` uses the numeric value of each series point: `y` for most series
170
+ * (line, area, bar-x, scatter, waterfall), `x` for bar-y, and `value` for
171
+ * pie, radar, heatmap, treemap, funnel. `null` values are sorted as lowest.
172
+ * @default undefined (sorting disabled)
173
+ */
174
+ key?: 'value' | undefined;
175
+ /**
176
+ * Sorting direction.
177
+ * @default 'asc'
178
+ */
179
+ direction?: 'asc' | 'desc';
180
+ } | ChartTooltipSortComparator<T>;
161
181
  }
@@ -50,9 +50,9 @@ export function getZoomedSeriesData(args) {
50
50
  }
51
51
  const zoomedSeriesData = [];
52
52
  const zoomedShapesSeriesData = [];
53
- let prevPointInRange = false;
54
- let currentPointInRange = false;
55
53
  seriesData.forEach((seriesItem) => {
54
+ let prevPointInRange = false;
55
+ let currentPointInRange = false;
56
56
  const filteredData = [];
57
57
  const filteredShapesData = SERIES_TYPE_WITH_HIDDEN_POINTS.includes(seriesItem.type) && (xAxis === null || xAxis === void 0 ? void 0 : xAxis.type) !== 'category'
58
58
  ? []
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import type { Dispatch } from 'd3';
3
- import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
3
+ import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, PreparedYAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
4
4
  import type { PreparedChart } from '../../hooks/types';
5
5
  import type { LegendConfig } from '../../types';
6
6
  import type { ChartInnerProps } from './types';
@@ -21,43 +21,7 @@ export declare function useChartInnerProps(props: Props): {
21
21
  boundsHeight: number;
22
22
  boundsWidth: number;
23
23
  xAxis: PreparedXAxis | null;
24
- yAxis: (Omit<import("../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
25
- type: import("../..").ChartAxisType;
26
- labels: Omit<import("../..").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../..").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
27
- style: import("../..").BaseTextStyle;
28
- rotation: number;
29
- height: number;
30
- width: number;
31
- lineHeight: number;
32
- maxWidth: number;
33
- };
34
- title: {
35
- height: number;
36
- width: number;
37
- text: string;
38
- margin: number;
39
- style: import("../..").BaseTextStyle;
40
- align: import("../..").ChartAxisTitleAlignment;
41
- maxRowCount: number;
42
- rotation: number;
43
- maxWidth: number;
44
- html: boolean;
45
- };
46
- min?: number;
47
- grid: {
48
- enabled: boolean;
49
- };
50
- maxPadding: number;
51
- ticks: {
52
- pixelInterval?: number;
53
- };
54
- tickMarks: import("../../hooks").PreparedAxisTickMarks;
55
- position: "left" | "right" | "top" | "bottom";
56
- plotIndex: number;
57
- plotLines: import("../../hooks").PreparedAxisPlotLine[];
58
- plotBands: import("../../hooks").PreparedAxisPlotBand[];
59
- crosshair: Required<import("../..").AxisCrosshair>;
60
- })[];
24
+ yAxis: PreparedYAxis[];
61
25
  shapesData: ShapeData[];
62
26
  shapesReady: boolean;
63
27
  handleLegendItemClick: OnLegendItemClick;
@@ -5,40 +5,4 @@ export declare function recalculateYAxisLabelsWidth(props: {
5
5
  seriesData: PreparedSeries[];
6
6
  yAxis: PreparedYAxis[];
7
7
  yScale?: (ChartScale | undefined)[];
8
- }): Promise<(Omit<import("../../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
9
- type: import("../../..").ChartAxisType;
10
- labels: Omit<import("../../..").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../../..").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
11
- style: import("../../..").BaseTextStyle;
12
- rotation: number;
13
- height: number;
14
- width: number;
15
- lineHeight: number;
16
- maxWidth: number;
17
- };
18
- title: {
19
- height: number;
20
- width: number;
21
- text: string;
22
- margin: number;
23
- style: import("../../..").BaseTextStyle;
24
- align: import("../../..").ChartAxisTitleAlignment;
25
- maxRowCount: number;
26
- rotation: number;
27
- maxWidth: number;
28
- html: boolean;
29
- };
30
- min?: number;
31
- grid: {
32
- enabled: boolean;
33
- };
34
- maxPadding: number;
35
- ticks: {
36
- pixelInterval?: number;
37
- };
38
- tickMarks: import("../../../hooks").PreparedAxisTickMarks;
39
- position: "left" | "right" | "top" | "bottom";
40
- plotIndex: number;
41
- plotLines: import("../../../hooks").PreparedAxisPlotLine[];
42
- plotBands: import("../../../hooks").PreparedAxisPlotBand[];
43
- crosshair: Required<import("../../..").AxisCrosshair>;
44
- })[]>;
8
+ }): Promise<PreparedYAxis[]>;
@@ -35,6 +35,12 @@ export declare function getPreparedAggregation(args: {
35
35
  xAxis?: ChartXAxis | null;
36
36
  yAxis?: ChartYAxis;
37
37
  }): ChartTooltipTotalsBuiltInAggregation | (() => ChartTooltipTotalsAggregationValue);
38
+ export declare function getSortedHovered(args: {
39
+ hovered: TooltipDataChunk[];
40
+ sorting?: ChartTooltip['sorting'];
41
+ xAxis?: ChartXAxis | null;
42
+ yAxis?: ChartYAxis;
43
+ }): TooltipDataChunk[];
38
44
  export declare function getTooltipRowColorSymbol({ series, color, height, width, }: {
39
45
  color?: string;
40
46
  series?: TooltipDataChunk['series'];
@@ -130,6 +130,47 @@ export function getPreparedAggregation(args) {
130
130
  }
131
131
  return 'sum';
132
132
  }
133
+ export function getSortedHovered(args) {
134
+ var _a;
135
+ const { hovered, sorting, xAxis, yAxis } = args;
136
+ if (!sorting) {
137
+ return hovered;
138
+ }
139
+ if (typeof sorting === 'function') {
140
+ return [...hovered].sort(sorting);
141
+ }
142
+ switch (sorting.key) {
143
+ case 'value': {
144
+ const values = getHoveredValues({ hovered, xAxis, yAxis });
145
+ const direction = (_a = sorting.direction) !== null && _a !== void 0 ? _a : 'asc';
146
+ const compareValue = (a, b) => {
147
+ const aNil = a === null || a === undefined;
148
+ const bNil = b === null || b === undefined;
149
+ if (aNil && bNil) {
150
+ return 0;
151
+ }
152
+ if (aNil) {
153
+ return -1;
154
+ }
155
+ if (bNil) {
156
+ return 1;
157
+ }
158
+ if (typeof a === 'number' && typeof b === 'number') {
159
+ return a - b;
160
+ }
161
+ return String(a).localeCompare(String(b));
162
+ };
163
+ const indices = hovered.map((_, i) => i);
164
+ indices.sort((i, j) => direction === 'asc'
165
+ ? compareValue(values[i], values[j])
166
+ : compareValue(values[j], values[i]));
167
+ return indices.map((i) => hovered[i]);
168
+ }
169
+ default: {
170
+ return hovered;
171
+ }
172
+ }
173
+ }
133
174
  export function getTooltipRowColorSymbol({ series, color, height = 8, width = 16, }) {
134
175
  if ((series === null || series === void 0 ? void 0 : series.type) === 'line') {
135
176
  const colorSymbol = create('svg').attr('height', height).attr('width', width);
@@ -10,6 +10,8 @@ export const Tooltip = (props) => {
10
10
  const { hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition } = useTooltip({
11
11
  dispatcher,
12
12
  tooltip,
13
+ xAxis,
14
+ yAxis,
13
15
  });
14
16
  const containerRect = (svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) || { left: 0, top: 0 };
15
17
  const left = ((pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) || 0) + containerRect.left;
@@ -16,43 +16,7 @@ interface UseAxesProps {
16
16
  }
17
17
  export declare function getAxes(props: UseAxesProps): Promise<{
18
18
  xAxis: import("./types").PreparedXAxis | null;
19
- yAxis: (Omit<import("../..").ChartAxis, "type" | "labels" | "plotLines" | "plotBands"> & {
20
- type: import("../..").ChartAxisType;
21
- labels: Omit<import("../..").ChartAxisLabels, "style" | "enabled" | "padding" | "autoRotation"> & Required<Pick<import("../..").ChartAxisLabels, "margin" | "enabled" | "html" | "rotation" | "padding">> & {
22
- style: import("../..").BaseTextStyle;
23
- rotation: number;
24
- height: number;
25
- width: number;
26
- lineHeight: number;
27
- maxWidth: number;
28
- };
29
- title: {
30
- height: number;
31
- width: number;
32
- text: string;
33
- margin: number;
34
- style: import("../..").BaseTextStyle;
35
- align: import("../..").ChartAxisTitleAlignment;
36
- maxRowCount: number;
37
- rotation: number;
38
- maxWidth: number;
39
- html: boolean;
40
- };
41
- min?: number;
42
- grid: {
43
- enabled: boolean;
44
- };
45
- maxPadding: number;
46
- ticks: {
47
- pixelInterval?: number;
48
- };
49
- tickMarks: import("./types").PreparedAxisTickMarks;
50
- position: "left" | "right" | "top" | "bottom";
51
- plotIndex: number;
52
- plotLines: import("./types").PreparedAxisPlotLine[];
53
- plotBands: import("./types").PreparedAxisPlotBand[];
54
- crosshair: Required<import("../..").AxisCrosshair>;
55
- })[];
19
+ yAxis: import("./types").PreparedYAxis[];
56
20
  }>;
57
21
  export declare function useAxis(props: UseAxesProps): AxesState;
58
22
  export {};
@@ -1,5 +1,5 @@
1
1
  import type { DashStyle } from '../../constants';
2
- import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
2
+ import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
3
3
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation' | 'html'>> & {
4
4
  style: BaseTextStyle;
5
5
  rotation: number;
@@ -51,7 +51,7 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
51
51
  style: BaseTextStyle;
52
52
  align: ChartAxisTitleAlignment;
53
53
  maxRowCount: number;
54
- rotation: number;
54
+ rotation: ChartAxisTitleRotation;
55
55
  maxWidth: number;
56
56
  html: boolean;
57
57
  };
@@ -64,7 +64,6 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
64
64
  pixelInterval?: number;
65
65
  };
66
66
  tickMarks: PreparedAxisTickMarks;
67
- position: 'left' | 'right' | 'top' | 'bottom';
68
67
  plotIndex: number;
69
68
  plotLines: PreparedAxisPlotLine[];
70
69
  plotBands: PreparedAxisPlotBand[];
@@ -72,8 +71,11 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
72
71
  };
73
72
  export type PreparedXAxis = PreparedBaseAxis & {
74
73
  rangeSlider: PreparedRangeSlider;
74
+ position: 'bottom';
75
+ };
76
+ export type PreparedYAxis = PreparedBaseAxis & {
77
+ position: 'left' | 'right';
75
78
  };
76
- export type PreparedYAxis = PreparedBaseAxis;
77
79
  export type PreparedAxis = PreparedXAxis | PreparedYAxis;
78
80
  export type AxesState = {
79
81
  xAxis: PreparedXAxis | null;
@@ -1,4 +1,4 @@
1
- import type { PreparedAxis, PreparedSeries, PreparedSplit, RangeSliderState, ZoomState } from '../../hooks';
1
+ import type { PreparedAxis, PreparedSeries, PreparedSplit, PreparedYAxis, RangeSliderState, ZoomState } from '../../hooks';
2
2
  import type { ChartScale } from './types';
3
3
  export { createXScale } from './x-scale';
4
4
  export { createYScale } from './y-scale';
@@ -7,7 +7,7 @@ type Args = {
7
7
  boundsHeight: number;
8
8
  series: PreparedSeries[];
9
9
  xAxis: PreparedAxis | null;
10
- yAxis: PreparedAxis[];
10
+ yAxis: PreparedYAxis[];
11
11
  split: PreparedSplit;
12
12
  isRangeSlider?: boolean;
13
13
  rangeSliderState?: RangeSliderState;
@@ -1,6 +1,7 @@
1
1
  import React from 'react';
2
2
  import { line, select } from 'd3';
3
3
  import { getAxisPlotsPosition, getLineDashArray } from '../../utils';
4
+ import { getXValue, getYValue } from '../useShapes/utils';
4
5
  import { useCrosshairHover } from './useCrosshairHover';
5
6
  export const useCrosshair = (props) => {
6
7
  var _a, _b;
@@ -29,15 +30,18 @@ export const useCrosshair = (props) => {
29
30
  crosshairSelection
30
31
  .append('path')
31
32
  .attr('d', (hoveredElement) => {
32
- var _a, _b, _c;
33
33
  let lineValue = 0;
34
- if (xAxis.crosshair.snap) {
35
- const offset = ((_b = (_a = xAxisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(xAxisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
36
- if (typeof hoveredElement.data === 'object' && 'x' in hoveredElement.data) {
37
- lineValue = Number(xAxisScale((_c = hoveredElement.data.x) !== null && _c !== void 0 ? _c : 0)) + offset;
38
- }
34
+ if (xAxis.crosshair.snap &&
35
+ typeof hoveredElement.data === 'object' &&
36
+ 'x' in hoveredElement.data) {
37
+ const xVal = getXValue({
38
+ point: hoveredElement.data,
39
+ xAxis,
40
+ xScale: xAxisScale,
41
+ });
42
+ lineValue = xVal !== null && !Number.isNaN(xVal) ? xVal : lineValue;
39
43
  }
40
- else {
44
+ else if (!xAxis.crosshair.snap) {
41
45
  lineValue = pointerXPos - boundsOffsetLeft;
42
46
  }
43
47
  const points = [
@@ -89,16 +93,18 @@ export const useCrosshair = (props) => {
89
93
  crosshairSelection
90
94
  .append('path')
91
95
  .attr('d', (hoveredElement) => {
92
- var _a, _b, _c;
93
96
  let lineValue = 0;
94
- if (yAxis.crosshair.snap) {
95
- const offset = ((_b = (_a = yAxisScale.bandwidth) === null || _a === void 0 ? void 0 : _a.call(yAxisScale)) !== null && _b !== void 0 ? _b : 0) / 2;
96
- if (typeof hoveredElement.data === 'object' &&
97
- 'y' in hoveredElement.data) {
98
- lineValue = Number(yAxisScale((_c = hoveredElement.data.y) !== null && _c !== void 0 ? _c : 0)) + offset;
99
- }
97
+ if (yAxis.crosshair.snap &&
98
+ typeof hoveredElement.data === 'object' &&
99
+ 'y' in hoveredElement.data) {
100
+ const yVal = getYValue({
101
+ point: hoveredElement.data,
102
+ yAxis,
103
+ yScale: yAxisScale,
104
+ });
105
+ lineValue = yVal !== null && !Number.isNaN(yVal) ? yVal : lineValue;
100
106
  }
101
- else {
107
+ else if (!yAxis.crosshair.snap) {
102
108
  lineValue = pointerYPos - boundsOffsetTop;
103
109
  }
104
110
  const points = [
@@ -178,7 +178,7 @@ export const prepareBarXData = async (args) => {
178
178
  }
179
179
  if (series.some((s) => s.stacking === 'percent')) {
180
180
  let acc = 0;
181
- const ratio = plotHeight / (positiveStackHeight - stackItems.length);
181
+ const ratio = plotHeight / (positiveStackHeight - (stackItems.length - 1) * stackGap);
182
182
  stackItems.forEach((item) => {
183
183
  item.height = item.height * ratio;
184
184
  item.y = plotHeight - item.height - acc;
@@ -1,11 +1,14 @@
1
1
  import type { Dispatch } from 'd3';
2
2
  import type { AxisPlotBand, AxisPlotLine, PointPosition, TooltipDataChunk } from '../../types';
3
3
  import type { PreparedTooltip } from '../types';
4
+ import type { PreparedXAxis, PreparedYAxis } from '../useAxis/types';
4
5
  type Args = {
5
6
  dispatcher: Dispatch<object>;
6
7
  tooltip: PreparedTooltip;
8
+ xAxis?: PreparedXAxis | null;
9
+ yAxis?: PreparedYAxis;
7
10
  };
8
- export declare const useTooltip: ({ dispatcher, tooltip }: Args) => {
11
+ export declare const useTooltip: ({ dispatcher, tooltip, xAxis, yAxis }: Args) => {
9
12
  hovered: TooltipDataChunk[] | undefined;
10
13
  hoveredPlotLines: AxisPlotLine[] | undefined;
11
14
  hoveredPlotBands: AxisPlotBand[] | undefined;
@@ -1,21 +1,28 @@
1
1
  import React from 'react';
2
2
  import isEqual from 'lodash/isEqual';
3
- export const useTooltip = ({ dispatcher, tooltip }) => {
3
+ import { getSortedHovered } from '../../components/Tooltip/DefaultTooltipContent/utils';
4
+ export const useTooltip = ({ dispatcher, tooltip, xAxis, yAxis }) => {
4
5
  const [{ hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition }, setTooltipState] = React.useState({});
5
6
  const prevHovered = React.useRef(hovered);
6
7
  React.useEffect(() => {
7
8
  if (tooltip === null || tooltip === void 0 ? void 0 : tooltip.enabled) {
8
9
  dispatcher.on('hover-shape.tooltip', (nextHovered, nextPointerPosition, nextHoveredPlots) => {
9
10
  const filteredNextHovered = nextHovered === null || nextHovered === void 0 ? void 0 : nextHovered.filter((item) => 'y' in item.data ? item.data.y !== null : true);
10
- const isHoveredChanged = !isEqual(prevHovered.current, filteredNextHovered);
11
+ const sortedHovered = getSortedHovered({
12
+ hovered: filteredNextHovered !== null && filteredNextHovered !== void 0 ? filteredNextHovered : [],
13
+ sorting: tooltip === null || tooltip === void 0 ? void 0 : tooltip.sorting,
14
+ xAxis,
15
+ yAxis,
16
+ });
17
+ const isHoveredChanged = !isEqual(prevHovered.current, sortedHovered);
11
18
  const newTooltipState = {
12
- hovered: isHoveredChanged ? filteredNextHovered : prevHovered.current,
19
+ hovered: isHoveredChanged ? sortedHovered : prevHovered.current,
13
20
  hoveredPlotLines: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.lines,
14
21
  hoveredPlotBands: nextHoveredPlots === null || nextHoveredPlots === void 0 ? void 0 : nextHoveredPlots.bands,
15
22
  pointerPosition: nextPointerPosition,
16
23
  };
17
24
  if (isHoveredChanged) {
18
- prevHovered.current = filteredNextHovered;
25
+ prevHovered.current = sortedHovered;
19
26
  }
20
27
  setTooltipState(newTooltipState);
21
28
  });
@@ -25,7 +32,7 @@ export const useTooltip = ({ dispatcher, tooltip }) => {
25
32
  dispatcher.on('hover-shape.tooltip', null);
26
33
  }
27
34
  };
28
- }, [dispatcher, tooltip]);
35
+ }, [dispatcher, tooltip, xAxis, yAxis]);
29
36
  return {
30
37
  hovered,
31
38
  hoveredPlotLines,
@@ -6,6 +6,7 @@ import type { BaseTextStyle } from './base';
6
6
  import type { ChartBrush } from './brush';
7
7
  export type ChartAxisType = (typeof AXIS_TYPE)[keyof typeof AXIS_TYPE];
8
8
  export type ChartAxisTitleAlignment = 'left' | 'center' | 'right';
9
+ export type ChartAxisTitleRotation = 0 | 90 | -90;
9
10
  export interface ChartAxisLabels {
10
11
  /** Enable or disable the axis labels. */
11
12
  enabled?: boolean;
@@ -314,7 +315,7 @@ export interface ChartYAxisTitle extends ChartAxisTitle {
314
315
  *
315
316
  * The default values are -90 for the left axis and 90 for the right.
316
317
  */
317
- rotation?: 0 | 90 | -90;
318
+ rotation?: ChartAxisTitleRotation;
318
319
  /**
319
320
  * Interval of the tick marks(absolute or relative to the chart area).
320
321
  *
@@ -115,6 +115,7 @@ export type ChartTooltipRowRendererArgs = {
115
115
  hovered?: TooltipDataChunk<unknown>[];
116
116
  className?: string;
117
117
  };
118
+ export type ChartTooltipSortComparator<T = MeaningfulAny> = (a: TooltipDataChunk<T>, b: TooltipDataChunk<T>) => number;
118
119
  export interface ChartTooltip<T = MeaningfulAny> {
119
120
  enabled?: boolean;
120
121
  /** Specifies the renderer for the tooltip. If returned null default tooltip renderer will be used. */
@@ -158,4 +159,23 @@ export interface ChartTooltip<T = MeaningfulAny> {
158
159
  * It is assigned as a data-qa attribute to an element.
159
160
  */
160
161
  qa?: string;
162
+ /**
163
+ * Controls the order of tooltip rows. Applied to `hovered` before rendering.
164
+ * Use a custom comparator `(a, b) => number` for arbitrary ordering.
165
+ */
166
+ sorting?: {
167
+ /**
168
+ * Determines what data should be used to sort by.
169
+ * `'value'` uses the numeric value of each series point: `y` for most series
170
+ * (line, area, bar-x, scatter, waterfall), `x` for bar-y, and `value` for
171
+ * pie, radar, heatmap, treemap, funnel. `null` values are sorted as lowest.
172
+ * @default undefined (sorting disabled)
173
+ */
174
+ key?: 'value' | undefined;
175
+ /**
176
+ * Sorting direction.
177
+ * @default 'asc'
178
+ */
179
+ direction?: 'asc' | 'desc';
180
+ } | ChartTooltipSortComparator<T>;
161
181
  }
@@ -50,9 +50,9 @@ export function getZoomedSeriesData(args) {
50
50
  }
51
51
  const zoomedSeriesData = [];
52
52
  const zoomedShapesSeriesData = [];
53
- let prevPointInRange = false;
54
- let currentPointInRange = false;
55
53
  seriesData.forEach((seriesItem) => {
54
+ let prevPointInRange = false;
55
+ let currentPointInRange = false;
56
56
  const filteredData = [];
57
57
  const filteredShapesData = SERIES_TYPE_WITH_HIDDEN_POINTS.includes(seriesItem.type) && (xAxis === null || xAxis === void 0 ? void 0 : xAxis.type) !== 'category'
58
58
  ? []
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gravity-ui/charts",
3
- "version": "1.39.0",
3
+ "version": "1.40.0",
4
4
  "description": "A flexible JavaScript library for data visualization and chart rendering using React",
5
5
  "license": "MIT",
6
6
  "main": "dist/cjs/index.js",