@gravity-ui/charts 1.43.1 → 1.45.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.
- package/dist/cjs/components/ChartInner/utils/zoom.js +3 -1
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/index.js +31 -6
- package/dist/cjs/components/Tooltip/DefaultTooltipContent/utils.js +4 -5
- package/dist/cjs/core/constants/chart-types.d.ts +1 -0
- package/dist/cjs/core/constants/chart-types.js +1 -0
- package/dist/cjs/core/constants/defaults/annotation.d.ts +12 -0
- package/dist/cjs/core/constants/defaults/annotation.js +12 -0
- package/dist/cjs/core/constants/defaults/index.d.ts +1 -0
- package/dist/cjs/core/constants/defaults/index.js +1 -0
- package/dist/cjs/core/constants/defaults/series-options.d.ts +5 -1
- package/dist/cjs/core/constants/defaults/series-options.js +13 -0
- package/dist/cjs/core/i18n/keysets/en.json +2 -1
- package/dist/cjs/core/i18n/keysets/ru.json +2 -1
- package/dist/cjs/core/series/constants.d.ts +1 -1
- package/dist/cjs/core/series/constants.js +1 -1
- package/dist/cjs/core/series/prepare-annotation.d.ts +12 -0
- package/dist/cjs/core/series/prepare-annotation.js +31 -0
- package/dist/cjs/core/series/prepare-legend.js +2 -2
- package/dist/cjs/core/series/prepare-x-range.d.ts +11 -0
- package/dist/cjs/core/series/prepare-x-range.js +41 -0
- package/dist/cjs/core/series/prepareSeries.js +9 -0
- package/dist/cjs/core/series/types.d.ts +34 -2
- package/dist/cjs/core/types/chart/annotation.d.ts +45 -0
- package/dist/cjs/core/types/chart/annotation.js +1 -0
- package/dist/cjs/core/types/chart/area.d.ts +10 -1
- package/dist/cjs/core/types/chart/bar-x.d.ts +6 -0
- package/dist/cjs/core/types/chart/line.d.ts +8 -0
- package/dist/cjs/core/types/chart/marker.d.ts +6 -4
- package/dist/cjs/core/types/chart/series.d.ts +36 -2
- package/dist/cjs/core/types/chart/tooltip.d.ts +7 -1
- package/dist/cjs/core/types/chart/x-range.d.ts +59 -0
- package/dist/cjs/core/types/chart/x-range.js +1 -0
- package/dist/cjs/core/types/chart/zoom.d.ts +1 -1
- package/dist/cjs/core/types/index.d.ts +2 -0
- package/dist/cjs/core/types/index.js +2 -0
- package/dist/cjs/core/utils/axis/x-axis.js +9 -1
- package/dist/cjs/core/utils/color.js +6 -0
- package/dist/cjs/core/utils/common.js +10 -0
- package/dist/cjs/core/utils/get-closest-data.js +19 -0
- package/dist/cjs/core/utils/text.d.ts +8 -0
- package/dist/cjs/core/utils/text.js +9 -1
- package/dist/cjs/core/validation/index.js +13 -0
- package/dist/cjs/core/zoom/zoom.js +24 -7
- package/dist/cjs/hooks/useShapes/annotation/index.d.ts +14 -0
- package/dist/cjs/hooks/useShapes/annotation/index.js +200 -0
- package/dist/cjs/hooks/useShapes/area/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/area/index.js +21 -2
- package/dist/cjs/hooks/useShapes/area/prepare-data.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +45 -26
- package/dist/cjs/hooks/useShapes/area/types.d.ts +4 -0
- package/dist/cjs/hooks/useShapes/bar-x/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/bar-x/index.js +30 -2
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +32 -11
- package/dist/cjs/hooks/useShapes/bar-x/types.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/index.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/index.js +22 -3
- package/dist/cjs/hooks/useShapes/line/index.d.ts +2 -0
- package/dist/cjs/hooks/useShapes/line/index.js +21 -7
- package/dist/cjs/hooks/useShapes/line/prepare-data.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/line/prepare-data.js +28 -10
- package/dist/cjs/hooks/useShapes/line/types.d.ts +4 -0
- package/dist/cjs/hooks/useShapes/x-range/index.d.ts +14 -0
- package/dist/cjs/hooks/useShapes/x-range/index.js +115 -0
- package/dist/cjs/hooks/useShapes/x-range/prepare-data.d.ts +15 -0
- package/dist/cjs/hooks/useShapes/x-range/prepare-data.js +147 -0
- package/dist/cjs/hooks/useShapes/x-range/types.d.ts +12 -0
- package/dist/cjs/hooks/useShapes/x-range/types.js +1 -0
- package/dist/esm/components/ChartInner/utils/zoom.js +3 -1
- package/dist/esm/components/Tooltip/DefaultTooltipContent/index.js +31 -6
- package/dist/esm/components/Tooltip/DefaultTooltipContent/utils.js +4 -5
- package/dist/esm/core/constants/chart-types.d.ts +1 -0
- package/dist/esm/core/constants/chart-types.js +1 -0
- package/dist/esm/core/constants/defaults/annotation.d.ts +12 -0
- package/dist/esm/core/constants/defaults/annotation.js +12 -0
- package/dist/esm/core/constants/defaults/index.d.ts +1 -0
- package/dist/esm/core/constants/defaults/index.js +1 -0
- package/dist/esm/core/constants/defaults/series-options.d.ts +5 -1
- package/dist/esm/core/constants/defaults/series-options.js +13 -0
- package/dist/esm/core/i18n/keysets/en.json +2 -1
- package/dist/esm/core/i18n/keysets/ru.json +2 -1
- package/dist/esm/core/series/constants.d.ts +1 -1
- package/dist/esm/core/series/constants.js +1 -1
- package/dist/esm/core/series/prepare-annotation.d.ts +12 -0
- package/dist/esm/core/series/prepare-annotation.js +31 -0
- package/dist/esm/core/series/prepare-legend.js +2 -2
- package/dist/esm/core/series/prepare-x-range.d.ts +11 -0
- package/dist/esm/core/series/prepare-x-range.js +41 -0
- package/dist/esm/core/series/prepareSeries.js +9 -0
- package/dist/esm/core/series/types.d.ts +34 -2
- package/dist/esm/core/types/chart/annotation.d.ts +45 -0
- package/dist/esm/core/types/chart/annotation.js +1 -0
- package/dist/esm/core/types/chart/area.d.ts +10 -1
- package/dist/esm/core/types/chart/bar-x.d.ts +6 -0
- package/dist/esm/core/types/chart/line.d.ts +8 -0
- package/dist/esm/core/types/chart/marker.d.ts +6 -4
- package/dist/esm/core/types/chart/series.d.ts +36 -2
- package/dist/esm/core/types/chart/tooltip.d.ts +7 -1
- package/dist/esm/core/types/chart/x-range.d.ts +59 -0
- package/dist/esm/core/types/chart/x-range.js +1 -0
- package/dist/esm/core/types/chart/zoom.d.ts +1 -1
- package/dist/esm/core/types/index.d.ts +2 -0
- package/dist/esm/core/types/index.js +2 -0
- package/dist/esm/core/utils/axis/x-axis.js +9 -1
- package/dist/esm/core/utils/color.js +6 -0
- package/dist/esm/core/utils/common.js +10 -0
- package/dist/esm/core/utils/get-closest-data.js +19 -0
- package/dist/esm/core/utils/text.d.ts +8 -0
- package/dist/esm/core/utils/text.js +9 -1
- package/dist/esm/core/validation/index.js +13 -0
- package/dist/esm/core/zoom/zoom.js +24 -7
- package/dist/esm/hooks/useShapes/annotation/index.d.ts +14 -0
- package/dist/esm/hooks/useShapes/annotation/index.js +200 -0
- package/dist/esm/hooks/useShapes/area/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/area/index.js +21 -2
- package/dist/esm/hooks/useShapes/area/prepare-data.d.ts +2 -1
- package/dist/esm/hooks/useShapes/area/prepare-data.js +45 -26
- package/dist/esm/hooks/useShapes/area/types.d.ts +4 -0
- package/dist/esm/hooks/useShapes/bar-x/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/bar-x/index.js +30 -2
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +32 -11
- package/dist/esm/hooks/useShapes/bar-x/types.d.ts +2 -0
- package/dist/esm/hooks/useShapes/index.d.ts +2 -1
- package/dist/esm/hooks/useShapes/index.js +22 -3
- package/dist/esm/hooks/useShapes/line/index.d.ts +2 -0
- package/dist/esm/hooks/useShapes/line/index.js +21 -7
- package/dist/esm/hooks/useShapes/line/prepare-data.d.ts +2 -1
- package/dist/esm/hooks/useShapes/line/prepare-data.js +28 -10
- package/dist/esm/hooks/useShapes/line/types.d.ts +4 -0
- package/dist/esm/hooks/useShapes/x-range/index.d.ts +14 -0
- package/dist/esm/hooks/useShapes/x-range/index.js +115 -0
- package/dist/esm/hooks/useShapes/x-range/prepare-data.d.ts +15 -0
- package/dist/esm/hooks/useShapes/x-range/prepare-data.js +147 -0
- package/dist/esm/hooks/useShapes/x-range/types.d.ts +12 -0
- package/dist/esm/hooks/useShapes/x-range/types.js +1 -0
- package/package.json +2 -2
|
@@ -288,6 +288,25 @@ export function getClosestPoints(args) {
|
|
|
288
288
|
}
|
|
289
289
|
break;
|
|
290
290
|
}
|
|
291
|
+
case 'x-range': {
|
|
292
|
+
const data = list;
|
|
293
|
+
const pointsInXRange = data.filter((d) => pointerX >= d.x &&
|
|
294
|
+
pointerX <= d.x + d.width &&
|
|
295
|
+
pointerY >= d.y &&
|
|
296
|
+
pointerY <= d.y + d.height);
|
|
297
|
+
if (pointsInXRange.length === 0) {
|
|
298
|
+
break;
|
|
299
|
+
}
|
|
300
|
+
const closestByX = pointsInXRange.length === 1
|
|
301
|
+
? pointsInXRange[0]
|
|
302
|
+
: sort(pointsInXRange, (d) => Math.abs(d.x + d.width / 2 - pointerX))[0];
|
|
303
|
+
result.push(...pointsInXRange.map((d) => ({
|
|
304
|
+
data: d.data,
|
|
305
|
+
series: d.series,
|
|
306
|
+
closest: d === closestByX,
|
|
307
|
+
})));
|
|
308
|
+
break;
|
|
309
|
+
}
|
|
291
310
|
}
|
|
292
311
|
});
|
|
293
312
|
if (closestPointsByXValue.length) {
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import type { Selection } from 'd3-selection';
|
|
2
2
|
import type { BaseTextStyle, MeaningfulAny } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Approximate ratio of descenders relative to the full font em height.
|
|
5
|
+
* Based on the Chromium hanging baseline algorithm where hanging offset ≈ ascent × 0.2.
|
|
6
|
+
* This means ascent ≈ 80% of em height, descenders ≈ 20%.
|
|
7
|
+
*
|
|
8
|
+
* @see https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/canvas/text_metrics.cc;l=32
|
|
9
|
+
*/
|
|
10
|
+
export declare const DESCENDER_RATIO = 0.2;
|
|
3
11
|
export declare function handleOverflowingText(tSpan: SVGTSpanElement | null, maxWidth: number, textWidth?: number): void;
|
|
4
12
|
export declare function setEllipsisForOverflowText<T>(selection: Selection<SVGTextElement, T, null, unknown>, maxWidth: number, textWidth?: number): void;
|
|
5
13
|
export declare function setEllipsisForOverflowTexts<T>(selection: Selection<SVGTextElement, T, MeaningfulAny, unknown>, maxWidth: ((datum: T) => number) | number, currentWidth?: (datum: T) => number): void;
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { select } from 'd3-selection';
|
|
2
2
|
import { block } from '../../utils/cn';
|
|
3
3
|
const b = block('chart');
|
|
4
|
+
/**
|
|
5
|
+
* Approximate ratio of descenders relative to the full font em height.
|
|
6
|
+
* Based on the Chromium hanging baseline algorithm where hanging offset ≈ ascent × 0.2.
|
|
7
|
+
* This means ascent ≈ 80% of em height, descenders ≈ 20%.
|
|
8
|
+
*
|
|
9
|
+
* @see https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/core/html/canvas/text_metrics.cc;l=32
|
|
10
|
+
*/
|
|
11
|
+
export const DESCENDER_RATIO = 0.2;
|
|
4
12
|
export function handleOverflowingText(tSpan, maxWidth, textWidth) {
|
|
5
13
|
var _a, _b, _c;
|
|
6
14
|
if (!tSpan) {
|
|
@@ -210,7 +218,7 @@ export function getTextSizeFn({ style }) {
|
|
|
210
218
|
return {
|
|
211
219
|
width: textMetric.width,
|
|
212
220
|
height: textMetric.fontBoundingBoxDescent + textMetric.fontBoundingBoxAscent,
|
|
213
|
-
hangingOffset: textMetric.fontBoundingBoxAscent *
|
|
221
|
+
hangingOffset: textMetric.fontBoundingBoxAscent * DESCENDER_RATIO,
|
|
214
222
|
};
|
|
215
223
|
};
|
|
216
224
|
}
|
|
@@ -265,6 +265,18 @@ function validateStacking({ series }) {
|
|
|
265
265
|
});
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
+
function validateStackingAreaNullMode({ series }) {
|
|
269
|
+
const availableStackingValues = ['normal', 'percent'];
|
|
270
|
+
const invalid = series.find((s) => s.type === 'area' &&
|
|
271
|
+
availableStackingValues.includes(s.stacking) &&
|
|
272
|
+
s.nullMode === 'connect');
|
|
273
|
+
if (invalid) {
|
|
274
|
+
throw new ChartError({
|
|
275
|
+
code: CHART_ERROR_CODE.INVALID_DATA,
|
|
276
|
+
message: i18n('error', 'label_stacking-area-connect-null-mode'),
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
}
|
|
268
280
|
function validateTreemapSeries({ series }) {
|
|
269
281
|
const parentIds = {};
|
|
270
282
|
series.data.forEach((d) => {
|
|
@@ -379,6 +391,7 @@ export function validateData(data) {
|
|
|
379
391
|
}
|
|
380
392
|
validateAxes({ xAxis: data.xAxis, yAxis: data.yAxis });
|
|
381
393
|
validateTooltip({ tooltip: data.tooltip });
|
|
394
|
+
validateStackingAreaNullMode({ series: data.series.data });
|
|
382
395
|
if (data.series.data.some((s) => isEmpty(s.data))) {
|
|
383
396
|
throw new ChartError({
|
|
384
397
|
code: CHART_ERROR_CODE.INVALID_DATA,
|
|
@@ -69,13 +69,30 @@ export function getZoomedSeriesData(args) {
|
|
|
69
69
|
prevPointInRange = currentPointInRange;
|
|
70
70
|
if (zoomState.x) {
|
|
71
71
|
const [xMin, xMax] = zoomState.x;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
if ('x0' in point && 'x1' in point) {
|
|
73
|
+
const isStartInRange = isValueInRange({
|
|
74
|
+
axis: xAxis,
|
|
75
|
+
value: point.x0,
|
|
76
|
+
min: xMin,
|
|
77
|
+
max: xMax,
|
|
78
|
+
});
|
|
79
|
+
const isEndInRange = isValueInRange({
|
|
80
|
+
axis: xAxis,
|
|
81
|
+
value: point.x1,
|
|
82
|
+
min: xMin,
|
|
83
|
+
max: xMax,
|
|
84
|
+
});
|
|
85
|
+
inXRange = isStartInRange || isEndInRange;
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
const x = 'x' in point ? ((_a = point.x) !== null && _a !== void 0 ? _a : undefined) : undefined;
|
|
89
|
+
inXRange = isValueInRange({
|
|
90
|
+
axis: xAxis,
|
|
91
|
+
value: x,
|
|
92
|
+
min: xMin,
|
|
93
|
+
max: xMax,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
79
96
|
}
|
|
80
97
|
if (zoomState.y) {
|
|
81
98
|
const yAxisIndex = 'yAxis' in seriesItem && typeof seriesItem.yAxis === 'number'
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Selection } from 'd3-selection';
|
|
2
|
+
import type { PreparedAnnotation } from '../../../core/series/types';
|
|
3
|
+
type AnnotationAnchor = {
|
|
4
|
+
annotation: PreparedAnnotation;
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
export { type AnnotationAnchor };
|
|
9
|
+
export declare function renderAnnotations(args: {
|
|
10
|
+
anchors: AnnotationAnchor[];
|
|
11
|
+
container: Selection<SVGGElement, unknown, null, undefined>;
|
|
12
|
+
plotHeight: number;
|
|
13
|
+
plotWidth: number;
|
|
14
|
+
}): void;
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { select } from 'd3-selection';
|
|
2
|
+
import { DESCENDER_RATIO } from '../../../core/utils/text';
|
|
3
|
+
import { block } from '../../../utils';
|
|
4
|
+
const b = block('annotation');
|
|
5
|
+
const ARROW_WIDTH = 18;
|
|
6
|
+
const ARROW_HEIGHT = 9;
|
|
7
|
+
// Base arrow path pointing downward (for "top" placement).
|
|
8
|
+
// Elliptical arc matching gravity-ui/uikit Popup arrow geometry.
|
|
9
|
+
// uikit builds the arrow from two 28×30 circles ($arrow-circle-width/height) with
|
|
10
|
+
// a 5px inset box-shadow ($arrow-border), clipped in 9×9 wrappers.
|
|
11
|
+
// The visible curve follows the inner edge of the ring:
|
|
12
|
+
// rx = circle_width/2 - (arrow_border - border_width) = 14 - 4 = 10
|
|
13
|
+
// ry = circle_height/2 - (arrow_border - border_width) = 15 - 4 = 11
|
|
14
|
+
const ARROW_RX = 10;
|
|
15
|
+
const ARROW_RY = 11;
|
|
16
|
+
const ARROW_PATH = (() => {
|
|
17
|
+
const hw = ARROW_WIDTH / 2;
|
|
18
|
+
const h = ARROW_HEIGHT;
|
|
19
|
+
return `M ${-hw},0 A ${ARROW_RX} ${ARROW_RY} 0 0 1 0,${h} A ${ARROW_RX} ${ARROW_RY} 0 0 1 ${hw},0 Z`;
|
|
20
|
+
})();
|
|
21
|
+
function getArrowRotation(placement) {
|
|
22
|
+
switch (placement) {
|
|
23
|
+
case 'top':
|
|
24
|
+
return 0;
|
|
25
|
+
case 'bottom':
|
|
26
|
+
return 180;
|
|
27
|
+
case 'right':
|
|
28
|
+
return 90;
|
|
29
|
+
case 'left':
|
|
30
|
+
default:
|
|
31
|
+
return -90;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
function clampX(x, width, plotWidth) {
|
|
35
|
+
return Math.max(0, Math.min(x, plotWidth - width));
|
|
36
|
+
}
|
|
37
|
+
function clampY(y, height, plotHeight) {
|
|
38
|
+
return Math.max(0, Math.min(y, plotHeight - height));
|
|
39
|
+
}
|
|
40
|
+
function calculateLayout(args) {
|
|
41
|
+
const { anchorX, anchorY, popupWidth, popupHeight, offset, plotWidth, plotHeight } = args;
|
|
42
|
+
// Minimum distance from popup edge to arrow center (arrow half-width + border radius clearance)
|
|
43
|
+
const arrowEdgePadding = ARROW_WIDTH / 2;
|
|
44
|
+
// Check if anchor falls within popup's horizontal span (for top/bottom placement)
|
|
45
|
+
function isAnchorInPopupX(popupX) {
|
|
46
|
+
return (anchorX >= popupX + arrowEdgePadding &&
|
|
47
|
+
anchorX <= popupX + popupWidth - arrowEdgePadding);
|
|
48
|
+
}
|
|
49
|
+
// Check if anchor falls within popup's vertical span (for right/left placement)
|
|
50
|
+
function isAnchorInPopupY(popupY) {
|
|
51
|
+
return (anchorY >= popupY + arrowEdgePadding &&
|
|
52
|
+
anchorY <= popupY + popupHeight - arrowEdgePadding);
|
|
53
|
+
}
|
|
54
|
+
// Try top
|
|
55
|
+
const topY = anchorY - offset - ARROW_HEIGHT - popupHeight;
|
|
56
|
+
if (topY >= 0) {
|
|
57
|
+
const popupX = clampX(anchorX - popupWidth / 2, popupWidth, plotWidth);
|
|
58
|
+
if (isAnchorInPopupX(popupX)) {
|
|
59
|
+
return {
|
|
60
|
+
arrowX: anchorX,
|
|
61
|
+
arrowY: anchorY,
|
|
62
|
+
popupX,
|
|
63
|
+
popupY: topY,
|
|
64
|
+
placement: 'top',
|
|
65
|
+
showArrow: true,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Try bottom
|
|
70
|
+
const bottomY = anchorY + offset + ARROW_HEIGHT;
|
|
71
|
+
if (bottomY + popupHeight <= plotHeight) {
|
|
72
|
+
const popupX = clampX(anchorX - popupWidth / 2, popupWidth, plotWidth);
|
|
73
|
+
if (isAnchorInPopupX(popupX)) {
|
|
74
|
+
return {
|
|
75
|
+
arrowX: anchorX,
|
|
76
|
+
arrowY: anchorY,
|
|
77
|
+
popupX,
|
|
78
|
+
popupY: bottomY,
|
|
79
|
+
placement: 'bottom',
|
|
80
|
+
showArrow: true,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Try right
|
|
85
|
+
const rightX = anchorX + offset + ARROW_HEIGHT;
|
|
86
|
+
if (rightX + popupWidth <= plotWidth) {
|
|
87
|
+
const popupY = clampY(anchorY - popupHeight / 2, popupHeight, plotHeight);
|
|
88
|
+
if (isAnchorInPopupY(popupY)) {
|
|
89
|
+
return {
|
|
90
|
+
arrowX: anchorX,
|
|
91
|
+
arrowY: anchorY,
|
|
92
|
+
popupX: rightX,
|
|
93
|
+
popupY,
|
|
94
|
+
placement: 'right',
|
|
95
|
+
showArrow: true,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Try left
|
|
100
|
+
const leftX = anchorX - offset - ARROW_HEIGHT - popupWidth;
|
|
101
|
+
if (leftX >= 0) {
|
|
102
|
+
const popupY = clampY(anchorY - popupHeight / 2, popupHeight, plotHeight);
|
|
103
|
+
if (isAnchorInPopupY(popupY)) {
|
|
104
|
+
return {
|
|
105
|
+
arrowX: anchorX,
|
|
106
|
+
arrowY: anchorY,
|
|
107
|
+
popupX: leftX,
|
|
108
|
+
popupY,
|
|
109
|
+
placement: 'left',
|
|
110
|
+
showArrow: true,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
// Fallback: no arrow, popup near anchor (prefer above, then below)
|
|
115
|
+
const popupX = clampX(anchorX - popupWidth / 2, popupWidth, plotWidth);
|
|
116
|
+
const fallbackTopY = anchorY - offset - popupHeight;
|
|
117
|
+
const popupY = fallbackTopY >= 0 ? fallbackTopY : Math.min(plotHeight - popupHeight, anchorY + offset);
|
|
118
|
+
return {
|
|
119
|
+
arrowX: anchorX,
|
|
120
|
+
arrowY: anchorY,
|
|
121
|
+
popupX,
|
|
122
|
+
popupY,
|
|
123
|
+
placement: 'top',
|
|
124
|
+
showArrow: false,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function getArrowTranslate(layout, popupWidth, popupHeight) {
|
|
128
|
+
const { arrowX, arrowY, popupX, popupY, placement } = layout;
|
|
129
|
+
// Overlap by 0.5px to avoid subpixel gap between arrow and popup rect
|
|
130
|
+
const overlap = 0.5;
|
|
131
|
+
switch (placement) {
|
|
132
|
+
case 'top':
|
|
133
|
+
return `translate(${arrowX}, ${popupY + popupHeight - overlap})`;
|
|
134
|
+
case 'bottom':
|
|
135
|
+
return `translate(${arrowX}, ${popupY + overlap})`;
|
|
136
|
+
case 'right':
|
|
137
|
+
return `translate(${popupX + overlap}, ${arrowY})`;
|
|
138
|
+
case 'left':
|
|
139
|
+
default:
|
|
140
|
+
return `translate(${popupX + popupWidth - overlap}, ${arrowY})`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
export function renderAnnotations(args) {
|
|
144
|
+
const { container, anchors, plotWidth, plotHeight } = args;
|
|
145
|
+
container.selectAll(`.${b()}`).remove();
|
|
146
|
+
if (!anchors.length) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
const groups = container
|
|
150
|
+
.selectAll(`.${b()}`)
|
|
151
|
+
.data(anchors)
|
|
152
|
+
.join('g')
|
|
153
|
+
.attr('class', b());
|
|
154
|
+
groups.each(function (d) {
|
|
155
|
+
const g = select(this);
|
|
156
|
+
const { annotation, x: anchorX, y: anchorY } = d;
|
|
157
|
+
const { label, popup } = annotation;
|
|
158
|
+
const [paddingV, paddingH] = popup.padding;
|
|
159
|
+
const popupWidth = label.size.width + paddingH * 2;
|
|
160
|
+
const popupHeight = label.size.height + paddingV * 2;
|
|
161
|
+
const layout = calculateLayout({
|
|
162
|
+
anchorX,
|
|
163
|
+
anchorY,
|
|
164
|
+
popupWidth,
|
|
165
|
+
popupHeight,
|
|
166
|
+
offset: popup.offset,
|
|
167
|
+
plotWidth,
|
|
168
|
+
plotHeight,
|
|
169
|
+
});
|
|
170
|
+
// Popup background
|
|
171
|
+
g.append('rect')
|
|
172
|
+
.attr('class', b('popup'))
|
|
173
|
+
.attr('x', layout.popupX)
|
|
174
|
+
.attr('y', layout.popupY)
|
|
175
|
+
.attr('width', popupWidth)
|
|
176
|
+
.attr('height', popupHeight)
|
|
177
|
+
.attr('rx', popup.borderRadius)
|
|
178
|
+
.attr('ry', popup.borderRadius)
|
|
179
|
+
.attr('fill', popup.backgroundColor);
|
|
180
|
+
// Arrow
|
|
181
|
+
if (layout.showArrow) {
|
|
182
|
+
const arrowTranslate = getArrowTranslate(layout, popupWidth, popupHeight);
|
|
183
|
+
const arrowRotation = getArrowRotation(layout.placement);
|
|
184
|
+
g.append('path')
|
|
185
|
+
.attr('class', b('arrow'))
|
|
186
|
+
.attr('d', ARROW_PATH)
|
|
187
|
+
.attr('fill', popup.backgroundColor)
|
|
188
|
+
.attr('transform', `${arrowTranslate} rotate(${arrowRotation})`);
|
|
189
|
+
}
|
|
190
|
+
// Text
|
|
191
|
+
g.append('text')
|
|
192
|
+
.attr('class', b('text'))
|
|
193
|
+
.text(label.text)
|
|
194
|
+
.attr('x', layout.popupX + paddingH)
|
|
195
|
+
.attr('y', layout.popupY + paddingV + label.size.height * (1 - DESCENDER_RATIO))
|
|
196
|
+
.style('font-size', label.style.fontSize)
|
|
197
|
+
.style('font-weight', label.style.fontWeight || '')
|
|
198
|
+
.style('fill', label.style.fontColor || '');
|
|
199
|
+
});
|
|
200
|
+
}
|
|
@@ -3,6 +3,8 @@ import type { Dispatch } from 'd3-dispatch';
|
|
|
3
3
|
import type { PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
4
|
import type { PreparedAreaData } from './types';
|
|
5
5
|
type Args = {
|
|
6
|
+
boundsHeight: number;
|
|
7
|
+
boundsWidth: number;
|
|
6
8
|
clipPathId: string;
|
|
7
9
|
htmlLayout: HTMLElement | null;
|
|
8
10
|
preparedData: PreparedAreaData[];
|
|
@@ -6,15 +6,17 @@ import get from 'lodash/get';
|
|
|
6
6
|
import { filterOverlappingLabels } from '../../../core/utils';
|
|
7
7
|
import { block } from '../../../utils';
|
|
8
8
|
import { HtmlLayer } from '../HtmlLayer';
|
|
9
|
+
import { renderAnnotations } from '../annotation';
|
|
9
10
|
import { getMarkerHaloVisibility, getMarkerVisibility, renderMarker, selectMarkerHalo, selectMarkerSymbol, setMarker, } from '../marker';
|
|
10
11
|
import { setActiveState } from '../utils';
|
|
11
12
|
const b = block('area');
|
|
12
13
|
export const AreaSeriesShapes = (args) => {
|
|
13
|
-
const { dispatcher, preparedData, seriesOptions, htmlLayout, clipPathId } = args;
|
|
14
|
+
const { boundsHeight, boundsWidth, dispatcher, preparedData, seriesOptions, htmlLayout, clipPathId, } = args;
|
|
14
15
|
const hoveredDataRef = React.useRef(null);
|
|
15
16
|
const plotRef = React.useRef(null);
|
|
16
17
|
const markersRef = React.useRef(null);
|
|
17
18
|
const hoverMarkersRef = React.useRef(null);
|
|
19
|
+
const annotationsRef = React.useRef(null);
|
|
18
20
|
const allowOverlapDataLabels = React.useMemo(() => {
|
|
19
21
|
return preparedData.some((d) => d === null || d === void 0 ? void 0 : d.series.dataLabels.allowOverlap);
|
|
20
22
|
}, [preparedData]);
|
|
@@ -83,6 +85,15 @@ export const AreaSeriesShapes = (args) => {
|
|
|
83
85
|
.data(markers)
|
|
84
86
|
.join('g')
|
|
85
87
|
.call(renderMarker);
|
|
88
|
+
if (annotationsRef.current) {
|
|
89
|
+
const anchors = preparedData.flatMap((d) => d.annotations);
|
|
90
|
+
renderAnnotations({
|
|
91
|
+
anchors,
|
|
92
|
+
container: select(annotationsRef.current),
|
|
93
|
+
plotHeight: boundsHeight,
|
|
94
|
+
plotWidth: boundsWidth,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
86
97
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
87
98
|
const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
|
|
88
99
|
function handleShapeHover(data) {
|
|
@@ -189,7 +200,14 @@ export const AreaSeriesShapes = (args) => {
|
|
|
189
200
|
return () => {
|
|
190
201
|
dispatcher === null || dispatcher === void 0 ? void 0 : dispatcher.on('hover-shape.area', null);
|
|
191
202
|
};
|
|
192
|
-
}, [
|
|
203
|
+
}, [
|
|
204
|
+
allowOverlapDataLabels,
|
|
205
|
+
boundsHeight,
|
|
206
|
+
boundsWidth,
|
|
207
|
+
dispatcher,
|
|
208
|
+
preparedData,
|
|
209
|
+
seriesOptions,
|
|
210
|
+
]);
|
|
193
211
|
const htmlLayerData = React.useMemo(() => {
|
|
194
212
|
const items = preparedData.map((d) => d === null || d === void 0 ? void 0 : d.htmlLabels).flat();
|
|
195
213
|
if (allowOverlapDataLabels) {
|
|
@@ -201,5 +219,6 @@ export const AreaSeriesShapes = (args) => {
|
|
|
201
219
|
React.createElement("g", { ref: plotRef, className: b(), clipPath: `url(#${clipPathId})` }),
|
|
202
220
|
React.createElement("g", { ref: markersRef }),
|
|
203
221
|
React.createElement("g", { ref: hoverMarkersRef }),
|
|
222
|
+
React.createElement("g", { ref: annotationsRef }),
|
|
204
223
|
React.createElement(HtmlLayer, { preparedData: htmlLayerData, htmlLayout: htmlLayout })));
|
|
205
224
|
};
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { PreparedSplit } from '../../../core/layout/split-types';
|
|
2
2
|
import type { ChartScale } from '../../../core/scales/types';
|
|
3
3
|
import type { PreparedXAxis, PreparedYAxis } from '../../useAxis/types';
|
|
4
|
-
import type { PreparedAreaSeries } from '../../useSeries/types';
|
|
4
|
+
import type { PreparedAreaSeries, PreparedSeriesOptions } from '../../useSeries/types';
|
|
5
5
|
import type { PreparedAreaData } from './types';
|
|
6
6
|
export declare const prepareAreaData: (args: {
|
|
7
7
|
series: PreparedAreaSeries[];
|
|
8
|
+
seriesOptions?: PreparedSeriesOptions;
|
|
8
9
|
xAxis: PreparedXAxis;
|
|
9
10
|
xScale: ChartScale;
|
|
10
11
|
yAxis: PreparedYAxis[];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { group, min } from 'd3-array';
|
|
1
|
+
import { group, min, sort } from 'd3-array';
|
|
2
2
|
import isNil from 'lodash/isNil';
|
|
3
3
|
import round from 'lodash/round';
|
|
4
|
+
import { prepareAnnotation } from '../../../core/series/prepare-annotation';
|
|
4
5
|
import { getDataCategoryValue, getLabelsSize, getTextSizeFn } from '../../../core/utils';
|
|
5
6
|
import { getFormattedValue } from '../../../core/utils/format';
|
|
6
7
|
import { getXValue, getYValue } from '../utils';
|
|
@@ -27,7 +28,7 @@ function getXValues(series, xAxis, xScale) {
|
|
|
27
28
|
return acc;
|
|
28
29
|
}, []);
|
|
29
30
|
}
|
|
30
|
-
return Array.from(xValues);
|
|
31
|
+
return sort(Array.from(xValues), (d) => d[1]);
|
|
31
32
|
}
|
|
32
33
|
async function prepareDataLabels({ series, points, xMax, yAxisTop, isOutsideBounds, }) {
|
|
33
34
|
var _a;
|
|
@@ -76,8 +77,8 @@ async function prepareDataLabels({ series, points, xMax, yAxisTop, isOutsideBoun
|
|
|
76
77
|
return { svgLabels, htmlLabels };
|
|
77
78
|
}
|
|
78
79
|
export const prepareAreaData = async (args) => {
|
|
79
|
-
var _a, _b, _c, _d;
|
|
80
|
-
const { series, xAxis, xScale, yAxis, yScale, split, isOutsideBounds, isRangeSlider } = args;
|
|
80
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
81
|
+
const { series, seriesOptions, xAxis, xScale, yAxis, yScale, split, isOutsideBounds, isRangeSlider, } = args;
|
|
81
82
|
const [_xMin, xRangeMax] = xScale.range();
|
|
82
83
|
const xMax = xRangeMax;
|
|
83
84
|
const result = [];
|
|
@@ -165,15 +166,25 @@ export const prepareAreaData = async (args) => {
|
|
|
165
166
|
: d.x);
|
|
166
167
|
return m.set(key, d);
|
|
167
168
|
}, new Map());
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
169
|
+
const annotationOpts = (_d = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions.area) === null || _d === void 0 ? void 0 : _d.annotation;
|
|
170
|
+
const points = [];
|
|
171
|
+
for (let xIdx = 0; xIdx < xValues.length; xIdx++) {
|
|
172
|
+
const [x, xValue] = xValues[xIdx];
|
|
173
|
+
const rawData = seriesData.get(x);
|
|
174
|
+
const d = rawData !== null && rawData !== void 0 ? rawData : {
|
|
171
175
|
x,
|
|
172
176
|
y: 0,
|
|
173
177
|
};
|
|
174
|
-
let yDataValue = (
|
|
175
|
-
|
|
176
|
-
|
|
178
|
+
let yDataValue = (_e = d.y) !== null && _e !== void 0 ? _e : null;
|
|
179
|
+
const pointAnnotation = d.annotation && !isRangeSlider
|
|
180
|
+
? await prepareAnnotation({
|
|
181
|
+
annotation: d.annotation,
|
|
182
|
+
optionsLabel: annotationOpts === null || annotationOpts === void 0 ? void 0 : annotationOpts.label,
|
|
183
|
+
optionsPopup: annotationOpts === null || annotationOpts === void 0 ? void 0 : annotationOpts.popup,
|
|
184
|
+
})
|
|
185
|
+
: undefined;
|
|
186
|
+
if (s.nullMode === 'connect' && (yDataValue === null || !rawData)) {
|
|
187
|
+
continue;
|
|
177
188
|
}
|
|
178
189
|
if (yDataValue && isPercentStacking) {
|
|
179
190
|
yDataValue = Number(yDataValue) * ratio[x];
|
|
@@ -187,21 +198,23 @@ export const prepareAreaData = async (args) => {
|
|
|
187
198
|
});
|
|
188
199
|
if (typeof yDataValue === 'number' && yValue !== null) {
|
|
189
200
|
yValue = round(yValue, 2);
|
|
190
|
-
const prevPoint = seriesData.get((
|
|
191
|
-
const nextPoint = seriesData.get((
|
|
201
|
+
const prevPoint = seriesData.get((_f = xValues[xIdx - 1]) === null || _f === void 0 ? void 0 : _f[0]);
|
|
202
|
+
const nextPoint = seriesData.get((_g = xValues[xIdx + 1]) === null || _g === void 0 ? void 0 : _g[0]);
|
|
192
203
|
const currentPointStackHeight = Math.abs(yMin - yValue);
|
|
193
204
|
if (yDataValue >= 0) {
|
|
194
205
|
const positiveStackHeights = positiveStackValues.get(x);
|
|
195
|
-
let prevSectionStackHeight = (
|
|
196
|
-
let nextSectionStackHeight = (
|
|
206
|
+
let prevSectionStackHeight = (_h = positiveStackHeights === null || positiveStackHeights === void 0 ? void 0 : positiveStackHeights.prev) !== null && _h !== void 0 ? _h : 0;
|
|
207
|
+
let nextSectionStackHeight = (_j = positiveStackHeights === null || positiveStackHeights === void 0 ? void 0 : positiveStackHeights.next) !== null && _j !== void 0 ? _j : 0;
|
|
197
208
|
const point = {
|
|
198
209
|
y0: yAxisTop + yMin - prevSectionStackHeight,
|
|
199
210
|
x: xValue,
|
|
200
211
|
y: yAxisTop + yValue - prevSectionStackHeight,
|
|
212
|
+
color: (_l = (_k = d.marker) === null || _k === void 0 ? void 0 : _k.color) !== null && _l !== void 0 ? _l : d.color,
|
|
201
213
|
data: d,
|
|
202
214
|
series: s,
|
|
215
|
+
annotation: pointAnnotation,
|
|
203
216
|
};
|
|
204
|
-
|
|
217
|
+
points.push(point);
|
|
205
218
|
if (prevSectionStackHeight !== nextSectionStackHeight) {
|
|
206
219
|
const point2 = {
|
|
207
220
|
y0: yAxisTop + yMin - nextSectionStackHeight,
|
|
@@ -210,7 +223,7 @@ export const prepareAreaData = async (args) => {
|
|
|
210
223
|
data: d,
|
|
211
224
|
series: s,
|
|
212
225
|
};
|
|
213
|
-
|
|
226
|
+
points.push(point2);
|
|
214
227
|
if (isPercentStacking) {
|
|
215
228
|
const newYValue = yAxisTop +
|
|
216
229
|
yValue -
|
|
@@ -219,11 +232,11 @@ export const prepareAreaData = async (args) => {
|
|
|
219
232
|
point2.y = newYValue;
|
|
220
233
|
}
|
|
221
234
|
}
|
|
222
|
-
if ((prevPoint === null || prevPoint === void 0 ? void 0 : prevPoint.y) !== null) {
|
|
235
|
+
if ((prevPoint === null || prevPoint === void 0 ? void 0 : prevPoint.y) !== null || s.nullMode === 'zero') {
|
|
223
236
|
prevSectionStackHeight =
|
|
224
237
|
prevSectionStackHeight + currentPointStackHeight;
|
|
225
238
|
}
|
|
226
|
-
if ((nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.y) !== null) {
|
|
239
|
+
if ((nextPoint === null || nextPoint === void 0 ? void 0 : nextPoint.y) !== null || s.nullMode === 'zero') {
|
|
227
240
|
nextSectionStackHeight =
|
|
228
241
|
nextSectionStackHeight + currentPointStackHeight;
|
|
229
242
|
}
|
|
@@ -234,9 +247,9 @@ export const prepareAreaData = async (args) => {
|
|
|
234
247
|
}
|
|
235
248
|
else {
|
|
236
249
|
const negativeStackHeights = negativeStackValues.get(x);
|
|
237
|
-
let prevSectionStackHeight = (
|
|
238
|
-
let nextSectionStackHeight = (
|
|
239
|
-
|
|
250
|
+
let prevSectionStackHeight = (_m = negativeStackHeights === null || negativeStackHeights === void 0 ? void 0 : negativeStackHeights.prev) !== null && _m !== void 0 ? _m : 0;
|
|
251
|
+
let nextSectionStackHeight = (_o = negativeStackHeights === null || negativeStackHeights === void 0 ? void 0 : negativeStackHeights.next) !== null && _o !== void 0 ? _o : 0;
|
|
252
|
+
points.push({
|
|
240
253
|
y0: yAxisTop + yMin + prevSectionStackHeight,
|
|
241
254
|
x: xValue,
|
|
242
255
|
y: yAxisTop + yValue + prevSectionStackHeight,
|
|
@@ -244,7 +257,7 @@ export const prepareAreaData = async (args) => {
|
|
|
244
257
|
series: s,
|
|
245
258
|
});
|
|
246
259
|
if (prevSectionStackHeight !== nextSectionStackHeight) {
|
|
247
|
-
|
|
260
|
+
points.push({
|
|
248
261
|
y0: yAxisTop + yMin + nextSectionStackHeight,
|
|
249
262
|
x: xValue,
|
|
250
263
|
y: yAxisTop + yValue + nextSectionStackHeight,
|
|
@@ -267,7 +280,7 @@ export const prepareAreaData = async (args) => {
|
|
|
267
280
|
}
|
|
268
281
|
}
|
|
269
282
|
else {
|
|
270
|
-
|
|
283
|
+
points.push({
|
|
271
284
|
y0: yAxisTop + yMin,
|
|
272
285
|
x: xValue,
|
|
273
286
|
y: null,
|
|
@@ -275,8 +288,7 @@ export const prepareAreaData = async (args) => {
|
|
|
275
288
|
series: s,
|
|
276
289
|
});
|
|
277
290
|
}
|
|
278
|
-
|
|
279
|
-
}, []);
|
|
291
|
+
}
|
|
280
292
|
let markers = [];
|
|
281
293
|
const hasPerPointNormalMarkers = s.data.some((d) => { var _a, _b, _c; return (_c = (_b = (_a = d.marker) === null || _a === void 0 ? void 0 : _a.states) === null || _b === void 0 ? void 0 : _b.normal) === null || _c === void 0 ? void 0 : _c.enabled; });
|
|
282
294
|
if (s.marker.states.normal.enabled || hasPerPointNormalMarkers) {
|
|
@@ -297,7 +309,14 @@ export const prepareAreaData = async (args) => {
|
|
|
297
309
|
return markersAcc;
|
|
298
310
|
}, []);
|
|
299
311
|
}
|
|
312
|
+
const annotations = points.reduce((result, p) => {
|
|
313
|
+
if (p.annotation && p.y !== null) {
|
|
314
|
+
result.push({ annotation: p.annotation, x: p.x, y: p.y });
|
|
315
|
+
}
|
|
316
|
+
return result;
|
|
317
|
+
}, []);
|
|
300
318
|
seriesStackData.push({
|
|
319
|
+
annotations,
|
|
301
320
|
points,
|
|
302
321
|
markers,
|
|
303
322
|
svgLabels: [],
|
|
@@ -314,7 +333,7 @@ export const prepareAreaData = async (args) => {
|
|
|
314
333
|
for (let itemIndex = 0; itemIndex < seriesStackData.length; itemIndex++) {
|
|
315
334
|
const item = seriesStackData[itemIndex];
|
|
316
335
|
const currentYAxis = yAxis[item.series.yAxis];
|
|
317
|
-
const itemYAxisTop = ((
|
|
336
|
+
const itemYAxisTop = ((_p = split.plots[currentYAxis.plotIndex]) === null || _p === void 0 ? void 0 : _p.top) || 0;
|
|
318
337
|
if (item.series.dataLabels.enabled && !isRangeSlider) {
|
|
319
338
|
const labelsData = await prepareDataLabels({
|
|
320
339
|
series: item.series,
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
+
import type { PreparedAnnotation } from '../../../core/series/types';
|
|
1
2
|
import type { AreaSeriesData, HtmlItem, LabelData } from '../../../types';
|
|
2
3
|
import type { PreparedAreaSeries } from '../../useSeries/types';
|
|
4
|
+
import type { AnnotationAnchor } from '../annotation';
|
|
3
5
|
export type PointData = {
|
|
4
6
|
y0: number;
|
|
5
7
|
x: number;
|
|
6
8
|
y: number | null;
|
|
7
9
|
data: AreaSeriesData;
|
|
8
10
|
series: PreparedAreaSeries;
|
|
11
|
+
annotation?: PreparedAnnotation;
|
|
9
12
|
color?: string;
|
|
10
13
|
};
|
|
11
14
|
export type MarkerPointData = PointData & {
|
|
@@ -18,6 +21,7 @@ export type MarkerData = {
|
|
|
18
21
|
clipped: boolean;
|
|
19
22
|
};
|
|
20
23
|
export type PreparedAreaData = {
|
|
24
|
+
annotations: AnnotationAnchor[];
|
|
21
25
|
id: string;
|
|
22
26
|
points: PointData[];
|
|
23
27
|
markers: MarkerData[];
|
|
@@ -5,6 +5,8 @@ import type { PreparedBarXData } from './types';
|
|
|
5
5
|
export { prepareBarXData } from './prepare-data';
|
|
6
6
|
export * from './types';
|
|
7
7
|
type Args = {
|
|
8
|
+
boundsHeight: number;
|
|
9
|
+
boundsWidth: number;
|
|
8
10
|
clipPathId: string;
|
|
9
11
|
htmlLayout: HTMLElement | null;
|
|
10
12
|
preparedData: PreparedBarXData[];
|