@gravity-ui/charts 1.21.0 → 1.23.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 (133) hide show
  1. package/dist/cjs/components/ChartInner/index.js +7 -3
  2. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +16 -2
  3. package/dist/cjs/components/ChartInner/useChartInnerProps.js +2 -3
  4. package/dist/cjs/components/ChartInner/utils.d.ts +10 -1
  5. package/dist/cjs/components/ChartInner/utils.js +60 -0
  6. package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.d.ts +2 -2
  7. package/dist/cjs/constants/index.d.ts +1 -0
  8. package/dist/cjs/constants/index.js +1 -0
  9. package/dist/cjs/constants/zoom.d.ts +6 -0
  10. package/dist/cjs/constants/zoom.js +5 -0
  11. package/dist/cjs/hooks/useBrush/index.js +7 -6
  12. package/dist/cjs/hooks/useBrush/types.d.ts +3 -2
  13. package/dist/cjs/hooks/useChartOptions/chart.js +1 -77
  14. package/dist/cjs/hooks/useChartOptions/zoom.d.ts +11 -0
  15. package/dist/cjs/hooks/useChartOptions/zoom.js +88 -0
  16. package/dist/cjs/hooks/useSeries/prepare-area.js +15 -1
  17. package/dist/cjs/hooks/useSeries/prepare-bar-x.js +13 -1
  18. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +2 -2
  19. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +13 -1
  20. package/dist/cjs/hooks/useSeries/prepare-heatmap.js +13 -1
  21. package/dist/cjs/hooks/useSeries/prepare-legend.js +1 -1
  22. package/dist/cjs/hooks/useSeries/prepare-line.js +15 -1
  23. package/dist/cjs/hooks/useSeries/prepare-pie.js +15 -2
  24. package/dist/cjs/hooks/useSeries/prepare-scatter.js +16 -1
  25. package/dist/cjs/hooks/useSeries/prepare-waterfall.js +18 -2
  26. package/dist/cjs/hooks/useShapes/area/index.js +2 -0
  27. package/dist/cjs/hooks/useShapes/area/prepare-data.js +37 -22
  28. package/dist/cjs/hooks/useShapes/area/types.d.ts +5 -2
  29. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +8 -2
  30. package/dist/cjs/hooks/useShapes/bar-y/index.d.ts +1 -1
  31. package/dist/cjs/hooks/useShapes/bar-y/index.js +19 -22
  32. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +24 -5
  33. package/dist/cjs/hooks/useShapes/bar-y/types.d.ts +2 -2
  34. package/dist/cjs/hooks/useShapes/bar-y/utils.d.ts +3 -0
  35. package/dist/cjs/hooks/useShapes/bar-y/utils.js +44 -0
  36. package/dist/cjs/hooks/useShapes/heatmap/prepare-data.js +7 -3
  37. package/dist/cjs/hooks/useShapes/line/index.js +1 -0
  38. package/dist/cjs/hooks/useShapes/line/prepare-data.js +41 -16
  39. package/dist/cjs/hooks/useShapes/line/types.d.ts +7 -3
  40. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +8 -4
  41. package/dist/cjs/hooks/useShapes/scatter/prepare-data.js +1 -1
  42. package/dist/cjs/hooks/useShapes/utils.d.ts +14 -6
  43. package/dist/cjs/hooks/useShapes/utils.js +66 -18
  44. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +18 -8
  45. package/dist/cjs/hooks/useTooltip/index.js +8 -4
  46. package/dist/cjs/hooks/useZoom/index.js +2 -0
  47. package/dist/cjs/hooks/useZoom/utils.d.ts +3 -2
  48. package/dist/cjs/hooks/useZoom/utils.js +4 -3
  49. package/dist/cjs/hooks/utils/bar-y.d.ts +8 -1
  50. package/dist/cjs/hooks/utils/bar-y.js +4 -0
  51. package/dist/cjs/i18n/keysets/en.json +2 -2
  52. package/dist/cjs/i18n/keysets/ru.json +2 -2
  53. package/dist/cjs/types/chart/area.d.ts +11 -1
  54. package/dist/cjs/types/chart/bar-x.d.ts +10 -1
  55. package/dist/cjs/types/chart/bar-y.d.ts +10 -1
  56. package/dist/cjs/types/chart/heatmap.d.ts +10 -1
  57. package/dist/cjs/types/chart/line.d.ts +11 -1
  58. package/dist/cjs/types/chart/pie.d.ts +10 -1
  59. package/dist/cjs/types/chart/scatter.d.ts +11 -2
  60. package/dist/cjs/types/chart/waterfall.d.ts +10 -1
  61. package/dist/cjs/types/chart/zoom.d.ts +31 -1
  62. package/dist/cjs/utils/chart/get-closest-data.js +12 -7
  63. package/dist/cjs/utils/chart/series/sorting.js +17 -4
  64. package/dist/cjs/utils/chart/text.js +24 -21
  65. package/dist/cjs/utils/chart/zoom.js +4 -2
  66. package/dist/cjs/validation/index.js +3 -3
  67. package/dist/esm/components/ChartInner/index.js +7 -3
  68. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +16 -2
  69. package/dist/esm/components/ChartInner/useChartInnerProps.js +2 -3
  70. package/dist/esm/components/ChartInner/utils.d.ts +10 -1
  71. package/dist/esm/components/ChartInner/utils.js +60 -0
  72. package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.d.ts +2 -2
  73. package/dist/esm/constants/index.d.ts +1 -0
  74. package/dist/esm/constants/index.js +1 -0
  75. package/dist/esm/constants/zoom.d.ts +6 -0
  76. package/dist/esm/constants/zoom.js +5 -0
  77. package/dist/esm/hooks/useBrush/index.js +7 -6
  78. package/dist/esm/hooks/useBrush/types.d.ts +3 -2
  79. package/dist/esm/hooks/useChartOptions/chart.js +1 -77
  80. package/dist/esm/hooks/useChartOptions/zoom.d.ts +11 -0
  81. package/dist/esm/hooks/useChartOptions/zoom.js +88 -0
  82. package/dist/esm/hooks/useSeries/prepare-area.js +15 -1
  83. package/dist/esm/hooks/useSeries/prepare-bar-x.js +13 -1
  84. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +2 -2
  85. package/dist/esm/hooks/useSeries/prepare-bar-y.js +13 -1
  86. package/dist/esm/hooks/useSeries/prepare-heatmap.js +13 -1
  87. package/dist/esm/hooks/useSeries/prepare-legend.js +1 -1
  88. package/dist/esm/hooks/useSeries/prepare-line.js +15 -1
  89. package/dist/esm/hooks/useSeries/prepare-pie.js +15 -2
  90. package/dist/esm/hooks/useSeries/prepare-scatter.js +16 -1
  91. package/dist/esm/hooks/useSeries/prepare-waterfall.js +18 -2
  92. package/dist/esm/hooks/useShapes/area/index.js +2 -0
  93. package/dist/esm/hooks/useShapes/area/prepare-data.js +37 -22
  94. package/dist/esm/hooks/useShapes/area/types.d.ts +5 -2
  95. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +8 -2
  96. package/dist/esm/hooks/useShapes/bar-y/index.d.ts +1 -1
  97. package/dist/esm/hooks/useShapes/bar-y/index.js +19 -22
  98. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +24 -5
  99. package/dist/esm/hooks/useShapes/bar-y/types.d.ts +2 -2
  100. package/dist/esm/hooks/useShapes/bar-y/utils.d.ts +3 -0
  101. package/dist/esm/hooks/useShapes/bar-y/utils.js +44 -0
  102. package/dist/esm/hooks/useShapes/heatmap/prepare-data.js +7 -3
  103. package/dist/esm/hooks/useShapes/line/index.js +1 -0
  104. package/dist/esm/hooks/useShapes/line/prepare-data.js +41 -16
  105. package/dist/esm/hooks/useShapes/line/types.d.ts +7 -3
  106. package/dist/esm/hooks/useShapes/pie/prepare-data.js +8 -4
  107. package/dist/esm/hooks/useShapes/scatter/prepare-data.js +1 -1
  108. package/dist/esm/hooks/useShapes/utils.d.ts +14 -6
  109. package/dist/esm/hooks/useShapes/utils.js +66 -18
  110. package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +18 -8
  111. package/dist/esm/hooks/useTooltip/index.js +8 -4
  112. package/dist/esm/hooks/useZoom/index.js +2 -0
  113. package/dist/esm/hooks/useZoom/utils.d.ts +3 -2
  114. package/dist/esm/hooks/useZoom/utils.js +4 -3
  115. package/dist/esm/hooks/utils/bar-y.d.ts +8 -1
  116. package/dist/esm/hooks/utils/bar-y.js +4 -0
  117. package/dist/esm/i18n/keysets/en.json +2 -2
  118. package/dist/esm/i18n/keysets/ru.json +2 -2
  119. package/dist/esm/types/chart/area.d.ts +11 -1
  120. package/dist/esm/types/chart/bar-x.d.ts +10 -1
  121. package/dist/esm/types/chart/bar-y.d.ts +10 -1
  122. package/dist/esm/types/chart/heatmap.d.ts +10 -1
  123. package/dist/esm/types/chart/line.d.ts +11 -1
  124. package/dist/esm/types/chart/pie.d.ts +10 -1
  125. package/dist/esm/types/chart/scatter.d.ts +11 -2
  126. package/dist/esm/types/chart/waterfall.d.ts +10 -1
  127. package/dist/esm/types/chart/zoom.d.ts +31 -1
  128. package/dist/esm/utils/chart/get-closest-data.js +12 -7
  129. package/dist/esm/utils/chart/series/sorting.js +17 -4
  130. package/dist/esm/utils/chart/text.js +24 -21
  131. package/dist/esm/utils/chart/zoom.js +4 -2
  132. package/dist/esm/validation/index.js +3 -3
  133. package/package.json +1 -1
