@gravity-ui/charts 1.9.0 → 1.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (199) hide show
  1. package/dist/cjs/components/Axis/AxisX.d.ts +2 -1
  2. package/dist/cjs/components/Axis/AxisX.js +149 -143
  3. package/dist/cjs/components/Axis/AxisY.d.ts +2 -1
  4. package/dist/cjs/components/Axis/AxisY.js +113 -91
  5. package/dist/cjs/components/ChartInner/index.js +23 -10
  6. package/dist/cjs/components/ChartInner/useChartInnerHandlers.d.ts +1 -1
  7. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +8 -5
  8. package/dist/cjs/components/ChartInner/useChartInnerProps.js +55 -9
  9. package/dist/cjs/components/ChartInner/utils.d.ts +3 -0
  10. package/dist/cjs/components/ChartInner/utils.js +28 -0
  11. package/dist/cjs/components/Legend/index.js +203 -195
  12. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +1 -1
  13. package/dist/cjs/components/Tooltip/DefaultContent.d.ts +1 -1
  14. package/dist/cjs/components/Tooltip/DefaultContent.js +1 -1
  15. package/dist/cjs/components/Tooltip/index.d.ts +1 -1
  16. package/dist/cjs/hooks/hooks-utils/index.d.ts +1 -0
  17. package/dist/cjs/hooks/hooks-utils/index.js +1 -0
  18. package/dist/cjs/hooks/hooks-utils/zoom.d.ts +8 -0
  19. package/dist/cjs/hooks/hooks-utils/zoom.js +81 -0
  20. package/dist/cjs/hooks/useAxisScales/index.d.ts +4 -2
  21. package/dist/cjs/hooks/useAxisScales/index.js +22 -8
  22. package/dist/cjs/hooks/useBrush/index.d.ts +3 -0
  23. package/dist/cjs/hooks/useBrush/index.js +70 -0
  24. package/dist/cjs/hooks/useBrush/styles.css +10 -0
  25. package/dist/cjs/hooks/useBrush/types.d.ts +24 -0
  26. package/dist/cjs/hooks/useBrush/types.js +1 -0
  27. package/dist/cjs/hooks/useChartDimensions/index.d.ts +3 -3
  28. package/dist/cjs/hooks/useChartDimensions/index.js +2 -2
  29. package/dist/cjs/hooks/useChartDimensions/utils.d.ts +2 -2
  30. package/dist/cjs/hooks/useChartOptions/chart.d.ts +2 -1
  31. package/dist/cjs/hooks/useChartOptions/chart.js +80 -1
  32. package/dist/cjs/hooks/useChartOptions/index.js +3 -2
  33. package/dist/cjs/hooks/useChartOptions/types.d.ts +3 -1
  34. package/dist/cjs/hooks/useChartOptions/x-axis.d.ts +3 -3
  35. package/dist/cjs/hooks/useChartOptions/x-axis.js +11 -11
  36. package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +3 -3
  37. package/dist/cjs/hooks/useChartOptions/y-axis.js +22 -18
  38. package/dist/cjs/hooks/useCrosshair/index.d.ts +1 -1
  39. package/dist/cjs/hooks/useCrosshair/index.js +2 -2
  40. package/dist/cjs/hooks/useSeries/index.d.ts +8 -6
  41. package/dist/cjs/hooks/useSeries/index.js +41 -22
  42. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +27 -2
  43. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +5 -5
  44. package/dist/cjs/hooks/useSeries/prepare-legend.d.ts +1 -1
  45. package/dist/cjs/hooks/useSeries/prepare-legend.js +6 -5
  46. package/dist/cjs/hooks/useSeries/prepareSeries.d.ts +1 -1
  47. package/dist/cjs/hooks/useSeries/prepareSeries.js +2 -2
  48. package/dist/cjs/hooks/useShapes/area/index.js +1 -1
  49. package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +1 -1
  50. package/dist/cjs/hooks/useShapes/area/prepare-data.js +32 -16
  51. package/dist/cjs/hooks/useShapes/area/types.d.ts +1 -0
  52. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  53. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +17 -13
  54. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
  55. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +6 -6
  56. package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
  57. package/dist/cjs/hooks/useShapes/index.js +40 -31
  58. package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +1 -1
  59. package/dist/cjs/hooks/useShapes/line/prepare-data.js +14 -11
  60. package/dist/cjs/hooks/useShapes/line/types.d.ts +1 -0
  61. package/dist/cjs/hooks/useShapes/marker.js +2 -2
  62. package/dist/cjs/hooks/useShapes/pie/index.js +3 -3
  63. package/dist/cjs/hooks/useShapes/pie/prepare-data.d.ts +1 -1
  64. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +15 -11
  65. package/dist/cjs/hooks/useShapes/radar/prepare-data.d.ts +1 -1
  66. package/dist/cjs/hooks/useShapes/radar/prepare-data.js +6 -7
  67. package/dist/cjs/hooks/useShapes/radar/types.d.ts +1 -0
  68. package/dist/cjs/hooks/useShapes/scatter/index.js +0 -1
  69. package/dist/cjs/hooks/useShapes/scatter/prepare-data.js +2 -0
  70. package/dist/cjs/hooks/useShapes/scatter/types.d.ts +1 -0
  71. package/dist/cjs/hooks/useShapes/treemap/prepare-data.d.ts +1 -1
  72. package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +19 -16
  73. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  74. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +8 -7
  75. package/dist/cjs/hooks/useZoom/index.d.ts +18 -0
  76. package/dist/cjs/hooks/useZoom/index.js +54 -0
  77. package/dist/cjs/hooks/useZoom/types.d.ts +19 -0
  78. package/dist/cjs/hooks/useZoom/types.js +1 -0
  79. package/dist/cjs/hooks/useZoom/utils.d.ts +12 -0
  80. package/dist/cjs/hooks/useZoom/utils.js +128 -0
  81. package/dist/cjs/types/chart/chart.d.ts +5 -0
  82. package/dist/cjs/types/chart/pie.d.ts +1 -1
  83. package/dist/cjs/types/chart/tooltip.d.ts +1 -1
  84. package/dist/cjs/types/chart/zoom.d.ts +36 -0
  85. package/dist/cjs/types/chart/zoom.js +1 -0
  86. package/dist/cjs/types/index.d.ts +1 -0
  87. package/dist/cjs/types/index.js +1 -0
  88. package/dist/cjs/types/misc.d.ts +7 -0
  89. package/dist/cjs/utils/chart/axis-generators/bottom.d.ts +1 -1
  90. package/dist/cjs/utils/chart/axis-generators/bottom.js +29 -28
  91. package/dist/cjs/utils/chart/axis.d.ts +1 -1
  92. package/dist/cjs/utils/chart/axis.js +2 -2
  93. package/dist/cjs/utils/chart/get-closest-data.js +1 -1
  94. package/dist/cjs/utils/chart/text.d.ts +7 -7
  95. package/dist/cjs/utils/chart/text.js +45 -30
  96. package/dist/cjs/utils/chart-ui/pie-center-text.d.ts +1 -1
  97. package/dist/cjs/utils/chart-ui/pie-center-text.js +2 -2
  98. package/dist/cjs/validation/index.d.ts +1 -1
  99. package/dist/cjs/validation/index.js +16 -16
  100. package/dist/esm/components/Axis/AxisX.d.ts +2 -1
  101. package/dist/esm/components/Axis/AxisX.js +149 -143
  102. package/dist/esm/components/Axis/AxisY.d.ts +2 -1
  103. package/dist/esm/components/Axis/AxisY.js +113 -91
  104. package/dist/esm/components/ChartInner/index.js +23 -10
  105. package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +1 -1
  106. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +8 -5
  107. package/dist/esm/components/ChartInner/useChartInnerProps.js +55 -9
  108. package/dist/esm/components/ChartInner/utils.d.ts +3 -0
  109. package/dist/esm/components/ChartInner/utils.js +28 -0
  110. package/dist/esm/components/Legend/index.js +203 -195
  111. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +1 -1
  112. package/dist/esm/components/Tooltip/DefaultContent.d.ts +1 -1
  113. package/dist/esm/components/Tooltip/DefaultContent.js +1 -1
  114. package/dist/esm/components/Tooltip/index.d.ts +1 -1
  115. package/dist/esm/hooks/hooks-utils/index.d.ts +1 -0
  116. package/dist/esm/hooks/hooks-utils/index.js +1 -0
  117. package/dist/esm/hooks/hooks-utils/zoom.d.ts +8 -0
  118. package/dist/esm/hooks/hooks-utils/zoom.js +81 -0
  119. package/dist/esm/hooks/useAxisScales/index.d.ts +4 -2
  120. package/dist/esm/hooks/useAxisScales/index.js +22 -8
  121. package/dist/esm/hooks/useBrush/index.d.ts +3 -0
  122. package/dist/esm/hooks/useBrush/index.js +70 -0
  123. package/dist/esm/hooks/useBrush/styles.css +10 -0
  124. package/dist/esm/hooks/useBrush/types.d.ts +24 -0
  125. package/dist/esm/hooks/useBrush/types.js +1 -0
  126. package/dist/esm/hooks/useChartDimensions/index.d.ts +3 -3
  127. package/dist/esm/hooks/useChartDimensions/index.js +2 -2
  128. package/dist/esm/hooks/useChartDimensions/utils.d.ts +2 -2
  129. package/dist/esm/hooks/useChartOptions/chart.d.ts +2 -1
  130. package/dist/esm/hooks/useChartOptions/chart.js +80 -1
  131. package/dist/esm/hooks/useChartOptions/index.js +3 -2
  132. package/dist/esm/hooks/useChartOptions/types.d.ts +3 -1
  133. package/dist/esm/hooks/useChartOptions/x-axis.d.ts +3 -3
  134. package/dist/esm/hooks/useChartOptions/x-axis.js +11 -11
  135. package/dist/esm/hooks/useChartOptions/y-axis.d.ts +3 -3
  136. package/dist/esm/hooks/useChartOptions/y-axis.js +22 -18
  137. package/dist/esm/hooks/useCrosshair/index.d.ts +1 -1
  138. package/dist/esm/hooks/useCrosshair/index.js +2 -2
  139. package/dist/esm/hooks/useSeries/index.d.ts +8 -6
  140. package/dist/esm/hooks/useSeries/index.js +41 -22
  141. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +27 -2
  142. package/dist/esm/hooks/useSeries/prepare-bar-y.js +5 -5
  143. package/dist/esm/hooks/useSeries/prepare-legend.d.ts +1 -1
  144. package/dist/esm/hooks/useSeries/prepare-legend.js +6 -5
  145. package/dist/esm/hooks/useSeries/prepareSeries.d.ts +1 -1
  146. package/dist/esm/hooks/useSeries/prepareSeries.js +2 -2
  147. package/dist/esm/hooks/useShapes/area/index.js +1 -1
  148. package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +1 -1
  149. package/dist/esm/hooks/useShapes/area/prepare-data.js +32 -16
  150. package/dist/esm/hooks/useShapes/area/types.d.ts +1 -0
  151. package/dist/esm/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  152. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +17 -13
  153. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
  154. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +6 -6
  155. package/dist/esm/hooks/useShapes/index.d.ts +1 -1
  156. package/dist/esm/hooks/useShapes/index.js +40 -31
  157. package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +1 -1
  158. package/dist/esm/hooks/useShapes/line/prepare-data.js +14 -11
  159. package/dist/esm/hooks/useShapes/line/types.d.ts +1 -0
  160. package/dist/esm/hooks/useShapes/marker.js +2 -2
  161. package/dist/esm/hooks/useShapes/pie/index.js +3 -3
  162. package/dist/esm/hooks/useShapes/pie/prepare-data.d.ts +1 -1
  163. package/dist/esm/hooks/useShapes/pie/prepare-data.js +15 -11
  164. package/dist/esm/hooks/useShapes/radar/prepare-data.d.ts +1 -1
  165. package/dist/esm/hooks/useShapes/radar/prepare-data.js +6 -7
  166. package/dist/esm/hooks/useShapes/radar/types.d.ts +1 -0
  167. package/dist/esm/hooks/useShapes/scatter/index.js +0 -1
  168. package/dist/esm/hooks/useShapes/scatter/prepare-data.js +2 -0
  169. package/dist/esm/hooks/useShapes/scatter/types.d.ts +1 -0
  170. package/dist/esm/hooks/useShapes/treemap/prepare-data.d.ts +1 -1
  171. package/dist/esm/hooks/useShapes/treemap/prepare-data.js +19 -16
  172. package/dist/esm/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  173. package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +8 -7
  174. package/dist/esm/hooks/useZoom/index.d.ts +18 -0
  175. package/dist/esm/hooks/useZoom/index.js +54 -0
  176. package/dist/esm/hooks/useZoom/types.d.ts +19 -0
  177. package/dist/esm/hooks/useZoom/types.js +1 -0
  178. package/dist/esm/hooks/useZoom/utils.d.ts +12 -0
  179. package/dist/esm/hooks/useZoom/utils.js +128 -0
  180. package/dist/esm/types/chart/chart.d.ts +5 -0
  181. package/dist/esm/types/chart/pie.d.ts +1 -1
  182. package/dist/esm/types/chart/tooltip.d.ts +1 -1
  183. package/dist/esm/types/chart/zoom.d.ts +36 -0
  184. package/dist/esm/types/chart/zoom.js +1 -0
  185. package/dist/esm/types/index.d.ts +1 -0
  186. package/dist/esm/types/index.js +1 -0
  187. package/dist/esm/types/misc.d.ts +7 -0
  188. package/dist/esm/utils/chart/axis-generators/bottom.d.ts +1 -1
  189. package/dist/esm/utils/chart/axis-generators/bottom.js +29 -28
  190. package/dist/esm/utils/chart/axis.d.ts +1 -1
  191. package/dist/esm/utils/chart/axis.js +2 -2
  192. package/dist/esm/utils/chart/get-closest-data.js +1 -1
  193. package/dist/esm/utils/chart/text.d.ts +7 -7
  194. package/dist/esm/utils/chart/text.js +45 -30
  195. package/dist/esm/utils/chart-ui/pie-center-text.d.ts +1 -1
  196. package/dist/esm/utils/chart-ui/pie-center-text.js +2 -2
  197. package/dist/esm/validation/index.d.ts +1 -1
  198. package/dist/esm/validation/index.js +16 -16
  199. package/package.json +2 -1
