@gravity-ui/chartkit 3.4.3 → 3.6.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/build/plugins/d3/renderer/D3Widget.js +3 -3
- package/build/plugins/d3/renderer/components/Chart.d.ts +3 -1
- package/build/plugins/d3/renderer/components/Chart.js +13 -12
- package/build/plugins/d3/renderer/components/Legend.d.ts +3 -2
- package/build/plugins/d3/renderer/components/Legend.js +101 -61
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +12 -0
- package/build/plugins/d3/renderer/components/styles.css +4 -13
- package/build/plugins/d3/renderer/constants.d.ts +3 -0
- package/build/plugins/d3/renderer/constants.js +3 -0
- package/build/plugins/d3/renderer/hooks/index.d.ts +1 -1
- package/build/plugins/d3/renderer/hooks/index.js +1 -1
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useAxisScales/index.js +2 -2
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +2 -2
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +2 -4
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +21 -15
- package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +7 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/title.js +2 -2
- package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +3 -1
- package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +3 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +3 -3
- package/build/plugins/d3/renderer/hooks/useSeries/constants.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/constants.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +10 -8
- package/build/plugins/d3/renderer/hooks/useSeries/index.js +43 -14
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.d.ts +9 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +85 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +29 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/utils.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useSeries/utils.js +11 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x.js +7 -3
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +7 -2
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +26 -2
- package/build/plugins/d3/renderer/hooks/useShapes/pie.d.ts +13 -0
- package/build/plugins/d3/renderer/hooks/useShapes/pie.js +126 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +6 -3
- package/build/plugins/d3/renderer/hooks/useShapes/styles.css +22 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +49 -7
- package/build/plugins/d3/renderer/utils/index.js +50 -18
- package/build/plugins/d3/renderer/utils/math.d.ts +23 -0
- package/build/plugins/d3/renderer/utils/math.js +43 -0
- package/build/plugins/highcharts/renderer/components/HighchartsComponent.js +1 -1
- package/build/plugins/highcharts/renderer/components/HighchartsReact.d.ts +18 -0
- package/build/plugins/highcharts/renderer/components/HighchartsReact.js +46 -0
- package/build/plugins/index.d.ts +1 -0
- package/build/plugins/index.js +1 -0
- package/build/types/widget-data/bar-x.d.ts +6 -1
- package/build/types/widget-data/base.d.ts +12 -0
- package/build/types/widget-data/legend.d.ts +32 -0
- package/build/types/widget-data/pie.d.ts +37 -1
- package/build/types/widget-data/scatter.d.ts +6 -1
- package/package.json +1 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.d.ts +0 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.js +0 -3
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.d.ts +0 -5
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.js +0 -18
- package/build/plugins/d3/renderer/hooks/useLegend/index.d.ts +0 -13
- package/build/plugins/d3/renderer/hooks/useLegend/index.js +0 -28
|
@@ -8,8 +8,8 @@ const D3Widget = React.forwardRef(function D3Widget(props, forwardedRef) {
|
|
|
8
8
|
const [dimensions, setDimensions] = React.useState();
|
|
9
9
|
const handleResize = React.useCallback(() => {
|
|
10
10
|
if (ref.current) {
|
|
11
|
-
const { width, height } = ref.current.getBoundingClientRect();
|
|
12
|
-
setDimensions({ width, height });
|
|
11
|
+
const { top, left, width, height } = ref.current.getBoundingClientRect();
|
|
12
|
+
setDimensions({ top, left, width, height });
|
|
13
13
|
}
|
|
14
14
|
}, []);
|
|
15
15
|
const debuncedHandleResize = React.useMemo(() => {
|
|
@@ -35,6 +35,6 @@ const D3Widget = React.forwardRef(function D3Widget(props, forwardedRef) {
|
|
|
35
35
|
// dimensions initialize
|
|
36
36
|
handleResize();
|
|
37
37
|
}, [handleResize]);
|
|
38
|
-
return (React.createElement("div", { ref: ref, style: { width: '100%', height: '100%' } }, (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) && (dimensions === null || dimensions === void 0 ? void 0 : dimensions.height) && (React.createElement(Chart, { width: dimensions.width, height: dimensions.height, data: props.data }))));
|
|
38
|
+
return (React.createElement("div", { ref: ref, style: { width: '100%', height: '100%', position: 'relative' } }, (dimensions === null || dimensions === void 0 ? void 0 : dimensions.width) && (dimensions === null || dimensions === void 0 ? void 0 : dimensions.height) && (React.createElement(Chart, { top: (dimensions === null || dimensions === void 0 ? void 0 : dimensions.top) || 0, left: dimensions.left || 0, width: dimensions.width, height: dimensions.height, data: props.data }))));
|
|
39
39
|
});
|
|
40
40
|
export default D3Widget;
|
|
@@ -2,9 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import type { ChartKitWidgetData } from '../../../../types/widget-data';
|
|
3
3
|
import './styles.css';
|
|
4
4
|
type Props = {
|
|
5
|
+
top: number;
|
|
6
|
+
left: number;
|
|
5
7
|
width: number;
|
|
6
8
|
height: number;
|
|
7
9
|
data: ChartKitWidgetData;
|
|
8
10
|
};
|
|
9
|
-
export declare const Chart: (
|
|
11
|
+
export declare const Chart: (props: Props) => React.JSX.Element;
|
|
10
12
|
export {};
|
|
@@ -5,18 +5,16 @@ import { AxisX } from './AxisX';
|
|
|
5
5
|
import { Legend } from './Legend';
|
|
6
6
|
import { Title } from './Title';
|
|
7
7
|
import { Tooltip } from './Tooltip';
|
|
8
|
-
import { useChartDimensions, useChartEvents, useChartOptions,
|
|
9
|
-
import { isAxisRelatedSeries } from '../utils';
|
|
8
|
+
import { useChartDimensions, useChartEvents, useChartOptions, useAxisScales, useSeries, useShapes, useTooltip, } from '../hooks';
|
|
10
9
|
import './styles.css';
|
|
11
10
|
const b = block('d3');
|
|
12
|
-
export const Chart = (
|
|
11
|
+
export const Chart = (props) => {
|
|
12
|
+
const { top, left, width, height, data } = props;
|
|
13
13
|
// FIXME: add data validation
|
|
14
|
-
const { series } = data;
|
|
15
14
|
const svgRef = React.createRef();
|
|
16
|
-
const hasAxisRelatedSeries = series.data.some(isAxisRelatedSeries);
|
|
17
15
|
const { chartHovered, handleMouseEnter, handleMouseLeave } = useChartEvents();
|
|
18
16
|
const { chart, legend, title, tooltip, xAxis, yAxis } = useChartOptions(data);
|
|
19
|
-
const { boundsWidth, boundsHeight
|
|
17
|
+
const { boundsWidth, boundsHeight } = useChartDimensions({
|
|
20
18
|
width,
|
|
21
19
|
height,
|
|
22
20
|
margin: chart.margin,
|
|
@@ -25,12 +23,11 @@ export const Chart = ({ width, height, data }) => {
|
|
|
25
23
|
xAxis,
|
|
26
24
|
yAxis,
|
|
27
25
|
});
|
|
28
|
-
const {
|
|
29
|
-
const { chartSeries } = useSeries({ activeLegendItems, series: series.data });
|
|
26
|
+
const { preparedSeries, handleLegendItemClick } = useSeries({ series: data.series, legend });
|
|
30
27
|
const { xScale, yScale } = useAxisScales({
|
|
31
28
|
boundsWidth,
|
|
32
29
|
boundsHeight,
|
|
33
|
-
series:
|
|
30
|
+
series: preparedSeries,
|
|
34
31
|
xAxis,
|
|
35
32
|
yAxis,
|
|
36
33
|
});
|
|
@@ -38,7 +35,11 @@ export const Chart = ({ width, height, data }) => {
|
|
|
38
35
|
tooltip,
|
|
39
36
|
});
|
|
40
37
|
const { shapes } = useShapes({
|
|
41
|
-
|
|
38
|
+
top,
|
|
39
|
+
left,
|
|
40
|
+
boundsWidth,
|
|
41
|
+
boundsHeight,
|
|
42
|
+
series: preparedSeries,
|
|
42
43
|
xAxis,
|
|
43
44
|
xScale,
|
|
44
45
|
yAxis,
|
|
@@ -54,11 +55,11 @@ export const Chart = ({ width, height, data }) => {
|
|
|
54
55
|
chart.margin.left,
|
|
55
56
|
chart.margin.top + ((title === null || title === void 0 ? void 0 : title.height) || 0),
|
|
56
57
|
].join(',')})` },
|
|
57
|
-
|
|
58
|
+
xScale && yScale && (React.createElement(React.Fragment, null,
|
|
58
59
|
React.createElement(AxisY, { axises: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale }),
|
|
59
60
|
React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
|
|
60
61
|
React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale })))),
|
|
61
62
|
shapes),
|
|
62
|
-
legend.enabled && (React.createElement(Legend, { width: boundsWidth, offsetWidth: chart.margin.left, height:
|
|
63
|
+
legend.enabled && (React.createElement(Legend, { width: boundsWidth, offsetWidth: chart.margin.left, height: legend.height, legend: legend, offsetHeight: height - legend.height / 2, chartSeries: preparedSeries, onItemClick: handleLegendItemClick }))),
|
|
63
64
|
React.createElement(Tooltip, { hovered: hovered, pointerPosition: pointerPosition, tooltip: tooltip, xAxis: xAxis, yAxis: yAxis[0] })));
|
|
64
65
|
};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import type {
|
|
2
|
+
import type { OnLegendItemClick, PreparedLegend, PreparedSeries } from '../hooks';
|
|
3
3
|
type Props = {
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
|
+
legend: PreparedLegend;
|
|
6
7
|
offsetWidth: number;
|
|
7
8
|
offsetHeight: number;
|
|
8
|
-
chartSeries:
|
|
9
|
+
chartSeries: PreparedSeries[];
|
|
9
10
|
onItemClick: OnLegendItemClick;
|
|
10
11
|
};
|
|
11
12
|
export declare const Legend: (props: Props) => React.JSX.Element;
|
|
@@ -1,66 +1,106 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { select } from 'd3';
|
|
2
|
+
import { select, sum } from 'd3';
|
|
3
|
+
import get from 'lodash/get';
|
|
3
4
|
import { block } from '../../../../utils/cn';
|
|
4
5
|
const b = block('d3-legend');
|
|
6
|
+
const getLegendItems = (series) => {
|
|
7
|
+
return series.reduce((acc, s) => {
|
|
8
|
+
const legendEnabled = get(s, 'legend.enabled', true);
|
|
9
|
+
if (legendEnabled) {
|
|
10
|
+
acc.push(Object.assign(Object.assign({}, s), { symbol: s.legend.symbol }));
|
|
11
|
+
}
|
|
12
|
+
return acc;
|
|
13
|
+
}, []);
|
|
14
|
+
};
|
|
15
|
+
function getLegendPosition(args) {
|
|
16
|
+
const { align, offsetWidth, width, contentWidth } = args;
|
|
17
|
+
const top = 0;
|
|
18
|
+
if (align === 'left') {
|
|
19
|
+
return { top, left: offsetWidth };
|
|
20
|
+
}
|
|
21
|
+
if (align === 'right') {
|
|
22
|
+
return { top, left: offsetWidth + width - contentWidth };
|
|
23
|
+
}
|
|
24
|
+
return { top, left: offsetWidth + width / 2 - contentWidth / 2 };
|
|
25
|
+
}
|
|
5
26
|
export const Legend = (props) => {
|
|
6
|
-
const { width, offsetWidth, height, offsetHeight, chartSeries, onItemClick } = props;
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
27
|
+
const { width, offsetWidth, height, offsetHeight, chartSeries, legend, onItemClick } = props;
|
|
28
|
+
const ref = React.useRef(null);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
if (!ref.current) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const legendItems = getLegendItems(chartSeries);
|
|
34
|
+
const textWidths = [0];
|
|
35
|
+
const svgElement = select(ref.current);
|
|
36
|
+
svgElement.selectAll('*').remove();
|
|
37
|
+
const legendItemTemplate = svgElement
|
|
38
|
+
.selectAll('legend-history')
|
|
39
|
+
.data(legendItems)
|
|
40
|
+
.enter()
|
|
41
|
+
.append('g')
|
|
42
|
+
.attr('class', b('item'))
|
|
43
|
+
.on('click', function (e, d) {
|
|
44
|
+
onItemClick({ name: d.name, metaKey: e.metaKey });
|
|
45
|
+
});
|
|
46
|
+
svgElement
|
|
47
|
+
.selectAll('*')
|
|
48
|
+
.data(legendItems)
|
|
49
|
+
.append('text')
|
|
50
|
+
.text(function (d) {
|
|
51
|
+
return d.name;
|
|
52
|
+
})
|
|
53
|
+
.each(function () {
|
|
54
|
+
textWidths.push(this.getComputedTextLength());
|
|
55
|
+
})
|
|
56
|
+
.remove();
|
|
57
|
+
legendItemTemplate
|
|
58
|
+
.append('rect')
|
|
59
|
+
.attr('x', function (legendItem, i) {
|
|
60
|
+
return (i * legendItem.symbol.width +
|
|
61
|
+
i * legend.itemDistance +
|
|
62
|
+
i * legendItem.symbol.padding +
|
|
63
|
+
textWidths.slice(0, i + 1).reduce((acc, tw) => acc + tw, 0));
|
|
64
|
+
})
|
|
65
|
+
.attr('y', (legendItem) => offsetHeight - legendItem.symbol.height / 2)
|
|
66
|
+
.attr('width', (legendItem) => {
|
|
67
|
+
return legendItem.symbol.width;
|
|
68
|
+
})
|
|
69
|
+
.attr('height', (legendItem) => legendItem.symbol.height)
|
|
70
|
+
.attr('rx', (legendItem) => legendItem.symbol.radius)
|
|
71
|
+
.attr('class', b('item-shape'))
|
|
72
|
+
.style('fill', function (d) {
|
|
73
|
+
return d.color;
|
|
74
|
+
});
|
|
75
|
+
legendItemTemplate
|
|
76
|
+
.append('text')
|
|
77
|
+
.attr('x', function (legendItem, i) {
|
|
78
|
+
return (i * legendItem.symbol.width +
|
|
79
|
+
i * legend.itemDistance +
|
|
80
|
+
i * legendItem.symbol.padding +
|
|
81
|
+
legendItem.symbol.width +
|
|
82
|
+
legendItem.symbol.padding +
|
|
83
|
+
textWidths.slice(0, i + 1).reduce((acc, tw) => acc + tw, 0));
|
|
84
|
+
})
|
|
85
|
+
.attr('y', offsetHeight)
|
|
86
|
+
.attr('class', function (d) {
|
|
87
|
+
const mods = { selected: d.visible, unselected: !d.visible };
|
|
88
|
+
return b('item-text', mods);
|
|
89
|
+
})
|
|
90
|
+
.text(function (d) {
|
|
91
|
+
return ('name' in d && d.name);
|
|
92
|
+
})
|
|
93
|
+
.style('alignment-baseline', 'middle');
|
|
94
|
+
const contentWidth = sum(textWidths) +
|
|
95
|
+
sum(legendItems, (item) => item.symbol.width + item.symbol.padding) +
|
|
96
|
+
legend.itemDistance * (legendItems.length - 1);
|
|
97
|
+
const { left } = getLegendPosition({
|
|
98
|
+
align: legend.align,
|
|
99
|
+
width,
|
|
100
|
+
offsetWidth,
|
|
101
|
+
contentWidth,
|
|
102
|
+
});
|
|
103
|
+
svgElement.attr('transform', `translate(${[left, 0].join(',')})`);
|
|
104
|
+
}, [width, offsetWidth, height, offsetHeight, chartSeries, onItemClick, legend]);
|
|
105
|
+
return React.createElement("g", { ref: ref, width: width, height: height });
|
|
66
106
|
};
|
|
@@ -14,6 +14,18 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
|
14
14
|
React.createElement("span", null, "Y:\u00A0"),
|
|
15
15
|
React.createElement("b", null, yRow))));
|
|
16
16
|
}
|
|
17
|
+
case 'bar-x': {
|
|
18
|
+
const barXData = data;
|
|
19
|
+
const xRow = xAxis.type === 'category' ? barXData.category : barXData.x;
|
|
20
|
+
const yRow = yAxis.type === 'category' ? barXData.category : barXData.y;
|
|
21
|
+
return (React.createElement("div", null,
|
|
22
|
+
React.createElement("div", null, xRow),
|
|
23
|
+
React.createElement("div", null,
|
|
24
|
+
React.createElement("span", null,
|
|
25
|
+
React.createElement("b", null, series.name),
|
|
26
|
+
": ",
|
|
27
|
+
yRow))));
|
|
28
|
+
}
|
|
17
29
|
default: {
|
|
18
30
|
return null;
|
|
19
31
|
}
|
|
@@ -19,6 +19,10 @@
|
|
|
19
19
|
user-select: none;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
.chartkit-d3-legend__item-shape {
|
|
23
|
+
fill: var(--g-color-base-misc-medium);
|
|
24
|
+
}
|
|
25
|
+
|
|
22
26
|
.chartkit-d3-legend__item-text {
|
|
23
27
|
fill: var(--g-color-text-secondary);
|
|
24
28
|
}
|
|
@@ -31,19 +35,6 @@
|
|
|
31
35
|
fill: var(--g-color-text-complementary);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
|
-
.chartkit-d3-scatter__point {
|
|
35
|
-
stroke-width: 1px;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.chartkit-d3_hovered .chartkit-d3-scatter__point {
|
|
39
|
-
opacity: 0.5;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
.chartkit-d3-scatter__point:hover {
|
|
43
|
-
stroke: #fff;
|
|
44
|
-
opacity: 1;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
38
|
.chartkit-d3-title {
|
|
48
39
|
font-size: var(--g-text-subheader-2-font-size);
|
|
49
40
|
font-weight: var(--g-text-subheader-font-weight);
|
|
@@ -2,9 +2,9 @@ export * from './useChartDimensions';
|
|
|
2
2
|
export * from './useChartEvents';
|
|
3
3
|
export * from './useChartOptions';
|
|
4
4
|
export * from './useChartOptions/types';
|
|
5
|
-
export * from './useLegend';
|
|
6
5
|
export * from './useAxisScales';
|
|
7
6
|
export * from './useSeries';
|
|
7
|
+
export * from './useSeries/types';
|
|
8
8
|
export * from './useShapes';
|
|
9
9
|
export * from './useTooltip';
|
|
10
10
|
export * from './useTooltip/types';
|
|
@@ -2,9 +2,9 @@ export * from './useChartDimensions';
|
|
|
2
2
|
export * from './useChartEvents';
|
|
3
3
|
export * from './useChartOptions';
|
|
4
4
|
export * from './useChartOptions/types';
|
|
5
|
-
export * from './useLegend';
|
|
6
5
|
export * from './useAxisScales';
|
|
7
6
|
export * from './useSeries';
|
|
7
|
+
export * from './useSeries/types';
|
|
8
8
|
export * from './useShapes';
|
|
9
9
|
export * from './useTooltip';
|
|
10
10
|
export * from './useTooltip/types';
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
|
-
import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
|
|
3
2
|
import type { ChartOptions } from '../useChartOptions/types';
|
|
3
|
+
import { PreparedSeries } from '../useSeries/types';
|
|
4
4
|
export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
|
|
5
5
|
type Args = {
|
|
6
6
|
boundsWidth: number;
|
|
7
7
|
boundsHeight: number;
|
|
8
|
-
series:
|
|
8
|
+
series: PreparedSeries[];
|
|
9
9
|
xAxis: ChartOptions['xAxis'];
|
|
10
10
|
yAxis: ChartOptions['yAxis'];
|
|
11
11
|
};
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { scaleBand, scaleLinear, scaleUtc, extent } from 'd3';
|
|
3
3
|
import get from 'lodash/get';
|
|
4
|
-
import { getOnlyVisibleSeries,
|
|
4
|
+
import { getOnlyVisibleSeries, getDomainDataYBySeries, isAxisRelatedSeries, getDomainDataXBySeries, isSeriesWithCategoryValues, } from '../../utils';
|
|
5
5
|
const isNumericalArrayData = (data) => {
|
|
6
6
|
return data.every((d) => typeof d === 'number' || d === null);
|
|
7
7
|
};
|
|
8
8
|
const filterCategoriesByVisibleSeries = (categories, series) => {
|
|
9
9
|
return categories.filter((category) => {
|
|
10
10
|
return series.some((s) => {
|
|
11
|
-
return s.data.some((d) =>
|
|
11
|
+
return isSeriesWithCategoryValues(s) && s.data.some((d) => d.category === category);
|
|
12
12
|
});
|
|
13
13
|
});
|
|
14
14
|
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ChartMargin } from '../../../../../types/widget-data';
|
|
2
|
-
import type {
|
|
2
|
+
import type { PreparedAxis, PreparedLegend, PreparedTitle } from '../useChartOptions/types';
|
|
3
3
|
type Args = {
|
|
4
4
|
width: number;
|
|
5
5
|
height: number;
|
|
6
6
|
margin: ChartMargin;
|
|
7
|
-
legend:
|
|
7
|
+
legend: PreparedLegend;
|
|
8
8
|
title?: PreparedTitle;
|
|
9
9
|
xAxis?: PreparedAxis;
|
|
10
10
|
yAxis?: PreparedAxis[];
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
const LEGEND_LINE_HEIGHT = 15;
|
|
2
1
|
export const useChartDimensions = (args) => {
|
|
3
2
|
const { margin, legend, title, width, height, xAxis, yAxis } = args;
|
|
4
|
-
const legendHeight = legend.enabled ? LEGEND_LINE_HEIGHT : 0;
|
|
5
3
|
const titleHeight = (title === null || title === void 0 ? void 0 : title.height) || 0;
|
|
6
4
|
const xAxisTitleHeight = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.title.height) || 0;
|
|
7
5
|
const yAxisTitleHeight = (yAxis === null || yAxis === void 0 ? void 0 : yAxis.reduce((acc, axis) => {
|
|
8
6
|
return acc + (axis.title.height || 0);
|
|
9
7
|
}, 0)) || 0;
|
|
10
8
|
const boundsWidth = width - margin.right - margin.left - yAxisTitleHeight;
|
|
11
|
-
const boundsHeight = height - margin.top - margin.bottom -
|
|
12
|
-
return { boundsWidth, boundsHeight, legendHeight };
|
|
9
|
+
const boundsHeight = height - margin.top - margin.bottom - legend.height - titleHeight - xAxisTitleHeight;
|
|
10
|
+
return { boundsWidth, boundsHeight, legendHeight: legend.height };
|
|
13
11
|
};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { select, max } from 'd3';
|
|
2
2
|
import get from 'lodash/get';
|
|
3
|
-
import { formatAxisTickLabel, getDomainDataYBySeries } from '../../utils';
|
|
4
|
-
import { getHorisontalSvgTextDimensions } from './utils';
|
|
3
|
+
import { formatAxisTickLabel, getDomainDataYBySeries, getHorisontalSvgTextHeight, isAxisRelatedSeries, } from '../../utils';
|
|
5
4
|
const AXIS_WIDTH = 1;
|
|
6
5
|
const getAxisLabelMaxWidth = (args) => {
|
|
7
6
|
const { axis, series } = args;
|
|
@@ -9,8 +8,8 @@ const getAxisLabelMaxWidth = (args) => {
|
|
|
9
8
|
let width = 0;
|
|
10
9
|
switch (axis.type) {
|
|
11
10
|
case 'category': {
|
|
12
|
-
const
|
|
13
|
-
maxDomainValue = [...
|
|
11
|
+
const yCategories = get(axis, 'categories', []);
|
|
12
|
+
maxDomainValue = [...yCategories].sort((c1, c2) => c2.length - c1.length)[0];
|
|
14
13
|
break;
|
|
15
14
|
}
|
|
16
15
|
case 'datetime': {
|
|
@@ -45,17 +44,24 @@ const getAxisLabelMaxWidth = (args) => {
|
|
|
45
44
|
};
|
|
46
45
|
export const getPreparedChart = (args) => {
|
|
47
46
|
const { chart, series, preparedXAxis, preparedY1Axis } = args;
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
const hasAxisRelatedSeries = series.data.some(isAxisRelatedSeries);
|
|
48
|
+
let marginBottom = get(chart, 'margin.bottom', 0);
|
|
49
|
+
let marginLeft = get(chart, 'margin.left', 0);
|
|
50
|
+
let marginTop = get(chart, 'margin.top', 0);
|
|
51
|
+
let marginRight = get(chart, 'margin.right', 0);
|
|
52
|
+
if (hasAxisRelatedSeries) {
|
|
53
|
+
marginBottom +=
|
|
54
|
+
preparedXAxis.labels.padding +
|
|
55
|
+
getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedXAxis.labels.style });
|
|
56
|
+
marginLeft +=
|
|
57
|
+
AXIS_WIDTH +
|
|
58
|
+
preparedY1Axis.labels.padding +
|
|
59
|
+
getAxisLabelMaxWidth({ axis: preparedY1Axis, series: series.data }) +
|
|
60
|
+
(preparedY1Axis.title.height || 0);
|
|
61
|
+
marginTop +=
|
|
62
|
+
getHorisontalSvgTextHeight({ text: 'Tmp', style: preparedY1Axis.labels.style }) / 2;
|
|
63
|
+
marginRight += getAxisLabelMaxWidth({ axis: preparedXAxis, series: series.data }) / 2;
|
|
64
|
+
}
|
|
59
65
|
return {
|
|
60
66
|
margin: {
|
|
61
67
|
top: marginTop,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
2
|
import type { ChartOptions } from './types';
|
|
3
|
-
|
|
3
|
+
type Args = ChartKitWidgetData;
|
|
4
|
+
export declare const useChartOptions: (args: Args) => ChartOptions;
|
|
5
|
+
export {};
|
|
@@ -1,7 +1,12 @@
|
|
|
1
|
+
const LEGEND_LINE_HEIGHT = 15;
|
|
1
2
|
export const getPreparedLegend = (args) => {
|
|
2
3
|
const { legend, series } = args;
|
|
3
|
-
const enabled = legend === null || legend === void 0 ? void 0 : legend.enabled;
|
|
4
|
+
const enabled = typeof (legend === null || legend === void 0 ? void 0 : legend.enabled) === 'boolean' ? legend === null || legend === void 0 ? void 0 : legend.enabled : series.data.length > 1;
|
|
5
|
+
const height = enabled ? LEGEND_LINE_HEIGHT : 0;
|
|
4
6
|
return {
|
|
5
|
-
|
|
7
|
+
align: (legend === null || legend === void 0 ? void 0 : legend.align) || 'center',
|
|
8
|
+
enabled,
|
|
9
|
+
itemDistance: (legend === null || legend === void 0 ? void 0 : legend.itemDistance) || 20,
|
|
10
|
+
height,
|
|
6
11
|
};
|
|
7
12
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import {
|
|
2
|
+
import { getHorisontalSvgTextHeight } from '../../utils';
|
|
3
3
|
const DEFAULT_TITLE_FONT_SIZE = '15px';
|
|
4
4
|
const TITLE_PADDINGS = 8 * 2;
|
|
5
5
|
export const getPreparedTitle = ({ title, }) => {
|
|
@@ -8,7 +8,7 @@ export const getPreparedTitle = ({ title, }) => {
|
|
|
8
8
|
fontSize: get(title, 'style.fontSize', DEFAULT_TITLE_FONT_SIZE),
|
|
9
9
|
};
|
|
10
10
|
const titleHeight = titleText
|
|
11
|
-
?
|
|
11
|
+
? getHorisontalSvgTextHeight({ text: titleText, style: titleStyle }) + TITLE_PADDINGS
|
|
12
12
|
: 0;
|
|
13
13
|
const preparedTitle = titleText
|
|
14
14
|
? { text: titleText, style: titleStyle, height: titleHeight }
|
|
@@ -5,7 +5,9 @@ type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' |
|
|
|
5
5
|
export type PreparedChart = {
|
|
6
6
|
margin: ChartMargin;
|
|
7
7
|
};
|
|
8
|
-
export type PreparedLegend = Required<ChartKitWidgetLegend
|
|
8
|
+
export type PreparedLegend = Required<ChartKitWidgetLegend> & {
|
|
9
|
+
height: number;
|
|
10
|
+
};
|
|
9
11
|
export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
|
|
10
12
|
type: ChartKitWidgetAxisType;
|
|
11
13
|
labels: PreparedAxisLabels;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '
|
|
3
|
-
import {
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
|
|
3
|
+
import { getHorisontalSvgTextHeight } from '../../utils';
|
|
4
4
|
export const getPreparedXAxis = ({ xAxis }) => {
|
|
5
5
|
const titleText = get(xAxis, 'title.text', '');
|
|
6
6
|
const titleStyle = {
|
|
@@ -21,7 +21,7 @@ export const getPreparedXAxis = ({ xAxis }) => {
|
|
|
21
21
|
text: titleText,
|
|
22
22
|
style: titleStyle,
|
|
23
23
|
height: titleText
|
|
24
|
-
?
|
|
24
|
+
? getHorisontalSvgTextHeight({ text: titleText, style: titleStyle })
|
|
25
25
|
: 0,
|
|
26
26
|
},
|
|
27
27
|
min: get(xAxis, 'min'),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '
|
|
3
|
-
import {
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from '../../constants';
|
|
3
|
+
import { getHorisontalSvgTextHeight } from '../../utils';
|
|
4
4
|
export const getPreparedYAxis = ({ yAxis }) => {
|
|
5
5
|
// FIXME: add support for n axises
|
|
6
6
|
const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
|
|
@@ -26,7 +26,7 @@ export const getPreparedYAxis = ({ yAxis }) => {
|
|
|
26
26
|
text: y1TitleText,
|
|
27
27
|
style: y1TitleStyle,
|
|
28
28
|
height: y1TitleText
|
|
29
|
-
?
|
|
29
|
+
? getHorisontalSvgTextHeight({ text: y1TitleText, style: y1TitleStyle })
|
|
30
30
|
: 0,
|
|
31
31
|
},
|
|
32
32
|
min: get(yAxis1, 'min'),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_LEGEND_SYMBOL_SIZE = 10;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const DEFAULT_LEGEND_SYMBOL_SIZE = 10;
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
|
+
import { PreparedLegend } from '../useChartOptions/types';
|
|
3
|
+
import { PreparedSeries } from './types';
|
|
4
|
+
export type OnLegendItemClick = (data: {
|
|
4
5
|
name: string;
|
|
5
|
-
|
|
6
|
-
};
|
|
6
|
+
metaKey: boolean;
|
|
7
|
+
}) => void;
|
|
7
8
|
type Args = {
|
|
8
|
-
|
|
9
|
-
series:
|
|
9
|
+
legend: PreparedLegend;
|
|
10
|
+
series: ChartKitWidgetData['series'];
|
|
10
11
|
};
|
|
11
12
|
export declare const useSeries: (args: Args) => {
|
|
12
|
-
|
|
13
|
+
preparedSeries: PreparedSeries[];
|
|
14
|
+
handleLegendItemClick: OnLegendItemClick;
|
|
13
15
|
};
|
|
14
16
|
export {};
|