@gravity-ui/charts 1.8.0 → 1.10.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 (255) hide show
  1. package/dist/cjs/components/Axis/AxisX.d.ts +2 -1
  2. package/dist/cjs/components/Axis/AxisX.js +147 -141
  3. package/dist/cjs/components/Axis/AxisY.d.ts +2 -1
  4. package/dist/cjs/components/Axis/AxisY.js +118 -116
  5. package/dist/cjs/components/ChartInner/index.js +36 -9
  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 +59 -10
  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 +202 -191
  12. package/dist/cjs/components/Legend/styles.css +2 -0
  13. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +1 -1
  14. package/dist/cjs/components/Tooltip/DefaultContent.d.ts +1 -1
  15. package/dist/cjs/components/Tooltip/DefaultContent.js +1 -1
  16. package/dist/cjs/components/Tooltip/index.d.ts +1 -1
  17. package/dist/cjs/constants/chart-types.d.ts +12 -0
  18. package/dist/cjs/constants/chart-types.js +12 -0
  19. package/dist/cjs/constants/defaults/axis.d.ts +3 -1
  20. package/dist/cjs/constants/defaults/axis.js +10 -0
  21. package/dist/cjs/constants/index.d.ts +6 -47
  22. package/dist/cjs/constants/index.js +6 -72
  23. package/dist/cjs/constants/layout-algorithms.d.ts +7 -0
  24. package/dist/cjs/constants/layout-algorithms.js +8 -0
  25. package/dist/cjs/constants/line-styles.d.ts +20 -0
  26. package/dist/cjs/constants/line-styles.js +20 -0
  27. package/dist/cjs/constants/palette.d.ts +1 -0
  28. package/dist/cjs/constants/palette.js +22 -0
  29. package/dist/cjs/constants/symbol-types.d.ts +7 -0
  30. package/dist/cjs/constants/symbol-types.js +8 -0
  31. package/dist/cjs/constants/typography.d.ts +1 -0
  32. package/dist/cjs/constants/typography.js +1 -0
  33. package/dist/cjs/hooks/hooks-utils/index.d.ts +1 -0
  34. package/dist/cjs/hooks/hooks-utils/index.js +1 -0
  35. package/dist/cjs/hooks/hooks-utils/zoom.d.ts +8 -0
  36. package/dist/cjs/hooks/hooks-utils/zoom.js +81 -0
  37. package/dist/cjs/hooks/index.d.ts +1 -0
  38. package/dist/cjs/hooks/index.js +1 -0
  39. package/dist/cjs/hooks/useAxisScales/index.d.ts +4 -2
  40. package/dist/cjs/hooks/useAxisScales/index.js +22 -8
  41. package/dist/cjs/hooks/useBrush/index.d.ts +3 -0
  42. package/dist/cjs/hooks/useBrush/index.js +70 -0
  43. package/dist/cjs/hooks/useBrush/styles.css +10 -0
  44. package/dist/cjs/hooks/useBrush/types.d.ts +24 -0
  45. package/dist/cjs/hooks/useBrush/types.js +1 -0
  46. package/dist/cjs/hooks/useChartDimensions/index.d.ts +3 -3
  47. package/dist/cjs/hooks/useChartDimensions/index.js +2 -2
  48. package/dist/cjs/hooks/useChartDimensions/utils.d.ts +2 -2
  49. package/dist/cjs/hooks/useChartOptions/chart.d.ts +2 -1
  50. package/dist/cjs/hooks/useChartOptions/chart.js +80 -1
  51. package/dist/cjs/hooks/useChartOptions/index.js +3 -2
  52. package/dist/cjs/hooks/useChartOptions/types.d.ts +6 -2
  53. package/dist/cjs/hooks/useChartOptions/x-axis.d.ts +3 -3
  54. package/dist/cjs/hooks/useChartOptions/x-axis.js +22 -13
  55. package/dist/cjs/hooks/useChartOptions/y-axis.d.ts +3 -3
  56. package/dist/cjs/hooks/useChartOptions/y-axis.js +36 -21
  57. package/dist/cjs/hooks/useCrosshair/index.d.ts +17 -0
  58. package/dist/cjs/hooks/useCrosshair/index.js +139 -0
  59. package/dist/cjs/hooks/useCrosshair/useCrosshairHover.d.ts +11 -0
  60. package/dist/cjs/hooks/useCrosshair/useCrosshairHover.js +18 -0
  61. package/dist/cjs/hooks/useSeries/index.d.ts +8 -6
  62. package/dist/cjs/hooks/useSeries/index.js +41 -22
  63. package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +27 -2
  64. package/dist/cjs/hooks/useSeries/prepare-bar-y.js +5 -5
  65. package/dist/cjs/hooks/useSeries/prepare-legend.d.ts +1 -1
  66. package/dist/cjs/hooks/useSeries/prepare-legend.js +27 -9
  67. package/dist/cjs/hooks/useSeries/prepare-line.d.ts +1 -2
  68. package/dist/cjs/hooks/useSeries/prepare-line.js +3 -3
  69. package/dist/cjs/hooks/useSeries/prepareSeries.d.ts +1 -1
  70. package/dist/cjs/hooks/useSeries/prepareSeries.js +2 -2
  71. package/dist/cjs/hooks/useSeries/types.d.ts +2 -1
  72. package/dist/cjs/hooks/useShapes/area/index.js +1 -1
  73. package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +1 -1
  74. package/dist/cjs/hooks/useShapes/area/prepare-data.js +32 -16
  75. package/dist/cjs/hooks/useShapes/area/types.d.ts +1 -0
  76. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  77. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +17 -13
  78. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
  79. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +6 -6
  80. package/dist/cjs/hooks/useShapes/index.d.ts +1 -1
  81. package/dist/cjs/hooks/useShapes/index.js +40 -31
  82. package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +1 -1
  83. package/dist/cjs/hooks/useShapes/line/prepare-data.js +14 -11
  84. package/dist/cjs/hooks/useShapes/line/types.d.ts +1 -0
  85. package/dist/cjs/hooks/useShapes/marker.js +2 -2
  86. package/dist/cjs/hooks/useShapes/pie/index.js +3 -3
  87. package/dist/cjs/hooks/useShapes/pie/prepare-data.d.ts +1 -1
  88. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +15 -11
  89. package/dist/cjs/hooks/useShapes/radar/prepare-data.d.ts +1 -1
  90. package/dist/cjs/hooks/useShapes/radar/prepare-data.js +6 -7
  91. package/dist/cjs/hooks/useShapes/radar/types.d.ts +1 -0
  92. package/dist/cjs/hooks/useShapes/scatter/index.js +0 -1
  93. package/dist/cjs/hooks/useShapes/scatter/prepare-data.js +2 -0
  94. package/dist/cjs/hooks/useShapes/scatter/types.d.ts +1 -0
  95. package/dist/cjs/hooks/useShapes/treemap/prepare-data.d.ts +1 -1
  96. package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +19 -16
  97. package/dist/cjs/hooks/useShapes/waterfall/index.js +2 -2
  98. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  99. package/dist/cjs/hooks/useShapes/waterfall/prepare-data.js +8 -7
  100. package/dist/cjs/hooks/useZoom/index.d.ts +18 -0
  101. package/dist/cjs/hooks/useZoom/index.js +54 -0
  102. package/dist/cjs/hooks/useZoom/types.d.ts +19 -0
  103. package/dist/cjs/hooks/useZoom/types.js +1 -0
  104. package/dist/cjs/hooks/useZoom/utils.d.ts +12 -0
  105. package/dist/cjs/hooks/useZoom/utils.js +128 -0
  106. package/dist/cjs/types/chart/axis.d.ts +26 -21
  107. package/dist/cjs/types/chart/chart.d.ts +5 -0
  108. package/dist/cjs/types/chart/line.d.ts +1 -1
  109. package/dist/cjs/types/chart/pie.d.ts +1 -1
  110. package/dist/cjs/types/chart/series.d.ts +1 -1
  111. package/dist/cjs/types/chart/tooltip.d.ts +1 -1
  112. package/dist/cjs/types/chart/zoom.d.ts +36 -0
  113. package/dist/cjs/types/chart/zoom.js +1 -0
  114. package/dist/cjs/types/index.d.ts +1 -0
  115. package/dist/cjs/types/index.js +1 -0
  116. package/dist/cjs/types/misc.d.ts +7 -0
  117. package/dist/cjs/utils/chart/axis-generators/bottom.d.ts +1 -1
  118. package/dist/cjs/utils/chart/axis-generators/bottom.js +25 -25
  119. package/dist/cjs/utils/chart/axis.d.ts +2 -1
  120. package/dist/cjs/utils/chart/axis.js +10 -2
  121. package/dist/cjs/utils/chart/get-closest-data.js +1 -1
  122. package/dist/cjs/utils/chart/text.d.ts +7 -7
  123. package/dist/cjs/utils/chart/text.js +37 -29
  124. package/dist/cjs/utils/chart-ui/pie-center-text.d.ts +1 -1
  125. package/dist/cjs/utils/chart-ui/pie-center-text.js +2 -2
  126. package/dist/cjs/validation/index.d.ts +1 -1
  127. package/dist/cjs/validation/index.js +16 -16
  128. package/dist/esm/components/Axis/AxisX.d.ts +2 -1
  129. package/dist/esm/components/Axis/AxisX.js +147 -141
  130. package/dist/esm/components/Axis/AxisY.d.ts +2 -1
  131. package/dist/esm/components/Axis/AxisY.js +118 -116
  132. package/dist/esm/components/ChartInner/index.js +36 -9
  133. package/dist/esm/components/ChartInner/useChartInnerHandlers.d.ts +1 -1
  134. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +8 -5
  135. package/dist/esm/components/ChartInner/useChartInnerProps.js +59 -10
  136. package/dist/esm/components/ChartInner/utils.d.ts +3 -0
  137. package/dist/esm/components/ChartInner/utils.js +28 -0
  138. package/dist/esm/components/Legend/index.js +202 -191
  139. package/dist/esm/components/Legend/styles.css +2 -0
  140. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +1 -1
  141. package/dist/esm/components/Tooltip/DefaultContent.d.ts +1 -1
  142. package/dist/esm/components/Tooltip/DefaultContent.js +1 -1
  143. package/dist/esm/components/Tooltip/index.d.ts +1 -1
  144. package/dist/esm/constants/chart-types.d.ts +12 -0
  145. package/dist/esm/constants/chart-types.js +12 -0
  146. package/dist/esm/constants/defaults/axis.d.ts +3 -1
  147. package/dist/esm/constants/defaults/axis.js +10 -0
  148. package/dist/esm/constants/index.d.ts +6 -47
  149. package/dist/esm/constants/index.js +6 -72
  150. package/dist/esm/constants/layout-algorithms.d.ts +7 -0
  151. package/dist/esm/constants/layout-algorithms.js +8 -0
  152. package/dist/esm/constants/line-styles.d.ts +20 -0
  153. package/dist/esm/constants/line-styles.js +20 -0
  154. package/dist/esm/constants/palette.d.ts +1 -0
  155. package/dist/esm/constants/palette.js +22 -0
  156. package/dist/esm/constants/symbol-types.d.ts +7 -0
  157. package/dist/esm/constants/symbol-types.js +8 -0
  158. package/dist/esm/constants/typography.d.ts +1 -0
  159. package/dist/esm/constants/typography.js +1 -0
  160. package/dist/esm/hooks/hooks-utils/index.d.ts +1 -0
  161. package/dist/esm/hooks/hooks-utils/index.js +1 -0
  162. package/dist/esm/hooks/hooks-utils/zoom.d.ts +8 -0
  163. package/dist/esm/hooks/hooks-utils/zoom.js +81 -0
  164. package/dist/esm/hooks/index.d.ts +1 -0
  165. package/dist/esm/hooks/index.js +1 -0
  166. package/dist/esm/hooks/useAxisScales/index.d.ts +4 -2
  167. package/dist/esm/hooks/useAxisScales/index.js +22 -8
  168. package/dist/esm/hooks/useBrush/index.d.ts +3 -0
  169. package/dist/esm/hooks/useBrush/index.js +70 -0
  170. package/dist/esm/hooks/useBrush/styles.css +10 -0
  171. package/dist/esm/hooks/useBrush/types.d.ts +24 -0
  172. package/dist/esm/hooks/useBrush/types.js +1 -0
  173. package/dist/esm/hooks/useChartDimensions/index.d.ts +3 -3
  174. package/dist/esm/hooks/useChartDimensions/index.js +2 -2
  175. package/dist/esm/hooks/useChartDimensions/utils.d.ts +2 -2
  176. package/dist/esm/hooks/useChartOptions/chart.d.ts +2 -1
  177. package/dist/esm/hooks/useChartOptions/chart.js +80 -1
  178. package/dist/esm/hooks/useChartOptions/index.js +3 -2
  179. package/dist/esm/hooks/useChartOptions/types.d.ts +6 -2
  180. package/dist/esm/hooks/useChartOptions/x-axis.d.ts +3 -3
  181. package/dist/esm/hooks/useChartOptions/x-axis.js +22 -13
  182. package/dist/esm/hooks/useChartOptions/y-axis.d.ts +3 -3
  183. package/dist/esm/hooks/useChartOptions/y-axis.js +36 -21
  184. package/dist/esm/hooks/useCrosshair/index.d.ts +17 -0
  185. package/dist/esm/hooks/useCrosshair/index.js +139 -0
  186. package/dist/esm/hooks/useCrosshair/useCrosshairHover.d.ts +11 -0
  187. package/dist/esm/hooks/useCrosshair/useCrosshairHover.js +18 -0
  188. package/dist/esm/hooks/useSeries/index.d.ts +8 -6
  189. package/dist/esm/hooks/useSeries/index.js +41 -22
  190. package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +27 -2
  191. package/dist/esm/hooks/useSeries/prepare-bar-y.js +5 -5
  192. package/dist/esm/hooks/useSeries/prepare-legend.d.ts +1 -1
  193. package/dist/esm/hooks/useSeries/prepare-legend.js +27 -9
  194. package/dist/esm/hooks/useSeries/prepare-line.d.ts +1 -2
  195. package/dist/esm/hooks/useSeries/prepare-line.js +3 -3
  196. package/dist/esm/hooks/useSeries/prepareSeries.d.ts +1 -1
  197. package/dist/esm/hooks/useSeries/prepareSeries.js +2 -2
  198. package/dist/esm/hooks/useSeries/types.d.ts +2 -1
  199. package/dist/esm/hooks/useShapes/area/index.js +1 -1
  200. package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +1 -1
  201. package/dist/esm/hooks/useShapes/area/prepare-data.js +32 -16
  202. package/dist/esm/hooks/useShapes/area/types.d.ts +1 -0
  203. package/dist/esm/hooks/useShapes/bar-x/prepare-data.d.ts +1 -1
  204. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +17 -13
  205. package/dist/esm/hooks/useShapes/bar-y/prepare-data.d.ts +1 -1
  206. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +6 -6
  207. package/dist/esm/hooks/useShapes/index.d.ts +1 -1
  208. package/dist/esm/hooks/useShapes/index.js +40 -31
  209. package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +1 -1
  210. package/dist/esm/hooks/useShapes/line/prepare-data.js +14 -11
  211. package/dist/esm/hooks/useShapes/line/types.d.ts +1 -0
  212. package/dist/esm/hooks/useShapes/marker.js +2 -2
  213. package/dist/esm/hooks/useShapes/pie/index.js +3 -3
  214. package/dist/esm/hooks/useShapes/pie/prepare-data.d.ts +1 -1
  215. package/dist/esm/hooks/useShapes/pie/prepare-data.js +15 -11
  216. package/dist/esm/hooks/useShapes/radar/prepare-data.d.ts +1 -1
  217. package/dist/esm/hooks/useShapes/radar/prepare-data.js +6 -7
  218. package/dist/esm/hooks/useShapes/radar/types.d.ts +1 -0
  219. package/dist/esm/hooks/useShapes/scatter/index.js +0 -1
  220. package/dist/esm/hooks/useShapes/scatter/prepare-data.js +2 -0
  221. package/dist/esm/hooks/useShapes/scatter/types.d.ts +1 -0
  222. package/dist/esm/hooks/useShapes/treemap/prepare-data.d.ts +1 -1
  223. package/dist/esm/hooks/useShapes/treemap/prepare-data.js +19 -16
  224. package/dist/esm/hooks/useShapes/waterfall/index.js +2 -2
  225. package/dist/esm/hooks/useShapes/waterfall/prepare-data.d.ts +1 -1
  226. package/dist/esm/hooks/useShapes/waterfall/prepare-data.js +8 -7
  227. package/dist/esm/hooks/useZoom/index.d.ts +18 -0
  228. package/dist/esm/hooks/useZoom/index.js +54 -0
  229. package/dist/esm/hooks/useZoom/types.d.ts +19 -0
  230. package/dist/esm/hooks/useZoom/types.js +1 -0
  231. package/dist/esm/hooks/useZoom/utils.d.ts +12 -0
  232. package/dist/esm/hooks/useZoom/utils.js +128 -0
  233. package/dist/esm/types/chart/axis.d.ts +26 -21
  234. package/dist/esm/types/chart/chart.d.ts +5 -0
  235. package/dist/esm/types/chart/line.d.ts +1 -1
  236. package/dist/esm/types/chart/pie.d.ts +1 -1
  237. package/dist/esm/types/chart/series.d.ts +1 -1
  238. package/dist/esm/types/chart/tooltip.d.ts +1 -1
  239. package/dist/esm/types/chart/zoom.d.ts +36 -0
  240. package/dist/esm/types/chart/zoom.js +1 -0
  241. package/dist/esm/types/index.d.ts +1 -0
  242. package/dist/esm/types/index.js +1 -0
  243. package/dist/esm/types/misc.d.ts +7 -0
  244. package/dist/esm/utils/chart/axis-generators/bottom.d.ts +1 -1
  245. package/dist/esm/utils/chart/axis-generators/bottom.js +25 -25
  246. package/dist/esm/utils/chart/axis.d.ts +2 -1
  247. package/dist/esm/utils/chart/axis.js +10 -2
  248. package/dist/esm/utils/chart/get-closest-data.js +1 -1
  249. package/dist/esm/utils/chart/text.d.ts +7 -7
  250. package/dist/esm/utils/chart/text.js +37 -29
  251. package/dist/esm/utils/chart-ui/pie-center-text.d.ts +1 -1
  252. package/dist/esm/utils/chart-ui/pie-center-text.js +2 -2
  253. package/dist/esm/validation/index.d.ts +1 -1
  254. package/dist/esm/validation/index.js +16 -16
  255. package/package.json +2 -1