@@ -86,7 +86,7 @@ function calculateXAxisPadding(series) {
86
86
  });
87
87
  return result;
88
88
  }
89
- export function createXScale(axis, series, boundsWidth) {
89
+ export function createXScale(axis, series, boundsWidth, hasZoomX) {
90
90
  const xMin = get(axis, 'min');
91
91
  const xMax = getDefaultMaxXAxisValue(series);
92
92
  const xType = get(axis, 'type', DEFAULT_AXIS_TYPE);
@@ -104,7 +104,11 @@ export function createXScale(axis, series, boundsWidth) {
104
104
  const xMinValue = typeof xMin === 'number' ? xMin : domainXMin;
105
105
  const xMaxValue = typeof xMax === 'number' ? Math.max(xMax, domainXMax) : domainXMax;
106
106
  const scaleFn = xType === 'logarithmic' ? scaleLog : scaleLinear;
107
- return scaleFn().domain([xMinValue, xMaxValue]).range(xRange).nice();
107
+ const scale = scaleFn().domain([xMinValue, xMaxValue]).range(xRange);
108
+ if (!hasZoomX) {
109
+ scale.nice();
110
+ }
111
+ return scale;
108
112
  }
109
113
  break;
110
114
  }
@@ -126,13 +130,21 @@ export function createXScale(axis, series, boundsWidth) {
126
130
  case 'datetime': {
127
131
  if (xTimestamps) {
128
132
  const [xMin, xMax] = extent(xTimestamps);
129
- return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
133
+ const scale = scaleUtc().domain([xMin, xMax]).range(xRange);
134
+ if (!hasZoomX) {
135
+ scale.nice();
136
+ }
137
+ return scale;
130
138
  }
131
139
  else {
132
140
  const domain = getDomainDataXBySeries(series);
133
141
  if (isNumericalArrayData(domain)) {
134
142
  const [xMin, xMax] = extent(domain);
135
- return scaleUtc().domain([xMin, xMax]).range(xRange).nice();
143
+ const scale = scaleUtc().domain([xMin, xMax]).range(xRange);
144
+ if (!hasZoomX) {
145
+ scale.nice();
146
+ }
147
+ return scale;
136
148
  }
137
149
  }
138
150
  break;
@@ -141,13 +153,13 @@ export function createXScale(axis, series, boundsWidth) {
141
153
  throw new Error('Failed to create xScale');
142
154
  }
143
155
  const createScales = (args) => {
144
- const { boundsWidth, boundsHeight, series, xAxis, yAxis, split } = args;
156
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis, split, hasZoomX } = args;
145
157
  let visibleSeries = getOnlyVisibleSeries(series);
146
158
  // Reassign to all series in case of all series unselected,
147
159
  // otherwise we will get an empty space without grid
148
160
  visibleSeries = visibleSeries.length === 0 ? series : visibleSeries;
149
161
  return {
150
- xScale: createXScale(xAxis, visibleSeries, boundsWidth),
162
+ xScale: xAxis ? createXScale(xAxis, visibleSeries, boundsWidth, hasZoomX) : undefined,
151
163
  yScale: yAxis.map((axis, index) => {
152
164
  const axisSeries = series.filter((s) => {
153
165
  const seriesAxisIndex = get(s, 'yAxis', 0);
@@ -163,7 +175,7 @@ const createScales = (args) => {
163
175
  * Uses to create scales for axis related series
164
176
  */
165
177
  export const useAxisScales = (args) => {
166
- const { boundsWidth, boundsHeight, series, xAxis, yAxis, split } = args;
178
+ const { boundsWidth, boundsHeight, series, xAxis, yAxis, split, hasZoomX, hasZoomY } = args;
167
179
  return React.useMemo(() => {
168
180
  let xScale;
169
181
  let yScale;
@@ -176,8 +188,10 @@ export const useAxisScales = (args) => {
176
188
  xAxis,
177
189
  yAxis,
178
190
  split,
191
+ hasZoomX,
192
+ hasZoomY,
179
193
  }));
180
194
  }
181
195
  return { xScale, yScale };
182
- }, [boundsWidth, boundsHeight, series, xAxis, yAxis, split]);
196
+ }, [boundsWidth, boundsHeight, series, xAxis, yAxis, split, hasZoomX, hasZoomY]);
183
197
  };
@@ -0,0 +1,3 @@
1
+ import type { UseBrushProps } from './types';
2
+ import './styles.css';
3
+ export declare function useBrush(props: UseBrushProps): void;
@@ -0,0 +1,70 @@
1
+ import React from 'react';
2
+ import { brush, brushX, brushY, select } from 'd3';
3
+ import { block } from '../../utils';
4
+ import './styles.css';
5
+ const b = block('brush');
6
+ export function useBrush(props) {
7
+ const { areas, brushOptions, node, type, onBrushStart, onBrush, onBrushEnd } = props;
8
+ React.useEffect(() => {
9
+ if (!node || !areas.length) {
10
+ return () => { };
11
+ }
12
+ const brushes = [];
13
+ const brushGroupSelections = [];
14
+ const nodeSelection = select(node);
15
+ areas.forEach((area) => {
16
+ let brushFn;
17
+ switch (type) {
18
+ case 'x': {
19
+ brushFn = brushX;
20
+ break;
21
+ }
22
+ case 'y': {
23
+ brushFn = brushY;
24
+ break;
25
+ }
26
+ case 'xy':
27
+ default: {
28
+ brushFn = brush;
29
+ break;
30
+ }
31
+ }
32
+ const brushInstance = brushFn()
33
+ .extent(area.extent)
34
+ .on('start', function () {
35
+ onBrushStart === null || onBrushStart === void 0 ? void 0 : onBrushStart.call(this, brushInstance);
36
+ })
37
+ .on('brush', function (event) {
38
+ onBrush === null || onBrush === void 0 ? void 0 : onBrush.call(this, brushInstance, event.selection);
39
+ })
40
+ .on('end', function (event) {
41
+ onBrushEnd === null || onBrushEnd === void 0 ? void 0 : onBrushEnd.call(this, brushInstance, event.selection);
42
+ });
43
+ brushes.push(brushInstance);
44
+ const brushGroupSelection = nodeSelection
45
+ .append('g')
46
+ .attr('class', b())
47
+ .on('pointerdown', function () {
48
+ this.setAttribute('data-gc-brush-pressed', 'true');
49
+ })
50
+ .on('pointerup', function () {
51
+ this.removeAttribute('data-gc-brush-pressed');
52
+ });
53
+ brushGroupSelection.call(brushInstance);
54
+ if (brushOptions) {
55
+ brushGroupSelection
56
+ .selectAll('.selection')
57
+ .attr('fill-opacity', brushOptions.style.fillOpacity);
58
+ }
59
+ brushGroupSelections.push(brushGroupSelection);
60
+ });
61
+ return () => {
62
+ brushes.forEach((brushInstance) => {
63
+ brushInstance.on('start', null).on('brush', null).on('end', null);
64
+ });
65
+ brushGroupSelections.forEach((selection) => {
66
+ selection === null || selection === void 0 ? void 0 : selection.remove();
67
+ });
68
+ };
69
+ }, [areas, brushOptions, node, type, onBrushStart, onBrush, onBrushEnd]);
70
+ }
@@ -0,0 +1,10 @@
1
+ .gcharts-brush {
2
+ --gcharts-brush-color: rgba(51, 92, 173, 0.25);
3
+ }
4
+ .gcharts-brush:not([data-gc-brush-pressed=true]) .overlay {
5
+ cursor: default;
6
+ }
7
+ .gcharts-brush .selection {
8
+ fill: var(--gcharts-brush-color);
9
+ stroke: none;
10
+ }
@@ -0,0 +1,24 @@
1
+ import type { BrushBehavior } from 'd3';
2
+ import type { PreparedZoom } from '../useChartOptions/types';
3
+ type BrushType = PreparedZoom['type'];
4
+ type BrushSelection = [number, number] | [[number, number], [number, number]];
5
+ export interface BrushArea {
6
+ /**
7
+ * Array of points [[x0, y0], [x1, y1]], where [x0, y0] is the top-left corner
8
+ * and [x1, y1] is the bottom-right corner.
9
+ *
10
+ * The brush extent determines the size of the invisible overlay and also constrains the brush selection;
11
+ * the brush selection cannot go outside the brush extent.
12
+ */
13
+ extent: [[number, number], [number, number]];
14
+ }
15
+ export interface UseBrushProps {
16
+ areas: BrushArea[];
17
+ node: SVGGElement | null;
18
+ type?: BrushType;
19
+ brushOptions?: PreparedZoom['brush'];
20
+ onBrushStart?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>) => void;
21
+ onBrush?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>, selection: BrushSelection) => void;
22
+ onBrushEnd?: (this: SVGGElement, brushInstance: BrushBehavior<unknown>, selection: BrushSelection | null) => void;
23
+ }
24
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -5,9 +5,9 @@ type Args = {
5
5
  width: number;
6
6
  height: number;
7
7
  margin: ChartMargin;
8
- preparedLegend: PreparedLegend;
9
- preparedXAxis: PreparedAxis;
10
- preparedYAxis: PreparedAxis[];
8
+ preparedLegend: PreparedLegend | null;
9
+ preparedXAxis: PreparedAxis | null;
10
+ preparedYAxis: PreparedAxis[] | null;
11
11
  preparedSeries: PreparedSeries[];
12
12
  };
13
13
  export declare const useChartDimensions: (args: Args) => {
@@ -5,10 +5,10 @@ export { getBoundsWidth } from './utils';
5
5
  const getBottomOffset = (args) => {
6
6
  const { hasAxisRelatedSeries, preparedLegend, preparedXAxis } = args;
7
7
  let result = 0;
8
- if (preparedLegend.enabled) {
8
+ if (preparedLegend === null || preparedLegend === void 0 ? void 0 : preparedLegend.enabled) {
9
9
  result += preparedLegend.height + preparedLegend.margin;
10
10
  }
11
- if (!preparedXAxis.visible) {
11
+ if (!(preparedXAxis === null || preparedXAxis === void 0 ? void 0 : preparedXAxis.visible)) {
12
12
  return result;
13
13
  }
14
14
  if (hasAxisRelatedSeries) {
@@ -2,9 +2,9 @@ import type { PreparedAxis, PreparedChart } from '../../hooks';
2
2
  export declare const getBoundsWidth: (args: {
3
3
  chartWidth: number;
4
4
  chartMargin: PreparedChart["margin"];
5
- preparedYAxis: PreparedAxis[];
5
+ preparedYAxis: PreparedAxis[] | null;
6
6
  }) => number;
7
7
  export declare function getYAxisWidth(axis: PreparedAxis | undefined): number;
8
8
  export declare function getWidthOccupiedByYAxis(args: {
9
- preparedAxis: PreparedAxis[];
9
+ preparedAxis: PreparedAxis[] | null;
10
10
  }): number;
@@ -1,6 +1,7 @@
1
- import type { ChartData } from '../../types';
1
+ import type { ChartData, ChartSeries } from '../../types';
2
2
  import type { PreparedChart, PreparedTitle } from './types';
3
3
  export declare const getPreparedChart: (args: {
4
4
  chart: ChartData["chart"];
5
+ seriesData: ChartSeries[];
5
6
  preparedTitle?: PreparedTitle;
6
7
  }) => PreparedChart;
@@ -1,4 +1,6 @@
1
1
  import get from 'lodash/get';
2
+ import intersection from 'lodash/intersection';
3
+ import { SeriesType } from '../../constants';
2
4
  const getMarginTop = (args) => {
3
5
  const { chart, preparedTitle } = args;
4
6
  let marginTop = get(chart, 'margin.top', 0);
@@ -11,12 +13,88 @@ const getMarginRight = (args) => {
11
13
  const { chart } = args;
12
14
  return get(chart, 'margin.right', 0);
13
15
  };
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
+ }
14
91
  export const getPreparedChart = (args) => {
15
- const { chart, preparedTitle } = args;
92
+ const { chart, preparedTitle, seriesData } = args;
16
93
  const marginTop = getMarginTop({ chart, preparedTitle });
17
94
  const marginBottom = get(chart, 'margin.bottom', 0);
18
95
  const marginLeft = get(chart, 'margin.left', 0);
19
96
  const marginRight = getMarginRight({ chart });
97
+ const zoom = getPreparedZoom({ zoom: chart === null || chart === void 0 ? void 0 : chart.zoom, seriesData });
20
98
  return {
21
99
  margin: {
22
100
  top: marginTop,
@@ -24,5 +102,6 @@ export const getPreparedChart = (args) => {
24
102
  bottom: marginBottom,
25
103
  left: marginLeft,
26
104
  },
105
+ zoom,
27
106
  };
28
107
  };
@@ -4,13 +4,14 @@ import { getPreparedChart } from './chart';
4
4
  import { getPreparedTitle } from './title';
5
5
  import { getPreparedTooltip } from './tooltip';
6
6
  export const useChartOptions = (args) => {
7
- const { data: { chart, title, tooltip, colors }, } = args;
7
+ const { data: { chart, title, tooltip, colors, series }, } = args;
8
8
  const options = React.useMemo(() => {
9
9
  const preparedTitle = getPreparedTitle({ title });
10
10
  const preparedTooltip = getPreparedTooltip({ tooltip });
11
11
  const preparedChart = getPreparedChart({
12
12
  chart,
13
13
  preparedTitle,
14
+ seriesData: series.data,
14
15
  });
15
16
  return {
16
17
  chart: preparedChart,
@@ -18,6 +19,6 @@ export const useChartOptions = (args) => {
18
19
  tooltip: preparedTooltip,
19
20
  colors: colors !== null && colors !== void 0 ? colors : DEFAULT_PALETTE,
20
21
  };
21
- }, [chart, colors, title, tooltip]);
22
+ }, [chart, colors, title, tooltip, series.data]);
22
23
  return options;
23
24
  };
@@ -1,5 +1,5 @@
1
1
  import type { DashStyle } from '../../constants';
2
- import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisTitleAlignment, ChartAxisType, ChartData, ChartMargin, PlotLayerPlacement } from '../../types';
2
+ import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisTitleAlignment, ChartAxisType, ChartData, ChartMargin, ChartZoom, DeepRequired, PlotLayerPlacement } from '../../types';
3
3
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation'>> & {
4
4
  style: BaseTextStyle;
5
5
  rotation: number;
@@ -8,8 +8,10 @@ type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style'
8
8
  lineHeight: number;
9
9
  maxWidth: number;
10
10
  };
11
+ export type PreparedZoom = DeepRequired<Omit<ChartZoom, 'enabled'>>;
11
12
  export type PreparedChart = {
12
13
  margin: ChartMargin;
14
+ zoom: PreparedZoom | null;
13
15
  };
14
16
  export type PreparedAxisPlotBand = Required<AxisPlotBand>;
15
17
  export type PreparedAxisCrosshair = Required<AxisCrosshair>;
@@ -1,7 +1,7 @@
1
1
  import type { ChartSeries, ChartXAxis } from '../../types';
2
2
  import type { PreparedAxis } from './types';
3
- export declare const getPreparedXAxis: ({ xAxis, series, width, }: {
3
+ export declare const getPreparedXAxis: ({ xAxis, seriesData, width, }: {
4
4
  xAxis?: ChartXAxis;
5
- series: ChartSeries[];
5
+ seriesData: ChartSeries[];
6
6
  width: number;
7
- }) => PreparedAxis;
7
+ }) => Promise<PreparedAxis>;
@@ -2,8 +2,8 @@ import get from 'lodash/get';
2
2
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, axisCrosshairDefaults, axisLabelsDefaults, xAxisTitleDefaults, } from '../../constants';
3
3
  import { CHART_SERIES_WITH_VOLUME_ON_X_AXIS, calculateCos, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getMaxTickCount, getTicksCount, getXAxisItems, hasOverlappingLabels, wrapText, } from '../../utils';
4
4
  import { createXScale } from '../useAxisScales';
5
- function getLabelSettings({ axis, series, width, autoRotation = true, }) {
6
- const scale = createXScale(axis, series, width);
5
+ async function getLabelSettings({ axis, seriesData, width, autoRotation = true, }) {
6
+ const scale = createXScale(axis, seriesData, width);
7
7
  const tickCount = getTicksCount({ axis, range: width });
8
8
  const ticks = getXAxisItems({
9
9
  scale: scale,
@@ -27,11 +27,11 @@ function getLabelSettings({ axis, series, width, autoRotation = true, }) {
27
27
  const defaultRotation = overlapping && autoRotation ? -45 : 0;
28
28
  const rotation = axis.labels.rotation || defaultRotation;
29
29
  const labelsHeight = rotation
30
- ? getLabelsSize({
30
+ ? (await getLabelsSize({
31
31
  labels,
32
32
  style: axis.labels.style,
33
33
  rotation,
34
- }).maxHeight
34
+ })).maxHeight
35
35
  : axis.labels.lineHeight;
36
36
  const maxHeight = rotation ? calculateCos(rotation) * axis.labels.maxWidth : labelsHeight;
37
37
  return { height: Math.min(maxHeight, labelsHeight), rotation };
@@ -48,17 +48,17 @@ function getAxisMin(axis, series) {
48
48
  }
49
49
  return min;
50
50
  }
51
- export const getPreparedXAxis = ({ xAxis, series, width, }) => {
51
+ export const getPreparedXAxis = async ({ xAxis, seriesData, width, }) => {
52
52
  var _a;
53
53
  const titleText = get(xAxis, 'title.text', '');
54
54
  const titleStyle = Object.assign(Object.assign({}, xAxisTitleDefaults.style), get(xAxis, 'title.style'));
55
55
  const titleMaxRowsCount = get(xAxis, 'title.maxRowCount', xAxisTitleDefaults.maxRowCount);
56
- const estimatedTitleRows = wrapText({
56
+ const estimatedTitleRows = (await wrapText({
57
57
  text: titleText,
58
58
  style: titleStyle,
59
59
  width,
60
- }).slice(0, titleMaxRowsCount);
61
- const titleSize = getLabelsSize({
60
+ })).slice(0, titleMaxRowsCount);
61
+ const titleSize = await getLabelsSize({
62
62
  labels: [titleText],
63
63
  style: titleStyle,
64
64
  });
@@ -92,7 +92,7 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
92
92
  align: get(xAxis, 'title.align', xAxisTitleDefaults.align),
93
93
  maxRowCount: get(xAxis, 'title.maxRowCount', xAxisTitleDefaults.maxRowCount),
94
94
  },
95
- min: getAxisMin(xAxis, series),
95
+ min: getAxisMin(xAxis, seriesData),
96
96
  maxPadding: get(xAxis, 'maxPadding', 0.01),
97
97
  grid: {
98
98
  enabled: get(xAxis, 'grid.enabled', true),
@@ -128,9 +128,9 @@ export const getPreparedXAxis = ({ xAxis, series, width, }) => {
128
128
  },
129
129
  visible: get(xAxis, 'visible', true),
130
130
  };
131
- const { height, rotation } = getLabelSettings({
131
+ const { height, rotation } = await getLabelSettings({
132
132
  axis: preparedXAxis,
133
- series,
133
+ seriesData,
134
134
  width,
135
135
  autoRotation: (_a = xAxis === null || xAxis === void 0 ? void 0 : xAxis.labels) === null || _a === void 0 ? void 0 : _a.autoRotation,
136
136
  });
@@ -1,7 +1,7 @@
1
1
  import type { ChartSeries, ChartYAxis } from '../../types';
2
2
  import type { PreparedAxis } from './types';
3
- export declare const getPreparedYAxis: ({ series, yAxis, height, }: {
4
- series: ChartSeries[];
3
+ export declare const getPreparedYAxis: ({ seriesData, yAxis, height, }: {
4
+ seriesData: ChartSeries[];
5
5
  yAxis: ChartYAxis[] | undefined;
6
6
  height: number;
7
- }) => PreparedAxis[];
7
+ }) => Promise<PreparedAxis[]>;
@@ -2,12 +2,12 @@ import get from 'lodash/get';
2
2
  import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, axisCrosshairDefaults, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
3
3
  import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, getWaterfallPointSubtotal, isAxisRelatedSeries, wrapText, } from '../../utils';
4
4
  import { createYScale } from '../useAxisScales';
5
- const getAxisLabelMaxWidth = (args) => {
6
- const { axis, series } = args;
5
+ const getAxisLabelMaxWidth = async (args) => {
6
+ const { axis, seriesData } = args;
7
7
  if (!axis.labels.enabled) {
8
8
  return 0;
9
9
  }
10
- const scale = createYScale(axis, series, 1);
10
+ const scale = createYScale(axis, seriesData, 1);
11
11
  const ticks = getScaleTicks(scale);
12
12
  // FIXME: it is necessary to filter data, since we do not draw overlapping ticks
13
13
  const step = getClosestPointsRange(axis, ticks);
@@ -16,17 +16,18 @@ const getAxisLabelMaxWidth = (args) => {
16
16
  value: tick,
17
17
  step,
18
18
  }));
19
- return getLabelsSize({
19
+ const size = await getLabelsSize({
20
20
  labels,
21
21
  style: axis.labels.style,
22
22
  rotation: axis.labels.rotation,
23
- }).maxWidth;
23
+ });
24
+ return size.maxWidth;
24
25
  };
25
- function getAxisMin(axis, series) {
26
+ function getAxisMin(axis, seriesData) {
26
27
  const min = axis === null || axis === void 0 ? void 0 : axis.min;
27
28
  if (typeof min === 'undefined' &&
28
- (series === null || series === void 0 ? void 0 : series.some((s) => CHART_SERIES_WITH_VOLUME_ON_Y_AXIS.includes(s.type)))) {
29
- return series.reduce((minValue, s) => {
29
+ (seriesData === null || seriesData === void 0 ? void 0 : seriesData.some((s) => CHART_SERIES_WITH_VOLUME_ON_Y_AXIS.includes(s.type)))) {
30
+ return seriesData.reduce((minValue, s) => {
30
31
  switch (s.type) {
31
32
  case 'waterfall': {
32
33
  const minSubTotal = s.data.reduce((res, d) => Math.min(res, getWaterfallPointSubtotal(d, s) || 0), 0);
@@ -42,14 +43,14 @@ function getAxisMin(axis, series) {
42
43
  }
43
44
  return min;
44
45
  }
45
- export const getPreparedYAxis = ({ series, yAxis, height, }) => {
46
+ export const getPreparedYAxis = ({ seriesData, yAxis, height, }) => {
46
47
  const axisByPlot = [];
47
48
  const axisItems = yAxis || [{}];
48
- const hasAxisRelatedSeries = series.some(isAxisRelatedSeries);
49
+ const hasAxisRelatedSeries = seriesData.some(isAxisRelatedSeries);
49
50
  if (!hasAxisRelatedSeries) {
50
- return [];
51
+ return Promise.resolve([]);
51
52
  }
52
- return axisItems.map((axisItem) => {
53
+ return Promise.all(axisItems.map(async (axisItem) => {
53
54
  var _a;
54
55
  const plotIndex = get(axisItem, 'plotIndex', 0);
55
56
  const firstPlotAxis = !axisByPlot[plotIndex];
@@ -65,12 +66,12 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
65
66
  const titleText = get(axisItem, 'title.text', '');
66
67
  const titleStyle = Object.assign(Object.assign({}, yAxisTitleDefaults.style), get(axisItem, 'title.style'));
67
68
  const titleMaxRowsCount = get(axisItem, 'title.maxRowCount', yAxisTitleDefaults.maxRowCount);
68
- const estimatedTitleRows = wrapText({
69
+ const estimatedTitleRows = (await wrapText({
69
70
  text: titleText,
70
71
  style: titleStyle,
71
72
  width: height,
72
- }).slice(0, titleMaxRowsCount);
73
- const titleSize = getLabelsSize({ labels: [titleText], style: titleStyle });
73
+ })).slice(0, titleMaxRowsCount);
74
+ const titleSize = await getLabelsSize({ labels: [titleText], style: titleStyle });
74
75
  const axisType = get(axisItem, 'type', DEFAULT_AXIS_TYPE);
75
76
  const preparedAxis = {
76
77
  type: axisType,
@@ -103,7 +104,7 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
103
104
  align: get(axisItem, 'title.align', yAxisTitleDefaults.align),
104
105
  maxRowCount: titleMaxRowsCount,
105
106
  },
106
- min: getAxisMin(axisItem, series),
107
+ min: getAxisMin(axisItem, seriesData),
107
108
  maxPadding: get(axisItem, 'maxPadding', 0.05),
108
109
  grid: {
109
110
  enabled: get(axisItem, 'grid.enabled', firstPlotAxis ||
@@ -141,8 +142,11 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
141
142
  visible: get(axisItem, 'visible', true),
142
143
  };
143
144
  if (labelsEnabled) {
144
- preparedAxis.labels.width = getAxisLabelMaxWidth({ axis: preparedAxis, series });
145
+ preparedAxis.labels.width = await getAxisLabelMaxWidth({
146
+ axis: preparedAxis,
147
+ seriesData,
148
+ });
145
149
  }
146
150
  return preparedAxis;
147
- });
151
+ }));
148
152
  };
@@ -1,7 +1,7 @@
1
1
  import type { Dispatch } from 'd3';
2
2
  import type { ChartScale, PreparedAxis, PreparedSplit } from '../../hooks';
3
3
  type Props = {
4
- xAxis: PreparedAxis;
4
+ xAxis: PreparedAxis | null;
5
5
  yAxes: PreparedAxis[];
6
6
  width: number;
7
7
  height: number;
@@ -5,7 +5,7 @@ import { useCrosshairHover } from './useCrosshairHover';
5
5
  export const useCrosshair = (props) => {
6
6
  var _a, _b;
7
7
  const { xScale, plotElement, yScale, dispatcher, xAxis, yAxes, split, width, height: totalHeight, boundsOffsetTop, boundsOffsetLeft, } = props;
8
- const crosshairEnabled = xAxis.crosshair.enabled || yAxes.some((axis) => axis.crosshair.enabled);
8
+ const crosshairEnabled = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.crosshair.enabled) || yAxes.some((axis) => axis.crosshair.enabled);
9
9
  const { hovered, pointerPosition } = useCrosshairHover({ dispatcher, enabled: crosshairEnabled });
10
10
  const pointerXPos = (_a = pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[0]) !== null && _a !== void 0 ? _a : 0;
11
11
  const pointerYPos = (_b = pointerPosition === null || pointerPosition === void 0 ? void 0 : pointerPosition[1]) !== null && _b !== void 0 ? _b : 0;
@@ -17,7 +17,7 @@ export const useCrosshair = (props) => {
17
17
  const svgElement = select(plotElement);
18
18
  svgElement.selectAll(`[${plotCrosshairDataAttr}]`).remove();
19
19
  const lineGenerator = line();
20
- if (xAxis.crosshair.enabled && (hovered === null || hovered === void 0 ? void 0 : hovered.length)) {
20
+ if ((xAxis === null || xAxis === void 0 ? void 0 : xAxis.crosshair.enabled) && (hovered === null || hovered === void 0 ? void 0 : hovered.length)) {
21
21
  const xAxisScale = xScale;
22
22
  const crosshairDataAttr = 'data-crosshair-x-line';
23
23
  const crosshairSelection = svgElement
@@ -1,17 +1,19 @@
1
1
  import type { ChartData } from '../../types';
2
2
  import type { PreparedAxis, PreparedChart } from '../useChartOptions/types';
3
- import type { OnLegendItemClick, PreparedSeries } from './types';
3
+ import type { OnLegendItemClick, PreparedLegend, PreparedSeries } from './types';
4
4
  type Args = {
5
5
  chartWidth: number;
6
6
  chartHeight: number;
7
7
  chartMargin: PreparedChart['margin'];
8
+ colors: string[];
8
9
  legend: ChartData['legend'];
9
- series: ChartData['series'];
10
+ originalSeriesData: ChartData['series']['data'];
11
+ seriesData: ChartData['series']['data'];
12
+ seriesOptions: ChartData['series']['options'];
10
13
  preparedYAxis: PreparedAxis[];
11
- colors: string[];
12
14
  };
13
15
  export declare const useSeries: (args: Args) => {
14
- legendItems: import("./types").LegendItem[][];
16
+ legendItems: never[] | import("./types").LegendItem[][];
15
17
  legendConfig: {
16
18
  offset: {
17
19
  left: number;
@@ -23,8 +25,8 @@ export declare const useSeries: (args: Args) => {
23
25
  end: number;
24
26
  }[];
25
27
  } | undefined;
26
- };
27
- preparedLegend: import("./types").PreparedLegend;
28
+ } | undefined;
29
+ preparedLegend: PreparedLegend | null;
28
30
  preparedSeries: PreparedSeries[];
29
31
  preparedSeriesOptions: import("../../constants").SeriesOptionsDefaults;
30
32
  handleLegendItemClick: OnLegendItemClick;