@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
@@ -14,13 +14,14 @@ import { Tooltip } from '../Tooltip';
14
14
  import { useChartInnerHandlers } from './useChartInnerHandlers';
15
15
  import { useChartInnerProps } from './useChartInnerProps';
16
16
  import { useChartInnerState } from './useChartInnerState';
17
- import { useAsyncState } from './utils';
17
+ import { getResetZoomButtonStyle, useAsyncState } from './utils';
18
18
  import './styles.css';
19
19
  const b = block('chart');
20
20
  export const ChartInner = (props) => {
21
21
  var _a, _b, _c, _d;
22
22
  const { width, height, data } = props;
23
23
  const svgRef = React.useRef(null);
24
+ const resetZoomButtonRef = React.useRef(null);
24
25
  const [htmlLayout, setHtmlLayout] = React.useState(null);
25
26
  const plotRef = React.useRef(null);
26
27
  const plotBeforeRef = React.useRef(null);
@@ -39,7 +40,7 @@ export const ChartInner = (props) => {
39
40
  dispatcher,
40
41
  tooltip: preparedTooltip,
41
42
  });
42
- const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, isOutsideBounds, legendConfig, legendItems, preparedSeries, preparedSplit, preparedLegend, prevHeight, prevWidth, shapes, shapesData, title, xAxis, xScale, yAxis, yScale, svgXPos, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
43
+ const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, isOutsideBounds, legendConfig, legendItems, preparedSeries, preparedSplit, preparedLegend, preparedZoom, prevHeight, prevWidth, shapes, shapesData, svgXPos, title, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { clipPathId,
43
44
  dispatcher,
44
45
  htmlLayout, plotNode: plotRef.current, svgContainer: svgRef.current, updateZoomState,
45
46
  zoomState }));