@@ -55,15 +55,18 @@ export function preparePieData(args) {
55
55
  },
56
56
  };
57
57
  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;
58
- const segments = items.map((item) => {
58
+ const segments = items.reduce((acc, item) => {
59
59
  var _a;
60
+ if (item.value === null) {
61
+ return acc;
62
+ }
60
63
  let maxSegmentRadius = maxRadius;
61
64
  if (dataLabels.enabled) {
62
65
  maxSegmentRadius -=
63
66
  dataLabels.distance + dataLabels.connectorPadding + labelMaxHeight;
64
67
  }
65
68
  const segmentRadius = (_a = calculateNumericProperty({ value: item.radius, base: maxSegmentRadius })) !== null && _a !== void 0 ? _a : maxSegmentRadius;
66
- return {
69
+ acc.push({
67
70
  value: item.value,
68
71
  color: item.color,
69
72
  opacity: item.opacity,
@@ -72,8 +75,9 @@ export function preparePieData(args) {
72
75
  active: true,
73
76
  pie: data,
74
77
  radius: segmentRadius,
75
- };
76
- });
78
+ });
79
+ return acc;
80
+ }, []);
77
81
  data.segments = pieGenerator(segments);
78
82
  return data;
79
83
  };
@@ -54,7 +54,7 @@ export function prepareScatterData(args) {
54
54
  var _a;
55
55
  const x = getXValue({ point: d, xAxis, xScale });
56
56
  const y = getYValue({ point: d, yAxis: seriesYAxis, yScale: seriesYScale });
57
- if (typeof x === 'undefined' || typeof y === 'undefined') {
57
+ if (typeof x === 'undefined' || typeof y === 'undefined' || x === null || y === null) {
58
58
  return;
59
59
  }
60
60
  acc.push({
@@ -4,24 +4,24 @@ import type { ChartScale } from '../useAxisScales';
4
4
  import type { PreparedAxis } from '../useChartOptions/types';
5
5
  export declare function getXValue(args: {
6
6
  point: {
7
- x?: number | string;
7
+ x?: number | string | null;
8
8
  };
9
9
  points?: {
10
- x?: number | string;
10
+ x?: number | string | null;
11
11
  }[];
12
12
  xAxis: PreparedAxis;
13
13
  xScale: ChartScale;
14
- }): number;
14
+ }): number | null;
15
15
  export declare function getYValue(args: {
16
16
  point: {
17
- y?: number | string;
17
+ y?: number | string | null;
18
18
  };
19
19
  points?: {
20
- y?: number | string;
20
+ y?: number | string | null;
21
21
  }[];
22
22
  yAxis: PreparedAxis;
23
23
  yScale: ChartScale;
24
- }): number;
24
+ }): number | null;
25
25
  export declare function shapeKey(d: unknown): string | -1;