@@ -4,7 +4,7 @@ import { getLabelsSize } from '../../../utils';
4
4
  import { getFormattedValue } from '../../../utils/chart/format';
5
5
  import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '../constants';
6
6
  import { getXValue, getYValue } from '../utils';
7
- function getLabelData(d, plotHeight) {
7
+ async function getLabelData(d, plotHeight) {
8
8
  var _a, _b;
9
9
  if (!d.series.dataLabels.enabled) {
10
10
  return undefined;
@@ -12,7 +12,7 @@ function getLabelData(d, plotHeight) {
12
12
  const labelValue = (_b = (_a = d.data.label) !== null && _a !== void 0 ? _a : d.data.y) !== null && _b !== void 0 ? _b : d.subTotal;
13
13
  const text = getFormattedValue(Object.assign({ value: labelValue }, d.series.dataLabels));
14
14
  const style = d.series.dataLabels.style;
15
- const { maxHeight: height, maxWidth: width } = getLabelsSize({ labels: [text], style });
15
+ const { maxHeight: height, maxWidth: width } = await getLabelsSize({ labels: [text], style });
16
16
  let y;
17
17
  if (Number(d.data.y) > 0 || d.data.total) {
18
18
  y = Math.max(height, d.y - d.series.dataLabels.padding);
@@ -52,7 +52,7 @@ function getBandWidth(args) {
52
52
  });
53
53
  return bandWidth;
54
54
  }
55
- export const prepareWaterfallData = (args) => {
55
+ export const prepareWaterfallData = async (args) => {
56
56
  const { series, seriesOptions, xAxis, xScale, yAxis: [yAxis], yScale: [yScale], } = args;
57
57
  const yLinearScale = yScale;
58
58
  const plotHeight = yLinearScale(yLinearScale.domain()[0]);
@@ -77,9 +77,10 @@ export const prepareWaterfallData = (args) => {
77
77
  });
78
78
  let totalValue = 0;
79
79
  const result = [];
80
- data.forEach((item, _index) => {
80
+ for (let i = 0; i < data.length; i++) {
81
+ const item = data[i];
81
82
  if (typeof item.data.y !== 'number' && !item.data.total) {
82
- return;
83
+ continue;
83
84
  }
84
85
  if (!item.data.total) {
85
86
  totalValue += Number(item.data.y);
@@ -129,8 +130,8 @@ export const prepareWaterfallData = (args) => {
129
130
  subTotal: totalValue,
130
131
  htmlElements: [],
131
132
  };
132
- preparedData.label = getLabelData(preparedData, plotHeight);
133
+ preparedData.label = await getLabelData(preparedData, plotHeight);
133
134
  result.push(preparedData);
134
- });
135
+ }
135
136
  return result;
136
137
  };
@@ -0,0 +1,18 @@
1
+ import type { ChartScale } from '../useAxisScales';
2
+ import type { PreparedAxis, PreparedZoom } from '../useChartOptions/types';
3
+ import type { PreparedSplit } from '../useSplit/types';
4
+ import type { ZoomState } from './types';
5
+ interface UseZoomProps {
6
+ node: SVGGElement | null;
7
+ onUpdate: (zoomState: Partial<ZoomState>) => void;
8
+ plotContainerHeight: number;
9
+ plotContainerWidth: number;
10
+ preparedSplit: PreparedSplit;
11
+ preparedZoom: PreparedZoom | null;
12
+ xAxis: PreparedAxis | null;
13
+ xScale?: ChartScale;
14
+ yAxis: PreparedAxis[];
15
+ yScale?: ChartScale[];
16
+ }
17
+ export declare function useZoom(props: UseZoomProps): void;
18
+ export {};
@@ -0,0 +1,54 @@
1
+ import React from 'react';
2
+ import { select } from 'd3';
3
+ import { useBrush } from '../useBrush';
4
+ import { selectionToZoomBounds } from './utils';
5
+ export function useZoom(props) {
6
+ const { node, onUpdate, plotContainerHeight, plotContainerWidth, preparedSplit, preparedZoom, xAxis, xScale, yAxis, yScale, } = props;
7
+ const areas = React.useMemo(() => {
8
+ const result = [];
9
+ if (!preparedZoom) {
10
+ return result;
11
+ }
12
+ if (preparedSplit.plots.length > 1) {
13
+ preparedSplit.plots.forEach((plot) => {
14
+ result.push({
15
+ extent: [
16
+ [0, plot.top],
17
+ [plotContainerWidth, plot.top + plot.height],
18
+ ],
19
+ });
20
+ });
21
+ }
22
+ else {
23
+ result.push({
24
+ extent: [
25
+ [0, 0],
26
+ [plotContainerWidth, plotContainerHeight],
27
+ ],
28
+ });
29
+ }
30
+ return result;
31
+ }, [plotContainerHeight, plotContainerWidth, preparedSplit.plots, preparedZoom]);
32
+ const handleChartBrushEnd = React.useCallback(function (brushInstance, selection) {
33
+ if (selection && yScale && xAxis && yAxis && xScale && (preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.type)) {
34
+ const nextZoomState = selectionToZoomBounds({
35
+ selection,
36
+ xAxis,
37
+ xScale,
38
+ yAxises: yAxis,
39
+ yScales: yScale,
40
+ zoomType: preparedZoom.type,
41
+ });
42
+ onUpdate(nextZoomState);
43
+ brushInstance.clear(select(this));
44
+ }
45
+ }, [onUpdate, preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.type, xAxis, xScale, yAxis, yScale]);
46
+ // Chart brush for manual zoom handling
47
+ useBrush({
48
+ areas,
49
+ brushOptions: preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.brush,
50
+ node,
51
+ type: preparedZoom === null || preparedZoom === void 0 ? void 0 : preparedZoom.type,
52
+ onBrushEnd: handleChartBrushEnd,
53
+ });
54
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Defines the zoom state for the chart.
3
+ */
4
+ export interface ZoomState {
5
+ /**
6
+ * The range for the X-axis.
7
+ * The first element is the minimum value on the axis (if the axis type is `linear`, `logarithmic`, or `datetime`)
8
+ * or the category index from the categories array specified in the axis settings (if the axis type is `category`).
9
+ * The second element is the corresponding maximum value.
10
+ */
11
+ x: [number, number];
12
+ /**
13
+ * An array of ranges for the Y-axes.
14
+ * For each range, the first element is the minimum value on the axis (if the axis type is `linear`, `logarithmic`, or `datetime`)
15
+ * or the category index from the categories array specified in the axis settings (if the axis type is `category`).
16
+ * The second element is the corresponding maximum value.
17
+ */
18
+ y: [number, number][];
19
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { BrushSelection } from 'd3';
2
+ import type { ChartScale } from '../useAxisScales';
3
+ import type { PreparedAxis, PreparedZoom } from '../useChartOptions/types';
4
+ import type { ZoomState } from './types';
5
+ export declare function selectionToZoomBounds(args: {
6
+ selection: BrushSelection;
7
+ xAxis: PreparedAxis;
8
+ xScale: ChartScale;
9
+ yAxises: PreparedAxis[];
10
+ yScales: ChartScale[];
11
+ zoomType: PreparedZoom['type'];
12
+ }): Partial<ZoomState>;
@@ -0,0 +1,128 @@
1
+ export function selectionToZoomBounds(args) {
2
+ const { selection, xAxis, xScale, yAxises, yScales, zoomType } = args;
3
+ const zoomState = {};
4
+ switch (zoomType) {
5
+ case 'x': {
6
+ const [x0, x1] = selection;
7
+ zoomState.x = selectionXToZoomBounds({ xAxis, xScale, selection: [x0, x1] });
8
+ break;
9
+ }
10
+ case 'y': {
11
+ const [y1, y0] = selection;
12
+ yAxises.forEach((yAxis, index) => {
13
+ if (!Array.isArray(zoomState.y)) {
14
+ zoomState.y = [];
15
+ }
16
+ zoomState.y.push(selectionYToZoomBounds({
17
+ yAxis,
18
+ yScale: yScales[index],
19
+ selection: [y1, y0],
20
+ }));
21
+ });
22
+ break;
23
+ }
24
+ case 'xy': {
25
+ const [x0, y0] = selection[0];
26
+ const [x1, y1] = selection[1];
27
+ zoomState.x = selectionXToZoomBounds({ xAxis, xScale, selection: [x0, x1] });
28
+ yAxises.forEach((yAxis, index) => {
29
+ if (!Array.isArray(zoomState.y)) {
30
+ zoomState.y = [];
31
+ }
32
+ zoomState.y.push(selectionYToZoomBounds({
33
+ yAxis,
34
+ yScale: yScales[index],
35
+ selection: [y0, y1],
36
+ }));
37
+ });
38
+ break;
39
+ }
40
+ }
41
+ return zoomState;
42
+ }
43
+ function selectionXToZoomBounds(args) {
44
+ const { xAxis, xScale, selection } = args;
45
+ switch (xAxis.type) {
46
+ case 'category': {
47
+ const [x0, x1] = selection;
48
+ const bandScale = xScale;
49
+ const categories = xAxis.categories || [];
50
+ const currentDomain = bandScale.domain();
51
+ const step = bandScale.step();
52
+ let startIndex = Math.floor(x0 / step);
53
+ let endIndex = Math.floor(x1 / step);
54
+ const startCategory = currentDomain[startIndex];
55
+ const endCategory = currentDomain[endIndex];
56
+ startIndex = categories.indexOf(startCategory);
57
+ endIndex = categories.indexOf(endCategory);
58
+ if (!categories[startIndex]) {
59
+ startIndex = 0;
60
+ }
61
+ if (!categories[endIndex]) {
62
+ endIndex = categories.length - 1;
63
+ }
64
+ return [startIndex, endIndex];
65
+ }
66
+ case 'datetime': {
67
+ const [x0, x1] = selection;
68
+ const timeScale = xScale;
69
+ const minTimestamp = timeScale.invert(x0).getTime();
70
+ const maxTimestamp = timeScale.invert(x1).getTime();
71
+ return [minTimestamp, maxTimestamp];
72
+ }
73
+ case 'linear':
74
+ case 'logarithmic': {
75
+ const [x0, x1] = selection;
76
+ const linearScale = xScale;
77
+ const minValue = linearScale.invert(x0);
78
+ const maxValue = linearScale.invert(x1);
79
+ return [minValue, maxValue];
80
+ }
81
+ default: {
82
+ throw new Error(`Invalid axis type: ${xAxis.type}`);
83
+ }
84
+ }
85
+ }
86
+ function selectionYToZoomBounds(args) {
87
+ const { yAxis, yScale, selection } = args;
88
+ switch (yAxis.type) {
89
+ case 'category': {
90
+ const [y1, y0] = selection;
91
+ const bandScale = yScale;
92
+ const categories = yAxis.categories || [];
93
+ const currentDomain = bandScale.domain();
94
+ const step = bandScale.step();
95
+ let startIndex = currentDomain.length - 1 - Math.floor(y0 / step);
96
+ let endIndex = currentDomain.length - 1 - Math.floor(y1 / step);
97
+ const startCategory = currentDomain[startIndex];
98
+ const endCategory = currentDomain[endIndex];
99
+ startIndex = categories.indexOf(startCategory);
100
+ endIndex = categories.indexOf(endCategory);
101
+ if (!categories[startIndex]) {
102
+ startIndex = 0;
103
+ }
104
+ if (!categories[endIndex]) {
105
+ endIndex = categories.length - 1;
106
+ }
107
+ return [startIndex, endIndex];
108
+ }
109
+ case 'datetime': {
110
+ const [y1, y0] = selection;
111
+ const timeScale = yScale;
112
+ const minTimestamp = timeScale.invert(y0).getTime();
113
+ const maxTimestamp = timeScale.invert(y1).getTime();
114
+ return [minTimestamp, maxTimestamp];
115
+ }
116
+ case 'linear':
117
+ case 'logarithmic': {
118
+ const [y1, y0] = selection;
119
+ const linearScale = yScale;
120
+ const minValue = linearScale.invert(y0);
121
+ const maxValue = linearScale.invert(y1);
122
+ return [minValue, maxValue];
123
+ }
124
+ default: {
125
+ throw new Error(`Invalid axis type: ${yAxis.type}`);
126
+ }
127
+ }
128
+ }
@@ -1,4 +1,4 @@
1
- import type { DashStyle } from 'src/constants';
1
+ import type { DashStyle } from '../../constants';
2
2
  import type { FormatNumberOptions } from '../formatter';
3
3
  import type { BaseTextStyle } from './base';
4
4
  export type ChartAxisType = 'category' | 'datetime' | 'linear' | 'logarithmic';
@@ -7,14 +7,12 @@ export interface ChartAxisLabels {
7
7
  /** Enable or disable the axis labels. */
8
8
  enabled?: boolean;
9
9
  /** The label's pixel distance from the perimeter of the plot area.
10
- *
11
- * @default: 10
10
+ * @default 10
12
11
  */
13
12
  margin?: number;
14
13
  /** The pixel padding for axis labels, to ensure white space between them.
15
- *
16
- * @defaults: 5
17
- * */
14
+ * @default 5
15
+ */
18
16
  padding?: number;
19
17
  dateFormat?: string;
20
18
  numberFormat?: FormatNumberOptions;
@@ -24,13 +22,14 @@ export interface ChartAxisLabels {
24
22
  * As the chart gets narrower, it will start rotating the labels -45 degrees. */
25
23
  autoRotation?: boolean;
26
24
  /** Rotation of the labels in degrees.
27
- *
28
- * @default: 0
25
+ * @default 0
29
26
  */
30
27
  rotation?: number;
31
28
  }
32
29
  export interface ChartAxis {
33
30
  categories?: string[];
31
+ /** Configure a crosshair that follows either the mouse pointer or the hovered point. */
32
+ crosshair?: AxisCrosshair;
34
33
  timestamps?: number[];
35
34
  type?: ChartAxisType;
36
35
  /** The axis labels show the number or category for each tick. */
@@ -42,14 +41,14 @@ export interface ChartAxis {
42
41
  /** CSS styles for the title */
43
42
  style?: Partial<BaseTextStyle>;
44
43
  /** The pixel distance between the axis labels or line and the title.
45
- *
46
- * Defaults to 4 for horizontal axes, 8 for vertical.
47
- * */
44
+ * @default 4 for horizontal axes, 8 for vertical
45
+ */
48
46
  margin?: number;
49
47
  /** Alignment of the title. */
50
48
  align?: ChartAxisTitleAlignment;
51
49
  /** Allows limiting of the contents of a title block to the specified number of lines.
52
- * Defaults to 1. */
50
+ * @default 1
51
+ */
53
52
  maxRowCount?: number;
54
53
  };
55
54
  /** The minimum value of the axis. If undefined the min value is automatically calculate. */
@@ -57,9 +56,8 @@ export interface ChartAxis {
57
56
  /** The grid lines settings. */
58
57
  grid?: {
59
58
  /** Enable or disable the grid lines.
60
- *
61
- * Defaults to true.
62
- * */
59
+ * @default true
60
+ */
63
61
  enabled?: boolean;
64
62
  };
65
63
  ticks?: {
@@ -69,9 +67,8 @@ export interface ChartAxis {
69
67
  };
70
68
  /** Padding of the max value relative to the length of the axis.
71
69
  * A padding of 0.05 will make a 100px axis 5px longer.
72
- *
73
- * Defaults to 0.05 for Y axis and to 0.01 for X axis.
74
- * */
70
+ * @default 0.05 for Y axis, 0.01 for X axis
71
+ */
75
72
  maxPadding?: number;
76
73
  /** An array of lines stretching across the plot area, marking a specific value */
77
74
  plotLines?: AxisPlotLine[];
@@ -90,7 +87,6 @@ export interface AxisPlot {
90
87
  color?: string;
91
88
  /**
92
89
  * Individual opacity for the line.
93
- *
94
90
  * @default 1
95
91
  * */
96
92
  opacity?: number;
@@ -101,12 +97,11 @@ export interface AxisPlotLine extends AxisPlot {
101
97
  /** The color of the plot line (hex, rgba). */
102
98
  color?: string;
103
99
  /** Pixel width of the plot line.
104
- *
105
100
  * @default 1
106
101
  * */
107
102
  width?: number;
108
103
  /** Option for line stroke style. */
109
- dashStyle?: `${DashStyle}`;
104
+ dashStyle?: DashStyle;
110
105
  }
111
106
  export interface AxisPlotBand extends AxisPlot {
112
107
  /**
@@ -124,6 +119,16 @@ export interface AxisPlotBand extends AxisPlot {
124
119
  */
125
120
  to: number | string;
126
121
  }
122
+ export interface AxisCrosshair extends Omit<AxisPlotLine, 'value'> {
123
+ /** Whether the crosshair should snap to the point or follow the pointer independent of points.
124
+ * @default true
125
+ */
126
+ snap?: boolean;
127
+ /** Enable or disable the axis crosshair.
128
+ * @default false
129
+ */
130
+ enabled?: boolean;
131
+ }
127
132
  export interface ChartYAxis extends ChartAxis {
128
133
  /** Axis location.
129
134
  * Possible values - 'left' and 'right'.
@@ -1,5 +1,6 @@
1
1
  import type { MeaningfulAny } from '../misc';
2
2
  import type { ChartTooltipRendererArgs } from './tooltip';
3
+ import type { ChartZoom } from './zoom';
3
4
  export interface ChartMargin {
4
5
  top: number;
5
6
  right: number;
@@ -15,4 +16,8 @@ export interface ChartOptions {
15
16
  }, event: PointerEvent) => void;
16
17
  pointermove?: (data: ChartTooltipRendererArgs | undefined, event: PointerEvent) => void;
17
18
  };
19
+ /**
20
+ * Configuration options for chart zooming functionality.
21
+ */
22
+ zoom?: ChartZoom;
18
23
  }
@@ -47,7 +47,7 @@ export interface LineSeries<T = MeaningfulAny> extends BaseSeries {
47
47
  /** Options for the point markers of line series */
48
48
  marker?: PointMarkerOptions;
49
49
  /** Option for line stroke style */
50
- dashStyle?: `${DashStyle}`;
50
+ dashStyle?: DashStyle;
51
51
  /** Option for line cap style */
52
52
  linecap?: `${LineCap}`;
53
53
  /** Individual opacity for the line. */
@@ -94,5 +94,5 @@ export interface PieSeries<T = MeaningfulAny> extends BaseSeries {
94
94
  series: {
95
95
  innerRadius: number;
96
96
  };
97
- }) => BaseType;
97
+ }) => BaseType | Promise<BaseType>;
98
98
  }
@@ -183,7 +183,7 @@ export interface ChartSeriesOptions {
183
183
  *
184
184
  * @default 'Solid'
185
185
  * */
186
- dashStyle?: `${DashStyle}`;
186
+ dashStyle?: DashStyle;
187
187
  /** Options for line cap style
188
188
  *
189
189
  * @default 'round' when dashStyle is not 'solid', 'none' when dashStyle is not 'solid'
@@ -75,7 +75,7 @@ export type TooltipDataChunk<T = MeaningfulAny> = (TooltipDataChunkBarX<T> | Too
75
75
  };
76
76
  export interface ChartTooltipRendererArgs<T = MeaningfulAny> {
77
77
  hovered: TooltipDataChunk<T>[];
78
- xAxis?: ChartXAxis;
78
+ xAxis?: ChartXAxis | null;
79
79
  yAxis?: ChartYAxis;
80
80
  }
81
81
  export interface ChartTooltip<T = MeaningfulAny> {
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Configuration options for chart zooming functionality using area selection.
3
+ * Working with only axis related series.
4
+ */
5
+ export interface ChartZoom {
6
+ enabled?: boolean;
7
+ /**
8
+ * Type of zoom to apply.
9
+ * - `x`: zoom only on X axis
10
+ * - `y`: zoom only on Y axis
11
+ * - `xy`: zoom on both X and Y axes
12
+ *
13
+ * The availability of zoom types depends on the series types used in the chart.
14
+ * If the specified zoom type is not supported by all series, it will be ignored.
15
+ * If no type is specified, a default will be chosen based on the series.
16
+ *
17
+ * Supported zoom types by series type:
18
+ * - `Area`, `Line`, `Scatter`: `x`, `y`, `xy`
19
+ * - `BarX`: `x`
20
+ * - `BarY`: `y`
21
+ *
22
+ * Default zoom type by series type:
23
+ * - `BarY`: `y`
24
+ * - `Scatter`: `xy`
25
+ * - All others: `x`
26
+ */
27
+ type?: 'x' | 'y' | 'xy';
28
+ /**
29
+ * Zoom brush configuration.
30
+ */
31
+ brush?: {
32
+ style?: {
33
+ fillOpacity?: number;
34
+ };
35
+ };
36
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -22,6 +22,7 @@ export * from './chart/series';
22
22
  export * from './chart/split';
23
23
  export * from './chart/title';
24
24
  export * from './chart/tooltip';
25
+ export * from './chart/zoom';
25
26
  export * from './chart/halo';
26
27
  export * from './chart/treemap';
27
28
  export * from './chart/waterfall';
@@ -14,6 +14,7 @@ export * from './chart/series';
14
14
  export * from './chart/split';
15
15
  export * from './chart/title';
16
16
  export * from './chart/tooltip';
17
+ export * from './chart/zoom';
17
18
  export * from './chart/halo';
18
19
  export * from './chart/treemap';
19
20
  export * from './chart/waterfall';
@@ -3,3 +3,10 @@
3
3
  */
4
4
  export type MeaningfulAny = any;
5
5
  export type PointPosition = [number, number];
6
+ /**
7
+ * Makes all properties in T required, including nested objects.
8
+ * Inspired by: https://stackoverflow.com/a/76927120
9
+ */
10
+ export type DeepRequired<T> = Required<{
11
+ [K in keyof T]: T[K] extends Required<T[K]> ? T[K] : DeepRequired<T[K]>;
12
+ }>;
@@ -21,5 +21,5 @@ type AxisBottomArgs = {
21
21
  };
22
22
  leftmostLimit?: number;
23
23
  };
24
- export declare function axisBottom(args: AxisBottomArgs): (selection: Selection<SVGGElement, unknown, null, undefined>) => void;
24
+ export declare function axisBottom(args: AxisBottomArgs): Promise<(selection: Selection<SVGGElement, unknown, null, undefined>) => void>;
25
25
  export {};
@@ -15,15 +15,15 @@ function addDomain(selection, options) {
15
15
  domainPath.style('stroke', color);
16
16
  }
17
17
  }
18
- export function axisBottom(args) {
18
+ export async function axisBottom(args) {
19
19
  const { leftmostLimit = 0, scale, ticks: { labelFormat = (value) => String(value), labelsPaddings = 0, labelsMargin = 0, labelsMaxWidth = Infinity, labelsStyle, labelsLineHeight, items: tickItems, count: ticksCount, maxTickCount, rotation = 0, tickColor, }, domain, } = args;
20
20
  const offset = getXAxisOffset();
21
21
  const position = getXTickPosition({ scale, offset });
22
22
  const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
23
- const labelHeight = getLabelsSize({
23
+ const labelHeight = (await getLabelsSize({
24
24
  labels: values.map(labelFormat),
25
25
  style: labelsStyle,
26
- }).maxHeight;
26
+ })).maxHeight;
27
27
  return function (selection) {
28
28
  var _a, _b, _c;
29
29
  const rect = (_a = selection.node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
@@ -44,32 +44,34 @@ export function axisBottom(args) {
44
44
  tickPath.moveTo(0, start);
45
45
  tickPath.lineTo(0, end);
46
46
  });
47
- selection
47
+ selection.selectAll('.tick').remove();
48
+ const ticks = selection
48
49
  .selectAll('.tick')
49
50
  .data(values)
50
51
  .order()
51
- .join((el) => {
52
- const tick = el.append('g').attr('class', 'tick');
53
- tick.append('path')
54
- .attr('d', tickPath.toString())
55
- .attr('stroke', tickColor !== null && tickColor !== void 0 ? tickColor : 'currentColor');
56
- tick.append('text')
57
- .text(labelFormat)
58
- .attr('fill', 'currentColor')
59
- .attr('text-anchor', () => {
60
- if (rotation) {
61
- return rotation > 0 ? 'start' : 'end';
62
- }
63
- return 'middle';
64
- })
65
- .style('transform', transform)
66
- .style('dominant-baseline', 'text-after-edge');
67
- return tick;
68
- })
52
+ .join('g')
53
+ .attr('class', 'tick')
69
54
  .attr('transform', function (d) {
70
55
  const left = position(d) + offset;
71
56
  return `translate(${left}, ${top})`;
72
57
  });
58
+ ticks
59
+ .append('path')
60
+ .attr('d', tickPath.toString())
61
+ .attr('stroke', tickColor !== null && tickColor !== void 0 ? tickColor : 'currentColor');
62
+ ticks
63
+ .append('text')
64
+ .text(labelFormat)
65
+ .style('font-size', (labelsStyle === null || labelsStyle === void 0 ? void 0 : labelsStyle.fontSize) || '')
66
+ .attr('fill', 'currentColor')
67
+ .attr('text-anchor', () => {
68
+ if (rotation) {
69
+ return rotation > 0 ? 'start' : 'end';
70
+ }
71
+ return 'middle';
72
+ })
73
+ .style('transform', transform)
74
+ .style('dominant-baseline', 'text-after-edge');
73
75
  // Remove tick that has the same x coordinate like domain
74
76
  selection
75
77
  .selectAll('.tick')
@@ -135,8 +137,6 @@ export function axisBottom(args) {
135
137
  });
136
138
  }
137
139
  const { size: domainSize, color: domainColor } = domain;
138
- selection
139
- .call(addDomain, { size: domainSize, color: domainColor })
140
- .style('font-size', (labelsStyle === null || labelsStyle === void 0 ? void 0 : labelsStyle.fontSize) || '');
140
+ selection.call(addDomain, { size: domainSize, color: domainColor });
141
141
  };
142
142
  }
@@ -29,12 +29,13 @@ export declare function getAxisHeight(args: {
29
29
  export declare function getAxisTitleRows(args: {
30
30
  axis: PreparedAxis;
31
31
  textMaxWidth: number;
32
- }): TextRow[];
32
+ }): Promise<TextRow[]>;
33
33
  interface GetBandsPositionArgs {
34
34
  band: PreparedAxisPlotBand;
35
35
  axisScale: AxisScale<AxisDomain>;
36
36
  axis: AxisDirection;
37
37
  }
38
+ export declare const getAxisPlotsPosition: (axis: PreparedAxis, split: PreparedSplit, width?: number) => string;
38
39
  export declare function getBandsPosition(args: GetBandsPositionArgs): {
39
40
  from: number;
40
41
  to: number;
@@ -50,12 +50,12 @@ export function getAxisHeight(args) {
50
50
  }
51
51
  return boundsHeight;
52
52
  }
53
- export function getAxisTitleRows(args) {
53
+ export async function getAxisTitleRows(args) {
54
54
  const { axis, textMaxWidth } = args;
55
55
  if (axis.title.maxRowCount < 1) {
56
56
  return [];
57
57
  }
58
- const textRows = wrapText({
58
+ const textRows = await wrapText({
59
59
  text: axis.title.text,
60
60
  style: axis.title.style,
61
61
  width: textMaxWidth,
@@ -70,6 +70,14 @@ export function getAxisTitleRows(args) {
70
70
  return acc;
71
71
  }, []);
72
72
  }
73
+ export const getAxisPlotsPosition = (axis, split, width = 0) => {
74
+ var _a;
75
+ const top = ((_a = split.plots[axis.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
76
+ if (axis.position === 'left') {
77
+ return `translate(0, ${top}px)`;
78
+ }
79
+ return `translate(${width}px, ${top}px)`;
80
+ };
73
81
  export function getBandsPosition(args) {
74
82
  var _a, _b, _c;
75
83
  const { band, axisScale } = args;