@gravity-ui/charts 1.42.3 → 1.43.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 (127) hide show
  1. package/dist/cjs/components/AxisX/AxisX.js +31 -4
  2. package/dist/cjs/components/AxisX/prepare-axis-data.js +58 -13
  3. package/dist/cjs/components/AxisX/types.d.ts +18 -1
  4. package/dist/cjs/components/AxisY/AxisY.js +31 -4
  5. package/dist/cjs/components/AxisY/prepare-axis-data.js +68 -21
  6. package/dist/cjs/components/AxisY/prepare-axis-title.js +8 -3
  7. package/dist/cjs/components/AxisY/styles.css +1 -1
  8. package/dist/cjs/components/AxisY/types.d.ts +18 -1
  9. package/dist/cjs/components/ChartInner/index.js +21 -15
  10. package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +6 -5
  11. package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +3 -2
  12. package/dist/cjs/components/ChartInner/useChartInnerProps.js +22 -11
  13. package/dist/cjs/components/ChartInner/useDefaultState.js +4 -3
  14. package/dist/cjs/components/ChartInner/utils/chart.js +1 -1
  15. package/dist/cjs/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
  16. package/dist/cjs/components/ChartInner/utils/title.d.ts +3 -2
  17. package/dist/cjs/components/ChartInner/utils/title.js +69 -11
  18. package/dist/cjs/components/Legend/index.js +8 -11
  19. package/dist/cjs/components/Legend/styles.css +1 -1
  20. package/dist/cjs/components/Title/index.js +3 -5
  21. package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +2 -1
  22. package/dist/cjs/components/Tooltip/ChartTooltipContent.js +3 -2
  23. package/dist/cjs/components/Tooltip/index.js +2 -2
  24. package/dist/cjs/components/utils/axis-title.js +1 -1
  25. package/dist/cjs/core/axes/types.d.ts +26 -9
  26. package/dist/cjs/core/axes/x-axis.js +16 -3
  27. package/dist/cjs/core/axes/y-axis.js +21 -8
  28. package/dist/cjs/core/constants/defaults/axis.d.ts +1 -0
  29. package/dist/cjs/core/constants/defaults/axis.js +1 -0
  30. package/dist/cjs/core/layout/split.d.ts +2 -2
  31. package/dist/cjs/core/layout/split.js +22 -19
  32. package/dist/cjs/core/scales/y-scale.js +37 -13
  33. package/dist/cjs/core/series/prepare-legend.js +7 -7
  34. package/dist/cjs/core/series/types.d.ts +2 -0
  35. package/dist/cjs/core/types/chart/axis.d.ts +43 -1
  36. package/dist/cjs/core/types/chart/title.d.ts +10 -0
  37. package/dist/cjs/core/types/chart/tooltip.d.ts +3 -1
  38. package/dist/cjs/core/utils/axis-generators/bottom.js +6 -16
  39. package/dist/cjs/core/utils/common.d.ts +0 -4
  40. package/dist/cjs/core/utils/common.js +1 -14
  41. package/dist/cjs/core/utils/get-hovered-plots.d.ts +3 -2
  42. package/dist/cjs/core/utils/get-hovered-plots.js +28 -4
  43. package/dist/cjs/core/utils/labels.d.ts +1 -0
  44. package/dist/cjs/core/utils/labels.js +5 -5
  45. package/dist/cjs/core/utils/text.d.ts +1 -0
  46. package/dist/cjs/core/utils/text.js +16 -2
  47. package/dist/cjs/hooks/types.d.ts +5 -2
  48. package/dist/cjs/hooks/useShapes/area/prepare-data.js +12 -7
  49. package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +12 -4
  50. package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +3 -2
  51. package/dist/cjs/hooks/useShapes/funnel/prepare-data.js +4 -1
  52. package/dist/cjs/hooks/useShapes/heatmap/prepare-data.js +1 -1
  53. package/dist/cjs/hooks/useShapes/line/prepare-data.js +4 -1
  54. package/dist/cjs/hooks/useShapes/pie/prepare-data.js +9 -2
  55. package/dist/cjs/hooks/useShapes/radar/prepare-data.js +17 -7
  56. package/dist/cjs/hooks/useShapes/sankey/prepare-data.js +1 -1
  57. package/dist/cjs/hooks/useShapes/sankey/sankey-layout.d.ts +49 -0
  58. package/dist/cjs/hooks/useShapes/sankey/sankey-layout.js +362 -0
  59. package/dist/cjs/hooks/useShapes/styles.css +4 -4
  60. package/dist/cjs/hooks/useShapes/treemap/prepare-data.js +3 -1
  61. package/dist/cjs/hooks/useTooltip/index.d.ts +3 -2
  62. package/dist/cjs/hooks/useTooltip/index.js +5 -3
  63. package/dist/cjs/types/chart-ui.d.ts +1 -0
  64. package/dist/esm/components/AxisX/AxisX.js +31 -4
  65. package/dist/esm/components/AxisX/prepare-axis-data.js +58 -13
  66. package/dist/esm/components/AxisX/types.d.ts +18 -1
  67. package/dist/esm/components/AxisY/AxisY.js +31 -4
  68. package/dist/esm/components/AxisY/prepare-axis-data.js +68 -21
  69. package/dist/esm/components/AxisY/prepare-axis-title.js +8 -3
  70. package/dist/esm/components/AxisY/styles.css +1 -1
  71. package/dist/esm/components/AxisY/types.d.ts +18 -1
  72. package/dist/esm/components/ChartInner/index.js +21 -15
  73. package/dist/esm/components/ChartInner/useChartInnerHandlers.js +6 -5
  74. package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +3 -2
  75. package/dist/esm/components/ChartInner/useChartInnerProps.js +22 -11
  76. package/dist/esm/components/ChartInner/useDefaultState.js +4 -3
  77. package/dist/esm/components/ChartInner/utils/chart.js +1 -1
  78. package/dist/esm/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
  79. package/dist/esm/components/ChartInner/utils/title.d.ts +3 -2
  80. package/dist/esm/components/ChartInner/utils/title.js +69 -11
  81. package/dist/esm/components/Legend/index.js +8 -11
  82. package/dist/esm/components/Legend/styles.css +1 -1
  83. package/dist/esm/components/Title/index.js +3 -5
  84. package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +2 -1
  85. package/dist/esm/components/Tooltip/ChartTooltipContent.js +3 -2
  86. package/dist/esm/components/Tooltip/index.js +2 -2
  87. package/dist/esm/components/utils/axis-title.js +1 -1
  88. package/dist/esm/core/axes/types.d.ts +26 -9
  89. package/dist/esm/core/axes/x-axis.js +16 -3
  90. package/dist/esm/core/axes/y-axis.js +21 -8
  91. package/dist/esm/core/constants/defaults/axis.d.ts +1 -0
  92. package/dist/esm/core/constants/defaults/axis.js +1 -0
  93. package/dist/esm/core/layout/split.d.ts +2 -2
  94. package/dist/esm/core/layout/split.js +22 -19
  95. package/dist/esm/core/scales/y-scale.js +37 -13
  96. package/dist/esm/core/series/prepare-legend.js +7 -7
  97. package/dist/esm/core/series/types.d.ts +2 -0
  98. package/dist/esm/core/types/chart/axis.d.ts +43 -1
  99. package/dist/esm/core/types/chart/title.d.ts +10 -0
  100. package/dist/esm/core/types/chart/tooltip.d.ts +3 -1
  101. package/dist/esm/core/utils/axis-generators/bottom.js +6 -16
  102. package/dist/esm/core/utils/common.d.ts +0 -4
  103. package/dist/esm/core/utils/common.js +1 -14
  104. package/dist/esm/core/utils/get-hovered-plots.d.ts +3 -2
  105. package/dist/esm/core/utils/get-hovered-plots.js +28 -4
  106. package/dist/esm/core/utils/labels.d.ts +1 -0
  107. package/dist/esm/core/utils/labels.js +5 -5
  108. package/dist/esm/core/utils/text.d.ts +1 -0
  109. package/dist/esm/core/utils/text.js +16 -2
  110. package/dist/esm/hooks/types.d.ts +5 -2
  111. package/dist/esm/hooks/useShapes/area/prepare-data.js +12 -7
  112. package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +12 -4
  113. package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +3 -2
  114. package/dist/esm/hooks/useShapes/funnel/prepare-data.js +4 -1
  115. package/dist/esm/hooks/useShapes/heatmap/prepare-data.js +1 -1
  116. package/dist/esm/hooks/useShapes/line/prepare-data.js +4 -1
  117. package/dist/esm/hooks/useShapes/pie/prepare-data.js +9 -2
  118. package/dist/esm/hooks/useShapes/radar/prepare-data.js +17 -7
  119. package/dist/esm/hooks/useShapes/sankey/prepare-data.js +1 -1
  120. package/dist/esm/hooks/useShapes/sankey/sankey-layout.d.ts +49 -0
  121. package/dist/esm/hooks/useShapes/sankey/sankey-layout.js +362 -0
  122. package/dist/esm/hooks/useShapes/styles.css +4 -4
  123. package/dist/esm/hooks/useShapes/treemap/prepare-data.js +3 -1
  124. package/dist/esm/hooks/useTooltip/index.d.ts +3 -2
  125. package/dist/esm/hooks/useTooltip/index.js +5 -3
  126. package/dist/esm/types/chart-ui.d.ts +1 -0
  127. package/package.json +1 -3
