@gravity-ui/chartkit 5.4.0 → 5.5.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/constants/widget-data.d.ts +1 -0
- package/build/constants/widget-data.js +1 -0
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +19 -2
- package/build/plugins/d3/renderer/constants/defaults/series-options.d.ts +7 -1
- package/build/plugins/d3/renderer/constants/defaults/series-options.js +14 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +13 -3
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-waterfall.d.ts +10 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-waterfall.js +36 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +8 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +14 -2
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +16 -0
- package/build/plugins/d3/renderer/hooks/useShapes/styles.css +4 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.d.ts +12 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.js +125 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/prepare-data.d.ts +12 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/prepare-data.js +132 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/types.d.ts +14 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/types.js +1 -0
- package/build/plugins/d3/renderer/utils/get-closest-data.js +16 -5
- package/build/plugins/d3/renderer/utils/index.d.ts +1 -0
- package/build/plugins/d3/renderer/utils/index.js +11 -0
- package/build/plugins/d3/renderer/utils/series/index.d.ts +1 -0
- package/build/plugins/d3/renderer/utils/series/index.js +1 -0
- package/build/plugins/d3/renderer/utils/series/waterfall.d.ts +4 -0
- package/build/plugins/d3/renderer/utils/series/waterfall.js +25 -0
- package/build/plugins/highcharts/renderer/components/HighchartsComponent.d.ts +5 -0
- package/build/plugins/highcharts/renderer/helpers/config/config.d.ts +5 -0
- package/build/plugins/highcharts/renderer/helpers/config/config.js +8 -0
- package/build/plugins/highcharts/renderer/helpers/config/options.js +1 -1
- package/build/plugins/highcharts/renderer/helpers/graph.d.ts +5 -0
- package/build/types/widget-data/index.d.ts +1 -0
- package/build/types/widget-data/index.js +1 -0
- package/build/types/widget-data/series.d.ts +21 -2
- package/build/types/widget-data/tooltip.d.ts +6 -1
- package/build/types/widget-data/waterfall.d.ts +39 -0
- package/build/types/widget-data/waterfall.js +1 -0
- package/package.json +1 -1
|
@@ -3,7 +3,7 @@ import { dateTime } from '@gravity-ui/date-utils';
|
|
|
3
3
|
import get from 'lodash/get';
|
|
4
4
|
import { block } from '../../../../../utils/cn';
|
|
5
5
|
import { formatNumber } from '../../../../shared';
|
|
6
|
-
import { getDataCategoryValue } from '../../utils';
|
|
6
|
+
import { getDataCategoryValue, getWaterfallPointSubtotal } from '../../utils';
|
|
7
7
|
const b = block('d3-tooltip');
|
|
8
8
|
const DEFAULT_DATE_FORMAT = 'DD.MM.YY';
|
|
9
9
|
const getRowData = (fieldName, axis, data) => {
|
|
@@ -30,7 +30,7 @@ const getXRowData = (xAxis, data) => getRowData('x', xAxis, data);
|
|
|
30
30
|
const getYRowData = (yAxis, data) => getRowData('y', yAxis, data);
|
|
31
31
|
const getMeasureValue = (data, xAxis, yAxis) => {
|
|
32
32
|
var _a, _b;
|
|
33
|
-
if (data.every((item) =>
|
|
33
|
+
if (data.every((item) => ['pie', 'treemap', 'waterfall'].includes(item.series.type))) {
|
|
34
34
|
return null;
|
|
35
35
|
}
|
|
36
36
|
if (data.some((item) => item.series.type === 'bar-y')) {
|
|
@@ -58,6 +58,23 @@ export const DefaultContent = ({ hovered, xAxis, yAxis }) => {
|
|
|
58
58
|
React.createElement("div", { className: b('color'), style: { backgroundColor: color } }),
|
|
59
59
|
React.createElement("div", null, closest ? React.createElement("b", null, value) : React.createElement("span", null, value))));
|
|
60
60
|
}
|
|
61
|
+
case 'waterfall': {
|
|
62
|
+
const isTotal = get(data, 'total', false);
|
|
63
|
+
const subTotal = getWaterfallPointSubtotal(data, series);
|
|
64
|
+
return (React.createElement("div", { key: `${id}_${get(data, 'x')}` },
|
|
65
|
+
!isTotal && (React.createElement(React.Fragment, null,
|
|
66
|
+
React.createElement("div", { key: id, className: b('content-row') },
|
|
67
|
+
React.createElement("b", null, getXRowData(xAxis, data))),
|
|
68
|
+
React.createElement("div", { className: b('content-row') },
|
|
69
|
+
React.createElement("span", null,
|
|
70
|
+
series.name,
|
|
71
|
+
"\u00A0"),
|
|
72
|
+
React.createElement("span", null, getYRowData(yAxis, data))))),
|
|
73
|
+
React.createElement("div", { key: id, className: b('content-row') },
|
|
74
|
+
isTotal ? 'Total' : 'Subtotal',
|
|
75
|
+
": ",
|
|
76
|
+
subTotal)));
|
|
77
|
+
}
|
|
61
78
|
case 'bar-y': {
|
|
62
79
|
const value = (React.createElement(React.Fragment, null,
|
|
63
80
|
series.name,
|
|
@@ -13,6 +13,12 @@ type DefaultBarYSeriesOptions = Partial<ChartKitWidgetSeriesOptions['bar-x']> &
|
|
|
13
13
|
groupPadding: number;
|
|
14
14
|
};
|
|
15
15
|
};
|
|
16
|
-
|
|
16
|
+
type DefaultWaterfallSeriesOptions = Partial<ChartKitWidgetSeriesOptions['waterfall']> & {
|
|
17
|
+
waterfall: {
|
|
18
|
+
barMaxWidth: number;
|
|
19
|
+
barPadding: number;
|
|
20
|
+
};
|
|
21
|
+
};
|
|
22
|
+
export type SeriesOptionsDefaults = Partial<ChartKitWidgetSeriesOptions> & DefaultBarXSeriesOptions & DefaultBarYSeriesOptions & DefaultWaterfallSeriesOptions;
|
|
17
23
|
export declare const seriesOptionsDefaults: SeriesOptionsDefaults;
|
|
18
24
|
export {};
|
|
@@ -89,4 +89,18 @@ export const seriesOptionsDefaults = {
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
},
|
|
92
|
+
waterfall: {
|
|
93
|
+
barMaxWidth: 50,
|
|
94
|
+
barPadding: 0.1,
|
|
95
|
+
states: {
|
|
96
|
+
hover: {
|
|
97
|
+
enabled: true,
|
|
98
|
+
brightness: 0.3,
|
|
99
|
+
},
|
|
100
|
+
inactive: {
|
|
101
|
+
enabled: false,
|
|
102
|
+
opacity: 0.5,
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
},
|
|
92
106
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import get from 'lodash/get';
|
|
2
2
|
import { DEFAULT_AXIS_LABEL_FONT_SIZE, axisLabelsDefaults, yAxisTitleDefaults, } from '../../constants';
|
|
3
|
-
import { formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, } from '../../utils';
|
|
3
|
+
import { formatAxisTickLabel, getClosestPointsRange, getHorisontalSvgTextHeight, getLabelsSize, getScaleTicks, getWaterfallPointSubtotal, } from '../../utils';
|
|
4
4
|
import { createYScale } from '../useAxisScales';
|
|
5
5
|
const getAxisLabelMaxWidth = (args) => {
|
|
6
6
|
const { axis, series } = args;
|
|
@@ -24,9 +24,19 @@ const getAxisLabelMaxWidth = (args) => {
|
|
|
24
24
|
};
|
|
25
25
|
function getAxisMin(axis, series) {
|
|
26
26
|
const min = axis === null || axis === void 0 ? void 0 : axis.min;
|
|
27
|
-
const seriesWithVolume = ['bar-x', 'area'];
|
|
27
|
+
const seriesWithVolume = ['bar-x', 'area', 'waterfall'];
|
|
28
28
|
if (typeof min === 'undefined' && (series === null || series === void 0 ? void 0 : series.some((s) => seriesWithVolume.includes(s.type)))) {
|
|
29
|
-
return
|
|
29
|
+
return series.reduce((minValue, s) => {
|
|
30
|
+
switch (s.type) {
|
|
31
|
+
case 'waterfall': {
|
|
32
|
+
const minSubTotal = s.data.reduce((res, d) => Math.min(res, getWaterfallPointSubtotal(d, s) || 0), 0);
|
|
33
|
+
return Math.min(minValue, minSubTotal);
|
|
34
|
+
}
|
|
35
|
+
default: {
|
|
36
|
+
return minValue;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}, 0);
|
|
30
40
|
}
|
|
31
41
|
return min;
|
|
32
42
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ScaleOrdinal } from 'd3';
|
|
2
|
+
import type { WaterfallSeries } from '../../../../../types';
|
|
3
|
+
import type { PreparedLegend, PreparedSeries } from './types';
|
|
4
|
+
type PrepareWaterfallSeriesArgs = {
|
|
5
|
+
colorScale: ScaleOrdinal<string, string>;
|
|
6
|
+
series: WaterfallSeries[];
|
|
7
|
+
legend: PreparedLegend;
|
|
8
|
+
};
|
|
9
|
+
export declare function prepareWaterfallSeries(args: PrepareWaterfallSeriesArgs): PreparedSeries[];
|
|
10
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { getRandomCKId } from '../../../../../utils';
|
|
3
|
+
import { DEFAULT_PALETTE } from '../../constants';
|
|
4
|
+
import { DEFAULT_DATALABELS_PADDING, DEFAULT_DATALABELS_STYLE } from './constants';
|
|
5
|
+
import { prepareLegendSymbol } from './utils';
|
|
6
|
+
export function prepareWaterfallSeries(args) {
|
|
7
|
+
const { colorScale, series: seriesList, legend } = args;
|
|
8
|
+
const [, negativeColor, positiveColor] = DEFAULT_PALETTE;
|
|
9
|
+
return seriesList.map((series) => {
|
|
10
|
+
var _a, _b, _c;
|
|
11
|
+
const name = series.name || '';
|
|
12
|
+
const color = series.color || colorScale(name);
|
|
13
|
+
const prepared = {
|
|
14
|
+
type: series.type,
|
|
15
|
+
color,
|
|
16
|
+
positiveColor: positiveColor,
|
|
17
|
+
negativeColor: negativeColor,
|
|
18
|
+
name,
|
|
19
|
+
id: getRandomCKId(),
|
|
20
|
+
visible: get(series, 'visible', true),
|
|
21
|
+
legend: {
|
|
22
|
+
enabled: get(series, 'legend.enabled', legend.enabled),
|
|
23
|
+
symbol: prepareLegendSymbol(series),
|
|
24
|
+
},
|
|
25
|
+
data: series.data,
|
|
26
|
+
dataLabels: {
|
|
27
|
+
enabled: ((_a = series.dataLabels) === null || _a === void 0 ? void 0 : _a.enabled) || false,
|
|
28
|
+
style: Object.assign({}, DEFAULT_DATALABELS_STYLE, (_b = series.dataLabels) === null || _b === void 0 ? void 0 : _b.style),
|
|
29
|
+
allowOverlap: ((_c = series.dataLabels) === null || _c === void 0 ? void 0 : _c.allowOverlap) || false,
|
|
30
|
+
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
31
|
+
},
|
|
32
|
+
cursor: get(series, 'cursor', null),
|
|
33
|
+
};
|
|
34
|
+
return prepared;
|
|
35
|
+
}, []);
|
|
36
|
+
}
|
|
@@ -6,6 +6,7 @@ import { prepareLineSeries } from './prepare-line';
|
|
|
6
6
|
import { preparePieSeries } from './prepare-pie';
|
|
7
7
|
import { prepareScatterSeries } from './prepare-scatter';
|
|
8
8
|
import { prepareTreemap } from './prepare-treemap';
|
|
9
|
+
import { prepareWaterfallSeries } from './prepare-waterfall';
|
|
9
10
|
export function prepareSeries(args) {
|
|
10
11
|
const { type, series, seriesOptions, legend, colorScale } = args;
|
|
11
12
|
switch (type) {
|
|
@@ -48,6 +49,13 @@ export function prepareSeries(args) {
|
|
|
48
49
|
colorScale,
|
|
49
50
|
});
|
|
50
51
|
}
|
|
52
|
+
case 'waterfall': {
|
|
53
|
+
return prepareWaterfallSeries({
|
|
54
|
+
series: series,
|
|
55
|
+
legend,
|
|
56
|
+
colorScale,
|
|
57
|
+
});
|
|
58
|
+
}
|
|
51
59
|
default: {
|
|
52
60
|
throw new ChartKitError({
|
|
53
61
|
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 { DashStyle, LayoutAlgorithm, LineCap, SymbolType } from '../../../../../constants';
|
|
2
|
-
import { AreaSeries, AreaSeriesData, BarXSeries, BarXSeriesData, BarYSeries, BarYSeriesData, BaseTextStyle, ChartKitWidgetLegend, ConnectorCurve, ConnectorShape, LineSeries, LineSeriesData, PathLegendSymbolOptions, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData, SymbolLegendSymbolOptions, TreemapSeries, TreemapSeriesData } from '../../../../../types';
|
|
2
|
+
import type { AreaSeries, AreaSeriesData, BarXSeries, BarXSeriesData, BarYSeries, BarYSeriesData, BaseTextStyle, ChartKitWidgetLegend, ConnectorCurve, ConnectorShape, LineSeries, LineSeriesData, PathLegendSymbolOptions, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData, SymbolLegendSymbolOptions, TreemapSeries, TreemapSeriesData, WaterfallSeries, WaterfallSeriesData } from '../../../../../types';
|
|
3
3
|
import type { SeriesOptionsDefaults } from '../../constants';
|
|
4
4
|
export type RectLegendSymbol = {
|
|
5
5
|
shape: 'rect';
|
|
@@ -208,7 +208,19 @@ export type PreparedTreemapSeries = {
|
|
|
208
208
|
};
|
|
209
209
|
layoutAlgorithm: `${LayoutAlgorithm}`;
|
|
210
210
|
} & BasePreparedSeries & Omit<TreemapSeries, keyof BasePreparedSeries>;
|
|
211
|
-
export type
|
|
211
|
+
export type PreparedWaterfallSeries = {
|
|
212
|
+
type: WaterfallSeries['type'];
|
|
213
|
+
data: WaterfallSeriesData[];
|
|
214
|
+
dataLabels: {
|
|
215
|
+
enabled: boolean;
|
|
216
|
+
style: BaseTextStyle;
|
|
217
|
+
allowOverlap: boolean;
|
|
218
|
+
padding: number;
|
|
219
|
+
};
|
|
220
|
+
positiveColor: string;
|
|
221
|
+
negativeColor: string;
|
|
222
|
+
} & BasePreparedSeries;
|
|
223
|
+
export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedBarYSeries | PreparedPieSeries | PreparedLineSeries | PreparedAreaSeries | PreparedTreemapSeries | PreparedWaterfallSeries;
|
|
212
224
|
export type PreparedSeriesOptions = SeriesOptionsDefaults;
|
|
213
225
|
export type StackedSeries = BarXSeries | AreaSeries | BarYSeries;
|
|
214
226
|
export {};
|
|
@@ -11,8 +11,9 @@ import type { PreparedPieData } from './pie/types';
|
|
|
11
11
|
import type { PreparedScatterData } from './scatter/types';
|
|
12
12
|
export type { PreparedBarXData } from './bar-x';
|
|
13
13
|
export type { PreparedScatterData } from './scatter/types';
|
|
14
|
+
import { PreparedWaterfallData } from './waterfall';
|
|
14
15
|
import './styles.css';
|
|
15
|
-
export type ShapeData = PreparedBarXData | PreparedBarYData | PreparedScatterData | PreparedLineData | PreparedPieData | PreparedAreaData;
|
|
16
|
+
export type ShapeData = PreparedBarXData | PreparedBarYData | PreparedScatterData | PreparedLineData | PreparedPieData | PreparedAreaData | PreparedWaterfallData;
|
|
16
17
|
type Args = {
|
|
17
18
|
boundsWidth: number;
|
|
18
19
|
boundsHeight: number;
|
|
@@ -12,6 +12,7 @@ import { preparePieData } from './pie/prepare-data';
|
|
|
12
12
|
import { ScatterSeriesShape, prepareScatterData } from './scatter';
|
|
13
13
|
import { TreemapSeriesShape } from './treemap';
|
|
14
14
|
import { prepareTreemapData } from './treemap/prepare-data';
|
|
15
|
+
import { WaterfallSeriesShapes, prepareWaterfallData } from './waterfall';
|
|
15
16
|
import './styles.css';
|
|
16
17
|
export const useShapes = (args) => {
|
|
17
18
|
const { boundsWidth, boundsHeight, dispatcher, series, seriesOptions, xAxis, xScale, yAxis, yScale, } = args;
|
|
@@ -52,6 +53,21 @@ export const useShapes = (args) => {
|
|
|
52
53
|
}
|
|
53
54
|
break;
|
|
54
55
|
}
|
|
56
|
+
case 'waterfall': {
|
|
57
|
+
if (xScale && yScale) {
|
|
58
|
+
const preparedData = prepareWaterfallData({
|
|
59
|
+
series: chartSeries,
|
|
60
|
+
seriesOptions,
|
|
61
|
+
xAxis,
|
|
62
|
+
xScale,
|
|
63
|
+
yAxis,
|
|
64
|
+
yScale,
|
|
65
|
+
});
|
|
66
|
+
acc.push(React.createElement(WaterfallSeriesShapes, { key: "waterfall", dispatcher: dispatcher, seriesOptions: seriesOptions, preparedData: preparedData }));
|
|
67
|
+
shapesData.push(...preparedData);
|
|
68
|
+
}
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
55
71
|
case 'line': {
|
|
56
72
|
if (xScale && yScale) {
|
|
57
73
|
const preparedData = prepareLineData({
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { Dispatch } from 'd3';
|
|
3
|
+
import type { PreparedSeriesOptions } from '../../useSeries/types';
|
|
4
|
+
import type { PreparedWaterfallData } from './types';
|
|
5
|
+
export { prepareWaterfallData } from './prepare-data';
|
|
6
|
+
export * from './types';
|
|
7
|
+
type Args = {
|
|
8
|
+
dispatcher: Dispatch<object>;
|
|
9
|
+
preparedData: PreparedWaterfallData[];
|
|
10
|
+
seriesOptions: PreparedSeriesOptions;
|
|
11
|
+
};
|
|
12
|
+
export declare const WaterfallSeriesShapes: (args: Args) => React.JSX.Element;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { color, line as lineGenerator, select } from 'd3';
|
|
3
|
+
import get from 'lodash/get';
|
|
4
|
+
import { DashStyle } from '../../../../../../constants';
|
|
5
|
+
import { block } from '../../../../../../utils/cn';
|
|
6
|
+
import { filterOverlappingLabels, getWaterfallPointColor } from '../../../utils';
|
|
7
|
+
import { getLineDashArray } from '../utils';
|
|
8
|
+
export { prepareWaterfallData } from './prepare-data';
|
|
9
|
+
export * from './types';
|
|
10
|
+
const b = block('d3-waterfall');
|
|
11
|
+
export const WaterfallSeriesShapes = (args) => {
|
|
12
|
+
const { dispatcher, preparedData, seriesOptions } = args;
|
|
13
|
+
const ref = React.useRef(null);
|
|
14
|
+
const connectorSelector = `.${b('connector')}`;
|
|
15
|
+
React.useEffect(() => {
|
|
16
|
+
var _a;
|
|
17
|
+
if (!ref.current) {
|
|
18
|
+
return () => { };
|
|
19
|
+
}
|
|
20
|
+
const svgElement = select(ref.current);
|
|
21
|
+
const hoverOptions = get(seriesOptions, 'waterfall.states.hover');
|
|
22
|
+
const inactiveOptions = get(seriesOptions, 'waterfall.states.inactive');
|
|
23
|
+
svgElement.selectAll('*').remove();
|
|
24
|
+
const rectSelection = svgElement
|
|
25
|
+
.selectAll('allRects')
|
|
26
|
+
.data(preparedData)
|
|
27
|
+
.join('rect')
|
|
28
|
+
.attr('class', b('segment'))
|
|
29
|
+
.attr('x', (d) => d.x)
|
|
30
|
+
.attr('y', (d) => d.y)
|
|
31
|
+
.attr('height', (d) => d.height)
|
|
32
|
+
.attr('width', (d) => d.width)
|
|
33
|
+
.attr('fill', (d) => getWaterfallPointColor(d.data, d.series))
|
|
34
|
+
.attr('opacity', (d) => d.opacity)
|
|
35
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
36
|
+
let dataLabels = preparedData.map((d) => d.label).filter(Boolean);
|
|
37
|
+
if (!((_a = preparedData[0]) === null || _a === void 0 ? void 0 : _a.series.dataLabels.allowOverlap)) {
|
|
38
|
+
dataLabels = filterOverlappingLabels(dataLabels);
|
|
39
|
+
}
|
|
40
|
+
const labelSelection = svgElement
|
|
41
|
+
.selectAll('text')
|
|
42
|
+
.data(dataLabels)
|
|
43
|
+
.join('text')
|
|
44
|
+
.text((d) => d.text)
|
|
45
|
+
.attr('class', b('label'))
|
|
46
|
+
.attr('x', (d) => d.x)
|
|
47
|
+
.attr('y', (d) => d.y)
|
|
48
|
+
.attr('text-anchor', (d) => d.textAnchor)
|
|
49
|
+
.style('font-size', (d) => d.style.fontSize)
|
|
50
|
+
.style('font-weight', (d) => d.style.fontWeight || null)
|
|
51
|
+
.style('fill', (d) => d.style.fontColor || null);
|
|
52
|
+
// Add the connector line between bars
|
|
53
|
+
svgElement
|
|
54
|
+
.selectAll(connectorSelector)
|
|
55
|
+
.data(preparedData)
|
|
56
|
+
.join('path')
|
|
57
|
+
.attr('class', b('connector'))
|
|
58
|
+
.attr('d', (d, index) => {
|
|
59
|
+
const line = lineGenerator();
|
|
60
|
+
const prev = preparedData[index - 1];
|
|
61
|
+
if (!prev) {
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
const points = [];
|
|
65
|
+
if (Number(prev.data.y) > 0) {
|
|
66
|
+
points.push([prev.x, prev.y]);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
points.push([prev.x, prev.y + prev.height]);
|
|
70
|
+
}
|
|
71
|
+
if (Number(d.data.y) > 0 && !d.data.total) {
|
|
72
|
+
points.push([d.x + d.width, d.y + d.height]);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
points.push([d.x + d.width, d.y]);
|
|
76
|
+
}
|
|
77
|
+
return line(points);
|
|
78
|
+
})
|
|
79
|
+
.attr('stroke-width', 1)
|
|
80
|
+
.attr('stroke-dasharray', () => getLineDashArray(DashStyle.Dash, 1));
|
|
81
|
+
dispatcher.on('hover-shape.waterfall', (data) => {
|
|
82
|
+
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
83
|
+
const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
|
|
84
|
+
if (!data) {
|
|
85
|
+
if (hoverEnabled) {
|
|
86
|
+
rectSelection.attr('fill', (d) => getWaterfallPointColor(d.data, d.series));
|
|
87
|
+
}
|
|
88
|
+
if (inactiveEnabled) {
|
|
89
|
+
rectSelection.attr('opacity', null);
|
|
90
|
+
labelSelection.attr('opacity', null);
|
|
91
|
+
}
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
if (hoverEnabled) {
|
|
95
|
+
const hoveredValues = data.map((d) => d.data.x);
|
|
96
|
+
rectSelection.attr('fill', (d) => {
|
|
97
|
+
var _a;
|
|
98
|
+
const fillColor = getWaterfallPointColor(d.data, d.series);
|
|
99
|
+
if (hoveredValues.includes(d.data.x)) {
|
|
100
|
+
const brightness = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.brightness;
|
|
101
|
+
return ((_a = color(fillColor)) === null || _a === void 0 ? void 0 : _a.brighter(brightness).toString()) || fillColor;
|
|
102
|
+
}
|
|
103
|
+
return fillColor;
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
if (inactiveEnabled) {
|
|
107
|
+
const hoveredSeries = data.map((d) => d.series.id);
|
|
108
|
+
rectSelection.attr('opacity', (d) => {
|
|
109
|
+
return hoveredSeries.includes(d.series.id)
|
|
110
|
+
? null
|
|
111
|
+
: (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
|
|
112
|
+
});
|
|
113
|
+
labelSelection.attr('opacity', (d) => {
|
|
114
|
+
return hoveredSeries.includes(d.series.id)
|
|
115
|
+
? null
|
|
116
|
+
: (inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.opacity) || null;
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
return () => {
|
|
121
|
+
dispatcher.on('hover-shape.waterfall', null);
|
|
122
|
+
};
|
|
123
|
+
}, [dispatcher, preparedData, seriesOptions]);
|
|
124
|
+
return React.createElement("g", { ref: ref, className: b() });
|
|
125
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ChartScale } from '../../useAxisScales';
|
|
2
|
+
import type { PreparedAxis } from '../../useChartOptions/types';
|
|
3
|
+
import type { PreparedSeriesOptions, PreparedWaterfallSeries } from '../../useSeries/types';
|
|
4
|
+
import type { PreparedWaterfallData } from './types';
|
|
5
|
+
export declare const prepareWaterfallData: (args: {
|
|
6
|
+
series: PreparedWaterfallSeries[];
|
|
7
|
+
seriesOptions: PreparedSeriesOptions;
|
|
8
|
+
xAxis: PreparedAxis;
|
|
9
|
+
xScale: ChartScale;
|
|
10
|
+
yAxis: PreparedAxis[];
|
|
11
|
+
yScale: ChartScale;
|
|
12
|
+
}) => PreparedWaterfallData[];
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import sortBy from 'lodash/sortBy';
|
|
3
|
+
import { getLabelsSize } from '../../../utils';
|
|
4
|
+
import { MIN_BAR_GAP, MIN_BAR_WIDTH } from '../constants';
|
|
5
|
+
import { getXValue, getYValue } from '../utils';
|
|
6
|
+
function getLabelData(d, plotHeight) {
|
|
7
|
+
if (!d.series.dataLabels.enabled) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
const text = String(d.data.label || d.subTotal);
|
|
11
|
+
const style = d.series.dataLabels.style;
|
|
12
|
+
const { maxHeight: height, maxWidth: width } = getLabelsSize({ labels: [text], style });
|
|
13
|
+
let y;
|
|
14
|
+
if (Number(d.data.y) > 0 || d.data.total) {
|
|
15
|
+
y = Math.max(height, d.y - d.series.dataLabels.padding);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
y = Math.min(plotHeight - d.series.dataLabels.padding, d.y + d.height + d.series.dataLabels.padding + height);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
text,
|
|
22
|
+
x: d.x + d.width / 2,
|
|
23
|
+
y,
|
|
24
|
+
style,
|
|
25
|
+
size: { width, height },
|
|
26
|
+
textAnchor: 'middle',
|
|
27
|
+
series: d.series,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function getBandWidth(args) {
|
|
31
|
+
const { series, xAxis, xScale } = args;
|
|
32
|
+
if (xAxis.type === 'category') {
|
|
33
|
+
const xBandScale = xScale;
|
|
34
|
+
return xBandScale.bandwidth();
|
|
35
|
+
}
|
|
36
|
+
const xLinearScale = xScale;
|
|
37
|
+
const xValues = series.reduce((acc, s) => {
|
|
38
|
+
s.data.forEach((dataItem) => acc.push(Number(dataItem.x)));
|
|
39
|
+
return acc;
|
|
40
|
+
}, []);
|
|
41
|
+
let bandWidth = Infinity;
|
|
42
|
+
xValues.sort().forEach((xValue, index) => {
|
|
43
|
+
if (index > 0 && xValue !== xValues[index - 1]) {
|
|
44
|
+
const dist = xLinearScale(xValue) - xLinearScale(xValues[index - 1]);
|
|
45
|
+
if (dist < bandWidth) {
|
|
46
|
+
bandWidth = dist;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
return bandWidth;
|
|
51
|
+
}
|
|
52
|
+
export const prepareWaterfallData = (args) => {
|
|
53
|
+
const { series, seriesOptions, xAxis, xScale, yAxis: [yAxis], yScale, } = args;
|
|
54
|
+
const yLinearScale = yScale;
|
|
55
|
+
const plotHeight = yLinearScale(yLinearScale.domain()[0]);
|
|
56
|
+
const barMaxWidth = get(seriesOptions, 'waterfall.barMaxWidth');
|
|
57
|
+
const barPadding = get(seriesOptions, 'waterfall.barPadding');
|
|
58
|
+
const flattenData = series.reduce((acc, s) => {
|
|
59
|
+
acc.push(...s.data.map((d) => ({ data: d, series: s })));
|
|
60
|
+
return acc;
|
|
61
|
+
}, []);
|
|
62
|
+
const data = sortBy(flattenData, (d) => d.data.x);
|
|
63
|
+
const bandWidth = getBandWidth({
|
|
64
|
+
series,
|
|
65
|
+
xAxis,
|
|
66
|
+
xScale,
|
|
67
|
+
});
|
|
68
|
+
const rectGap = Math.max(bandWidth * barPadding, MIN_BAR_GAP);
|
|
69
|
+
const rectWidth = Math.max(MIN_BAR_WIDTH, Math.min(bandWidth - rectGap, barMaxWidth));
|
|
70
|
+
const yZero = getYValue({
|
|
71
|
+
point: { y: 0 },
|
|
72
|
+
yScale,
|
|
73
|
+
yAxis,
|
|
74
|
+
});
|
|
75
|
+
let totalValue = 0;
|
|
76
|
+
const result = [];
|
|
77
|
+
data.forEach((item, _index) => {
|
|
78
|
+
if (typeof item.data.y !== 'number' && !item.data.total) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (!item.data.total) {
|
|
82
|
+
totalValue += Number(item.data.y);
|
|
83
|
+
}
|
|
84
|
+
const prevPoint = result[result.length - 1];
|
|
85
|
+
const xCenter = getXValue({ point: item.data, xAxis, xScale });
|
|
86
|
+
const x = xCenter - rectWidth / 2;
|
|
87
|
+
const yValue = Number(item.data.total ? totalValue : item.data.y);
|
|
88
|
+
const height = yZero -
|
|
89
|
+
getYValue({
|
|
90
|
+
point: { y: Math.abs(yValue) },
|
|
91
|
+
yScale,
|
|
92
|
+
yAxis,
|
|
93
|
+
});
|
|
94
|
+
let y;
|
|
95
|
+
if (!prevPoint || item.data.total) {
|
|
96
|
+
y = getYValue({
|
|
97
|
+
point: {
|
|
98
|
+
y: yValue > 0 ? yValue : 0,
|
|
99
|
+
},
|
|
100
|
+
yScale,
|
|
101
|
+
yAxis,
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else if (Number(prevPoint.data.y) < 0) {
|
|
105
|
+
if (Number(item.data.y) > 0) {
|
|
106
|
+
y = prevPoint.y + prevPoint.height - height;
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
y = prevPoint.y + prevPoint.height;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
else if (Number(item.data.y) < 0) {
|
|
113
|
+
y = prevPoint.y;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
y = prevPoint.y - height;
|
|
117
|
+
}
|
|
118
|
+
const preparedData = {
|
|
119
|
+
x,
|
|
120
|
+
y,
|
|
121
|
+
width: rectWidth,
|
|
122
|
+
height,
|
|
123
|
+
opacity: get(item.data, 'opacity', null),
|
|
124
|
+
data: item.data,
|
|
125
|
+
series: item.series,
|
|
126
|
+
subTotal: totalValue,
|
|
127
|
+
};
|
|
128
|
+
preparedData.label = getLabelData(preparedData, plotHeight);
|
|
129
|
+
result.push(preparedData);
|
|
130
|
+
});
|
|
131
|
+
return result;
|
|
132
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { WaterfallSeriesData } from '../../../../../../types';
|
|
2
|
+
import { LabelData } from '../../../types';
|
|
3
|
+
import { PreparedWaterfallSeries } from '../../useSeries/types';
|
|
4
|
+
export type PreparedWaterfallData = {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
width: number;
|
|
8
|
+
height: number;
|
|
9
|
+
opacity: number | null;
|
|
10
|
+
series: PreparedWaterfallSeries;
|
|
11
|
+
data: WaterfallSeriesData;
|
|
12
|
+
label?: LabelData;
|
|
13
|
+
subTotal: number;
|
|
14
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -45,7 +45,18 @@ export function getClosestPoints(args) {
|
|
|
45
45
|
y0: d.y,
|
|
46
46
|
y1: d.y + d.height,
|
|
47
47
|
}));
|
|
48
|
-
|
|
48
|
+
result.push(...getClosestPointsByXValue(pointerX, pointerY, points));
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
case 'waterfall': {
|
|
52
|
+
const points = list.map((d) => ({
|
|
53
|
+
data: d.data,
|
|
54
|
+
series: d.series,
|
|
55
|
+
x: d.x + d.width / 2,
|
|
56
|
+
y0: d.y,
|
|
57
|
+
y1: d.y + d.height,
|
|
58
|
+
}));
|
|
59
|
+
result.push(...getClosestPointsByXValue(pointerX, pointerY, points));
|
|
49
60
|
break;
|
|
50
61
|
}
|
|
51
62
|
case 'area': {
|
|
@@ -59,12 +70,12 @@ export function getClosestPoints(args) {
|
|
|
59
70
|
})));
|
|
60
71
|
return acc;
|
|
61
72
|
}, []);
|
|
62
|
-
|
|
73
|
+
result.push(...getClosestPointsByXValue(pointerX, pointerY, points));
|
|
63
74
|
break;
|
|
64
75
|
}
|
|
65
76
|
case 'line': {
|
|
66
77
|
const points = list.reduce((acc, d) => {
|
|
67
|
-
|
|
78
|
+
acc.push(...d.points.map((p) => ({
|
|
68
79
|
data: p.data,
|
|
69
80
|
series: p.series,
|
|
70
81
|
x: p.x,
|
|
@@ -73,7 +84,7 @@ export function getClosestPoints(args) {
|
|
|
73
84
|
})));
|
|
74
85
|
return acc;
|
|
75
86
|
}, []);
|
|
76
|
-
|
|
87
|
+
result.push(...getClosestPointsByXValue(pointerX, pointerY, points));
|
|
77
88
|
break;
|
|
78
89
|
}
|
|
79
90
|
case 'bar-y': {
|
|
@@ -96,7 +107,7 @@ export function getClosestPoints(args) {
|
|
|
96
107
|
closestXIndex = closestPoints.findIndex((p) => pointerX > p.x && pointerX < p.x + p.width);
|
|
97
108
|
}
|
|
98
109
|
}
|
|
99
|
-
|
|
110
|
+
result.push(...closestPoints.map((p, i) => ({
|
|
100
111
|
data: p.data,
|
|
101
112
|
series: p.series,
|
|
102
113
|
closest: i === closestXIndex,
|
|
@@ -13,6 +13,7 @@ export * from './time';
|
|
|
13
13
|
export * from './axis';
|
|
14
14
|
export * from './labels';
|
|
15
15
|
export * from './symbol';
|
|
16
|
+
export * from './series';
|
|
16
17
|
const CHARTS_WITHOUT_AXIS = ['pie', 'treemap'];
|
|
17
18
|
/**
|
|
18
19
|
* Checks whether the series should be drawn with axes.
|
|
@@ -70,6 +71,16 @@ export const getDomainDataYBySeries = (series) => {
|
|
|
70
71
|
});
|
|
71
72
|
break;
|
|
72
73
|
}
|
|
74
|
+
case 'waterfall': {
|
|
75
|
+
let yValue = 0;
|
|
76
|
+
seriesList.forEach((s) => {
|
|
77
|
+
s.data.forEach((d) => {
|
|
78
|
+
yValue += Number(d.y) || 0;
|
|
79
|
+
acc.push(yValue);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
73
84
|
default: {
|
|
74
85
|
seriesList.filter(isSeriesWithNumericalYValues).forEach((s) => {
|
|
75
86
|
acc.push(...s.data.map((d) => d.y));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './waterfall';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './waterfall';
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { WaterfallSeriesData } from '../../../../../types';
|
|
2
|
+
import { PreparedWaterfallSeries } from '../../hooks';
|
|
3
|
+
export declare function getWaterfallPointColor(point: WaterfallSeriesData, series: PreparedWaterfallSeries): string;
|
|
4
|
+
export declare function getWaterfallPointSubtotal(point: WaterfallSeriesData, series: PreparedWaterfallSeries): number | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export function getWaterfallPointColor(point, series) {
|
|
2
|
+
if (point.color) {
|
|
3
|
+
return point.color;
|
|
4
|
+
}
|
|
5
|
+
if (point.total) {
|
|
6
|
+
return series.color;
|
|
7
|
+
}
|
|
8
|
+
if (Number(point.y) > 0) {
|
|
9
|
+
return series.positiveColor;
|
|
10
|
+
}
|
|
11
|
+
return series.negativeColor;
|
|
12
|
+
}
|
|
13
|
+
export function getWaterfallPointSubtotal(point, series) {
|
|
14
|
+
const pointIndex = series.data.indexOf(point);
|
|
15
|
+
if (pointIndex === -1) {
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
return series.data.reduce((sum, d, index) => {
|
|
19
|
+
if (index <= pointIndex) {
|
|
20
|
+
const value = d.total ? 0 : Number(d.y);
|
|
21
|
+
return sum + value;
|
|
22
|
+
}
|
|
23
|
+
return sum;
|
|
24
|
+
}, 0);
|
|
25
|
+
}
|
|
@@ -363,6 +363,11 @@ export declare class HighchartsComponent extends React.PureComponent<Props, Stat
|
|
|
363
363
|
mouseOut: () => void;
|
|
364
364
|
click: (event: any) => void;
|
|
365
365
|
};
|
|
366
|
+
point: {
|
|
367
|
+
events: {
|
|
368
|
+
click: () => false;
|
|
369
|
+
};
|
|
370
|
+
};
|
|
366
371
|
marker: {
|
|
367
372
|
states: {
|
|
368
373
|
hover: {
|
|
@@ -526,6 +526,11 @@ export function prepareConfig(data: any, options: any, isMobile: any, holidays:
|
|
|
526
526
|
mouseOut: () => void;
|
|
527
527
|
click: (event: any) => void;
|
|
528
528
|
};
|
|
529
|
+
point: {
|
|
530
|
+
events: {
|
|
531
|
+
click: () => false;
|
|
532
|
+
};
|
|
533
|
+
};
|
|
529
534
|
marker: {
|
|
530
535
|
states: {
|
|
531
536
|
hover: {
|
|
@@ -1264,6 +1264,14 @@ export function prepareConfig(data, options, isMobile, holidays) {
|
|
|
1264
1264
|
}
|
|
1265
1265
|
},
|
|
1266
1266
|
},
|
|
1267
|
+
point: {
|
|
1268
|
+
events: {
|
|
1269
|
+
click: function () {
|
|
1270
|
+
// Prevent slicing of pie segment after clicking it
|
|
1271
|
+
return false;
|
|
1272
|
+
},
|
|
1273
|
+
},
|
|
1274
|
+
},
|
|
1267
1275
|
marker: options.splitTooltip
|
|
1268
1276
|
? {
|
|
1269
1277
|
states: {
|
|
@@ -357,6 +357,11 @@ declare function getGraph({ options, data, comments, isMobile, holidays }: GetGr
|
|
|
357
357
|
mouseOut: () => void;
|
|
358
358
|
click: (event: any) => void;
|
|
359
359
|
};
|
|
360
|
+
point: {
|
|
361
|
+
events: {
|
|
362
|
+
click: () => false;
|
|
363
|
+
};
|
|
364
|
+
};
|
|
360
365
|
marker: {
|
|
361
366
|
states: {
|
|
362
367
|
hover: {
|
|
@@ -9,8 +9,9 @@ import type { PointMarkerOptions } from './marker';
|
|
|
9
9
|
import type { PieSeries, PieSeriesData } from './pie';
|
|
10
10
|
import type { ScatterSeries, ScatterSeriesData } from './scatter';
|
|
11
11
|
import type { TreemapSeries, TreemapSeriesData } from './treemap';
|
|
12
|
-
|
|
13
|
-
export type
|
|
12
|
+
import type { WaterfallSeries, WaterfallSeriesData } from './waterfall';
|
|
13
|
+
export type ChartKitWidgetSeries<T = any> = ScatterSeries<T> | PieSeries<T> | BarXSeries<T> | BarYSeries<T> | LineSeries<T> | AreaSeries<T> | TreemapSeries<T> | WaterfallSeries<T>;
|
|
14
|
+
export type ChartKitWidgetSeriesData<T = any> = ScatterSeriesData<T> | PieSeriesData<T> | BarXSeriesData<T> | BarYSeriesData<T> | LineSeriesData<T> | AreaSeriesData<T> | TreemapSeriesData<T> | WaterfallSeriesData<T>;
|
|
14
15
|
export type DataLabelRendererData<T = any> = {
|
|
15
16
|
data: ChartKitWidgetSeriesData<T>;
|
|
16
17
|
};
|
|
@@ -202,5 +203,23 @@ export type ChartKitWidgetSeriesOptions = {
|
|
|
202
203
|
inactive?: BasicInactiveState;
|
|
203
204
|
};
|
|
204
205
|
};
|
|
206
|
+
waterfall?: {
|
|
207
|
+
/** The maximum allowed pixel width for a column.
|
|
208
|
+
* This prevents the columns from becoming too wide when there is a small number of points in the chart.
|
|
209
|
+
*
|
|
210
|
+
* @default 50
|
|
211
|
+
*/
|
|
212
|
+
barMaxWidth?: number;
|
|
213
|
+
/** Padding between each column or bar, in x axis units.
|
|
214
|
+
*
|
|
215
|
+
* @default 0.1
|
|
216
|
+
* */
|
|
217
|
+
barPadding?: number;
|
|
218
|
+
/** Options for the series states that provide additional styling information to the series. */
|
|
219
|
+
states?: {
|
|
220
|
+
hover?: BasicHoverState;
|
|
221
|
+
inactive?: BasicInactiveState;
|
|
222
|
+
};
|
|
223
|
+
};
|
|
205
224
|
};
|
|
206
225
|
export {};
|
|
@@ -6,6 +6,7 @@ import type { LineSeries, LineSeriesData } from './line';
|
|
|
6
6
|
import type { PieSeries, PieSeriesData } from './pie';
|
|
7
7
|
import type { ScatterSeries, ScatterSeriesData } from './scatter';
|
|
8
8
|
import type { TreemapSeries, TreemapSeriesData } from './treemap';
|
|
9
|
+
import type { WaterfallSeries, WaterfallSeriesData } from './waterfall';
|
|
9
10
|
export type TooltipDataChunkBarX<T = any> = {
|
|
10
11
|
data: BarXSeriesData<T>;
|
|
11
12
|
series: BarXSeries<T>;
|
|
@@ -50,7 +51,11 @@ export type TooltipDataChunkTreemap<T = any> = {
|
|
|
50
51
|
data: TreemapSeriesData<T>;
|
|
51
52
|
series: TreemapSeries<T>;
|
|
52
53
|
};
|
|
53
|
-
export type
|
|
54
|
+
export type TooltipDataChunkWaterfall<T = any> = {
|
|
55
|
+
data: WaterfallSeriesData<T>;
|
|
56
|
+
series: WaterfallSeries<T>;
|
|
57
|
+
};
|
|
58
|
+
export type TooltipDataChunk<T = any> = (TooltipDataChunkBarX<T> | TooltipDataChunkBarY<T> | TooltipDataChunkPie<T> | TooltipDataChunkScatter<T> | TooltipDataChunkLine<T> | TooltipDataChunkArea<T> | TooltipDataChunkTreemap<T> | TooltipDataChunkWaterfall<T>) & {
|
|
54
59
|
closest?: boolean;
|
|
55
60
|
};
|
|
56
61
|
export type ChartKitWidgetTooltip<T = any> = {
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { SeriesType } from '../../constants';
|
|
2
|
+
import type { BaseSeries, BaseSeriesData } from './base';
|
|
3
|
+
import { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
4
|
+
export type WaterfallSeriesData<T = any> = BaseSeriesData<T> & {
|
|
5
|
+
/**
|
|
6
|
+
* The `x` value. Depending on the context , it may represents:
|
|
7
|
+
* - numeric value (for `linear` x axis)
|
|
8
|
+
* - timestamp value (for `datetime` x axis)
|
|
9
|
+
* - x axis category value (for `category` x axis). If the type is a string, then it is a category value itself. If the type is a number, then it is the index of an element in the array of categories described in `xAxis.categories`
|
|
10
|
+
*/
|
|
11
|
+
x?: string | number;
|
|
12
|
+
/**
|
|
13
|
+
* The `y` value. Depending on the context , it may represents:
|
|
14
|
+
* - numeric value (for `linear` y axis)
|
|
15
|
+
*/
|
|
16
|
+
y?: number;
|
|
17
|
+
/** Data label value of the point. If not specified, the y value is used. */
|
|
18
|
+
label?: string | number;
|
|
19
|
+
/** Individual opacity for the point. */
|
|
20
|
+
opacity?: number;
|
|
21
|
+
/** When this property is true, the point display the total sum across the entire series. */
|
|
22
|
+
total?: boolean;
|
|
23
|
+
};
|
|
24
|
+
export type WaterfallSeries<T = any> = BaseSeries & {
|
|
25
|
+
type: typeof SeriesType.Waterfall;
|
|
26
|
+
data: WaterfallSeriesData<T>[];
|
|
27
|
+
/** The name of the series (used in legend, tooltip etc). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** The main color of the series (hex, rgba). */
|
|
30
|
+
color?: string;
|
|
31
|
+
/** The color used for positive values. If it is not specified, the general color of the series is used. */
|
|
32
|
+
positiveColor?: string;
|
|
33
|
+
/** The color used for negative values. If it is not specified, the general color of the series is used. */
|
|
34
|
+
negativeColor?: string;
|
|
35
|
+
/** Individual series legend options. Has higher priority than legend options in widget data. */
|
|
36
|
+
legend?: ChartKitWidgetLegend & {
|
|
37
|
+
symbol?: RectLegendSymbolOptions;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED