@gravity-ui/charts 1.42.4 → 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.
- package/dist/cjs/components/AxisX/AxisX.js +27 -0
- package/dist/cjs/components/AxisX/prepare-axis-data.js +41 -0
- package/dist/cjs/components/AxisX/types.d.ts +18 -1
- package/dist/cjs/components/AxisY/AxisY.js +27 -0
- package/dist/cjs/components/AxisY/prepare-axis-data.js +41 -0
- package/dist/cjs/components/AxisY/types.d.ts +18 -1
- package/dist/cjs/components/ChartInner/index.js +16 -0
- package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +6 -5
- package/dist/cjs/components/ChartInner/useChartInnerProps.d.ts +2 -4
- package/dist/cjs/components/ChartInner/useChartInnerProps.js +1 -1
- package/dist/cjs/components/ChartInner/useDefaultState.js +4 -3
- package/dist/cjs/components/ChartInner/utils/chart.js +1 -1
- package/dist/cjs/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
- package/dist/cjs/components/ChartInner/utils/title.d.ts +2 -1
- package/dist/cjs/components/ChartInner/utils/title.js +69 -11
- package/dist/cjs/components/Title/index.js +3 -5
- package/dist/cjs/components/Tooltip/ChartTooltipContent.d.ts +2 -1
- package/dist/cjs/components/Tooltip/ChartTooltipContent.js +3 -2
- package/dist/cjs/components/Tooltip/index.js +2 -2
- package/dist/cjs/core/axes/types.d.ts +26 -9
- package/dist/cjs/core/axes/x-axis.js +14 -1
- package/dist/cjs/core/axes/y-axis.js +20 -7
- package/dist/cjs/core/constants/defaults/axis.d.ts +1 -0
- package/dist/cjs/core/constants/defaults/axis.js +1 -0
- package/dist/cjs/core/scales/y-scale.js +37 -13
- package/dist/cjs/core/types/chart/axis.d.ts +43 -1
- package/dist/cjs/core/types/chart/title.d.ts +10 -0
- package/dist/cjs/core/types/chart/tooltip.d.ts +3 -1
- package/dist/cjs/core/utils/common.js +1 -1
- package/dist/cjs/core/utils/get-hovered-plots.d.ts +3 -2
- package/dist/cjs/core/utils/get-hovered-plots.js +28 -4
- package/dist/cjs/core/utils/text.js +12 -2
- package/dist/cjs/hooks/types.d.ts +5 -2
- package/dist/cjs/hooks/useShapes/area/prepare-data.js +11 -6
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +12 -4
- package/dist/cjs/hooks/useTooltip/index.d.ts +3 -2
- package/dist/cjs/hooks/useTooltip/index.js +5 -3
- package/dist/esm/components/AxisX/AxisX.js +27 -0
- package/dist/esm/components/AxisX/prepare-axis-data.js +41 -0
- package/dist/esm/components/AxisX/types.d.ts +18 -1
- package/dist/esm/components/AxisY/AxisY.js +27 -0
- package/dist/esm/components/AxisY/prepare-axis-data.js +41 -0
- package/dist/esm/components/AxisY/types.d.ts +18 -1
- package/dist/esm/components/ChartInner/index.js +16 -0
- package/dist/esm/components/ChartInner/useChartInnerHandlers.js +6 -5
- package/dist/esm/components/ChartInner/useChartInnerProps.d.ts +2 -4
- package/dist/esm/components/ChartInner/useChartInnerProps.js +1 -1
- package/dist/esm/components/ChartInner/useDefaultState.js +4 -3
- package/dist/esm/components/ChartInner/utils/chart.js +1 -1
- package/dist/esm/components/ChartInner/utils/normalized-original-data.d.ts +1 -0
- package/dist/esm/components/ChartInner/utils/title.d.ts +2 -1
- package/dist/esm/components/ChartInner/utils/title.js +69 -11
- package/dist/esm/components/Title/index.js +3 -5
- package/dist/esm/components/Tooltip/ChartTooltipContent.d.ts +2 -1
- package/dist/esm/components/Tooltip/ChartTooltipContent.js +3 -2
- package/dist/esm/components/Tooltip/index.js +2 -2
- package/dist/esm/core/axes/types.d.ts +26 -9
- package/dist/esm/core/axes/x-axis.js +14 -1
- package/dist/esm/core/axes/y-axis.js +20 -7
- package/dist/esm/core/constants/defaults/axis.d.ts +1 -0
- package/dist/esm/core/constants/defaults/axis.js +1 -0
- package/dist/esm/core/scales/y-scale.js +37 -13
- package/dist/esm/core/types/chart/axis.d.ts +43 -1
- package/dist/esm/core/types/chart/title.d.ts +10 -0
- package/dist/esm/core/types/chart/tooltip.d.ts +3 -1
- package/dist/esm/core/utils/common.js +1 -1
- package/dist/esm/core/utils/get-hovered-plots.d.ts +3 -2
- package/dist/esm/core/utils/get-hovered-plots.js +28 -4
- package/dist/esm/core/utils/text.js +12 -2
- package/dist/esm/hooks/types.d.ts +5 -2
- package/dist/esm/hooks/useShapes/area/prepare-data.js +11 -6
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +12 -4
- package/dist/esm/hooks/useTooltip/index.d.ts +3 -2
- package/dist/esm/hooks/useTooltip/index.js +5 -3
- package/package.json +1 -1
|
@@ -23,6 +23,7 @@ export const AxisX = (props) => {
|
|
|
23
23
|
const plotDataAttr = 'data-plot-x';
|
|
24
24
|
const plotBandDataAttr = `data-plot-x-band-${preparedAxisData.id}`;
|
|
25
25
|
const plotLineDataAttr = `data-plot-x-line-${preparedAxisData.id}`;
|
|
26
|
+
const plotShapeDataAttr = `data-plot-x-shape-${preparedAxisData.id}`;
|
|
26
27
|
if (plotBeforeRef === null || plotBeforeRef === void 0 ? void 0 : plotBeforeRef.current) {
|
|
27
28
|
plotBeforeContainer = select(plotBeforeRef.current);
|
|
28
29
|
}
|
|
@@ -186,14 +187,40 @@ export const AxisX = (props) => {
|
|
|
186
187
|
setPlotLines(plotBeforeContainer, preparedAxisData.plotLines.filter((item) => item.layerPlacement === 'before'));
|
|
187
188
|
setPlotLines(plotAfterContainer, preparedAxisData.plotLines.filter((item) => item.layerPlacement === 'after'));
|
|
188
189
|
}
|
|
190
|
+
if (preparedAxisData.plotShapes.length > 0) {
|
|
191
|
+
const setPlotShapes = (plotContainer, plotShapes) => {
|
|
192
|
+
if (!plotContainer || !plotShapes.length) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
plotContainer
|
|
196
|
+
.selectAll(`[${plotShapeDataAttr}]`)
|
|
197
|
+
.remove()
|
|
198
|
+
.data(plotShapes)
|
|
199
|
+
.join('g')
|
|
200
|
+
.attr(plotDataAttr, 1)
|
|
201
|
+
.attr(plotShapeDataAttr, 1)
|
|
202
|
+
.attr('transform', (d) => `translate(${d.x}, ${d.y})`)
|
|
203
|
+
.attr('opacity', (d) => d.opacity)
|
|
204
|
+
.html((d) => d.renderer({
|
|
205
|
+
x: d.x,
|
|
206
|
+
y: 0,
|
|
207
|
+
plotHeight: d.plotHeight,
|
|
208
|
+
plotWidth: d.plotWidth,
|
|
209
|
+
}));
|
|
210
|
+
};
|
|
211
|
+
setPlotShapes(plotBeforeContainer, preparedAxisData.plotShapes.filter((item) => item.layerPlacement === 'before'));
|
|
212
|
+
setPlotShapes(plotAfterContainer, preparedAxisData.plotShapes.filter((item) => item.layerPlacement === 'after'));
|
|
213
|
+
}
|
|
189
214
|
return () => {
|
|
190
215
|
if (plotBeforeContainer) {
|
|
191
216
|
plotBeforeContainer.selectAll(`[${plotBandDataAttr}]`).remove();
|
|
192
217
|
plotBeforeContainer.selectAll(`[${plotLineDataAttr}]`).remove();
|
|
218
|
+
plotBeforeContainer.selectAll(`[${plotShapeDataAttr}]`).remove();
|
|
193
219
|
}
|
|
194
220
|
if (plotAfterContainer) {
|
|
195
221
|
plotAfterContainer.selectAll(`[${plotBandDataAttr}]`).remove();
|
|
196
222
|
plotAfterContainer.selectAll(`[${plotLineDataAttr}]`).remove();
|
|
223
|
+
plotAfterContainer.selectAll(`[${plotShapeDataAttr}]`).remove();
|
|
197
224
|
}
|
|
198
225
|
};
|
|
199
226
|
}, [lineGenerator, plotAfterRef, plotBeforeRef, preparedAxisData]);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getUniqId } from '@gravity-ui/uikit';
|
|
2
|
+
import { select } from 'd3-selection';
|
|
2
3
|
import { calculateCos, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, } from '../../core/utils';
|
|
3
4
|
import { getXAxisTickValues } from '../../core/utils/axis/x-axis';
|
|
4
5
|
import { getMultilineTitleContentRows } from '../utils/axis-title';
|
|
@@ -328,6 +329,45 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
|
|
|
328
329
|
dashStyle: plotLine.dashStyle,
|
|
329
330
|
});
|
|
330
331
|
}
|
|
332
|
+
const plotShapes = [];
|
|
333
|
+
const measureContainer = axis.plotShapes.length
|
|
334
|
+
? select(document.body)
|
|
335
|
+
.append('svg')
|
|
336
|
+
.style('visibility', 'hidden')
|
|
337
|
+
.style('position', 'absolute')
|
|
338
|
+
.style('top', '-200vw')
|
|
339
|
+
: null;
|
|
340
|
+
for (let i = 0; i < axis.plotShapes.length; i++) {
|
|
341
|
+
if (!measureContainer) {
|
|
342
|
+
break;
|
|
343
|
+
}
|
|
344
|
+
const plotShape = axis.plotShapes[i];
|
|
345
|
+
const axisScale = scale;
|
|
346
|
+
const shapeX = Number(axisScale(plotShape.value));
|
|
347
|
+
if (shapeX < 0 || shapeX > boundsWidth) {
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
const markup = plotShape.renderer({
|
|
351
|
+
x: shapeX,
|
|
352
|
+
y: 0,
|
|
353
|
+
plotHeight: axisHeight,
|
|
354
|
+
plotWidth: axisWidth,
|
|
355
|
+
});
|
|
356
|
+
const wrapper = measureContainer.append('g').html(markup);
|
|
357
|
+
const bbox = wrapper.node().getBBox();
|
|
358
|
+
wrapper.remove();
|
|
359
|
+
plotShapes.push({
|
|
360
|
+
hitbox: { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height },
|
|
361
|
+
layerPlacement: plotShape.layerPlacement,
|
|
362
|
+
opacity: plotShape.opacity,
|
|
363
|
+
plotHeight: axisHeight,
|
|
364
|
+
plotWidth: axisWidth,
|
|
365
|
+
renderer: plotShape.renderer,
|
|
366
|
+
x: shapeX,
|
|
367
|
+
y: axisTop,
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
measureContainer === null || measureContainer === void 0 ? void 0 : measureContainer.remove();
|
|
331
371
|
xAxisItems.push({
|
|
332
372
|
id: getUniqId(),
|
|
333
373
|
gridEnabled: axis.grid.enabled,
|
|
@@ -336,6 +376,7 @@ export async function prepareXAxisData({ axis, boundsOffsetLeft, boundsOffsetRig
|
|
|
336
376
|
domain,
|
|
337
377
|
plotBands,
|
|
338
378
|
plotLines,
|
|
379
|
+
plotShapes,
|
|
339
380
|
});
|
|
340
381
|
}
|
|
341
382
|
return xAxisItems;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DashStyle } from 'src/core/constants';
|
|
2
|
+
import type { AxisPlotShape } from '../../core/types/chart/axis';
|
|
2
3
|
import type { BaseTextStyle, HtmlItem, PlotLayerPlacement, PointPosition } from '../../types';
|
|
3
4
|
import type { TextRowData } from '../types';
|
|
4
5
|
export type AxisSvgLabelData = {
|
|
@@ -67,6 +68,21 @@ export type AxisPlotBandData = {
|
|
|
67
68
|
opacity: number;
|
|
68
69
|
label: AxisPlotLineLabel | null;
|
|
69
70
|
};
|
|
71
|
+
export type AxisPlotShapeData = {
|
|
72
|
+
hitbox: {
|
|
73
|
+
x: number;
|
|
74
|
+
y: number;
|
|
75
|
+
width: number;
|
|
76
|
+
height: number;
|
|
77
|
+
};
|
|
78
|
+
layerPlacement: PlotLayerPlacement;
|
|
79
|
+
opacity: number;
|
|
80
|
+
plotHeight: number;
|
|
81
|
+
plotWidth: number;
|
|
82
|
+
renderer: AxisPlotShape['renderer'];
|
|
83
|
+
x: number;
|
|
84
|
+
y: number;
|
|
85
|
+
};
|
|
70
86
|
export type AxisDomainData = {
|
|
71
87
|
start: [number, number];
|
|
72
88
|
end: [number, number];
|
|
@@ -78,6 +94,7 @@ export type AxisXData = {
|
|
|
78
94
|
title: AxisTitleData | null;
|
|
79
95
|
domain: AxisDomainData | null;
|
|
80
96
|
ticks: AxisTickData[];
|
|
81
|
-
plotLines: AxisPlotLineData[];
|
|
82
97
|
plotBands: AxisPlotBandData[];
|
|
98
|
+
plotLines: AxisPlotLineData[];
|
|
99
|
+
plotShapes: AxisPlotShapeData[];
|
|
83
100
|
};
|
|
@@ -28,6 +28,7 @@ export const AxisY = (props) => {
|
|
|
28
28
|
const plotDataAttr = 'data-plot-y';
|
|
29
29
|
const plotBandDataAttr = `data-plot-y-band-${preparedAxisData.id}`;
|
|
30
30
|
const plotLineDataAttr = `data-plot-y-line-${preparedAxisData.id}`;
|
|
31
|
+
const plotShapeDataAttr = `data-plot-y-shape-${preparedAxisData.id}`;
|
|
31
32
|
if (plotBeforeRef === null || plotBeforeRef === void 0 ? void 0 : plotBeforeRef.current) {
|
|
32
33
|
plotBeforeContainer = select(plotBeforeRef.current);
|
|
33
34
|
}
|
|
@@ -191,14 +192,40 @@ export const AxisY = (props) => {
|
|
|
191
192
|
setPlotLines(plotBeforeContainer, preparedAxisData.plotLines.filter((item) => item.layerPlacement === 'before'));
|
|
192
193
|
setPlotLines(plotAfterContainer, preparedAxisData.plotLines.filter((item) => item.layerPlacement === 'after'));
|
|
193
194
|
}
|
|
195
|
+
if (preparedAxisData.plotShapes.length > 0) {
|
|
196
|
+
const setPlotShapes = (plotContainer, plotShapes) => {
|
|
197
|
+
if (!plotContainer || !plotShapes.length) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
plotContainer
|
|
201
|
+
.selectAll(`[${plotShapeDataAttr}]`)
|
|
202
|
+
.remove()
|
|
203
|
+
.data(plotShapes)
|
|
204
|
+
.join('g')
|
|
205
|
+
.attr(plotDataAttr, 1)
|
|
206
|
+
.attr(plotShapeDataAttr, 1)
|
|
207
|
+
.attr('transform', (d) => `translate(${d.x}, ${d.y})`)
|
|
208
|
+
.attr('opacity', (d) => d.opacity)
|
|
209
|
+
.html((d) => d.renderer({
|
|
210
|
+
x: 0,
|
|
211
|
+
y: d.y,
|
|
212
|
+
plotHeight: d.plotHeight,
|
|
213
|
+
plotWidth: d.plotWidth,
|
|
214
|
+
}));
|
|
215
|
+
};
|
|
216
|
+
setPlotShapes(plotBeforeContainer, preparedAxisData.plotShapes.filter((item) => item.layerPlacement === 'before'));
|
|
217
|
+
setPlotShapes(plotAfterContainer, preparedAxisData.plotShapes.filter((item) => item.layerPlacement === 'after'));
|
|
218
|
+
}
|
|
194
219
|
return () => {
|
|
195
220
|
if (plotBeforeContainer) {
|
|
196
221
|
plotBeforeContainer.selectAll(`[${plotBandDataAttr}]`).remove();
|
|
197
222
|
plotBeforeContainer.selectAll(`[${plotLineDataAttr}]`).remove();
|
|
223
|
+
plotBeforeContainer.selectAll(`[${plotShapeDataAttr}]`).remove();
|
|
198
224
|
}
|
|
199
225
|
if (plotAfterContainer) {
|
|
200
226
|
plotAfterContainer.selectAll(`[${plotBandDataAttr}]`).remove();
|
|
201
227
|
plotAfterContainer.selectAll(`[${plotLineDataAttr}]`).remove();
|
|
228
|
+
plotAfterContainer.selectAll(`[${plotShapeDataAttr}]`).remove();
|
|
202
229
|
}
|
|
203
230
|
};
|
|
204
231
|
}, [lineGenerator, plotAfterRef, plotBeforeRef, preparedAxisData]);
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getUniqId } from '@gravity-ui/uikit';
|
|
2
|
+
import { select } from 'd3-selection';
|
|
2
3
|
import { calculateCos, calculateSin, formatAxisTickLabel, getBandsPosition, getLabelsSize, getMinSpaceBetween, getTextSizeFn, getTextWithElipsis, wrapText, } from '../../core/utils';
|
|
3
4
|
import { prepareHtmlYAxisTitle, prepareSvgYAxisTitle } from './prepare-axis-title';
|
|
4
5
|
import { getTickValues } from './utils';
|
|
@@ -290,6 +291,45 @@ export async function prepareYAxisData({ axis, split, scale, top: topOffset, wid
|
|
|
290
291
|
dashStyle: plotLine.dashStyle,
|
|
291
292
|
});
|
|
292
293
|
}
|
|
294
|
+
const plotShapes = [];
|
|
295
|
+
const measureContainer = axis.plotShapes.length
|
|
296
|
+
? select(document.body)
|
|
297
|
+
.append('svg')
|
|
298
|
+
.style('visibility', 'hidden')
|
|
299
|
+
.style('position', 'absolute')
|
|
300
|
+
.style('top', '-200vw')
|
|
301
|
+
: null;
|
|
302
|
+
for (let i = 0; i < axis.plotShapes.length; i++) {
|
|
303
|
+
if (!measureContainer) {
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
const plotShape = axis.plotShapes[i];
|
|
307
|
+
const axisScale = scale;
|
|
308
|
+
const shapeY = Number(axisScale(plotShape.value));
|
|
309
|
+
if (shapeY < 0 || shapeY > axisHeight) {
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
const markup = plotShape.renderer({
|
|
313
|
+
x: 0,
|
|
314
|
+
y: shapeY,
|
|
315
|
+
plotHeight: axisHeight,
|
|
316
|
+
plotWidth: width,
|
|
317
|
+
});
|
|
318
|
+
const wrapper = measureContainer.append('g').html(markup);
|
|
319
|
+
const bbox = wrapper.node().getBBox();
|
|
320
|
+
wrapper.remove();
|
|
321
|
+
plotShapes.push({
|
|
322
|
+
hitbox: { x: bbox.x, y: bbox.y, width: bbox.width, height: bbox.height },
|
|
323
|
+
layerPlacement: plotShape.layerPlacement,
|
|
324
|
+
opacity: plotShape.opacity,
|
|
325
|
+
plotHeight: axisHeight,
|
|
326
|
+
plotWidth: width,
|
|
327
|
+
renderer: plotShape.renderer,
|
|
328
|
+
x: 0,
|
|
329
|
+
y: axisPlotTopPosition + shapeY,
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
measureContainer === null || measureContainer === void 0 ? void 0 : measureContainer.remove();
|
|
293
333
|
return {
|
|
294
334
|
id: getUniqId(),
|
|
295
335
|
gridEnabled: axis.grid.enabled,
|
|
@@ -298,5 +338,6 @@ export async function prepareYAxisData({ axis, split, scale, top: topOffset, wid
|
|
|
298
338
|
domain,
|
|
299
339
|
plotBands,
|
|
300
340
|
plotLines,
|
|
341
|
+
plotShapes,
|
|
301
342
|
};
|
|
302
343
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { DashStyle } from 'src/core/constants';
|
|
2
|
+
import type { AxisPlotShape } from '../../core/types/chart/axis';
|
|
2
3
|
import type { BaseTextStyle, HtmlItem, PlotLayerPlacement, PointPosition } from '../../types';
|
|
3
4
|
import type { TextRowData } from '../types';
|
|
4
5
|
export type AxisSvgLabelData = {
|
|
@@ -78,6 +79,21 @@ export type AxisPlotBandData = {
|
|
|
78
79
|
opacity: number;
|
|
79
80
|
label: AxisPlotLineLabel | null;
|
|
80
81
|
};
|
|
82
|
+
export type AxisPlotShapeData = {
|
|
83
|
+
hitbox: {
|
|
84
|
+
x: number;
|
|
85
|
+
y: number;
|
|
86
|
+
width: number;
|
|
87
|
+
height: number;
|
|
88
|
+
};
|
|
89
|
+
layerPlacement: PlotLayerPlacement;
|
|
90
|
+
opacity: number;
|
|
91
|
+
plotHeight: number;
|
|
92
|
+
plotWidth: number;
|
|
93
|
+
renderer: AxisPlotShape['renderer'];
|
|
94
|
+
x: number;
|
|
95
|
+
y: number;
|
|
96
|
+
};
|
|
81
97
|
export type AxisDomainData = {
|
|
82
98
|
start: [number, number];
|
|
83
99
|
end: [number, number];
|
|
@@ -89,6 +105,7 @@ export type AxisYData = {
|
|
|
89
105
|
title: HtmlAxisTitleData | SvgAxisTitleData | null;
|
|
90
106
|
domain: AxisDomainData | null;
|
|
91
107
|
ticks: AxisTickData[];
|
|
92
|
-
plotLines: AxisPlotLineData[];
|
|
93
108
|
plotBands: AxisPlotBandData[];
|
|
109
|
+
plotLines: AxisPlotLineData[];
|
|
110
|
+
plotShapes: AxisPlotShapeData[];
|
|
94
111
|
};
|
|
@@ -154,6 +154,13 @@ export const ChartInner = (props) => {
|
|
|
154
154
|
split: preparedSplit,
|
|
155
155
|
series: preparedSeries.filter((s) => s.visible),
|
|
156
156
|
});
|
|
157
|
+
axisData.plotShapes.forEach((shapeData, j) => {
|
|
158
|
+
if (axis.plotShapes[j]) {
|
|
159
|
+
axis.plotShapes[j].hitbox = shapeData.hitbox;
|
|
160
|
+
axis.plotShapes[j].x = shapeData.x;
|
|
161
|
+
axis.plotShapes[j].y = shapeData.y;
|
|
162
|
+
}
|
|
163
|
+
});
|
|
157
164
|
items.push(axisData);
|
|
158
165
|
}
|
|
159
166
|
}
|
|
@@ -180,6 +187,15 @@ export const ChartInner = (props) => {
|
|
|
180
187
|
split: preparedSplit,
|
|
181
188
|
yAxis,
|
|
182
189
|
});
|
|
190
|
+
axisData.forEach((data) => {
|
|
191
|
+
data.plotShapes.forEach((shapeData, i) => {
|
|
192
|
+
if (axis.plotShapes[i]) {
|
|
193
|
+
axis.plotShapes[i].hitbox = shapeData.hitbox;
|
|
194
|
+
axis.plotShapes[i].x = shapeData.x;
|
|
195
|
+
axis.plotShapes[i].y = shapeData.y;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
});
|
|
183
199
|
items.push(...axisData);
|
|
184
200
|
}
|
|
185
201
|
return items;
|
|
@@ -29,7 +29,7 @@ export function useChartInnerHandlers(props) {
|
|
|
29
29
|
boundsHeight,
|
|
30
30
|
boundsWidth,
|
|
31
31
|
});
|
|
32
|
-
const { plotLines,
|
|
32
|
+
const { plotBands, plotLines, plotShapes } = getHoveredPlots({
|
|
33
33
|
pointerX: x,
|
|
34
34
|
pointerY: y,
|
|
35
35
|
xAxis,
|
|
@@ -37,7 +37,7 @@ export function useChartInnerHandlers(props) {
|
|
|
37
37
|
xScale,
|
|
38
38
|
yScale,
|
|
39
39
|
});
|
|
40
|
-
const hoveredPlotsArg = { lines: plotLines,
|
|
40
|
+
const hoveredPlotsArg = { bands: plotBands, lines: plotLines, shapes: plotShapes };
|
|
41
41
|
dispatcher.call(EventType.HOVER_SHAPE, event.target, closest, [pointerX, pointerY], hoveredPlotsArg);
|
|
42
42
|
dispatcher.call(EventType.POINTERMOVE_CHART, {}, {
|
|
43
43
|
hovered: closest,
|
|
@@ -93,7 +93,7 @@ export function useChartInnerHandlers(props) {
|
|
|
93
93
|
dispatcher.call(EventType.CLICK_CHART, undefined, { point: selected.data, series: selected.series }, event);
|
|
94
94
|
const nextTooltipFixed = !tooltipPinned;
|
|
95
95
|
if (!nextTooltipFixed) {
|
|
96
|
-
const { plotLines,
|
|
96
|
+
const { plotBands, plotLines, plotShapes } = getHoveredPlots({
|
|
97
97
|
pointerX: x,
|
|
98
98
|
pointerY: y,
|
|
99
99
|
xAxis,
|
|
@@ -101,14 +101,15 @@ export function useChartInnerHandlers(props) {
|
|
|
101
101
|
xScale,
|
|
102
102
|
yScale,
|
|
103
103
|
});
|
|
104
|
-
const hoveredPlotsArg = { lines: plotLines,
|
|
104
|
+
const hoveredPlotsArg = { bands: plotBands, lines: plotLines, shapes: plotShapes };
|
|
105
105
|
dispatcher.call(EventType.HOVER_SHAPE, event.target, items, [pointerX, pointerY], hoveredPlotsArg);
|
|
106
106
|
dispatcher.call(EventType.POINTERMOVE_CHART, {}, {
|
|
107
107
|
hovered: items,
|
|
108
108
|
xAxis,
|
|
109
109
|
yAxis: yAxis[0],
|
|
110
|
-
hoveredPlotLines: plotLines,
|
|
111
110
|
hoveredPlotBands: plotBands,
|
|
111
|
+
hoveredPlotLines: plotLines,
|
|
112
|
+
hoveredPlotShapes: plotShapes,
|
|
112
113
|
}, event);
|
|
113
114
|
}
|
|
114
115
|
togglePinTooltip === null || togglePinTooltip === void 0 ? void 0 : togglePinTooltip(nextTooltipFixed, event);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Dispatch } from 'd3-dispatch';
|
|
3
3
|
import type { ChartScale, LegendItem, OnLegendItemClick, PreparedLegend, PreparedSeries, PreparedSplit, PreparedXAxis, PreparedYAxis, RangeSliderState, ShapeData, ZoomState } from '../../hooks';
|
|
4
|
-
import type { PreparedChart } from '../../hooks/types';
|
|
4
|
+
import type { PreparedChart, PreparedTitle } from '../../hooks/types';
|
|
5
5
|
import type { LegendConfig } from '../../types';
|
|
6
6
|
import type { ChartInnerProps } from './types';
|
|
7
7
|
type Props = ChartInnerProps & {
|
|
@@ -24,9 +24,7 @@ export declare function useChartInnerProps(props: Props): {
|
|
|
24
24
|
shapesData: ShapeData[];
|
|
25
25
|
shapesReady: boolean;
|
|
26
26
|
handleLegendItemClick: OnLegendItemClick;
|
|
27
|
-
preparedTitle:
|
|
28
|
-
height: number;
|
|
29
|
-
}) | undefined;
|
|
27
|
+
preparedTitle: PreparedTitle | undefined;
|
|
30
28
|
preparedChart: PreparedChart | undefined;
|
|
31
29
|
allPreparedSeries?: PreparedSeries[] | undefined;
|
|
32
30
|
legendConfig?: LegendConfig | undefined;
|
|
@@ -50,7 +50,7 @@ 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 });
|
|
53
|
+
const preparedTitle = await getPreparedTitle({ title: data.title, chartWidth: width });
|
|
54
54
|
const preparedChart = getPreparedChart({
|
|
55
55
|
chart: data.chart,
|
|
56
56
|
seriesData: data.series.data,
|
|
@@ -29,7 +29,7 @@ export function useDefaultState(props) {
|
|
|
29
29
|
boundsHeight,
|
|
30
30
|
boundsWidth,
|
|
31
31
|
});
|
|
32
|
-
const { plotLines,
|
|
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,
|
|
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
|
+
chartWidth: number;
|
|
5
6
|
}) => Promise<PreparedTitle | undefined>;
|
|
@@ -1,20 +1,78 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import { getTextSizeFn } from '../../../core/utils';
|
|
2
|
+
import { getTextSizeFn, getTextWithElipsis, wrapText } from '../../../core/utils';
|
|
3
3
|
const DEFAULT_TITLE_FONT_SIZE = '15px';
|
|
4
|
-
const
|
|
5
|
-
export const getPreparedTitle = async ({ 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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
export const Title = (props) => {
|
|
3
|
-
const { chartWidth,
|
|
4
|
-
return (React.createElement("text", {
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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,
|
|
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
|
};
|