@gravity-ui/charts 0.7.0 → 0.8.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/README.md +1 -1
- package/dist/cjs/components/Axis/AxisY.d.ts +1 -0
- package/dist/cjs/components/Axis/AxisY.js +55 -13
- package/dist/cjs/components/ChartInner/index.js +3 -2
- package/dist/cjs/components/ChartInner/useChartInnerHandlers.js +4 -0
- package/dist/cjs/components/Legend/index.js +1 -2
- package/dist/cjs/components/PlotTitle/index.js +1 -1
- package/dist/cjs/components/PlotTitle/styles.css +1 -1
- package/dist/cjs/components/Tooltip/DefaultContent.js +19 -3
- package/dist/cjs/constants/index.d.ts +1 -0
- package/dist/cjs/constants/index.js +1 -0
- package/dist/cjs/hooks/useChartOptions/types.d.ts +11 -1
- package/dist/cjs/hooks/useChartOptions/x-axis.js +1 -0
- package/dist/cjs/hooks/useChartOptions/y-axis.js +9 -1
- package/dist/cjs/hooks/useSeries/prepare-bar-x.d.ts +2 -1
- package/dist/cjs/hooks/useSeries/prepare-bar-x.js +2 -1
- package/dist/cjs/hooks/useSeries/prepare-bar-y.d.ts +2 -1
- package/dist/cjs/hooks/useSeries/prepare-bar-y.js +3 -1
- package/dist/cjs/hooks/useSeries/prepare-pie.js +2 -2
- package/dist/cjs/hooks/useSeries/prepare-sankey.d.ts +11 -0
- package/dist/cjs/hooks/useSeries/prepare-sankey.js +38 -0
- package/dist/cjs/hooks/useSeries/prepareSeries.js +21 -2
- package/dist/cjs/hooks/useSeries/types.d.ts +12 -2
- package/dist/cjs/hooks/useSeries/utils.js +1 -1
- package/dist/cjs/hooks/useShapes/bar-x/index.js +16 -2
- package/dist/cjs/hooks/useShapes/bar-x/prepare-data.js +2 -1
- package/dist/cjs/hooks/useShapes/bar-x/types.d.ts +1 -0
- package/dist/cjs/hooks/useShapes/bar-y/index.js +16 -2
- package/dist/cjs/hooks/useShapes/bar-y/prepare-data.js +2 -1
- package/dist/cjs/hooks/useShapes/bar-y/types.d.ts +1 -0
- package/dist/cjs/hooks/useShapes/index.d.ts +2 -1
- package/dist/cjs/hooks/useShapes/index.js +19 -0
- package/dist/cjs/hooks/useShapes/line/index.js +2 -2
- package/dist/cjs/hooks/useShapes/pie/index.js +3 -3
- package/dist/cjs/hooks/useShapes/pie/prepare-data.js +37 -35
- package/dist/cjs/hooks/useShapes/pie/types.d.ts +1 -1
- package/dist/cjs/hooks/useShapes/sankey/index.d.ts +12 -0
- package/dist/cjs/hooks/useShapes/sankey/index.js +67 -0
- package/dist/cjs/hooks/useShapes/sankey/prepare-data.d.ts +7 -0
- package/dist/cjs/hooks/useShapes/sankey/prepare-data.js +72 -0
- package/dist/cjs/hooks/useShapes/sankey/types.d.ts +33 -0
- package/dist/cjs/hooks/useShapes/sankey/types.js +1 -0
- package/dist/cjs/hooks/useShapes/styles.css +2 -2
- package/dist/cjs/hooks/useShapes/utils.d.ts +7 -2
- package/dist/cjs/hooks/useShapes/utils.js +22 -17
- package/dist/cjs/hooks/useShapes/waterfall/index.js +1 -2
- package/dist/cjs/types/chart/axis.d.ts +24 -0
- package/dist/cjs/types/chart/bar-x.d.ts +5 -0
- package/dist/cjs/types/chart/bar-y.d.ts +5 -0
- package/dist/cjs/types/chart/pie.d.ts +2 -0
- package/dist/cjs/types/chart/sankey.d.ts +22 -0
- package/dist/cjs/types/chart/sankey.js +1 -0
- package/dist/cjs/types/chart/series.d.ts +13 -2
- package/dist/cjs/types/chart/tooltip.d.ts +7 -1
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/cjs/types/index.js +1 -0
- package/dist/cjs/utils/chart/get-closest-data.d.ts +2 -0
- package/dist/cjs/utils/chart/get-closest-data.js +39 -3
- package/dist/cjs/utils/chart/index.js +1 -1
- package/dist/cjs/utils/chart/series/index.d.ts +1 -0
- package/dist/cjs/utils/chart/series/index.js +1 -0
- package/dist/cjs/utils/chart/series/line.d.ts +2 -0
- package/dist/cjs/utils/chart/series/line.js +17 -0
- package/dist/esm/components/Axis/AxisY.d.ts +1 -0
- package/dist/esm/components/Axis/AxisY.js +55 -13
- package/dist/esm/components/ChartInner/index.js +3 -2
- package/dist/esm/components/ChartInner/useChartInnerHandlers.js +4 -0
- package/dist/esm/components/Legend/index.js +1 -2
- package/dist/esm/components/PlotTitle/index.js +1 -1
- package/dist/esm/components/PlotTitle/styles.css +1 -1
- package/dist/esm/components/Tooltip/DefaultContent.js +19 -3
- package/dist/esm/constants/index.d.ts +1 -0
- package/dist/esm/constants/index.js +1 -0
- package/dist/esm/hooks/useChartOptions/types.d.ts +11 -1
- package/dist/esm/hooks/useChartOptions/x-axis.js +1 -0
- package/dist/esm/hooks/useChartOptions/y-axis.js +9 -1
- package/dist/esm/hooks/useSeries/prepare-bar-x.d.ts +2 -1
- package/dist/esm/hooks/useSeries/prepare-bar-x.js +2 -1
- package/dist/esm/hooks/useSeries/prepare-bar-y.d.ts +2 -1
- package/dist/esm/hooks/useSeries/prepare-bar-y.js +3 -1
- package/dist/esm/hooks/useSeries/prepare-pie.js +2 -2
- package/dist/esm/hooks/useSeries/prepare-sankey.d.ts +11 -0
- package/dist/esm/hooks/useSeries/prepare-sankey.js +38 -0
- package/dist/esm/hooks/useSeries/prepareSeries.js +21 -2
- package/dist/esm/hooks/useSeries/types.d.ts +12 -2
- package/dist/esm/hooks/useSeries/utils.js +1 -1
- package/dist/esm/hooks/useShapes/bar-x/index.js +16 -2
- package/dist/esm/hooks/useShapes/bar-x/prepare-data.js +2 -1
- package/dist/esm/hooks/useShapes/bar-x/types.d.ts +1 -0
- package/dist/esm/hooks/useShapes/bar-y/index.js +16 -2
- package/dist/esm/hooks/useShapes/bar-y/prepare-data.js +2 -1
- package/dist/esm/hooks/useShapes/bar-y/types.d.ts +1 -0
- package/dist/esm/hooks/useShapes/index.d.ts +2 -1
- package/dist/esm/hooks/useShapes/index.js +19 -0
- package/dist/esm/hooks/useShapes/line/index.js +2 -2
- package/dist/esm/hooks/useShapes/pie/index.js +3 -3
- package/dist/esm/hooks/useShapes/pie/prepare-data.js +37 -35
- package/dist/esm/hooks/useShapes/pie/types.d.ts +1 -1
- package/dist/esm/hooks/useShapes/sankey/index.d.ts +12 -0
- package/dist/esm/hooks/useShapes/sankey/index.js +67 -0
- package/dist/esm/hooks/useShapes/sankey/prepare-data.d.ts +7 -0
- package/dist/esm/hooks/useShapes/sankey/prepare-data.js +72 -0
- package/dist/esm/hooks/useShapes/sankey/types.d.ts +33 -0
- package/dist/esm/hooks/useShapes/sankey/types.js +1 -0
- package/dist/esm/hooks/useShapes/styles.css +2 -2
- package/dist/esm/hooks/useShapes/utils.d.ts +7 -2
- package/dist/esm/hooks/useShapes/utils.js +22 -17
- package/dist/esm/hooks/useShapes/waterfall/index.js +1 -2
- package/dist/esm/types/chart/axis.d.ts +24 -0
- package/dist/esm/types/chart/bar-x.d.ts +5 -0
- package/dist/esm/types/chart/bar-y.d.ts +5 -0
- package/dist/esm/types/chart/pie.d.ts +2 -0
- package/dist/esm/types/chart/sankey.d.ts +22 -0
- package/dist/esm/types/chart/sankey.js +1 -0
- package/dist/esm/types/chart/series.d.ts +13 -2
- package/dist/esm/types/chart/tooltip.d.ts +7 -1
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/esm/types/index.js +1 -0
- package/dist/esm/utils/chart/get-closest-data.d.ts +2 -0
- package/dist/esm/utils/chart/get-closest-data.js +39 -3
- package/dist/esm/utils/chart/index.js +1 -1
- package/dist/esm/utils/chart/series/index.d.ts +1 -0
- package/dist/esm/utils/chart/series/index.js +1 -0
- package/dist/esm/utils/chart/series/line.d.ts +2 -0
- package/dist/esm/utils/chart/series/line.js +17 -0
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Gravity Charts · [](https://www.npmjs.com/package/@gravity-ui/charts) [](https://github.com/gravity-ui/charts/actions/workflows/ci.yml?query=branch:main) [](https://preview.gravity-ui.com/charts/)
|
|
2
2
|
|
|
3
3
|
> [!WARNING]
|
|
4
4
|
> The library may have major changes in minor releases while it is on version `0.*.*`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { axisLeft, axisRight, line, select } from 'd3';
|
|
3
|
-
import { block, calculateCos, calculateSin, formatAxisTickLabel, getAxisHeight, getAxisTitleRows, getClosestPointsRange, getScaleTicks, getTicksCount, handleOverflowingText, parseTransformStyle, setEllipsisForOverflowTexts, wrapText, } from '../../utils';
|
|
3
|
+
import { block, calculateCos, calculateSin, formatAxisTickLabel, getAxisHeight, getAxisTitleRows, getClosestPointsRange, getLineDashArray, getScaleTicks, getTicksCount, handleOverflowingText, parseTransformStyle, setEllipsisForOverflowTexts, wrapText, } from '../../utils';
|
|
4
4
|
import './styles.css';
|
|
5
5
|
const b = block('d3-axis');
|
|
6
6
|
function transformLabel(args) {
|
|
@@ -79,7 +79,7 @@ function getTitlePosition(args) {
|
|
|
79
79
|
return { x, y };
|
|
80
80
|
}
|
|
81
81
|
export const AxisY = (props) => {
|
|
82
|
-
const { axes, width, height: totalHeight, scale, split } = props;
|
|
82
|
+
const { axes, width, height: totalHeight, scale, split, plotRef } = props;
|
|
83
83
|
const height = getAxisHeight({ split, boundsHeight: totalHeight });
|
|
84
84
|
const ref = React.useRef(null);
|
|
85
85
|
React.useEffect(() => {
|
|
@@ -88,26 +88,34 @@ export const AxisY = (props) => {
|
|
|
88
88
|
}
|
|
89
89
|
const svgElement = select(ref.current);
|
|
90
90
|
svgElement.selectAll('*').remove();
|
|
91
|
+
const getAxisPosition = (axis) => {
|
|
92
|
+
var _a;
|
|
93
|
+
const top = ((_a = split.plots[axis.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
|
|
94
|
+
if (axis.position === 'left') {
|
|
95
|
+
return `translate(0, ${top}px)`;
|
|
96
|
+
}
|
|
97
|
+
return `translate(${width}px, 0)`;
|
|
98
|
+
};
|
|
99
|
+
const plotLines = axes.reduce((acc, axis) => {
|
|
100
|
+
if (axis.plotLines.length) {
|
|
101
|
+
acc.push(...axis.plotLines.map((plotLine) => {
|
|
102
|
+
return Object.assign(Object.assign({}, plotLine), { transform: getAxisPosition(axis) });
|
|
103
|
+
}));
|
|
104
|
+
}
|
|
105
|
+
return acc;
|
|
106
|
+
}, []);
|
|
91
107
|
const axisSelection = svgElement
|
|
92
108
|
.selectAll('axis')
|
|
93
109
|
.data(axes)
|
|
94
110
|
.join('g')
|
|
95
111
|
.attr('class', b())
|
|
96
|
-
.style('transform', (d) =>
|
|
97
|
-
var _a;
|
|
98
|
-
const top = ((_a = split.plots[d.plotIndex]) === null || _a === void 0 ? void 0 : _a.top) || 0;
|
|
99
|
-
if (d.position === 'left') {
|
|
100
|
-
return `translate(0, ${top}px)`;
|
|
101
|
-
}
|
|
102
|
-
return `translate(${width}px, 0)`;
|
|
103
|
-
});
|
|
112
|
+
.style('transform', (d) => getAxisPosition(d));
|
|
104
113
|
axisSelection.each((d, index, node) => {
|
|
105
114
|
const seriesScale = scale[index];
|
|
106
115
|
const axisItem = select(node[index]);
|
|
116
|
+
const axisScale = seriesScale;
|
|
107
117
|
const yAxisGenerator = getAxisGenerator({
|
|
108
|
-
axisGenerator: d.position === 'left'
|
|
109
|
-
? axisLeft(seriesScale)
|
|
110
|
-
: axisRight(seriesScale),
|
|
118
|
+
axisGenerator: d.position === 'left' ? axisLeft(axisScale) : axisRight(axisScale),
|
|
111
119
|
preparedAxis: d,
|
|
112
120
|
height,
|
|
113
121
|
width,
|
|
@@ -148,6 +156,40 @@ export const AxisY = (props) => {
|
|
|
148
156
|
})
|
|
149
157
|
.remove();
|
|
150
158
|
}
|
|
159
|
+
if (plotRef && d.plotLines.length > 0) {
|
|
160
|
+
const plotLineClassName = b('plotLine');
|
|
161
|
+
const plotLineContainer = select(plotRef.current);
|
|
162
|
+
plotLineContainer.selectAll(`.${plotLineClassName}`).remove();
|
|
163
|
+
const plotLinesSelection = plotLineContainer
|
|
164
|
+
.selectAll(`.${plotLineClassName}`)
|
|
165
|
+
.data(plotLines)
|
|
166
|
+
.join('g')
|
|
167
|
+
.attr('class', plotLineClassName)
|
|
168
|
+
.style('transform', (plotLine) => plotLine.transform);
|
|
169
|
+
plotLinesSelection
|
|
170
|
+
.append('path')
|
|
171
|
+
.attr('d', (plotLine) => {
|
|
172
|
+
const plotLineValue = Number(axisScale(plotLine.value));
|
|
173
|
+
const points = [
|
|
174
|
+
[0, plotLineValue],
|
|
175
|
+
[width, plotLineValue],
|
|
176
|
+
];
|
|
177
|
+
return line()(points);
|
|
178
|
+
})
|
|
179
|
+
.attr('stroke', (plotLine) => plotLine.color)
|
|
180
|
+
.attr('stroke-width', (plotLine) => plotLine.width)
|
|
181
|
+
.attr('stroke-dasharray', (plotLine) => getLineDashArray(plotLine.dashStyle, plotLine.width))
|
|
182
|
+
.attr('opacity', (plotLine) => plotLine.opacity);
|
|
183
|
+
plotLinesSelection.each((plotLineData, i, nodes) => {
|
|
184
|
+
const plotLineSelection = select(nodes[i]);
|
|
185
|
+
if (plotLineData.layerPlacement === 'before') {
|
|
186
|
+
plotLineSelection.lower();
|
|
187
|
+
}
|
|
188
|
+
else {
|
|
189
|
+
plotLineSelection.raise();
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
}
|
|
151
193
|
return axisItem;
|
|
152
194
|
});
|
|
153
195
|
axisSelection
|
|
@@ -15,6 +15,7 @@ export const ChartInner = (props) => {
|
|
|
15
15
|
const { width, height, data } = props;
|
|
16
16
|
const svgRef = React.useRef(null);
|
|
17
17
|
const htmlLayerRef = React.useRef(null);
|
|
18
|
+
const plotRef = React.useRef(null);
|
|
18
19
|
const dispatcher = React.useMemo(() => getD3Dispatcher(), []);
|
|
19
20
|
const { boundsHeight, boundsOffsetLeft, boundsOffsetTop, boundsWidth, handleLegendItemClick, legendConfig, legendItems, preparedSeries, preparedSplit, preparedLegend, prevHeight, prevWidth, shapes, shapesData, title, tooltip, xAxis, xScale, yAxis, yScale, } = useChartInnerProps(Object.assign(Object.assign({}, props), { dispatcher, htmlLayout: htmlLayerRef.current }));
|
|
20
21
|
const { tooltipPinned, togglePinTooltip, unpinTooltip } = useChartInnerState({
|
|
@@ -63,9 +64,9 @@ export const ChartInner = (props) => {
|
|
|
63
64
|
React.createElement("g", { transform: `translate(0, ${boundsOffsetTop})` }, preparedSplit.plots.map((plot, index) => {
|
|
64
65
|
return React.createElement(PlotTitle, { key: `plot-${index}`, title: plot.title });
|
|
65
66
|
})),
|
|
66
|
-
React.createElement("g", { width: boundsWidth, height: boundsHeight, transform: `translate(${[boundsOffsetLeft, boundsOffsetTop].join(',')})
|
|
67
|
+
React.createElement("g", { width: boundsWidth, height: boundsHeight, transform: `translate(${[boundsOffsetLeft, boundsOffsetTop].join(',')})`, ref: plotRef },
|
|
67
68
|
xScale && (yScale === null || yScale === void 0 ? void 0 : yScale.length) && (React.createElement(React.Fragment, null,
|
|
68
|
-
React.createElement(AxisY, { axes: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale, split: preparedSplit }),
|
|
69
|
+
React.createElement(AxisY, { axes: yAxis, width: boundsWidth, height: boundsHeight, scale: yScale, split: preparedSplit, plotRef: plotRef }),
|
|
69
70
|
React.createElement("g", { transform: `translate(0, ${boundsHeight})` },
|
|
70
71
|
React.createElement(AxisX, { axis: xAxis, width: boundsWidth, height: boundsHeight, scale: xScale, split: preparedSplit })))),
|
|
71
72
|
shapes),
|
|
@@ -24,6 +24,8 @@ export function useChartInnerHandlers(props) {
|
|
|
24
24
|
const closest = getClosestPoints({
|
|
25
25
|
position: [x, y],
|
|
26
26
|
shapesData,
|
|
27
|
+
boundsHeight,
|
|
28
|
+
boundsWidth,
|
|
27
29
|
});
|
|
28
30
|
dispatcher.call(EventType.HOVER_SHAPE, event.target, closest, [pointerX, pointerY]);
|
|
29
31
|
dispatcher.call(EventType.POINTERMOVE_CHART, {}, {
|
|
@@ -65,6 +67,8 @@ export function useChartInnerHandlers(props) {
|
|
|
65
67
|
const items = getClosestPoints({
|
|
66
68
|
position: [x, y],
|
|
67
69
|
shapesData,
|
|
70
|
+
boundsHeight,
|
|
71
|
+
boundsWidth,
|
|
68
72
|
});
|
|
69
73
|
const selected = items === null || items === void 0 ? void 0 : items.find((item) => item.closest);
|
|
70
74
|
if (!selected) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { line as lineGenerator, scaleLinear, select, symbol } from 'd3';
|
|
3
3
|
import { CONTINUOUS_LEGEND_SIZE } from '../../constants';
|
|
4
|
-
import { getLineDashArray } from '../../hooks/useShapes/utils';
|
|
5
4
|
import { formatNumber } from '../../libs';
|
|
6
|
-
import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getSymbol, } from '../../utils';
|
|
5
|
+
import { block, createGradientRect, getContinuesColorFn, getLabelsSize, getLineDashArray, getSymbol, } from '../../utils';
|
|
7
6
|
import { axisBottom } from '../../utils/chart/axis-generators';
|
|
8
7
|
import './styles.css';
|
|
9
8
|
const b = block('d3-legend');
|
|
@@ -3,7 +3,7 @@ import { dateTime } from '@gravity-ui/date-utils';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { formatNumber } from '../../libs';
|
|
5
5
|
import { block, getDataCategoryValue, getWaterfallPointSubtotal } from '../../utils';
|
|
6
|
-
const b = block('
|
|
6
|
+
const b = block('tooltip');
|
|
7
7
|
const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
|
|
8
8
|
const getRowData = (fieldName, data, axis) => {
|
|
9
9
|
switch (axis === null || axis === void 0 ? void 0 : axis.type) {
|
|
@@ -29,7 +29,7 @@ const getXRowData = (data, xAxis) => getRowData('x', data, xAxis);
|
|
|
29
29
|
const getYRowData = (data, yAxis) => getRowData('y', data, yAxis);
|
|
30
30
|
const getMeasureValue = (data, xAxis, yAxis) => {
|
|
31
31
|
var _a, _b;
|
|
32
|
-
if (data.every((item) => ['pie', 'treemap', 'waterfall'].includes(item.series.type))) {
|
|
32
|
+
if (data.every((item) => ['pie', 'treemap', 'waterfall', 'sankey'].includes(item.series.type))) {
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
if (data.some((item) => item.series.type === 'bar-y')) {
|
|
@@ -41,7 +41,9 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
|
41
41
|
const measureValue = getMeasureValue(hovered, xAxis, yAxis);
|
|
42
42
|
return (React.createElement(React.Fragment, null,
|
|
43
43
|
measureValue && React.createElement("div", null, measureValue),
|
|
44
|
-
hovered.map((
|
|
44
|
+
hovered.map((seriesItem, i) => {
|
|
45
|
+
var _a;
|
|
46
|
+
const { data, series, closest } = seriesItem;
|
|
45
47
|
const id = `${get(series, 'id')}_${i}`;
|
|
46
48
|
const color = get(series, 'color');
|
|
47
49
|
switch (series.type) {
|
|
@@ -93,6 +95,20 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
|
93
95
|
"\u00A0"),
|
|
94
96
|
React.createElement("span", null, seriesData.value)));
|
|
95
97
|
}
|
|
98
|
+
case 'sankey': {
|
|
99
|
+
const { target, data: source } = seriesItem;
|
|
100
|
+
const value = (_a = source.links.find((d) => d.name === (target === null || target === void 0 ? void 0 : target.name))) === null || _a === void 0 ? void 0 : _a.value;
|
|
101
|
+
return (React.createElement("div", { key: id, className: b('content-row') },
|
|
102
|
+
React.createElement("div", { className: b('color'), style: { backgroundColor: source.color } }),
|
|
103
|
+
React.createElement("div", { style: { display: 'flex', gap: 8, verticalAlign: 'center' } },
|
|
104
|
+
source.name,
|
|
105
|
+
" ",
|
|
106
|
+
React.createElement("span", null, "\u2192"),
|
|
107
|
+
" ", target === null || target === void 0 ? void 0 :
|
|
108
|
+
target.name,
|
|
109
|
+
": ",
|
|
110
|
+
value)));
|
|
111
|
+
}
|
|
96
112
|
default: {
|
|
97
113
|
return null;
|
|
98
114
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { DashStyle } from 'src/constants';
|
|
2
|
+
import type { AxisPlotLine, BaseTextStyle, ChartAxis, ChartAxisLabels, ChartAxisTitleAlignment, ChartAxisType, ChartData, ChartMargin } from '../../types';
|
|
2
3
|
type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style' | 'autoRotation'> & Required<Pick<ChartAxisLabels, 'enabled' | 'padding' | 'margin' | 'rotation'>> & {
|
|
3
4
|
style: BaseTextStyle;
|
|
4
5
|
rotation: number;
|
|
@@ -10,6 +11,14 @@ type PreparedAxisLabels = Omit<ChartAxisLabels, 'enabled' | 'padding' | 'style'
|
|
|
10
11
|
export type PreparedChart = {
|
|
11
12
|
margin: ChartMargin;
|
|
12
13
|
};
|
|
14
|
+
export type PreparedAxisPlotLine = {
|
|
15
|
+
value: number;
|
|
16
|
+
color: string;
|
|
17
|
+
width: number;
|
|
18
|
+
dashStyle: DashStyle;
|
|
19
|
+
opacity: number;
|
|
20
|
+
layerPlacement: AxisPlotLine['layerPlacement'];
|
|
21
|
+
};
|
|
13
22
|
export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels'> & {
|
|
14
23
|
type: ChartAxisType;
|
|
15
24
|
labels: PreparedAxisLabels;
|
|
@@ -32,6 +41,7 @@ export type PreparedAxis = Omit<ChartAxis, 'type' | 'labels'> & {
|
|
|
32
41
|
};
|
|
33
42
|
position: 'left' | 'right' | 'top' | 'bottom';
|
|
34
43
|
plotIndex: number;
|
|
44
|
+
plotLines: PreparedAxisPlotLine[];
|
|
35
45
|
};
|
|
36
46
|
export type PreparedTitle = ChartData['title'] & {
|
|
37
47
|
height: number;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
|
-
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_TYPE, DashStyle, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
|
|
3
3
|
import { CHART_SERIES_WITH_VOLUME_ON_Y_AXIS, formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, getWaterfallPointSubtotal, wrapText, } from '../../utils';
|
|
4
4
|
import { createYScale } from '../useAxisScales';
|
|
5
5
|
const getAxisLabelMaxWidth = (args) => {
|
|
@@ -108,6 +108,14 @@ export const getPreparedYAxis = ({ series, yAxis, height, }) => {
|
|
|
108
108
|
},
|
|
109
109
|
position: get(axisItem, 'position', defaultAxisPosition),
|
|
110
110
|
plotIndex: get(axisItem, 'plotIndex', 0),
|
|
111
|
+
plotLines: get(axisItem, 'plotLines', []).map((d) => ({
|
|
112
|
+
value: get(d, 'value', 0),
|
|
113
|
+
color: get(d, 'color', 'var(--g-color-base-brand)'),
|
|
114
|
+
width: get(d, 'width', 1),
|
|
115
|
+
dashStyle: get(d, 'dashStyle', DashStyle.Solid),
|
|
116
|
+
opacity: get(d, 'opacity', 1),
|
|
117
|
+
layerPlacement: get(d, 'layerPlacement', 'before'),
|
|
118
|
+
})),
|
|
111
119
|
};
|
|
112
120
|
if (labelsEnabled) {
|
|
113
121
|
preparedAxis.labels.width = getAxisLabelMaxWidth({ axis: preparedAxis, series });
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ScaleOrdinal } from 'd3';
|
|
2
|
-
import type { BarXSeries } from '../../types';
|
|
2
|
+
import type { BarXSeries, ChartSeriesOptions } from '../../types';
|
|
3
3
|
import type { PreparedLegend, PreparedSeries } from './types';
|
|
4
4
|
type PrepareBarXSeriesArgs = {
|
|
5
5
|
colorScale: ScaleOrdinal<string, string>;
|
|
6
6
|
series: BarXSeries[];
|
|
7
7
|
legend: PreparedLegend;
|
|
8
|
+
seriesOptions?: ChartSeriesOptions;
|
|
8
9
|
};
|
|
9
10
|
export declare function prepareBarXSeries(args: PrepareBarXSeriesArgs): PreparedSeries[];
|
|
10
11
|
export {};
|
|
@@ -3,7 +3,7 @@ import { getUniqId } from '../../utils';
|
|
|
3
3
|
import { DEFAULT_DATALABELS_PADDING, DEFAULT_DATALABELS_STYLE } from './constants';
|
|
4
4
|
import { getSeriesStackId, prepareLegendSymbol } from './utils';
|
|
5
5
|
export function prepareBarXSeries(args) {
|
|
6
|
-
const { colorScale, series: seriesList, legend } = args;
|
|
6
|
+
const { colorScale, series: seriesList, seriesOptions, legend } = args;
|
|
7
7
|
return seriesList.map((series) => {
|
|
8
8
|
var _a, _b, _c, _d, _e;
|
|
9
9
|
const name = series.name || '';
|
|
@@ -33,6 +33,7 @@ export function prepareBarXSeries(args) {
|
|
|
33
33
|
},
|
|
34
34
|
cursor: get(series, 'cursor', null),
|
|
35
35
|
yAxis: get(series, 'yAxis', 0),
|
|
36
|
+
borderRadius: get(series, 'borderRadius', get(seriesOptions, 'bar-x.borderRadius', 0)),
|
|
36
37
|
};
|
|
37
38
|
}, []);
|
|
38
39
|
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import type { ScaleOrdinal } from 'd3';
|
|
2
|
-
import type { BarYSeries } from '../../types';
|
|
2
|
+
import type { BarYSeries, ChartSeriesOptions } from '../../types';
|
|
3
3
|
import type { PreparedLegend, PreparedSeries } from './types';
|
|
4
4
|
type PrepareBarYSeriesArgs = {
|
|
5
5
|
colorScale: ScaleOrdinal<string, string>;
|
|
6
6
|
series: BarYSeries[];
|
|
7
7
|
legend: PreparedLegend;
|
|
8
|
+
seriesOptions?: ChartSeriesOptions;
|
|
8
9
|
};
|
|
9
10
|
export declare function prepareBarYSeries(args: PrepareBarYSeriesArgs): PreparedSeries[];
|
|
10
11
|
export {};
|
|
@@ -24,8 +24,9 @@ function prepareDataLabels(series) {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
export function prepareBarYSeries(args) {
|
|
27
|
-
const { colorScale, series: seriesList, legend } = args;
|
|
27
|
+
const { colorScale, series: seriesList, seriesOptions, legend } = args;
|
|
28
28
|
return seriesList.map((series) => {
|
|
29
|
+
var _a, _b, _c;
|
|
29
30
|
const name = series.name || '';
|
|
30
31
|
const color = series.color || colorScale(name);
|
|
31
32
|
return {
|
|
@@ -43,6 +44,7 @@ export function prepareBarYSeries(args) {
|
|
|
43
44
|
stackId: getSeriesStackId(series),
|
|
44
45
|
dataLabels: prepareDataLabels(series),
|
|
45
46
|
cursor: get(series, 'cursor', null),
|
|
47
|
+
borderRadius: (_c = (_a = series.borderRadius) !== null && _a !== void 0 ? _a : (_b = seriesOptions === null || seriesOptions === void 0 ? void 0 : seriesOptions['bar-y']) === null || _b === void 0 ? void 0 : _b.borderRadius) !== null && _c !== void 0 ? _c : 0,
|
|
46
48
|
};
|
|
47
49
|
}, []);
|
|
48
50
|
}
|
|
@@ -11,7 +11,7 @@ export function preparePieSeries(args) {
|
|
|
11
11
|
const stackId = getUniqId();
|
|
12
12
|
const seriesHoverState = get(seriesOptions, 'pie.states.hover');
|
|
13
13
|
const preparedSeries = series.data.map((dataItem, i) => {
|
|
14
|
-
var _a, _b, _c;
|
|
14
|
+
var _a, _b, _c, _d, _e;
|
|
15
15
|
const result = {
|
|
16
16
|
type: 'pie',
|
|
17
17
|
data: dataItem,
|
|
@@ -40,7 +40,7 @@ export function preparePieSeries(args) {
|
|
|
40
40
|
borderColor: series.borderColor || '',
|
|
41
41
|
borderRadius: (_b = series.borderRadius) !== null && _b !== void 0 ? _b : 0,
|
|
42
42
|
borderWidth: (_c = series.borderWidth) !== null && _c !== void 0 ? _c : 1,
|
|
43
|
-
radius: series.radius
|
|
43
|
+
radius: (_e = (_d = dataItem.radius) !== null && _d !== void 0 ? _d : series.radius) !== null && _e !== void 0 ? _e : '100%',
|
|
44
44
|
innerRadius: series.innerRadius || 0,
|
|
45
45
|
stackId,
|
|
46
46
|
states: {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ScaleOrdinal } from 'd3';
|
|
2
|
+
import type { ChartSeriesOptions, SankeySeries } from '../../types';
|
|
3
|
+
import type { PreparedLegend, PreparedSankeySeries } from './types';
|
|
4
|
+
type PrepareSankeySeriesArgs = {
|
|
5
|
+
colorScale: ScaleOrdinal<string, string>;
|
|
6
|
+
legend: PreparedLegend;
|
|
7
|
+
series: SankeySeries[];
|
|
8
|
+
seriesOptions?: ChartSeriesOptions;
|
|
9
|
+
};
|
|
10
|
+
export declare function prepareSankeySeries(args: PrepareSankeySeriesArgs): PreparedSankeySeries[];
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { getUniqId } from '../../utils';
|
|
3
|
+
import { DEFAULT_DATALABELS_STYLE } from './constants';
|
|
4
|
+
import { prepareLegendSymbol } from './utils';
|
|
5
|
+
export function prepareSankeySeries(args) {
|
|
6
|
+
const { colorScale, legend, series } = args;
|
|
7
|
+
return series.map((s) => {
|
|
8
|
+
var _a;
|
|
9
|
+
const id = getUniqId();
|
|
10
|
+
const name = s.name || '';
|
|
11
|
+
const color = colorScale(name);
|
|
12
|
+
const preparedSeries = {
|
|
13
|
+
color,
|
|
14
|
+
data: s.data.map((d) => {
|
|
15
|
+
var _a;
|
|
16
|
+
return ({
|
|
17
|
+
name: d.name,
|
|
18
|
+
color: (_a = d.color) !== null && _a !== void 0 ? _a : colorScale(d.name),
|
|
19
|
+
links: d.links,
|
|
20
|
+
});
|
|
21
|
+
}),
|
|
22
|
+
dataLabels: {
|
|
23
|
+
enabled: get(s, 'dataLabels.enabled', true),
|
|
24
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_a = s.dataLabels) === null || _a === void 0 ? void 0 : _a.style),
|
|
25
|
+
},
|
|
26
|
+
id,
|
|
27
|
+
type: s.type,
|
|
28
|
+
name,
|
|
29
|
+
visible: get(s, 'visible', true),
|
|
30
|
+
legend: {
|
|
31
|
+
enabled: get(s, 'legend.enabled', legend.enabled),
|
|
32
|
+
symbol: prepareLegendSymbol(s),
|
|
33
|
+
},
|
|
34
|
+
cursor: get(s, 'cursor', null),
|
|
35
|
+
};
|
|
36
|
+
return preparedSeries;
|
|
37
|
+
});
|
|
38
|
+
}
|
|
@@ -4,6 +4,7 @@ import { prepareBarXSeries } from './prepare-bar-x';
|
|
|
4
4
|
import { prepareBarYSeries } from './prepare-bar-y';
|
|
5
5
|
import { prepareLineSeries } from './prepare-line';
|
|
6
6
|
import { preparePieSeries } from './prepare-pie';
|
|
7
|
+
import { prepareSankeySeries } from './prepare-sankey';
|
|
7
8
|
import { prepareScatterSeries } from './prepare-scatter';
|
|
8
9
|
import { prepareTreemap } from './prepare-treemap';
|
|
9
10
|
import { prepareWaterfallSeries } from './prepare-waterfall';
|
|
@@ -17,10 +18,20 @@ export function prepareSeries(args) {
|
|
|
17
18
|
}, []);
|
|
18
19
|
}
|
|
19
20
|
case 'bar-x': {
|
|
20
|
-
return prepareBarXSeries({
|
|
21
|
+
return prepareBarXSeries({
|
|
22
|
+
series: series,
|
|
23
|
+
legend,
|
|
24
|
+
colorScale,
|
|
25
|
+
seriesOptions,
|
|
26
|
+
});
|
|
21
27
|
}
|
|
22
28
|
case 'bar-y': {
|
|
23
|
-
return prepareBarYSeries({
|
|
29
|
+
return prepareBarYSeries({
|
|
30
|
+
series: series,
|
|
31
|
+
legend,
|
|
32
|
+
colorScale,
|
|
33
|
+
seriesOptions,
|
|
34
|
+
});
|
|
24
35
|
}
|
|
25
36
|
case 'scatter': {
|
|
26
37
|
return prepareScatterSeries({ series: series, legend, colorScale });
|
|
@@ -56,6 +67,14 @@ export function prepareSeries(args) {
|
|
|
56
67
|
colorScale,
|
|
57
68
|
});
|
|
58
69
|
}
|
|
70
|
+
case 'sankey': {
|
|
71
|
+
return prepareSankeySeries({
|
|
72
|
+
series: series,
|
|
73
|
+
seriesOptions,
|
|
74
|
+
colorScale,
|
|
75
|
+
legend,
|
|
76
|
+
});
|
|
77
|
+
}
|
|
59
78
|
default: {
|
|
60
79
|
throw new ChartError({
|
|
61
80
|
message: `Series type "${type}" does not support data preparation for series that do not support the presence of axes`,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { DashStyle, LayoutAlgorithm, LineCap, SeriesOptionsDefaults, SymbolType } from '../../constants';
|
|
2
|
-
import type { AreaSeries, AreaSeriesData, BarXSeries, BarXSeriesData, BarYSeries, BarYSeriesData, BaseTextStyle, ChartLegend, ConnectorCurve, ConnectorShape, LineSeries, LineSeriesData, PathLegendSymbolOptions, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData, SymbolLegendSymbolOptions, TreemapSeries, TreemapSeriesData, WaterfallSeries, WaterfallSeriesData } from '../../types';
|
|
2
|
+
import type { AreaSeries, AreaSeriesData, BarXSeries, BarXSeriesData, BarYSeries, BarYSeriesData, BaseTextStyle, ChartLegend, ConnectorCurve, ConnectorShape, LineSeries, LineSeriesData, PathLegendSymbolOptions, PieSeries, PieSeriesData, RectLegendSymbolOptions, SankeySeries, SankeySeriesData, ScatterSeries, ScatterSeriesData, SymbolLegendSymbolOptions, TreemapSeries, TreemapSeriesData, WaterfallSeries, WaterfallSeriesData } from '../../types';
|
|
3
3
|
export type RectLegendSymbol = {
|
|
4
4
|
shape: 'rect';
|
|
5
5
|
} & Required<RectLegendSymbolOptions>;
|
|
@@ -107,6 +107,7 @@ export type PreparedBarXSeries = {
|
|
|
107
107
|
padding: number;
|
|
108
108
|
html: boolean;
|
|
109
109
|
};
|
|
110
|
+
borderRadius: number;
|
|
110
111
|
yAxis: number;
|
|
111
112
|
} & BasePreparedSeries;
|
|
112
113
|
export type PreparedBarYSeries = {
|
|
@@ -122,6 +123,7 @@ export type PreparedBarYSeries = {
|
|
|
122
123
|
maxWidth: number;
|
|
123
124
|
html: boolean;
|
|
124
125
|
};
|
|
126
|
+
borderRadius: number;
|
|
125
127
|
} & BasePreparedSeries;
|
|
126
128
|
export type PreparedPieSeries = {
|
|
127
129
|
type: PieSeries['type'];
|
|
@@ -248,7 +250,15 @@ export type PreparedWaterfallSeries = {
|
|
|
248
250
|
positiveColor: string;
|
|
249
251
|
negativeColor: string;
|
|
250
252
|
} & BasePreparedSeries;
|
|
251
|
-
export type
|
|
253
|
+
export type PreparedSankeySeries = {
|
|
254
|
+
type: SankeySeries['type'];
|
|
255
|
+
data: SankeySeriesData[];
|
|
256
|
+
dataLabels: {
|
|
257
|
+
enabled: boolean;
|
|
258
|
+
style: BaseTextStyle;
|
|
259
|
+
};
|
|
260
|
+
} & BasePreparedSeries & Omit<SankeySeries, keyof BasePreparedSeries>;
|
|
261
|
+
export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedBarYSeries | PreparedPieSeries | PreparedLineSeries | PreparedAreaSeries | PreparedTreemapSeries | PreparedWaterfallSeries | PreparedSankeySeries;
|
|
252
262
|
export type PreparedSeriesOptions = SeriesOptionsDefaults;
|
|
253
263
|
export type StackedSeries = BarXSeries | AreaSeries | BarYSeries;
|
|
254
264
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import memoize from 'lodash/memoize';
|
|
2
2
|
import { SymbolType } from '../../constants';
|
|
3
|
-
import { getUniqId } from '../../utils';
|
|
3
|
+
import { getUniqId } from '../../utils/misc';
|
|
4
4
|
import { DEFAULT_LEGEND_SYMBOL_PADDING, DEFAULT_LEGEND_SYMBOL_SIZE } from './constants';
|
|
5
5
|
export const getActiveLegendItems = (series) => {
|
|
6
6
|
return series.reduce((acc, s) => {
|
|
@@ -3,9 +3,10 @@ import { color, select } from 'd3';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block, filterOverlappingLabels } from '../../../utils';
|
|
5
5
|
import { HtmlLayer } from '../HtmlLayer';
|
|
6
|
+
import { getRectPath } from '../utils';
|
|
6
7
|
export { prepareBarXData } from './prepare-data';
|
|
7
8
|
export * from './types';
|
|
8
|
-
const b = block('
|
|
9
|
+
const b = block('bar-x');
|
|
9
10
|
export const BarXSeriesShapes = (args) => {
|
|
10
11
|
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
11
12
|
const hoveredDataRef = React.useRef(null);
|
|
@@ -22,7 +23,20 @@ export const BarXSeriesShapes = (args) => {
|
|
|
22
23
|
const rectSelection = svgElement
|
|
23
24
|
.selectAll('allRects')
|
|
24
25
|
.data(preparedData)
|
|
25
|
-
.join('
|
|
26
|
+
.join('path')
|
|
27
|
+
.attr('d', (d) => {
|
|
28
|
+
const borderRadius = d.isLastStackItem
|
|
29
|
+
? Math.min(d.height, d.width / 2, d.series.borderRadius)
|
|
30
|
+
: 0;
|
|
31
|
+
const p = getRectPath({
|
|
32
|
+
x: d.x,
|
|
33
|
+
y: d.y,
|
|
34
|
+
width: d.width,
|
|
35
|
+
height: d.height,
|
|
36
|
+
borderRadius: [borderRadius, borderRadius, 0, 0],
|
|
37
|
+
});
|
|
38
|
+
return p.toString();
|
|
39
|
+
})
|
|
26
40
|
.attr('class', b('segment'))
|
|
27
41
|
.attr('x', (d) => d.x)
|
|
28
42
|
.attr('y', (d) => d.y)
|
|
@@ -103,7 +103,7 @@ export const prepareBarXData = (args) => {
|
|
|
103
103
|
const sortedData = sortKey
|
|
104
104
|
? sort(yValues, (a, b) => comparator(get(a, sortKey), get(b, sortKey)))
|
|
105
105
|
: yValues;
|
|
106
|
-
sortedData.forEach((yValue) => {
|
|
106
|
+
sortedData.forEach((yValue, yValueIndex) => {
|
|
107
107
|
const yAxisIndex = yValue.series.yAxis;
|
|
108
108
|
const seriesYScale = yScale[yAxisIndex];
|
|
109
109
|
let xCenter;
|
|
@@ -129,6 +129,7 @@ export const prepareBarXData = (args) => {
|
|
|
129
129
|
data: yValue.data,
|
|
130
130
|
series: yValue.series,
|
|
131
131
|
htmlElements: [],
|
|
132
|
+
isLastStackItem: yValueIndex === sortedData.length - 1,
|
|
132
133
|
};
|
|
133
134
|
const label = getLabelData(barData);
|
|
134
135
|
if (yValue.series.dataLabels.html && label) {
|
|
@@ -3,8 +3,9 @@ import { color, select } from 'd3';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../utils';
|
|
5
5
|
import { HtmlLayer } from '../HtmlLayer';
|
|
6
|
+
import { getRectPath } from '../utils';
|
|
6
7
|
export { prepareBarYData } from './prepare-data';
|
|
7
|
-
const b = block('
|
|
8
|
+
const b = block('bar-y');
|
|
8
9
|
export const BarYSeriesShapes = (args) => {
|
|
9
10
|
const { dispatcher, preparedData, seriesOptions, htmlLayout } = args;
|
|
10
11
|
const hoveredDataRef = React.useRef(null);
|
|
@@ -18,7 +19,20 @@ export const BarYSeriesShapes = (args) => {
|
|
|
18
19
|
const rectSelection = svgElement
|
|
19
20
|
.selectAll('rect')
|
|
20
21
|
.data(preparedData)
|
|
21
|
-
.join('
|
|
22
|
+
.join('path')
|
|
23
|
+
.attr('d', (d) => {
|
|
24
|
+
const borderRadius = d.isLastStackItem
|
|
25
|
+
? Math.min(d.height, d.width / 2, d.series.borderRadius)
|
|
26
|
+
: 0;
|
|
27
|
+
const p = getRectPath({
|
|
28
|
+
x: d.x,
|
|
29
|
+
y: d.y,
|
|
30
|
+
width: d.width,
|
|
31
|
+
height: d.height,
|
|
32
|
+
borderRadius: [0, borderRadius, borderRadius, 0],
|
|
33
|
+
});
|
|
34
|
+
return p.toString();
|
|
35
|
+
})
|
|
22
36
|
.attr('class', b('segment'))
|
|
23
37
|
.attr('x', (d) => d.x)
|
|
24
38
|
.attr('y', (d) => d.y)
|