@@ -143,7 +144,10 @@ export const ChartInner = (props) => {
143
144
  React.createElement("div", { className: b('html-layer'), ref: setHtmlLayout, style: {
144
145
  '--g-html-layout-transform': `translate(${boundsOffsetLeft}px, ${boundsOffsetTop}px)`,
145
146
  } }),
146
- Object.keys(zoomState).length > 0 && (React.createElement(Button, { style: { position: 'absolute', top: 0, right: 0 }, onClick: () => updateZoomState({}) },
147
+ Object.keys(zoomState).length > 0 && preparedZoom && (React.createElement(Button, { onClick: () => updateZoomState({}), ref: resetZoomButtonRef, style: getResetZoomButtonStyle(Object.assign({ boundsHeight,
148
+ boundsOffsetLeft,
149
+ boundsOffsetTop,
150
+ boundsWidth, node: resetZoomButtonRef.current, titleHeight: title === null || title === void 0 ? void 0 : title.height }, preparedZoom.resetButton)) },
147
151
  React.createElement(ButtonIcon, null,
148
152
  React.createElement(ArrowRotateLeft, null)))),
149
153
  React.createElement(Tooltip, { dispatcher: dispatcher, tooltip: preparedTooltip, svgContainer: svgRef.current, xAxis: xAxis, yAxis: yAxis[0], onOutsideClick: unpinTooltip, tooltipPinned: tooltipPinned })));
@@ -12,8 +12,6 @@ type Props = ChartInnerProps & {
12
12
  zoomState: Partial<ZoomState>;
13
13
  };
14
14
  export declare function useChartInnerProps(props: Props): {
15
- svgBottomPos: number | undefined;
16
- svgTopPos: number | undefined;
17
15
  svgXPos: number | undefined;
18
16
  boundsHeight: number;
19
17
  boundsOffsetLeft: number;
@@ -38,6 +36,22 @@ export declare function useChartInnerProps(props: Props): {
38
36
  preparedLegend: import("../../hooks").PreparedLegend | null;
39
37
  preparedSeries: import("../../hooks").PreparedSeries[];
40
38
  preparedSplit: import("../../hooks").PreparedSplit;
39
+ preparedZoom: Required<{
40
+ type?: import("../../constants").ZoomType | undefined;
41
+ brush?: Required<{
42
+ style?: Required<{
43
+ fillOpacity?: number | undefined;
44
+ } | undefined>;
45
+ } | undefined>;
46
+ resetButton?: Required<{
47
+ align?: ("bottom-left" | "bottom-right" | "top-left" | "top-right") | undefined;
48
+ offset?: Required<{
49
+ x?: number | undefined;
50
+ y?: number | undefined;
51
+ } | undefined>;
52
+ relativeTo?: ("chart-box" | "plot-box") | undefined;
53
+ } | undefined>;
54
+ }> | null;
41
55
  prevHeight: number | undefined;
42
56
  prevWidth: number | undefined;
43
57
  shapes: React.ReactElement<any, string | React.JSXElementConstructor<any>>[];
@@ -138,10 +138,8 @@ export function useChartInnerProps(props) {
138
138
  }
139
139
  return acc;
140
140
  }, 0);
141
- const { bottom, top, x } = (_a = svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {};
141
+ const { x } = (_a = svgContainer === null || svgContainer === void 0 ? void 0 : svgContainer.getBoundingClientRect()) !== null && _a !== void 0 ? _a : {};
142
142
  return {
143
- svgBottomPos: bottom,
144
- svgTopPos: top,
145
143
  svgXPos: x,
146
144
  boundsHeight,
147
145
  boundsOffsetLeft,
@@ -154,6 +152,7 @@ export function useChartInnerProps(props) {
154
152
  preparedLegend,
155
153
  preparedSeries,
156
154
  preparedSplit,
155
+ preparedZoom: chart.zoom,
157
156
  prevHeight,
158
157
  prevWidth,
159
158
  shapes,
@@ -1,4 +1,13 @@
1
+ import React from 'react';
1
2
  import type { PreparedSeries } from '../../hooks';
2
- import type { PreparedAxis } from '../../hooks/useChartOptions/types';
3
+ import type { PreparedAxis, PreparedZoom } from '../../hooks/useChartOptions/types';
3
4
  export declare function hasAtLeastOneSeriesDataPerPlot(seriesData: PreparedSeries[], yAxes?: PreparedAxis[]): boolean;
4
5
  export declare function useAsyncState<T>(value: T, setState: () => Promise<T>): T;
6
+ export declare function getResetZoomButtonStyle(args: {
7
+ boundsHeight: number;
8
+ boundsOffsetLeft: number;
9
+ boundsOffsetTop: number;
10
+ boundsWidth: number;
11
+ node: HTMLElement | null;
12
+ titleHeight?: number;
13
+ } & PreparedZoom['resetButton']): React.CSSProperties;
@@ -47,3 +47,63 @@ export function useAsyncState(value, setState) {
47
47
  }, [setState]);
48
48
  return stateValue;
49
49
  }
50
+ export function getResetZoomButtonStyle(args) {
51
+ const { align, boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, node, offset, relativeTo, titleHeight, } = args;
52
+ const style = {
53
+ position: 'absolute',
54
+ transform: `translate(${offset.x}px, ${offset.y}px)`,
55
+ };
56
+ switch (relativeTo) {
57
+ case 'chart-box': {
58
+ switch (align) {
59
+ case 'bottom-left': {
60
+ style.bottom = 0;
61
+ style.left = 0;
62
+ break;
63
+ }
64
+ case 'bottom-right': {
65
+ style.bottom = 0;
66
+ style.right = 0;
67
+ break;
68
+ }
69
+ case 'top-left': {
70
+ style.top = 0;
71
+ style.left = 0;
72
+ break;
73
+ }
74
+ case 'top-right': {
75
+ style.top = 0;
76
+ style.right = 0;
77
+ break;
78
+ }
79
+ }
80
+ break;
81
+ }
82
+ case 'plot-box': {
83
+ switch (align) {
84
+ case 'bottom-left': {
85
+ style.left = boundsOffsetLeft;
86
+ style.top = boundsHeight - ((node === null || node === void 0 ? void 0 : node.clientHeight) || 0) + (titleHeight || 0);
87
+ break;
88
+ }
89
+ case 'bottom-right': {
90
+ style.left = boundsWidth + boundsOffsetLeft - ((node === null || node === void 0 ? void 0 : node.clientWidth) || 0);
91
+ style.top = boundsHeight - ((node === null || node === void 0 ? void 0 : node.clientHeight) || 0) + (titleHeight || 0);
92
+ break;
93
+ }
94
+ case 'top-left': {
95
+ style.left = boundsOffsetLeft;
96
+ style.top = boundsOffsetTop;
97
+ break;
98
+ }
99
+ case 'top-right': {
100
+ style.left = boundsWidth + boundsOffsetLeft - ((node === null || node === void 0 ? void 0 : node.clientWidth) || 0);
101
+ style.top = boundsOffsetTop;
102
+ break;
103
+ }
104
+ }
105
+ break;
106
+ }
107
+ }
108
+ return style;
109
+ }
@@ -1,6 +1,6 @@
1
1
  import type { ChartSeriesData, ChartTooltip, ChartTooltipTotalsAggregationValue, ChartTooltipTotalsBuiltInAggregation, ChartXAxis, ChartYAxis, TooltipDataChunk, ValueFormat } from '../../../types';
2
2
  export type HoveredValue = string | number | null | undefined;
3
- export declare function getXRowData(data: ChartSeriesData, xAxis?: ChartXAxis | null): string | number | undefined;
3
+ export declare function getXRowData(data: ChartSeriesData, xAxis?: ChartXAxis | null): string | number | null | undefined;
4
4
  export declare function getDefaultValueFormat({ axis, closestPointsRange, }: {
5
5
  axis?: ChartXAxis | ChartYAxis | null;
6
6
  closestPointsRange?: number;
@@ -14,7 +14,7 @@ export declare const getMeasureValue: ({ data, xAxis, yAxis, headerFormat, }: {
14
14
  value: string | null;
15
15
  formattedValue?: undefined;
16
16
  } | {
17
- value: string | number | undefined;
17
+ value: string | number | null | undefined;
18
18
  formattedValue: string;
19
19
  } | null;
20
20
  export declare function getHoveredValues(args: {
@@ -9,3 +9,4 @@ export * from './palette';
9
9
  export * from './symbol-types';
10
10
  export * from './tooltip';
11
11
  export * from './typography';
12
+ export * from './zoom';
@@ -9,3 +9,4 @@ export * from './palette';
9
9
  export * from './symbol-types';
10
10
  export * from './tooltip';
11
11
  export * from './typography';
12
+ export * from './zoom';
@@ -0,0 +1,6 @@
1
+ export declare const ZOOM_TYPE: {
2
+ readonly X: "x";
3
+ readonly XY: "xy";
4
+ readonly Y: "y";
5
+ };
6
+ export type ZoomType = (typeof ZOOM_TYPE)[keyof typeof ZOOM_TYPE];
@@ -0,0 +1,5 @@
1
+ export const ZOOM_TYPE = {
2
+ X: 'x',
3
+ XY: 'xy',
4
+ Y: 'y',
5
+ };
@@ -1,12 +1,13 @@
1
1
  import React from 'react';
2
2
  import { brush, brushX, brushY, select } from 'd3';
3
+ import { ZOOM_TYPE } from '../../constants';
3
4
  import { block } from '../../utils';
4
5
  import './styles.css';
5
6
  const b = block('brush');
6
7
  export function useBrush(props) {
7
- const { areas, brushOptions, node, type, onBrushStart, onBrush, onBrushEnd } = props;
8
+ const { areas, brushOptions, disabled, node, type, onBrushStart, onBrush, onBrushEnd } = props;
8
9
  React.useEffect(() => {
9
- if (!node || !areas.length) {
10
+ if (!node || !areas.length || disabled) {
10
11
  return () => { };
11
12
  }
12
13
  const brushes = [];
@@ -15,15 +16,15 @@ export function useBrush(props) {
15
16
  areas.forEach((area) => {
16
17
  let brushFn;
17
18
  switch (type) {
18
- case 'x': {
19
+ case ZOOM_TYPE.X: {
19
20
  brushFn = brushX;
20
21
  break;
21
22
  }
22
- case 'y': {
23
+ case ZOOM_TYPE.Y: {
23
24
  brushFn = brushY;
24
25
  break;
25
26
  }
26
- case 'xy':
27
+ case ZOOM_TYPE.XY:
27
28
  default: {
28
29
  brushFn = brush;
29
30
  break;
@@ -66,5 +67,5 @@ export function useBrush(props) {
66
67
  selection === null || selection === void 0 ? void 0 : selection.remove();
67
68
  });
68
69
  };
69
- }, [areas, brushOptions, node, type, onBrushStart, onBrush, onBrushEnd]);
70
+ }, [areas, brushOptions, disabled, node, type, onBrushStart, onBrush, onBrushEnd]);
70
71
  }
@@ -1,6 +1,6 @@
1
1
  import type { BrushBehavior } from 'd3';
2
+ import type { ZoomType } from '../../constants';
2
3
  import type { PreparedZoom } from '../useChartOptions/types';
3
- type BrushType = PreparedZoom['type'];
4
4
  type BrushSelection = [number, number] | [[number, number], [number, number]];
5
5
  export interface BrushArea {
6
6
  /**
@@ -15,8 +15,9 @@ export interface BrushArea {
15
15
  export interface UseBrushProps {
16
16
  areas: BrushArea[];
17
17
  node: SVGGElement | null;
18
- type?: BrushType;
18
+ type?: ZoomType;
19
19
  brushOptions?: PreparedZoom['brush'];
20
+ disabled?: boolean;
20
21
  onBrushStart?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>) => void;
21
22
  onBrush?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>, selection: BrushSelection) => void;
22
23
  onBrushEnd?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>, selection: BrushSelection | null) => void;
@@ -1,6 +1,5 @@
1
1
  import get from 'lodash/get';
2
- import intersection from 'lodash/intersection';
3
- import { SeriesType } from '../../constants';
2
+ import { getPreparedZoom } from './zoom';
4
3
  const getMarginTop = (args) => {
5
4
  const { chart, preparedTitle } = args;
6
5
  let marginTop = get(chart, 'margin.top', 0);
@@ -13,81 +12,6 @@ const getMarginRight = (args) => {
13
12
  const { chart } = args;
14
13
  return get(chart, 'margin.right', 0);
15
14
  };
16
- function mapSeriesTypeToZoomType(seriesType) {
17
- switch (seriesType) {
18
- case SeriesType.Area: {
19
- return ['x', 'y', 'xy'];
20
- }
21
- case SeriesType.BarX: {
22
- return ['x'];
23
- }
24
- case SeriesType.BarY: {
25
- return ['y'];
26
- }
27
- case SeriesType.Line: {
28
- return ['x', 'y', 'xy'];
29
- }
30
- case SeriesType.Scatter: {
31
- return ['x', 'y', 'xy'];
32
- }
33
- case SeriesType.Waterfall: {
34
- return ['x', 'y', 'xy'];
35
- }
36
- default: {
37
- return [];
38
- }
39
- }
40
- }
41
- function getDefaultZoomType(seriesType) {
42
- switch (seriesType) {
43
- case SeriesType.BarY: {
44
- return 'y';
45
- }
46
- case SeriesType.Scatter: {
47
- return 'xy';
48
- }
49
- default: {
50
- return 'x';
51
- }
52
- }
53
- }
54
- function getZoomType(args) {
55
- const { seriesData, zoomType } = args;
56
- const possibleDefaultZoomTypes = seriesData.map((s) => {
57
- return getDefaultZoomType(s.type);
58
- });
59
- const availableDefaultZoomTypes = intersection(possibleDefaultZoomTypes);
60
- if (zoomType) {
61
- const possibleZoomTypes = seriesData.map((s) => {
62
- return mapSeriesTypeToZoomType(s.type);
63
- });
64
- const availableZoomTypes = intersection(...possibleZoomTypes);
65
- if (availableZoomTypes.includes(zoomType)) {
66
- return zoomType;
67
- }
68
- }
69
- if (availableDefaultZoomTypes.length) {
70
- return availableDefaultZoomTypes[0];
71
- }
72
- return undefined;
73
- }
74
- function getPreparedZoom(args) {
75
- var _a;
76
- const { zoom, seriesData } = args;
77
- if (!(zoom === null || zoom === void 0 ? void 0 : zoom.enabled)) {
78
- return null;
79
- }
80
- const type = getZoomType({ seriesData, zoomType: zoom.type });
81
- if (!type) {
82
- return null;
83
- }
84
- return {
85
- type,
86
- brush: {
87
- style: Object.assign({ fillOpacity: 1 }, (_a = zoom === null || zoom === void 0 ? void 0 : zoom.brush) === null || _a === void 0 ? void 0 : _a.style),
88
- },
89
- };
90
- }
91
15
  export const getPreparedChart = (args) => {
92
16
  const { chart, preparedTitle, seriesData } = args;
93
17
  const marginTop = getMarginTop({ chart, preparedTitle });
@@ -0,0 +1,11 @@
1
+ import type { ZoomType } from '../../constants';
2
+ import type { ChartSeries, ChartZoom } from '../../types';
3
+ import type { PreparedZoom } from './types';
4
+ export declare function getZoomType(args: {
5
+ seriesData: ChartSeries[];
6
+ zoomType?: ZoomType;
7
+ }): ZoomType | undefined;
8
+ export declare function getPreparedZoom(args: {
9
+ zoom?: ChartZoom;
10
+ seriesData: ChartSeries[];
11
+ }): PreparedZoom | null;
@@ -0,0 +1,88 @@
1
+ import intersection from 'lodash/intersection';
2
+ import { SeriesType, ZOOM_TYPE } from '../../constants';
3
+ function mapSeriesTypeToZoomType(seriesType) {
4
+ switch (seriesType) {
5
+ case SeriesType.Area: {
6
+ return [ZOOM_TYPE.X, ZOOM_TYPE.XY, ZOOM_TYPE.Y];
7
+ }
8
+ case SeriesType.BarX: {
9
+ return [ZOOM_TYPE.X];
10
+ }
11
+ case SeriesType.BarY: {
12
+ return [ZOOM_TYPE.Y];
13
+ }
14
+ case SeriesType.Line: {
15
+ return [ZOOM_TYPE.X, ZOOM_TYPE.XY, ZOOM_TYPE.Y];
16
+ }
17
+ case SeriesType.Scatter: {
18
+ return [ZOOM_TYPE.X, ZOOM_TYPE.XY, ZOOM_TYPE.Y];
19
+ }
20
+ case SeriesType.Waterfall: {
21
+ return [ZOOM_TYPE.X, ZOOM_TYPE.XY, ZOOM_TYPE.Y];
22
+ }
23
+ default: {
24
+ return [];
25
+ }
26
+ }
27
+ }
28
+ function getDefaultZoomType(seriesType) {
29
+ switch (seriesType) {
30
+ case SeriesType.BarY: {
31
+ return ZOOM_TYPE.Y;
32
+ }
33
+ case SeriesType.Scatter: {
34
+ return ZOOM_TYPE.XY;
35
+ }
36
+ case SeriesType.Area:
37
+ case SeriesType.BarX:
38
+ case SeriesType.Line:
39
+ case SeriesType.Waterfall: {
40
+ return ZOOM_TYPE.X;
41
+ }
42
+ default: {
43
+ return undefined;
44
+ }
45
+ }
46
+ }
47
+ export function getZoomType(args) {
48
+ const { seriesData, zoomType } = args;
49
+ const possibleZoomTypes = seriesData.map((s) => {
50
+ return mapSeriesTypeToZoomType(s.type);
51
+ });
52
+ const availableZoomTypes = intersection(...possibleZoomTypes);
53
+ if (zoomType && availableZoomTypes.includes(zoomType)) {
54
+ return zoomType;
55
+ }
56
+ const possibleDefaultZoomTypes = seriesData
57
+ .map((s) => {
58
+ return getDefaultZoomType(s.type);
59
+ })
60
+ .filter(Boolean);
61
+ const availableDefaultZoomTypes = intersection(possibleDefaultZoomTypes, ...possibleZoomTypes);
62
+ if (availableDefaultZoomTypes.length) {
63
+ return availableDefaultZoomTypes[0];
64
+ }
65
+ return undefined;
66
+ }
67
+ export function getPreparedZoom(args) {
68
+ var _a, _b, _c, _d;
69
+ const { zoom, seriesData } = args;
70
+ if (!(zoom === null || zoom === void 0 ? void 0 : zoom.enabled)) {
71
+ return null;
72
+ }
73
+ const type = getZoomType({ seriesData, zoomType: zoom.type });
74
+ if (!type) {
75
+ return null;
76
+ }
77
+ return {
78
+ type,
79
+ brush: {
80
+ style: Object.assign({ fillOpacity: 1 }, (_a = zoom === null || zoom === void 0 ? void 0 : zoom.brush) === null || _a === void 0 ? void 0 : _a.style),
81
+ },
82
+ resetButton: {
83
+ align: ((_b = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _b === void 0 ? void 0 : _b.align) || 'top-right',
84
+ offset: Object.assign({ x: 0, y: 0 }, (_c = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _c === void 0 ? void 0 : _c.offset),
85
+ relativeTo: ((_d = zoom === null || zoom === void 0 ? void 0 : zoom.resetButton) === null || _d === void 0 ? void 0 : _d.relativeTo) || 'chart-box',
86
+ },
87
+ };
88
+ }
@@ -24,6 +24,20 @@ function prepareMarker(series, seriesOptions) {
24
24
  },
25
25
  };
26
26
  }
27
+ function prepareSeriesData(series) {
28
+ var _a;
29
+ const nullMode = (_a = series.nullMode) !== null && _a !== void 0 ? _a : 'skip';
30
+ const data = series.data;
31
+ switch (nullMode) {
32
+ case 'zero':
33
+ return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { y: (_a = p.y) !== null && _a !== void 0 ? _a : 0 })); });
34
+ case 'connect':
35
+ return data.filter((p) => p.y !== null);
36
+ case 'skip':
37
+ default:
38
+ return data;
39
+ }
40
+ }
27
41
  export function prepareArea(args) {
28
42
  const { colorScale, series: seriesList, seriesOptions, legend } = args;
29
43
  const defaultAreaWidth = get(seriesOptions, 'area.lineWidth', DEFAULT_LINE_WIDTH);
@@ -45,7 +59,7 @@ export function prepareArea(args) {
45
59
  enabled: get(series, 'legend.enabled', legend.enabled),
46
60
  symbol: prepareLegendSymbol(series),
47
61
  },
48
- data: series.data,
62
+ data: prepareSeriesData(series),
49
63
  stacking: series.stacking,
50
64
  stackId: getSeriesStackId(series),
51
65
  dataLabels: {
@@ -3,6 +3,18 @@ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
3
3
  import { getUniqId } from '../../utils';
4
4
  import { DEFAULT_DATALABELS_PADDING } from './constants';
5
5
  import { getSeriesStackId, prepareLegendSymbol } from './utils';
6
+ function prepareSeriesData(series) {
7
+ var _a;
8
+ const nullMode = (_a = series.nullMode) !== null && _a !== void 0 ? _a : 'skip';
9
+ const data = series.data;
10
+ switch (nullMode) {
11
+ case 'zero':
12
+ return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { y: (_a = p.y) !== null && _a !== void 0 ? _a : 0 })); });
13
+ case 'skip':
14
+ default:
15
+ return data.filter((p) => p.y !== null);
16
+ }
17
+ }
6
18
  export function prepareBarXSeries(args) {
7
19
  const { colorScale, series: seriesList, seriesOptions, legend } = args;
8
20
  return seriesList.map((series) => {
@@ -19,7 +31,7 @@ export function prepareBarXSeries(args) {
19
31
  enabled: get(series, 'legend.enabled', legend.enabled),
20
32
  symbol: prepareLegendSymbol(series),
21
33
  },
22
- data: series.data,
34
+ data: prepareSeriesData(series),
23
35
  stacking: series.stacking,
24
36
  stackId: getSeriesStackId(series),
25
37
  dataLabels: {
@@ -1,5 +1,5 @@
1
1
  import type { ScaleOrdinal } from 'd3';
2
- import type { BarYSeries, ChartSeriesOptions } from '../../types';
2
+ import type { BarYSeries, BarYSeriesData, ChartSeriesOptions } from '../../types';
3
3
  import type { PreparedLegend } from './types';
4
4
  type PrepareBarYSeriesArgs = {
5
5
  colorScale: ScaleOrdinal<string, string>;
@@ -9,7 +9,7 @@ type PrepareBarYSeriesArgs = {
9
9
  };
10
10
  export declare function prepareBarYSeries(args: PrepareBarYSeriesArgs): Promise<({
11
11
  type: BarYSeries["type"];
12
- data: import("../../types").BarYSeriesData[];
12
+ data: BarYSeriesData[];
13
13
  stackId: string;
14
14
  stacking: BarYSeries["stacking"];
15
15
  dataLabels: {
@@ -3,6 +3,18 @@ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
3
3
  import { getLabelsSize, getUniqId } from '../../utils';
4
4
  import { getFormattedValue } from '../../utils/chart/format';
5
5
  import { getSeriesStackId, prepareLegendSymbol } from './utils';
6
+ function prepareSeriesData(series) {
7
+ var _a;
8
+ const nullMode = (_a = series.nullMode) !== null && _a !== void 0 ? _a : 'skip';
9
+ const data = series.data;
10
+ switch (nullMode) {
11
+ case 'zero':
12
+ return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { x: (_a = p.x) !== null && _a !== void 0 ? _a : 0 })); });
13
+ case 'skip':
14
+ default:
15
+ return data.filter((p) => p.x !== null);
16
+ }
17
+ }
6
18
  async function prepareDataLabels(series) {
7
19
  var _a, _b, _c, _d;
8
20
  const enabled = get(series, 'dataLabels.enabled', false);
@@ -46,7 +58,7 @@ export function prepareBarYSeries(args) {
46
58
  enabled: get(series, 'legend.enabled', legend.enabled),
47
59
  symbol: prepareLegendSymbol(series),
48
60
  },
49
- data: series.data.filter((d) => d.x !== null),
61
+ data: prepareSeriesData(series),
50
62
  stacking: series.stacking,
51
63
  stackId: getSeriesStackId(series),
52
64
  dataLabels: await prepareDataLabels(series),
@@ -3,6 +3,18 @@ import { DEFAULT_DATALABELS_STYLE } from '../../constants';
3
3
  import { getUniqId } from '../../utils';
4
4
  import { DEFAULT_DATALABELS_PADDING } from './constants';
5
5
  import { prepareLegendSymbol } from './utils';
6
+ function prepareSeriesData(series) {
7
+ var _a;
8
+ const nullMode = (_a = series.nullMode) !== null && _a !== void 0 ? _a : 'skip';
9
+ const data = series.data;
10
+ switch (nullMode) {
11
+ case 'zero':
12
+ return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { value: (_a = p.value) !== null && _a !== void 0 ? _a : 0 })); });
13
+ case 'skip':
14
+ default:
15
+ return data;
16
+ }
17
+ }
6
18
  export function prepareHeatmapSeries(args) {
7
19
  const { colorScale, series: seriesList, seriesOptions, legend } = args;
8
20
  return seriesList.map((series) => {
@@ -19,7 +31,7 @@ export function prepareHeatmapSeries(args) {
19
31
  enabled: get(series, 'legend.enabled', legend.enabled),
20
32
  symbol: prepareLegendSymbol(series),
21
33
  },
22
- data: series.data,
34
+ data: prepareSeriesData(series),
23
35
  dataLabels: {
24
36
  enabled: ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) || false,
25
37
  style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_b = series.dataLabels) === null || _b === void 0 ? void 0 : _b.style),
@@ -150,7 +150,7 @@ function getPagination(args) {
150
150
  if (!pages[currentPageIndex]) {
151
151
  pages[currentPageIndex] = { start: i, end: i };
152
152
  }
153
- const legendLineHeight = Math.max(...item.map((item) => item.height));
153
+ const legendLineHeight = Math.max(...item.map(({ height }) => height));
154
154
  currentHeight += legendLineHeight;
155
155
  if (currentHeight > maxLegendHeight - paginatorHeight) {
156
156
  pages[currentPageIndex].end = i;
@@ -41,6 +41,20 @@ function prepareMarker(series, seriesOptions) {
41
41
  },
42
42
  };
43
43
  }
44
+ function prepareSeriesData(series) {
45
+ var _a;
46
+ const nullMode = (_a = series.nullMode) !== null && _a !== void 0 ? _a : 'skip';
47
+ const data = series.data;
48
+ switch (nullMode) {
49
+ case 'zero':
50
+ return data.map((p) => { var _a; return (Object.assign(Object.assign({}, p), { y: (_a = p.y) !== null && _a !== void 0 ? _a : 0 })); });
51
+ case 'connect':
52
+ return data.filter((p) => p.y !== null);
53
+ case 'skip':
54
+ default:
55
+ return data;
56
+ }
57
+ }
44
58
  export function prepareLineSeries(args) {
45
59
  const { colorScale, series: seriesList, seriesOptions, legend } = args;
46
60
  const defaultLineWidth = get(seriesOptions, 'line.lineWidth', DEFAULT_LINE_WIDTH);
@@ -62,7 +76,7 @@ export function prepareLineSeries(args) {
62
76
  enabled: get(series, 'legend.enabled', legend.enabled),
63
77
  symbol: prepareLineLegendSymbol(series, seriesOptions),
64
78
  },
65
- data: series.data,
79
+ data: prepareSeriesData(series),
66
80
  dataLabels: {
67
81
  enabled: ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) || false,
68
82
  style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_b = series.dataLabels) === null || _b === void 0 ? void 0 : _b.style),