@@ -6,7 +6,7 @@ import { getPreparedOptions } from '../../core/series/prepare-options';
6
6
  import { getChartDimensions, getEffectiveXRange, getSortedSeriesData, getYAxisWidth, getZoomedSeriesData, isAxisRelatedSeries, } from '../../core/utils';
7
7
  import { createScales, getAxes, getPreparedSeries, getShapes, getSplit, getVisibleSeries, useZoom, } from '../../hooks';
8
8
  import { getActiveLegendItems, getAllLegendItems } from '../../hooks/useSeries/utils';
9
- import { getNormalizedXAxis, getNormalizedYAxis, recalculateYAxisLabelsWidth } from './utils';
9
+ import { getNormalizedXAxis, getNormalizedYAxis, getPreparedChart, getPreparedTitle, recalculateYAxisLabelsWidth, } from './utils';
10
10
  import { hasAtLeastOneSeriesDataPerPlot } from './utils/common';
11
11
  const CLIP_PATH_BY_SERIES_TYPE = {
12
12
  [SERIES_TYPE.Scatter]: false,
@@ -37,8 +37,8 @@ function getBoundsOffsetLeft(args) {
37
37
  return chartMarginLeft + legendOffset + leftAxisWidth;
38
38
  }
39
39
  export function useChartInnerProps(props) {
40
- var _a, _b, _c, _d, _e, _f;
41
- const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, preparedChart, rangeSliderState, width, updateZoomState, zoomState, } = props;
40
+ var _a, _b, _c, _d, _e, _f, _g, _h;
41
+ const { clipPathId, data, dispatcher, height, htmlLayout, plotNode, rangeSliderState, width, updateZoomState, zoomState, } = props;
42
42
  const [selectedLegendItems, setSelectedLegendItems] = React.useState(null);
43
43
  const [chartState, setState] = React.useState(null);
44
44
  const prevStateValue = React.useRef(chartState);
@@ -50,6 +50,12 @@ export function useChartInnerProps(props) {
50
50
  (async function () {
51
51
  var _a, _b, _c;
52
52
  const chartDataChanged = !(previousChartData.current && isEqual(previousChartData.current, data));
53
+ const preparedTitle = await getPreparedTitle({ title: data.title, chartWidth: width });
54
+ const preparedChart = getPreparedChart({
55
+ chart: data.chart,
56
+ seriesData: data.series.data,
57
+ preparedTitle,
58
+ });
53
59
  const colors = (_a = data.colors) !== null && _a !== void 0 ? _a : DEFAULT_PALETTE;
54
60
  const normalizedSeriesData = getSortedSeriesData({
55
61
  seriesData: data.series.data,
@@ -119,7 +125,7 @@ export function useChartInnerProps(props) {
119
125
  let yScale;
120
126
  let boundsWidth = 0;
121
127
  let boundsHeight = 0;
122
- const calculateAxisBasedProps = () => {
128
+ const calculateAxisBasedProps = async () => {
123
129
  const chartDimensions = getChartDimensions({
124
130
  height,
125
131
  margin: preparedChart.margin,
@@ -132,7 +138,11 @@ export function useChartInnerProps(props) {
132
138
  });
133
139
  boundsHeight = chartDimensions.boundsHeight;
134
140
  boundsWidth = chartDimensions.boundsWidth;
135
- preparedSplit = getSplit({ split: data.split, boundsHeight, chartWidth: width });
141
+ preparedSplit = await getSplit({
142
+ split: data.split,
143
+ boundsHeight,
144
+ chartWidth: width,
145
+ });
136
146
  if (preparedSeries.some(isAxisRelatedSeries)) {
137
147
  ({ xScale, yScale } = createScales({
138
148
  boundsWidth,
@@ -147,7 +157,7 @@ export function useChartInnerProps(props) {
147
157
  }));
148
158
  }
149
159
  };
150
- calculateAxisBasedProps();
160
+ await calculateAxisBasedProps();
151
161
  const newYAxis = await recalculateYAxisLabelsWidth({
152
162
  seriesData: preparedSeries,
153
163
  yAxis,
@@ -155,7 +165,7 @@ export function useChartInnerProps(props) {
155
165
  });
156
166
  if (!isEqual(yAxis, newYAxis)) {
157
167
  yAxis = newYAxis;
158
- calculateAxisBasedProps();
168
+ await calculateAxisBasedProps();
159
169
  }
160
170
  const { shapes, shapesData } = await getShapes({
161
171
  boundsWidth,
@@ -209,6 +219,8 @@ export function useChartInnerProps(props) {
209
219
  yAxis,
210
220
  yScale,
211
221
  activeLegendItems,
222
+ preparedChart,
223
+ preparedTitle,
212
224
  };
213
225
  if (currentRunRef.current === currentRun) {
214
226
  if (!isEqual(prevStateValue.current, newStateValue)) {
@@ -225,7 +237,6 @@ export function useChartInnerProps(props) {
225
237
  selectedLegendItems,
226
238
  zoomState,
227
239
  rangeSliderState,
228
- preparedChart,
229
240
  dispatcher,
230
241
  htmlLayout,
231
242
  clipPathId,
@@ -277,15 +288,15 @@ export function useChartInnerProps(props) {
277
288
  plotContainerHeight: boundsHeight,
278
289
  plotContainerWidth: boundsWidth,
279
290
  preparedSplit: chartState === null || chartState === void 0 ? void 0 : chartState.preparedSplit,
280
- preparedZoom: preparedChart.zoom,
291
+ preparedZoom: (_e = (_d = chartState === null || chartState === void 0 ? void 0 : chartState.preparedChart) === null || _d === void 0 ? void 0 : _d.zoom) !== null && _e !== void 0 ? _e : null,
281
292
  xAxis,
282
293
  xScale: chartState === null || chartState === void 0 ? void 0 : chartState.xScale,
283
294
  yAxis,
284
295
  yScale: chartState === null || chartState === void 0 ? void 0 : chartState.yScale,
285
296
  });
286
297
  // additional end
287
- return Object.assign(Object.assign({}, chartState), { preparedSeries, boundsOffsetLeft: (_d = chartState === null || chartState === void 0 ? void 0 : chartState.boundsOffsetLeft) !== null && _d !== void 0 ? _d : 0, boundsOffsetTop: (_e = chartState === null || chartState === void 0 ? void 0 : chartState.boundsOffsetTop) !== null && _e !== void 0 ? _e : 0, boundsHeight,
298
+ return Object.assign(Object.assign({}, chartState), { preparedSeries, boundsOffsetLeft: (_f = chartState === null || chartState === void 0 ? void 0 : chartState.boundsOffsetLeft) !== null && _f !== void 0 ? _f : 0, boundsOffsetTop: (_g = chartState === null || chartState === void 0 ? void 0 : chartState.boundsOffsetTop) !== null && _g !== void 0 ? _g : 0, boundsHeight,
288
299
  boundsWidth,
289
300
  xAxis,
290
- yAxis, shapesData: (_f = chartState === null || chartState === void 0 ? void 0 : chartState.shapesData) !== null && _f !== void 0 ? _f : [], shapesReady: Boolean(chartState), handleLegendItemClick });
301
+ yAxis, shapesData: (_h = chartState === null || chartState === void 0 ? void 0 : chartState.shapesData) !== null && _h !== void 0 ? _h : [], shapesReady: Boolean(chartState), handleLegendItemClick, preparedTitle: chartState === null || chartState === void 0 ? void 0 : chartState.preparedTitle, preparedChart: chartState === null || chartState === void 0 ? void 0 : chartState.preparedChart });
291
302
  }
@@ -29,7 +29,7 @@ export function useDefaultState(props) {
29
29
  boundsHeight,
30
30
  boundsWidth,
31
31
  });
32
- const { plotLines, plotBands } = getHoveredPlots({
32
+ const { plotBands, plotLines, plotShapes } = getHoveredPlots({
33
33
  pointerX: x,
34
34
  pointerY: y,
35
35
  xAxis,
@@ -37,7 +37,7 @@ export function useDefaultState(props) {
37
37
  xScale,
38
38
  yScale,
39
39
  });
40
- const hoveredPlotsArg = { lines: plotLines, bands: plotBands };
40
+ const hoveredPlotsArg = { bands: plotBands, lines: plotLines, shapes: plotShapes };
41
41
  const svgPointerX = x + boundsOffsetLeft;
42
42
  const svgPointerY = y + boundsOffsetTop;
43
43
  dispatcher.call(EventType.HOVER_SHAPE, undefined, closest, [svgPointerX, svgPointerY], hoveredPlotsArg);
@@ -55,8 +55,9 @@ export function useDefaultState(props) {
55
55
  hovered: closest,
56
56
  xAxis,
57
57
  yAxis: yAxis[0],
58
- hoveredPlotLines: plotLines,
59
58
  hoveredPlotBands: plotBands,
59
+ hoveredPlotLines: plotLines,
60
+ hoveredPlotShapes: plotShapes,
60
61
  }, syntheticEvent);
61
62
  });
62
63
  }, [
@@ -4,7 +4,7 @@ const getMarginTop = (args) => {
4
4
  const { chart, preparedTitle } = args;
5
5
  let marginTop = get(chart, 'margin.top', 0);
6
6
  if (preparedTitle === null || preparedTitle === void 0 ? void 0 : preparedTitle.height) {
7
- marginTop += preparedTitle.height;
7
+ marginTop += preparedTitle.height + preparedTitle.margin;
8
8
  }
9
9
  return marginTop;
10
10
  };
@@ -22,6 +22,7 @@ export declare function getNormalizedXAxis(props: {
22
22
  maxPadding?: number;
23
23
  plotLines?: import("../../..").AxisPlotLine[];
24
24
  plotBands?: import("../../..").AxisPlotBand[];
25
+ plotShapes?: import("../../..").AxisPlotShape[];
25
26
  tickMarks?: import("../../..").ChartAxisTickMarks;
26
27
  visible?: boolean;
27
28
  order?: "sortAsc" | "sortDesc" | "reverse";
@@ -1,5 +1,6 @@
1
1
  import type { PreparedTitle } from '../../../hooks/types';
2
2
  import type { ChartData } from '../../../types';
3
- export declare const getPreparedTitle: ({ title, }: {
3
+ export declare const getPreparedTitle: ({ title, chartWidth, }: {
4
4
  title: ChartData["title"];
5
- }) => PreparedTitle | undefined;
5
+ chartWidth: number;
6
+ }) => Promise<PreparedTitle | undefined>;
@@ -1,20 +1,78 @@
1
1
  import get from 'lodash/get';
2
- import { getHorizontalSvgTextHeight } from '../../../core/utils';
2
+ import { getTextSizeFn, getTextWithElipsis, wrapText } from '../../../core/utils';
3
3
  const DEFAULT_TITLE_FONT_SIZE = '15px';
4
- const TITLE_PADDINGS = 8 * 2;
5
- export const getPreparedTitle = ({ title, }) => {
6
- var _a, _b, _c, _d, _e, _f;
4
+ const DEFAULT_TITLE_MARGIN = 10;
5
+ export const getPreparedTitle = async ({ title, chartWidth, }) => {
6
+ var _a, _b, _c, _d, _e, _f, _g, _h;
7
7
  const titleText = get(title, 'text');
8
8
  const titleStyle = {
9
9
  fontSize: (_b = (_a = title === null || title === void 0 ? void 0 : title.style) === null || _a === void 0 ? void 0 : _a.fontSize) !== null && _b !== void 0 ? _b : DEFAULT_TITLE_FONT_SIZE,
10
10
  fontWeight: (_d = (_c = title === null || title === void 0 ? void 0 : title.style) === null || _c === void 0 ? void 0 : _c.fontWeight) !== null && _d !== void 0 ? _d : 'var(--g-text-subheader-font-weight)',
11
11
  fontColor: (_f = (_e = title === null || title === void 0 ? void 0 : title.style) === null || _e === void 0 ? void 0 : _e.fontColor) !== null && _f !== void 0 ? _f : 'var(--g-color-text-primary)',
12
12
  };
13
- const titleHeight = titleText
14
- ? getHorizontalSvgTextHeight({ text: titleText, style: titleStyle }) + TITLE_PADDINGS
15
- : 0;
16
- const preparedTitle = titleText
17
- ? { text: titleText, style: titleStyle, height: titleHeight, qa: title === null || title === void 0 ? void 0 : title.qa }
18
- : undefined;
19
- return preparedTitle;
13
+ if (!titleText) {
14
+ return undefined;
15
+ }
16
+ const getTitleTextSize = getTextSizeFn({ style: titleStyle });
17
+ const maxRowCount = (_g = title === null || title === void 0 ? void 0 : title.maxRowCount) !== null && _g !== void 0 ? _g : 1;
18
+ const contentRows = [];
19
+ if (maxRowCount > 1) {
20
+ let titleTextRows = await wrapText({
21
+ text: titleText,
22
+ style: titleStyle,
23
+ width: chartWidth,
24
+ getTextSize: getTitleTextSize,
25
+ });
26
+ titleTextRows = titleTextRows.reduce((acc, row, index) => {
27
+ if (index < maxRowCount) {
28
+ acc.push(row);
29
+ }
30
+ else {
31
+ acc[maxRowCount - 1].text += row.text;
32
+ }
33
+ return acc;
34
+ }, []);
35
+ for (let i = 0; i < titleTextRows.length; i++) {
36
+ const textRow = titleTextRows[i];
37
+ let textRowContent = textRow.text.trim();
38
+ if (i === titleTextRows.length - 1) {
39
+ textRowContent = await getTextWithElipsis({
40
+ text: textRowContent,
41
+ maxWidth: chartWidth,
42
+ getTextWidth: async (s) => (await getTitleTextSize(s)).width,
43
+ });
44
+ }
45
+ const textRowSize = await getTitleTextSize(textRowContent);
46
+ contentRows.push({
47
+ text: textRowContent,
48
+ x: 0,
49
+ y: textRow.y + textRowSize.hangingOffset,
50
+ size: textRowSize,
51
+ });
52
+ }
53
+ }
54
+ else {
55
+ const truncatedText = await getTextWithElipsis({
56
+ text: titleText,
57
+ maxWidth: chartWidth,
58
+ getTextWidth: async (s) => (await getTitleTextSize(s)).width,
59
+ });
60
+ const textSize = await getTitleTextSize(truncatedText);
61
+ contentRows.push({
62
+ text: truncatedText,
63
+ x: 0,
64
+ y: textSize.hangingOffset,
65
+ size: textSize,
66
+ });
67
+ }
68
+ const totalTextHeight = contentRows.reduce((acc, row) => acc + row.size.height, 0);
69
+ const titleHeight = totalTextHeight;
70
+ return {
71
+ text: titleText,
72
+ style: titleStyle,
73
+ height: titleHeight,
74
+ margin: (_h = title === null || title === void 0 ? void 0 : title.margin) !== null && _h !== void 0 ? _h : DEFAULT_TITLE_MARGIN,
75
+ qa: title === null || title === void 0 ? void 0 : title.qa,
76
+ contentRows,
77
+ };
20
78
  };
@@ -3,7 +3,7 @@ import { scaleLinear } from 'd3-scale';
3
3
  import { select } from 'd3-selection';
4
4
  import { symbol } from 'd3-shape';
5
5
  import { CONTINUOUS_LEGEND_SIZE } from '../../core/constants';
6
- import { createGradientRect, getContinuesColorFn, getLabelsSize, getSymbol, getUniqId, } from '../../core/utils';
6
+ import { createGradientRect, getContinuesColorFn, getSymbol, getTextSizeFn, getUniqId, } from '../../core/utils';
7
7
  import { axisBottom } from '../../core/utils/axis-generators';
8
8
  import { formatNumber } from '../../libs';
9
9
  import { block } from '../../utils';
@@ -116,15 +116,13 @@ function renderLegendSymbol(args) {
116
116
  }
117
117
  case 'symbol': {
118
118
  const symbolAreaSize = Math.pow(d.symbol.width, 2);
119
- const y = legendLineHeight / 2;
120
119
  const bboxWidth = d.symbol.bboxWidth;
120
+ const translateX = x + bboxWidth / 2;
121
+ const translateY = legendLineHeight / 2;
121
122
  element
122
123
  .append('svg:path')
123
124
  .attr('d', () => symbol(scatterSymbol, symbolAreaSize)())
124
- .attr('transform', () => {
125
- const translateX = x + bboxWidth / 2;
126
- return 'translate(' + translateX + ',' + y + ')';
127
- })
125
+ .attr('transform', 'translate(' + translateX + ',' + translateY + ')')
128
126
  .attr('class', className)
129
127
  .style('fill', color);
130
128
  break;
@@ -234,6 +232,7 @@ export const Legend = (props) => {
234
232
  legendItem.symbol.bboxWidth +
235
233
  legendItem.symbol.padding);
236
234
  })
235
+ .attr('y', legend.hangingOffset)
237
236
  .attr('height', legend.height)
238
237
  .attr('class', function (d) {
239
238
  const mods = { selected: d.visible, unselected: !d.visible };
@@ -364,10 +363,7 @@ export const Legend = (props) => {
364
363
  }
365
364
  const legendTitleClassname = b('title');
366
365
  if (legend.title.enable) {
367
- const { maxWidth: titleWidth } = await getLabelsSize({
368
- labels: [legend.title.text],
369
- style: legend.title.style,
370
- });
366
+ const { width: titleWidth } = await getTextSizeFn({ style: legend.title.style })(legend.title.text);
371
367
  let dx = 0;
372
368
  switch (legend.title.align) {
373
369
  case 'center': {
@@ -390,10 +386,11 @@ export const Legend = (props) => {
390
386
  .attr('class', legendTitleClassname)
391
387
  .append('text')
392
388
  .attr('dx', dx)
389
+ .attr('y', legend.title.hangingOffset)
393
390
  .attr('font-weight', (_f = legend.title.style.fontWeight) !== null && _f !== void 0 ? _f : null)
394
391
  .attr('font-size', (_g = legend.title.style.fontSize) !== null && _g !== void 0 ? _g : null)
395
392
  .attr('fill', (_h = legend.title.style.fontColor) !== null && _h !== void 0 ? _h : null)
396
- .style('dominant-baseline', 'text-before-edge')
393
+ .style('dominant-baseline', 'hanging')
397
394
  .html(legend.title.text);
398
395
  }
399
396
  else {
@@ -19,7 +19,7 @@
19
19
  }
20
20
  .gcharts-legend__item-text {
21
21
  fill: var(--g-color-text-secondary);
22
- dominant-baseline: text-before-edge;
22
+ dominant-baseline: hanging;
23
23
  }
24
24
  .gcharts-legend__item-text_unselected {
25
25
  fill: var(--g-color-text-hint);
@@ -1,11 +1,9 @@
1
1
  import React from 'react';
2
2
  export const Title = (props) => {
3
- const { chartWidth, text, height, style, qa } = props;
4
- return (React.createElement("text", { dx: chartWidth / 2, dy: height / 2, dominantBaseline: "middle", textAnchor: "middle", style: {
3
+ const { chartWidth, style, qa, contentRows } = props;
4
+ return (React.createElement("text", { dominantBaseline: "hanging", textAnchor: "middle", style: {
5
5
  fill: style === null || style === void 0 ? void 0 : style.fontColor,
6
6
  fontSize: style === null || style === void 0 ? void 0 : style.fontSize,
7
7
  fontWeight: style === null || style === void 0 ? void 0 : style.fontWeight,
8
- lineHeight: `${height}px`,
9
- }, "data-qa": qa },
10
- React.createElement("tspan", { dangerouslySetInnerHTML: { __html: text } })));
8
+ }, "data-qa": qa }, contentRows.map((row, i) => (React.createElement("tspan", { key: i, x: chartWidth / 2, y: row.y, dominantBaseline: "hanging", dangerouslySetInnerHTML: { __html: row.text } })))));
11
9
  };
@@ -7,8 +7,9 @@ export interface ChartTooltipContentProps {
7
7
  rowRenderer?: ChartTooltip['rowRenderer'];
8
8
  valueFormat?: ChartTooltip['valueFormat'];
9
9
  headerFormat?: ChartTooltip['headerFormat'];
10
- hoveredPlotLines?: ChartTooltipRendererArgs['hoveredPlotLines'];
11
10
  hoveredPlotBands?: ChartTooltipRendererArgs['hoveredPlotBands'];
11
+ hoveredPlotLines?: ChartTooltipRendererArgs['hoveredPlotLines'];
12
+ hoveredPlotShapes?: ChartTooltipRendererArgs['hoveredPlotShapes'];
12
13
  totals?: ChartTooltip['totals'];
13
14
  xAxis?: ChartXAxis | null;
14
15
  yAxis?: ChartYAxis;
@@ -2,15 +2,16 @@ import React from 'react';
2
2
  import isNil from 'lodash/isNil';
3
3
  import { DefaultTooltipContent } from './DefaultTooltipContent';
4
4
  export const ChartTooltipContent = React.memo((props) => {
5
- const { hovered, hoveredPlotLines, hoveredPlotBands, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, qa, } = props;
5
+ const { hovered, hoveredPlotBands, hoveredPlotLines, hoveredPlotShapes, xAxis, yAxis, renderer, rowRenderer, valueFormat, headerFormat, totals, pinned, qa, } = props;
6
6
  if (!hovered) {
7
7
  return null;
8
8
  }
9
9
  const customTooltip = renderer === null || renderer === void 0 ? void 0 : renderer({
10
10
  headerFormat,
11
11
  hovered,
12
- hoveredPlotLines,
13
12
  hoveredPlotBands,
13
+ hoveredPlotLines,
14
+ hoveredPlotShapes,
14
15
  xAxis,
15
16
  yAxis,
16
17
  });
@@ -7,7 +7,7 @@ import './styles.css';
7
7
  const b = block('tooltip');
8
8
  export const Tooltip = (props) => {
9
9
  const { tooltip, xAxis, yAxis, svgContainer, dispatcher, tooltipPinned, onOutsideClick } = props;
10
- const { hovered, hoveredPlotLines, hoveredPlotBands, pointerPosition } = useTooltip({
10
+ const { hovered, hoveredPlotBands, hoveredPlotLines, hoveredPlotShapes, pointerPosition } = useTooltip({
11
11
  dispatcher,
12
12
  tooltip,
13
13
  xAxis,
@@ -28,5 +28,5 @@ export const Tooltip = (props) => {
28
28
  }, [left, top]);
29
29
  return (hovered === null || hovered === void 0 ? void 0 : hovered.length) ? (React.createElement(Popup, { anchorElement: anchor, className: b({ pinned: tooltipPinned }), disableTransition: true, floatingStyles: tooltipPinned ? undefined : { pointerEvents: 'none' }, offset: { mainAxis: 20 }, onOpenChange: tooltipPinned ? handleOnOpenChange : undefined, open: true, placement: ['right', 'left', 'top', 'bottom'] },
30
30
  React.createElement("div", { className: b('popup-content') },
31
- React.createElement(ChartTooltipContent, { hovered: hovered, hoveredPlotLines: hoveredPlotLines, hoveredPlotBands: hoveredPlotBands, pinned: tooltipPinned, renderer: tooltip.renderer, rowRenderer: tooltip.rowRenderer, totals: tooltip.totals, valueFormat: tooltip.valueFormat, headerFormat: tooltip.headerFormat, xAxis: xAxis, yAxis: yAxis, qa: tooltip.qa })))) : null;
31
+ React.createElement(ChartTooltipContent, { hovered: hovered, hoveredPlotBands: hoveredPlotBands, hoveredPlotLines: hoveredPlotLines, hoveredPlotShapes: hoveredPlotShapes, pinned: tooltipPinned, renderer: tooltip.renderer, rowRenderer: tooltip.rowRenderer, totals: tooltip.totals, valueFormat: tooltip.valueFormat, headerFormat: tooltip.headerFormat, xAxis: xAxis, yAxis: yAxis, qa: tooltip.qa })))) : null;
32
32
  };
@@ -31,7 +31,7 @@ export async function getMultilineTitleContentRows({ axis, titleMaxWidth, }) {
31
31
  titleContent.push({
32
32
  text: textRowContent,
33
33
  x: 0,
34
- y: textRow.y,
34
+ y: textRow.y + textRowSize.hangingOffset,
35
35
  size: textRowSize,
36
36
  });
37
37
  }
@@ -1,4 +1,4 @@
1
- import type { AxisCrosshair, AxisPlotBand, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
1
+ import type { AxisCrosshair, AxisPlotBand, AxisPlotShape, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisRangeSlider, ChartAxisTitleAlignment, ChartAxisTitleRotation, ChartAxisType, DeepRequired, MeaningfulAny, PlotLayerPlacement } from '../../types';
2
2
  import type { DashStyle } from '../constants';
3
3
  type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation' | 'html'>> & {
4
4
  style: BaseTextStyle;
@@ -19,19 +19,35 @@ export type PreparedAxisPlotBand = Required<AxisPlotBand> & {
19
19
  };
20
20
  type PreparedAxisCrosshair = Required<AxisCrosshair>;
21
21
  export type PreparedAxisPlotLine = {
22
- value: number;
23
22
  color: string;
24
- width: number;
25
- dashStyle: DashStyle;
26
- opacity: number;
27
- layerPlacement: PlotLayerPlacement;
28
23
  custom?: MeaningfulAny;
24
+ dashStyle: DashStyle;
25
+ hoverThreshold: number;
29
26
  label: {
30
- text: string;
31
- style: BaseTextStyle;
32
27
  padding: number;
33
28
  qa?: string;
29
+ style: BaseTextStyle;
30
+ text: string;
34
31
  };
32
+ layerPlacement: PlotLayerPlacement;
33
+ opacity: number;
34
+ value: number;
35
+ width: number;
36
+ };
37
+ export type PreparedAxisPlotShape = {
38
+ custom?: MeaningfulAny;
39
+ hitbox: {
40
+ height: number;
41
+ width: number;
42
+ x: number;
43
+ y: number;
44
+ };
45
+ layerPlacement: PlotLayerPlacement;
46
+ opacity: number;
47
+ renderer: AxisPlotShape['renderer'];
48
+ value: number | string;
49
+ x: number;
50
+ y: number;
35
51
  };
36
52
  export type PreparedRangeSlider = DeepRequired<Omit<ChartAxisRangeSlider, 'defaultRange'>> & {
37
53
  defaultRange?: ChartAxisRangeSlider['defaultRange'];
@@ -40,7 +56,7 @@ export type PreparedAxisTickMarks = {
40
56
  enabled: boolean;
41
57
  length: number;
42
58
  };
43
- type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotBands'> & {
59
+ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotBands' | 'plotShapes'> & {
44
60
  type: ChartAxisType;
45
61
  labels: PreparedAxisLabels;
46
62
  title: {
@@ -67,6 +83,7 @@ type PreparedBaseAxis = Omit<ChartAxis, 'type' | 'labels' | 'plotLines' | 'plotB
67
83
  plotIndex: number;
68
84
  plotLines: PreparedAxisPlotLine[];
69
85
  plotBands: PreparedAxisPlotBand[];
86
+ plotShapes: PreparedAxisPlotShape[];
70
87
  crosshair: PreparedAxisCrosshair;
71
88
  };
72
89
  export type PreparedXAxis = PreparedBaseAxis & {
@@ -1,6 +1,6 @@
1
1
  import get from 'lodash/get';
2
- import { TIME_UNITS, calculateCos, calculateNumericProperty, calculateSin, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../utils';
3
- import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, xAxisTitleDefaults, } from '../constants';
2
+ import { TIME_UNITS, calculateCos, calculateNumericProperty, calculateSin, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, wrapText, } from '../utils';
3
+ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, PLOT_LINE_HOVER_THRESHOLD, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, xAxisTitleDefaults, } from '../constants';
4
4
  import { createXScale } from '../scales/x-scale';
5
5
  import { getXAxisTickValues } from '../utils/axis/x-axis';
6
6
  import { getPreparedRangeSlider } from './range-slider';
@@ -90,7 +90,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
90
90
  if (isLabelsEnabled) {
91
91
  labelsLineHeight = labelsHtml
92
92
  ? getHorizontalHtmlTextHeight({ text: 'Tmp', style: labelsStyle })
93
- : getHorizontalSvgTextHeight({ text: 'Tmp', style: labelsStyle });
93
+ : (await getTextSizeFn({ style: labelsStyle })('Tmp')).height;
94
94
  }
95
95
  const shouldHideGrid = isAxisVisible === false || seriesData.some((s) => s.type === SERIES_TYPE.Heatmap);
96
96
  const preparedRangeSlider = getPreparedRangeSlider({ xAxis });
@@ -155,6 +155,7 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
155
155
  color: get(d, 'color', 'var(--g-color-base-brand)'),
156
156
  width: get(d, 'width', 1),
157
157
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
158
+ hoverThreshold: get(d, 'hoverThreshold', PLOT_LINE_HOVER_THRESHOLD),
158
159
  opacity: get(d, 'opacity', 1),
159
160
  layerPlacement: get(d, 'layerPlacement', 'before'),
160
161
  custom: d.custom,
@@ -169,6 +170,18 @@ export const getPreparedXAxis = async ({ xAxis, seriesData, width, boundsWidth,
169
170
  custom: d.custom,
170
171
  label: prepareAxisPlotLabel(d),
171
172
  })),
173
+ // x, y and hitbox are populated later in prepare-axis-data
174
+ // after pixel coordinates and element dimensions are computed
175
+ plotShapes: get(xAxis, 'plotShapes', []).map((d) => ({
176
+ custom: d.custom,
177
+ hitbox: { x: 0, y: 0, width: 0, height: 0 },
178
+ layerPlacement: get(d, 'layerPlacement', 'before'),
179
+ opacity: get(d, 'opacity', 1),
180
+ renderer: d.renderer,
181
+ value: d.value,
182
+ x: 0,
183
+ y: 0,
184
+ })),
172
185
  crosshair: {
173
186
  enabled: get(xAxis, 'crosshair.enabled', axisCrosshairDefaults.enabled),
174
187
  color: get(xAxis, 'crosshair.color', axisCrosshairDefaults.color),
@@ -1,7 +1,7 @@
1
1
  import get from 'lodash/get';
2
- import { calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getDefaultMinYAxisValue, getHorizontalHtmlTextHeight, getHorizontalSvgTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, shouldSyncAxisWithPrimary, wrapText, } from '../utils';
2
+ import { calculateNumericProperty, formatAxisTickLabel, getDefaultDateFormat, getHorizontalHtmlTextHeight, getLabelsSize, getMinSpaceBetween, getTextSizeFn, isAxisRelatedSeries, shouldSyncAxisWithPrimary, wrapText, } from '../utils';
3
3
  import { getTickValues } from '../../components/AxisY/utils';
4
- import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, yAxisTitleDefaults, } from '../constants';
4
+ import { DASH_STYLE, DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, PLOT_LINE_HOVER_THRESHOLD, SERIES_TYPE, axisCrosshairDefaults, axisLabelsDefaults, axisTickMarksDefaults, yAxisTitleDefaults, } from '../constants';
5
5
  import { createYScale } from '../scales/y-scale';
6
6
  import { prepareAxisPlotLabel } from './utils';
7
7
  export const getYAxisLabelMaxWidth = async (args) => {
@@ -50,7 +50,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
50
50
  return Promise.resolve([]);
51
51
  }
52
52
  return Promise.all(axisItems.map(async (axisItem, axisIndex) => {
53
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
53
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
54
54
  const plotIndex = get(axisItem, 'plotIndex', 0);
55
55
  const firstPlotAxis = !axisByPlot[plotIndex];
56
56
  if (firstPlotAxis) {
@@ -68,7 +68,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
68
68
  const labelsHtml = get(axisItem, 'labels.html', false);
69
69
  const labelsLineHeight = labelsHtml
70
70
  ? getHorizontalHtmlTextHeight({ text: 'Tmp', style: labelsStyle })
71
- : getHorizontalSvgTextHeight({ text: 'Tmp', style: labelsStyle });
71
+ : (await getTextSizeFn({ style: labelsStyle })('Tmp')).height;
72
72
  const titleText = isAxisVisible ? get(axisItem, 'title.text', '') : '';
73
73
  const titleStyle = Object.assign(Object.assign({}, yAxisTitleDefaults.style), get(axisItem, 'title.style'));
74
74
  const titleMaxRowsCount = get(axisItem, 'title.maxRowCount', yAxisTitleDefaults.maxRowCount);
@@ -142,7 +142,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
142
142
  maxWidth: titleMaxWidth !== null && titleMaxWidth !== void 0 ? titleMaxWidth : Infinity,
143
143
  rotation: titleRotation,
144
144
  },
145
- min: (_o = get(axisItem, 'min')) !== null && _o !== void 0 ? _o : getDefaultMinYAxisValue(axisSeriesData),
145
+ min: get(axisItem, 'min'),
146
146
  max: get(axisItem, 'max'),
147
147
  startOnTick: get(axisItem, 'startOnTick'),
148
148
  endOnTick: get(axisItem, 'endOnTick'),
@@ -151,12 +151,12 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
151
151
  enabled: gridEnabled,
152
152
  },
153
153
  ticks: {
154
- pixelInterval: ((_p = axisItem.ticks) === null || _p === void 0 ? void 0 : _p.interval)
154
+ pixelInterval: ((_o = axisItem.ticks) === null || _o === void 0 ? void 0 : _o.interval)
155
155
  ? calculateNumericProperty({
156
156
  base: height,
157
- value: (_q = axisItem.ticks) === null || _q === void 0 ? void 0 : _q.interval,
157
+ value: (_p = axisItem.ticks) === null || _p === void 0 ? void 0 : _p.interval,
158
158
  })
159
- : (_r = axisItem.ticks) === null || _r === void 0 ? void 0 : _r.pixelInterval,
159
+ : (_q = axisItem.ticks) === null || _q === void 0 ? void 0 : _q.pixelInterval,
160
160
  },
161
161
  tickMarks: {
162
162
  enabled: isAxisVisible &&
@@ -170,6 +170,7 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
170
170
  color: get(d, 'color', 'var(--g-color-base-brand)'),
171
171
  width: get(d, 'width', 1),
172
172
  dashStyle: get(d, 'dashStyle', DASH_STYLE.Solid),
173
+ hoverThreshold: get(d, 'hoverThreshold', PLOT_LINE_HOVER_THRESHOLD),
173
174
  opacity: get(d, 'opacity', 1),
174
175
  layerPlacement: get(d, 'layerPlacement', 'before'),
175
176
  custom: d.custom,
@@ -184,6 +185,18 @@ export const getPreparedYAxis = ({ height, boundsHeight, width, seriesData, yAxi
184
185
  custom: d.custom,
185
186
  label: prepareAxisPlotLabel(d),
186
187
  })),
188
+ // x, y and hitbox are populated later in prepare-axis-data
189
+ // after pixel coordinates and element dimensions are computed
190
+ plotShapes: get(axisItem, 'plotShapes', []).map((d) => ({
191
+ custom: d.custom,
192
+ hitbox: { x: 0, y: 0, width: 0, height: 0 },
193
+ layerPlacement: get(d, 'layerPlacement', 'before'),
194
+ opacity: get(d, 'opacity', 1),
195
+ renderer: d.renderer,
196
+ value: d.value,
197
+ x: 0,
198
+ y: 0,
199
+ })),
187
200
  crosshair: {
188
201
  enabled: get(axisItem, 'crosshair.enabled', axisCrosshairDefaults.enabled),
189
202
  color: get(axisItem, 'crosshair.color', axisCrosshairDefaults.color),
@@ -17,4 +17,5 @@ export declare const axisTickMarksDefaults: {
17
17
  length: number;
18
18
  };
19
19
  export declare const DEFAULT_AXIS_TYPE: ChartAxisType;
20
+ export declare const PLOT_LINE_HOVER_THRESHOLD = 4;
20
21
  export {};
@@ -30,3 +30,4 @@ export const axisTickMarksDefaults = {
30
30
  length: 6,
31
31
  };
32
32
  export const DEFAULT_AXIS_TYPE = 'linear';
33
+ export const PLOT_LINE_HOVER_THRESHOLD = 4;
@@ -10,8 +10,8 @@ export declare function getPlotHeight(args: {
10
10
  boundsHeight: number;
11
11
  gap: number;
12
12
  }): number;
13
- export declare function getSplit(args: UseSplitArgs): {
13
+ export declare function getSplit(args: UseSplitArgs): Promise<{
14
14
  plots: PreparedPlot[];
15
15
  gap: number;
16
- };
16
+ }>;
17
17
  export {};