26
26
  export declare function setActiveState<T extends {
27
27
  active?: boolean;
@@ -38,3 +38,11 @@ export declare function getRectPath(args: {
38
38
  height: number;
39
39
  borderRadius?: number | number[];
40
40
  }): import("d3-path").Path;
41
+ export declare function getRectBorderPath(args: {
42
+ x: number;
43
+ y: number;
44
+ width: number;
45
+ height: number;
46
+ borderWidth: number;
47
+ borderRadius?: number | number[];
48
+ }): string;
@@ -14,16 +14,18 @@ export function getXValue(args) {
14
14
  const [xMinDomain, xMaxDomain] = xLinearScale.domain();
15
15
  if (Number(xMinDomain) === Number(xMaxDomain) &&
16
16
  (points === null || points === void 0 ? void 0 : points.length) === ONE_POINT_DOMAIN_DATA_CAPACITY) {
17
- const x1 = points[0].x;
18
- const xTarget = points[1].x;
19
- const x3 = points[2].x;
20
- const xMin = Math.min(x1, xTarget, x3);
21
- const xMax = Math.max(x1, xTarget, x3);
22
- xLinearScale = xLinearScale
23
- .copy()
24
- .domain([xMin + (xTarget - xMin) / 2, xMax - (xMax - xTarget) / 2]);
17
+ const x1 = Number(points[0].x);
18
+ const xTarget = Number(points[1].x);
19
+ const x3 = Number(points[2].x);
20
+ if (!Number.isNaN(x1) && !Number.isNaN(xTarget) && !Number.isNaN(x3)) {
21
+ const xMin = Math.min(x1, xTarget, x3);
22
+ const xMax = Math.max(x1, xTarget, x3);
23
+ xLinearScale = xLinearScale
24
+ .copy()
25
+ .domain([xMin + (xTarget - xMin) / 2, xMax - (xMax - xTarget) / 2]);
26
+ }
25
27
  }
26
- return xLinearScale(point.x);
28
+ return point.x === null ? null : xLinearScale(point.x);
27
29
  }
28
30
  export function getYValue(args) {
29
31
  const { point, points, yAxis, yScale } = args;
@@ -37,16 +39,18 @@ export function getYValue(args) {
37
39
  const [yMinDomain, yMaxDomain] = yLinearScale.domain();
38
40
  if (Number(yMinDomain) === Number(yMaxDomain) &&
39
41
  (points === null || points === void 0 ? void 0 : points.length) === ONE_POINT_DOMAIN_DATA_CAPACITY) {
40
- const y1 = points[0].y;
41
- const yTarget = points[1].y;
42
- const y2 = points[2].y;
43
- const yMin = Math.min(y1, yTarget, y2);
44
- const yMax = Math.max(y1, yTarget, y2);
45
- yLinearScale = yLinearScale
46
- .copy()
47
- .domain([yMin + (yTarget - yMin) / 2, yMax - (yMax - yTarget) / 2]);
42
+ const y1 = Number(points[0].y);
43
+ const yTarget = Number(points[1].y);
44
+ const y2 = Number(points[2].y);
45
+ if (!Number.isNaN(y1) && !Number.isNaN(yTarget) && !Number.isNaN(y2)) {
46
+ const yMin = Math.min(y1, yTarget, y2);
47
+ const yMax = Math.max(y1, yTarget, y2);
48
+ yLinearScale = yLinearScale
49
+ .copy()
50
+ .domain([yMin + (yTarget - yMin) / 2, yMax - (yMax - yTarget) / 2]);
51
+ }
48
52
  }
49
- return yLinearScale(point.y);
53
+ return point.y === null ? null : yLinearScale(point.y);
50
54
  }
51
55
  export function shapeKey(d) {
52
56
  return d.id || -1;
@@ -83,3 +87,47 @@ export function getRectPath(args) {
83
87
  p.closePath();
84
88
  return p;
85
89
  }
90
+ export function getRectBorderPath(args) {
91
+ const { x, y, width, height, borderWidth, borderRadius = 0 } = args;
92
+ if (!borderWidth) {
93
+ return '';
94
+ }
95
+ const halfWidth = borderWidth / 2;
96
+ const expandedWidth = width + borderWidth;
97
+ const expandedHeight = height + borderWidth;
98
+ const innerWidth = width - borderWidth;
99
+ const innerHeight = height - borderWidth;
100
+ const borderRadiuses = typeof borderRadius === 'number' ? new Array(4).fill(borderRadius) : borderRadius;
101
+ const [borderRadiusTopLeft = 0, borderRadiusTopRight = 0, borderRadiusBottomRight = 0, borderRadiusBottomLeft = 0,] = borderRadiuses !== null && borderRadiuses !== void 0 ? borderRadiuses : [];
102
+ const adjustOuterRadius = (radius) => (radius ? radius + halfWidth : 0);
103
+ const outerBorderRadius = [
104
+ adjustOuterRadius(borderRadiusTopLeft),
105
+ adjustOuterRadius(borderRadiusTopRight),
106
+ adjustOuterRadius(borderRadiusBottomRight),
107
+ adjustOuterRadius(borderRadiusBottomLeft),
108
+ ];
109
+ const outerPath = getRectPath({
110
+ x: x - halfWidth,
111
+ y: y - halfWidth,
112
+ width: expandedWidth,
113
+ height: expandedHeight,
114
+ borderRadius: outerBorderRadius,
115
+ }).toString();
116
+ if (innerWidth <= 0 || innerHeight <= 0) {
117
+ return outerPath;
118
+ }
119
+ const innerBorderRadius = [
120
+ Math.max(borderRadiusTopLeft - halfWidth, 0),
121
+ Math.max(borderRadiusTopRight - halfWidth, 0),
122
+ Math.max(borderRadiusBottomRight - halfWidth, 0),
123
+ Math.max(borderRadiusBottomLeft - halfWidth, 0),
124
+ ];
125
+ const innerPath = getRectPath({
126
+ x: x + halfWidth,
127
+ y: y + halfWidth,
128
+ width: innerWidth,
129
+ height: innerHeight,
130
+ borderRadius: innerBorderRadius,
131
+ }).toString();
132
+ return `${outerPath} ${innerPath}`;
133
+ }
@@ -53,6 +53,7 @@ function getBandWidth(args) {
53
53
  return bandWidth;
54
54
  }
55
55
  export const prepareWaterfallData = async (args) => {
56
+ var _a;
56
57
  const { series, seriesOptions, xAxis, xScale, yAxis: [yAxis], yScale: [yScale], } = args;
57
58
  const yLinearScale = yScale;
58
59
  if (!yLinearScale) {
@@ -73,11 +74,11 @@ export const prepareWaterfallData = async (args) => {
73
74
  });
74
75
  const rectGap = Math.max(bandWidth * barPadding, MIN_BAR_GAP);
75
76
  const rectWidth = Math.max(MIN_BAR_WIDTH, Math.min(bandWidth - rectGap, barMaxWidth));
76
- const yZero = getYValue({
77
+ const yZero = (_a = getYValue({
77
78
  point: { y: 0 },
78
79
  yScale: yLinearScale,
79
80
  yAxis,
80
- });
81
+ })) !== null && _a !== void 0 ? _a : 0;
81
82
  let totalValue = 0;
82
83
  const result = [];
83
84
  for (let i = 0; i < data.length; i++) {
@@ -90,14 +91,20 @@ export const prepareWaterfallData = async (args) => {
90
91
  }
91
92
  const prevPoint = result[result.length - 1];
92
93
  const xCenter = getXValue({ point: item.data, xAxis, xScale });
94
+ if (xCenter === null) {
95
+ continue;
96
+ }
93
97
  const x = xCenter - rectWidth / 2;
94
98
  const yValue = Number(item.data.total ? totalValue : item.data.y);
95
- const height = yZero -
96
- getYValue({
97
- point: { y: Math.abs(yValue) },
98
- yScale: yLinearScale,
99
- yAxis,
100
- });
99
+ const calculatedYValue = getYValue({
100
+ point: { y: Math.abs(yValue) },
101
+ yScale: yLinearScale,
102
+ yAxis,
103
+ });
104
+ if (calculatedYValue === null) {
105
+ continue;
106
+ }
107
+ const height = yZero - calculatedYValue;
101
108
  let y;
102
109
  if (!prevPoint || item.data.total) {
103
110
  y = getYValue({
@@ -122,6 +129,9 @@ export const prepareWaterfallData = async (args) => {
122
129
  else {
123
130
  y = prevPoint.y - height;
124
131
  }
132
+ if (y === null) {
133
+ continue;
134
+ }
125
135
  const preparedData = {
126
136
  x,
127
137
  y,
@@ -6,13 +6,14 @@ export const useTooltip = ({ dispatcher, tooltip }) => {
6
6
  React.useEffect(() => {
7
7
  if (tooltip === null || tooltip === void 0 ? void 0 : tooltip.enabled) {
8
8
  dispatcher.on('hover-shape.tooltip', (nextHovered, nextPointerPosition) => {
9
- const isHoveredChanged = !isEqual(prevHovered.current, nextHovered);
9
+ 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);
10
11
  const newTooltipState = {
11
12
  pointerPosition: nextPointerPosition,
12
- hovered: isHoveredChanged ? nextHovered : prevHovered.current,
13
+ hovered: isHoveredChanged ? filteredNextHovered : prevHovered.current,
13
14
  };
14
15
  if (isHoveredChanged) {
15
- prevHovered.current = nextHovered;
16
+ prevHovered.current = filteredNextHovered;
16
17
  }
17
18
  setTooltipState(newTooltipState);
18
19
  });
@@ -23,5 +24,8 @@ export const useTooltip = ({ dispatcher, tooltip }) => {
23
24
  }
24
25
  };
25
26
  }, [dispatcher, tooltip]);
26
- return { hovered, pointerPosition };
27
+ return {
28
+ hovered,
29
+ pointerPosition,
30
+ };
27
31
  };
@@ -4,6 +4,7 @@ import { useBrush } from '../useBrush';
4
4
  import { selectionToZoomBounds } from './utils';
5
5
  export function useZoom(props) {
6
6
  const { node, onUpdate, plotContainerHeight, plotContainerWidth, preparedSplit, preparedZoom, xAxis, xScale, yAxis, yScale, } = props;
7
+ const isBrushDisabled = Boolean(!xAxis || !yAxis || !xScale || !yScale);
7
8
  const areas = React.useMemo(() => {
8
9
  const result = [];
9
10
  if (!preparedZoom) {
@@ -47,6 +48,7 @@ export function useZoom(props) {
47
48
  useBrush({
48
49
  areas,
49
50
  brushOptions: preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.brush,
51
+ disabled: isBrushDisabled,
50
52
  node,
51
53
  type: preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.type,
52
54
  onBrushEnd: handleChartBrushEnd,
@@ -1,6 +1,7 @@
1
1
  import type { BrushSelection } from 'd3';
2
+ import type { ZoomType } from '../../constants';
2
3
  import type { ChartScale } from '../useAxisScales';
3
- import type { PreparedAxis, PreparedZoom } from '../useChartOptions/types';
4
+ import type { PreparedAxis } from '../useChartOptions/types';
4
5
  import type { ZoomState } from './types';
5
6
  export declare function selectionToZoomBounds(args: {
6
7
  selection: BrushSelection;
@@ -8,5 +9,5 @@ export declare function selectionToZoomBounds(args: {
8
9
  xScale: ChartScale;
9
10
  yAxes: PreparedAxis[];
10
11
  yScales: (ChartScale | undefined)[];
11
- zoomType: PreparedZoom['type'];
12
+ zoomType: ZoomType;
12
13
  }): Partial<ZoomState>;
@@ -1,13 +1,14 @@
1
+ import { ZOOM_TYPE } from '../../constants';
1
2
  export function selectionToZoomBounds(args) {
2
3
  const { selection, xAxis, xScale, yAxes, yScales, zoomType } = args;
3
4
  const zoomState = {};
4
5
  switch (zoomType) {
5
- case 'x': {
6
+ case ZOOM_TYPE.X: {
6
7
  const [x0, x1] = selection;
7
8
  zoomState.x = selectionXToZoomBounds({ xAxis, xScale, selection: [x0, x1] });
8
9
  break;
9
10
  }
10
- case 'y': {
11
+ case ZOOM_TYPE.Y: {
11
12
  const [y1, y0] = selection;
12
13
  yAxes.forEach((yAxis, index) => {
13
14
  if (!Array.isArray(zoomState.y)) {
@@ -27,7 +28,7 @@ export function selectionToZoomBounds(args) {
27
28
  });
28
29
  break;
29
30
  }
30
- case 'xy': {
31
+ case ZOOM_TYPE.XY: {
31
32
  const [x0, y0] = selection[0];
32
33
  const [x1, y1] = selection[1];
33
34
  zoomState.x = selectionXToZoomBounds({ xAxis, xScale, selection: [x0, x1] });
@@ -2,8 +2,14 @@ import type { BarYSeries, BarYSeriesData } from '../../types';
2
2
  import type { ChartScale } from '../useAxisScales';
3
3
  import type { PreparedAxis } from '../useChartOptions/types';
4
4
  import type { PreparedBarYSeries, PreparedSeriesOptions } from '../useSeries/types';
5
+ /**
6
+ * BarY always filters out data with null or replace null by zero.
7
+ */
8
+ type PreparedBarYSeriesData = BarYSeriesData & {
9
+ x?: number | string;
10
+ };
5
11
  export declare function groupBarYDataByYValue<T extends BarYSeries | PreparedBarYSeries>(series: T[], yAxis: PreparedAxis[]): Record<string | number, Record<string, {
6
- data: BarYSeriesData;
12
+ data: PreparedBarYSeriesData;
7
13
  series: T;
8
14
  }[]>>;
9
15
  export declare function getBarYLayout(args: {
@@ -16,3 +22,4 @@ export declare function getBarYLayout(args: {
16
22
  barGap: number;
17
23
  barSize: number;
18
24
  };
25
+ export {};
@@ -4,10 +4,14 @@ import { getDataCategoryValue } from '../../utils';
4
4
  import { MIN_BAR_GAP, MIN_BAR_GROUP_GAP, MIN_BAR_WIDTH } from '../constants';
5
5
  import { getSeriesStackId } from '../useSeries/utils';
6
6
  import { getBandSize } from './get-band-size';
7
+ const isSeriesDataValid = (d) => d.x !== null;
7
8
  export function groupBarYDataByYValue(series, yAxis) {
8
9
  const data = {};
9
10
  series.forEach((s) => {
10
11
  s.data.forEach((d) => {
12
+ if (!isSeriesDataValid(d)) {
13
+ return;
14
+ }
11
15
  const axisIndex = get(s, 'yAxis', 0);
12
16
  const seriesYAxis = yAxis[axisIndex];
13
17
  const categories = get(seriesYAxis, 'categories', []);
@@ -4,9 +4,9 @@
4
4
  "label_unknown-plugin": "Unknown plugin type \"{{type}}\"",
5
5
  "label_unknown-error": "Unknown error",
6
6
  "label_invalid-axis-category-data-point": "It seems you are trying to use inappropriate data type for \"{{key}}\" value in series \"{{seriesName}}\" for axis with type \"category\". Strings and numbers are allowed.",
7
- "label_invalid-axis-datetime-data-point": "It seems you are trying to use inappropriate data type for \"{{key}}\" value in series \"{{seriesName}}\" for axis with type \"datetime\". Only numbers are allowed.",
7
+ "label_invalid-axis-datetime-data-point": "It seems you are trying to use inappropriate data type for \"{{key}}\" value in series \"{{seriesName}}\" for axis with type \"datetime\". Numbers are allowed.",
8
8
  "label_invalid-axis-linear-data-point": "It seems you are trying to use inappropriate data type for \"{{key}}\" value in series \"{{seriesName}}\" for axis with type \"linear\". Numbers and nulls are allowed.",
9
- "label_invalid-pie-data-value": "It seems you are trying to use inappropriate data type for \"value\" value. Only numbers are allowed.",
9
+ "label_invalid-pie-data-value": "It seems you are trying to use inappropriate data type for \"value\" value. Only numbers or nulls are allowed.",
10
10
  "label_invalid-series-type": "It seems you haven't defined \"series.type\" property, or defined it incorrectly. Available values: [{{types}}].",
11
11
  "label_invalid-series-property": "It seems you are trying to use inappropriate value for \"{{key}}\", or defined it incorrectly. Available values: [{{values}}].",
12
12
  "label_invalid-treemap-redundant-value": "It seems you are trying to set \"value\" for container node. Check node with this properties: { id: \"{{id}}\", name: \"{{name}}\" }",
@@ -4,9 +4,9 @@
4
4
  "label_unknown-plugin": "Неизвестный тип плагина \"{{type}}\"",
5
5
  "label_unknown-error": "Неизвестная ошибка",
6
6
  "label_invalid-axis-category-data-point": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"{{key}}\" в серии \"{{seriesName}}\" для оси с типом \"category\". Допускается использование строк и чисел.",
7
- "label_invalid-axis-datetime-data-point": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"{{key}}\" в серии \"{{seriesName}}\" для оси с типом \"datetime\". Допускается только использование чисел.",
7
+ "label_invalid-axis-datetime-data-point": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"{{key}}\" в серии \"{{seriesName}}\" для оси с типом \"datetime\". Допускается использование чисел.",
8
8
  "label_invalid-axis-linear-data-point": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"{{key}}\" в серии \"{{seriesName}}\" для оси с типом \"linear\". Допускается использование чисел и значений null.",
9
- "label_invalid-pie-data-value": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"value\". Допускается только использование чисел.",
9
+ "label_invalid-pie-data-value": "Похоже, что вы пытаетесь использовать недопустимый тип данных для значения \"value\". Допускается только использование чисел или null.",
10
10
  "label_invalid-series-type": "Похоже, что вы не указали значение \"series.type\" или указали его неверно. Доступные значения: [{{types}}].",
11
11
  "label_invalid-series-property": "Похоже, что вы пытаетесь использовать недопустимое значение для \"{{key}}\", или указали его неверно. Доступные значения: [{{values}}].",
12
12
  "label_invalid-treemap-redundant-value": "Похоже, что вы пытаетесь установить значение \"value\" для узла, используемого в качестве контейнера. Проверьте узел с этими свойствами: { id: \"{{id}}\", name: \"{{name}}\" }",
@@ -17,7 +17,7 @@ export interface AreaSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
17
17
  * - timestamp value (for `datetime` y axis)
18
18
  * - 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`
19
19
  */
20
- y?: string | number;
20
+ y?: string | number | null;
21
21
  /** Data label value of the point. If not specified, the y value is used. */
22
22
  label?: string | number;
23
23
  /** Individual marker options for the point. */
@@ -73,4 +73,14 @@ export interface AreaSeries<T = MeaningfulAny> extends BaseSeries {
73
73
  marker?: AreaMarkerOptions;
74
74
  /** Y-axis index (when using two axes) */
75
75
  yAxis?: number;
76
+ /**
77
+ * Specifies how null or undefined values should be handled in the series.
78
+ *
79
+ * - `'connect'`: Connect points across null values (skip nulls in rendering)
80
+ * - `'zero'`: Treat null values as zero
81
+ * - `'skip'`: Omit the data point (creates gap in area)
82
+ *
83
+ * @default 'skip'
84
+ */
85
+ nullMode?: 'connect' | 'zero' | 'skip';
76
86
  }
@@ -17,7 +17,7 @@ export interface BarXSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
17
17
  * - timestamp value (for `datetime` y axis)
18
18
  * - 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`
19
19
  */
20
- y?: string | number;
20
+ y?: string | number | null;
21
21
  /**
22
22
  * Corresponding value of axis category.
23
23
  *
@@ -69,4 +69,13 @@ export interface BarXSeries<T = MeaningfulAny> extends BaseSeries {
69
69
  };
70
70
  /** Y-axis index (when using two axes) */
71
71
  yAxis?: number;
72
+ /**
73
+ * Specifies how null or undefined values should be handled in the series.
74
+ *
75
+ * - `'skip'`: Omit data points with null values (no bar shown)
76
+ * - `'zero'`: Treat null values as zero
77
+ *
78
+ * @default 'skip'
79
+ */
80
+ nullMode?: 'zero' | 'skip';
72
81
  }
@@ -9,7 +9,7 @@ export interface BarYSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
9
9
  * - timestamp value (for `datetime` x axis)
10
10
  * - 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`
11
11
  */
12
- x?: string | number;
12
+ x?: string | number | null;
13
13
  /**
14
14
  * The `y` value of the bar. Depending on the context , it may represents:
15
15
  * - numeric value (for `linear` y axis)
@@ -71,4 +71,13 @@ export interface BarYSeries<T = MeaningfulAny> extends BaseSeries {
71
71
  legend?: ChartLegend & {
72
72
  symbol?: RectLegendSymbolOptions;
73
73
  };
74
+ /**
75
+ * Specifies how null or undefined values should be handled in the series.
76
+ *
77
+ * - `'skip'`: Omit data points with null values (no bar shown)
78
+ * - `'zero'`: Treat null values as zero
79
+ *
80
+ * @default 'skip'
81
+ */
82
+ nullMode?: 'zero' | 'skip';
74
83
  }
@@ -18,7 +18,7 @@ export interface HeatmapSeriesData<T = MeaningfulAny> extends BaseSeriesData<T>
18
18
  */
19
19
  y?: string | number;
20
20
  /** Value of the heatmap cell */
21
- value?: number;
21
+ value?: number | null;
22
22
  /** Data label value of the heatmap cell. If not specified, the value is used. */
23
23
  label?: string;
24
24
  }
@@ -44,4 +44,13 @@ export interface HeatmapSeries<T = MeaningfulAny> extends BaseSeries {
44
44
  * The color of the border surrounding each cell.
45
45
  */
46
46
  borderColor?: string;
47
+ /**
48
+ * Specifies how null or undefined values should be handled in the series.
49
+ *
50
+ * - `'zero'`: Treat null values as zero
51
+ * - `'skip'`: Omit data points with null values (show gaps)
52
+ *
53
+ * @default 'skip'
54
+ */
55
+ nullMode?: 'zero' | 'skip';
47
56
  }
@@ -17,7 +17,7 @@ export interface LineSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
17
17
  * - timestamp value (for `datetime` y axis)
18
18
  * - 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`
19
19
  */
20
- y?: string | number;
20
+ y?: string | number | null;
21
21
  /** Data label value of the point. If not specified, the y value is used. */
22
22
  label?: string | number;
23
23
  marker?: {
@@ -54,4 +54,14 @@ export interface LineSeries<T = MeaningfulAny> extends BaseSeries {
54
54
  opacity?: number;
55
55
  /** Y-axis index (when using two axes) */
56
56
  yAxis?: number;
57
+ /**
58
+ * Specifies how null or undefined values should be handled in the series.
59
+ *
60
+ * - `'connect'`: Connect points across null values (skip nulls in rendering)
61
+ * - `'zero'`: Treat null values as zero
62
+ * - `'skip'`: Omit the data point (creates gap in line)
63
+ *
64
+ * @default 'skip'
65
+ */
66
+ nullMode?: 'connect' | 'zero' | 'skip';
57
67
  }
@@ -5,7 +5,7 @@ import type { BaseSeries, BaseSeriesData } from './base';
5
5
  import type { ChartLegend, RectLegendSymbolOptions } from './legend';
6
6
  export interface PieSeriesData<T = MeaningfulAny> extends BaseSeriesData<T> {
7
7
  /** The value of the pie segment. */
8
- value: number;
8
+ value: number | null;
9
9
  /** The name of the pie segment (used in legend, tooltip etc). */
10
10
  name: string;
11
11
  /** Initial visibility of the pie segment. */
@@ -95,4 +95,13 @@ export interface PieSeries<T = MeaningfulAny> extends BaseSeries {
95
95
  innerRadius: number;
96
96
  };
97
97
  }) => BaseType | Promise<BaseType>;
98
+ /**
99
+ * Specifies how null or undefined values should be handled in the series.
100
+ *
101
+ * - `'zero'`: Treat null values as zero
102
+ * - `'skip'`: Omit segments with null values (don't render them)
103
+ *
104
+ * @default 'skip'
105
+ */
106
+ nullMode?: 'zero' | 'skip';
98
107
  }
@@ -9,14 +9,14 @@ export interface ScatterSeriesData<T = MeaningfulAny> extends BaseSeriesData<T>
9
9
  * - timestamp value (for `datetime` x axis)
10
10
  * - 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`
11
11
  */
12
- x?: string | number;
12
+ x?: string | number | null;
13
13
  /**
14
14
  * The `y` value of the point. Depending on the context , it may represents:
15
15
  * - numeric value (for `linear` y axis)
16
16
  * - timestamp value (for `datetime` y axis)
17
17
  * - 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`
18
18
  */
19
- y?: string | number;
19
+ y?: string | number | null;
20
20
  /**
21
21
  * Corresponding value of axis category.
22
22
  *
@@ -43,4 +43,13 @@ export interface ScatterSeries<T = MeaningfulAny> extends BaseSeries {
43
43
  };
44
44
  /** Y-axis index (when using two axes) */
45
45
  yAxis?: number;
46
+ /**
47
+ * Defines how to handle null values in the data.
48
+ *
49
+ * - `'zero'`: Treat null values as zero
50
+ * - `'skip'`: Omit data points with null values (don't render them)
51
+ *
52
+ * @default 'skip'
53
+ */
54
+ nullMode?: 'zero' | 'skip';
46
55
  }
@@ -14,7 +14,7 @@ export interface WaterfallSeriesData<T = MeaningfulAny> extends BaseSeriesData<T
14
14
  * The `y` value. Depending on the context , it may represents:
15
15
  * - numeric value (for `linear` y axis)
16
16
  */
17
- y?: number;
17
+ y?: number | null;
18
18
  /** Data label value of the point. If not specified, the y value is used. */
19
19
  label?: string | number;
20
20
  /** Individual opacity for the point. */
@@ -46,4 +46,13 @@ export interface WaterfallSeries<T = MeaningfulAny> extends BaseSeries {
46
46
  totals?: string;
47
47
  };
48
48
  };
49
+ /**
50
+ * Defines how to handle null values in the data.
51
+ *
52
+ * - `'zero'`: Treat null values as zero
53
+ * - `'skip'`: Omit data points with null values (don't render them)
54
+ *
55
+ * @default 'skip'
56
+ */
57
+ nullMode?: 'zero' | 'skip';
49
58
  }
@@ -1,3 +1,4 @@
1
+ import type { ZoomType } from '../../constants';
1
2
  /**
2
3
  * Configuration options for chart zooming functionality using area selection.
3
4
  * Working with only axis related series.
@@ -24,7 +25,7 @@ export interface ChartZoom {
24
25
  * - `Scatter`: `xy`
25
26
  * - All others: `x`
26
27
  */
27
- type?: 'x' | 'y' | 'xy';
28
+ type?: ZoomType;
28
29
  /**
29
30
  * Zoom brush configuration.
30
31
  */
@@ -33,4 +34,33 @@ export interface ChartZoom {
33
34
  fillOpacity?: number;
34
35
  };
35
36
  };
37
+ /**
38
+ * Reset zoom button configuration.
39
+ * The button appears only after the zoom has been applied.
40
+ */
41
+ resetButton?: {
42
+ /**
43
+ * The alignment of the button.
44
+ *
45
+ * @default 'top-right'
46
+ */
47
+ align?: 'bottom-left' | 'bottom-right' | 'top-left' | 'top-right';
48
+ /**
49
+ * The offset of the button.
50
+ *
51
+ * @default {x: 0, y: 0}
52
+ */
53
+ offset?: {
54
+ x?: number;
55
+ y?: number;
56
+ };
57
+ /**
58
+ * The box to which the button is positioned relative to.
59
+ * - `chart-box` refers to the entire chart area, including titles and legends.
60
+ * - `plot-box` refers to the area where the series are drawn.
61
+ *
62
+ * @default 'chart-box'
63
+ */
64
+ relativeTo?: 'chart-box' | 'plot-box';
65
+ };
36
66
  }