@gravity-ui/chartkit 5.0.0 → 5.2.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/components/Chart.js +10 -0
- package/build/plugins/d3/renderer/components/Tooltip/TooltipTriggerArea.js +17 -5
- package/build/plugins/d3/renderer/d3-dispatcher.js +1 -1
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-area.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-x.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-bar-y.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-line.js +2 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-pie.js +2 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-scatter.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-treemap.js +3 -1
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +4 -1
- package/build/plugins/d3/renderer/hooks/useShapes/area/index.js +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.js +3 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/types.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.js +3 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.js +3 -1
- package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/types.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/marker.js +8 -1
- package/build/plugins/d3/renderer/hooks/useShapes/pie/index.js +20 -9
- package/build/plugins/d3/renderer/hooks/useShapes/pie/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/pie/types.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +13 -2
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/types.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/index.js +12 -4
- package/build/plugins/highcharts/renderer/components/withSplitPane/withSplitPane.d.ts +1 -0
- package/build/plugins/highcharts/renderer/components/withSplitPane/withSplitPane.js +2 -0
- package/build/plugins/yagr/renderer/tooltip/renderTooltip.d.ts +2 -2
- package/build/plugins/yagr/renderer/tooltip/renderTooltip.js +23 -2
- package/build/plugins/yagr/renderer/utils.js +1 -1
- package/build/plugins/yagr/types.d.ts +12 -2
- package/build/types/widget-data/area.d.ts +15 -0
- package/build/types/widget-data/bar-x.d.ts +2 -0
- package/build/types/widget-data/bar-y.d.ts +2 -0
- package/build/types/widget-data/base.d.ts +2 -0
- package/build/types/widget-data/chart.d.ts +6 -0
- package/build/types/widget-data/line.d.ts +9 -0
- package/build/types/widget-data/pie.d.ts +2 -0
- package/build/types/widget-data/scatter.d.ts +3 -0
- package/package.json +4 -3
|
@@ -13,6 +13,7 @@ import { Tooltip, TooltipTriggerArea } from './Tooltip';
|
|
|
13
13
|
import './styles.css';
|
|
14
14
|
const b = block('d3');
|
|
15
15
|
export const Chart = (props) => {
|
|
16
|
+
var _a, _b;
|
|
16
17
|
const { width, height, data } = props;
|
|
17
18
|
const svgRef = React.useRef(null);
|
|
18
19
|
const dispatcher = React.useMemo(() => {
|
|
@@ -60,6 +61,15 @@ export const Chart = (props) => {
|
|
|
60
61
|
yScale,
|
|
61
62
|
svgContainer: svgRef.current,
|
|
62
63
|
});
|
|
64
|
+
const clickHandler = (_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click;
|
|
65
|
+
React.useEffect(() => {
|
|
66
|
+
if (clickHandler) {
|
|
67
|
+
dispatcher.on('click-chart', clickHandler);
|
|
68
|
+
}
|
|
69
|
+
return () => {
|
|
70
|
+
dispatcher.on('click-chart', null);
|
|
71
|
+
};
|
|
72
|
+
}, [dispatcher, clickHandler]);
|
|
63
73
|
const boundsOffsetTop = chart.margin.top;
|
|
64
74
|
const boundsOffsetLeft = chart.margin.left + getWidthOccupiedByYAxis({ preparedAxis: yAxis });
|
|
65
75
|
return (React.createElement(React.Fragment, null,
|
|
@@ -101,7 +101,7 @@ export const TooltipTriggerArea = (args) => {
|
|
|
101
101
|
});
|
|
102
102
|
return sort(result, (item) => item.y);
|
|
103
103
|
}, [shapesData]);
|
|
104
|
-
const
|
|
104
|
+
const getShapeData = (point) => {
|
|
105
105
|
var _a, _b;
|
|
106
106
|
const { left: ownLeft, top: ownTop } = ((_a = rectRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect()) || {
|
|
107
107
|
left: 0,
|
|
@@ -111,9 +111,9 @@ export const TooltipTriggerArea = (args) => {
|
|
|
111
111
|
left: 0,
|
|
112
112
|
top: 0,
|
|
113
113
|
};
|
|
114
|
-
const [pointerX, pointerY] = pointer(e, svgContainer);
|
|
115
|
-
const
|
|
116
|
-
|
|
114
|
+
const [pointerX, pointerY] = point; //pointer(e, svgContainer);
|
|
115
|
+
const result = [];
|
|
116
|
+
result === null || result === void 0 ? void 0 : result.push(...getBarXShapeData({
|
|
117
117
|
shapesData,
|
|
118
118
|
point: [pointerX, pointerY],
|
|
119
119
|
left: ownLeft - containerLeft,
|
|
@@ -127,6 +127,11 @@ export const TooltipTriggerArea = (args) => {
|
|
|
127
127
|
data: barYData,
|
|
128
128
|
point: [pointerX - (ownLeft - containerLeft), pointerY - (ownTop - containerTop)],
|
|
129
129
|
}));
|
|
130
|
+
return result;
|
|
131
|
+
};
|
|
132
|
+
const handleMouseMove = (e) => {
|
|
133
|
+
const [pointerX, pointerY] = pointer(e, svgContainer);
|
|
134
|
+
const hoverShapeData = getShapeData([pointerX, pointerY]);
|
|
130
135
|
if (hoverShapeData.length) {
|
|
131
136
|
const position = [pointerX, pointerY];
|
|
132
137
|
dispatcher.call('hover-shape', e.target, hoverShapeData, position);
|
|
@@ -137,5 +142,12 @@ export const TooltipTriggerArea = (args) => {
|
|
|
137
142
|
throttledHandleMouseMove.cancel();
|
|
138
143
|
dispatcher.call('hover-shape', {}, undefined);
|
|
139
144
|
};
|
|
140
|
-
|
|
145
|
+
const handleClick = (e) => {
|
|
146
|
+
const [pointerX, pointerY] = pointer(e, svgContainer);
|
|
147
|
+
const shapeData = getShapeData([pointerX, pointerY]);
|
|
148
|
+
if (shapeData.length) {
|
|
149
|
+
dispatcher.call('click-chart', undefined, { point: get(shapeData, '[0].data'), series: get(shapeData, '[0].series') }, e);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
return (React.createElement("rect", { ref: rectRef, width: boundsWidth, height: boundsHeight, fill: "transparent", onMouseMove: throttledHandleMouseMove, onMouseLeave: handleMouseLeave, onClick: handleClick }));
|
|
141
153
|
};
|
|
@@ -30,6 +30,7 @@ export function prepareBarXSeries(args) {
|
|
|
30
30
|
allowOverlap: ((_e = series.dataLabels) === null || _e === void 0 ? void 0 : _e.allowOverlap) || false,
|
|
31
31
|
padding: get(series, 'dataLabels.padding', DEFAULT_DATALABELS_PADDING),
|
|
32
32
|
},
|
|
33
|
+
cursor: get(series, 'cursor', null),
|
|
33
34
|
};
|
|
34
35
|
}, []);
|
|
35
36
|
}
|
|
@@ -72,6 +72,8 @@ export function prepareLineSeries(args) {
|
|
|
72
72
|
marker: prepareMarker(series, seriesOptions),
|
|
73
73
|
dashStyle: dashStyle,
|
|
74
74
|
linecap: prepareLinecap(dashStyle, series, seriesOptions),
|
|
75
|
+
opacity: get(series, 'opacity', null),
|
|
76
|
+
cursor: get(series, 'cursor', null),
|
|
75
77
|
};
|
|
76
78
|
return prepared;
|
|
77
79
|
}, []);
|
|
@@ -10,7 +10,7 @@ export function prepareTreemap(args) {
|
|
|
10
10
|
const id = getRandomCKId();
|
|
11
11
|
const name = s.name || '';
|
|
12
12
|
const color = s.color || colorScale(name);
|
|
13
|
-
|
|
13
|
+
const preparedSeries = {
|
|
14
14
|
color,
|
|
15
15
|
data: s.data,
|
|
16
16
|
dataLabels: {
|
|
@@ -29,6 +29,8 @@ export function prepareTreemap(args) {
|
|
|
29
29
|
},
|
|
30
30
|
levels: s.levels,
|
|
31
31
|
layoutAlgorithm: get(s, 'layoutAlgorithm', LayoutAlgorithm.Binary),
|
|
32
|
+
cursor: get(s, 'cursor', null),
|
|
32
33
|
};
|
|
34
|
+
return preparedSeries;
|
|
33
35
|
});
|
|
34
36
|
}
|
|
@@ -53,6 +53,7 @@ type BasePreparedSeries = {
|
|
|
53
53
|
enabled: boolean;
|
|
54
54
|
symbol: PreparedLegendSymbol;
|
|
55
55
|
};
|
|
56
|
+
cursor: string | null;
|
|
56
57
|
};
|
|
57
58
|
export type PreparedScatterSeries = {
|
|
58
59
|
type: ScatterSeries['type'];
|
|
@@ -130,6 +131,7 @@ export type PreparedPieSeries = {
|
|
|
130
131
|
};
|
|
131
132
|
};
|
|
132
133
|
renderCustomShape?: PieSeries['renderCustomShape'];
|
|
134
|
+
opacity: number | null;
|
|
133
135
|
} & BasePreparedSeries;
|
|
134
136
|
export type PreparedLineSeries = {
|
|
135
137
|
type: LineSeries['type'];
|
|
@@ -161,6 +163,7 @@ export type PreparedLineSeries = {
|
|
|
161
163
|
};
|
|
162
164
|
dashStyle: DashStyle;
|
|
163
165
|
linecap: LineCap;
|
|
166
|
+
opacity: number | null;
|
|
164
167
|
} & BasePreparedSeries;
|
|
165
168
|
export type PreparedAreaSeries = {
|
|
166
169
|
type: AreaSeries['type'];
|
|
@@ -204,7 +207,7 @@ export type PreparedTreemapSeries = {
|
|
|
204
207
|
allowOverlap: boolean;
|
|
205
208
|
};
|
|
206
209
|
layoutAlgorithm: `${LayoutAlgorithm}`;
|
|
207
|
-
} & BasePreparedSeries & TreemapSeries
|
|
210
|
+
} & BasePreparedSeries & Omit<TreemapSeries, keyof BasePreparedSeries>;
|
|
208
211
|
export type PreparedSeries = PreparedScatterSeries | PreparedBarXSeries | PreparedBarYSeries | PreparedPieSeries | PreparedLineSeries | PreparedAreaSeries | PreparedTreemapSeries;
|
|
209
212
|
export type PreparedSeriesOptions = SeriesOptionsDefaults;
|
|
210
213
|
export type StackedSeries = BarXSeries | AreaSeries | BarYSeries;
|
|
@@ -25,7 +25,8 @@ export const AreaSeriesShapes = (args) => {
|
|
|
25
25
|
.selectAll('shape')
|
|
26
26
|
.data(preparedData)
|
|
27
27
|
.join('g')
|
|
28
|
-
.attr('class', b('series'))
|
|
28
|
+
.attr('class', b('series'))
|
|
29
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
29
30
|
shapeSelection
|
|
30
31
|
.append('path')
|
|
31
32
|
.attr('class', b('line'))
|
|
@@ -27,7 +27,9 @@ export const BarXSeriesShapes = (args) => {
|
|
|
27
27
|
.attr('y', (d) => d.y)
|
|
28
28
|
.attr('height', (d) => d.height)
|
|
29
29
|
.attr('width', (d) => d.width)
|
|
30
|
-
.attr('fill', (d) => d.data.color || d.series.color)
|
|
30
|
+
.attr('fill', (d) => d.data.color || d.series.color)
|
|
31
|
+
.attr('opacity', (d) => d.opacity)
|
|
32
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
31
33
|
let dataLabels = preparedData.map((d) => d.label).filter(Boolean);
|
|
32
34
|
if (!((_a = preparedData[0]) === null || _a === void 0 ? void 0 : _a.series.dataLabels.allowOverlap)) {
|
|
33
35
|
dataLabels = filterOverlappingLabels(dataLabels);
|
|
@@ -23,7 +23,9 @@ export const BarYSeriesShapes = (args) => {
|
|
|
23
23
|
.attr('y', (d) => d.y)
|
|
24
24
|
.attr('height', (d) => d.height)
|
|
25
25
|
.attr('width', (d) => d.width)
|
|
26
|
-
.attr('fill', (d) => d.color)
|
|
26
|
+
.attr('fill', (d) => d.color)
|
|
27
|
+
.attr('opacity', (d) => d.data.opacity || null)
|
|
28
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
27
29
|
const dataLabels = preparedData.filter((d) => d.series.dataLabels.enabled);
|
|
28
30
|
const labelSelection = svgElement
|
|
29
31
|
.selectAll('text')
|
|
@@ -31,7 +31,9 @@ export const LineSeriesShapes = (args) => {
|
|
|
31
31
|
.attr('stroke-width', (d) => d.width)
|
|
32
32
|
.attr('stroke-linejoin', (d) => d.linecap)
|
|
33
33
|
.attr('stroke-linecap', (d) => d.linecap)
|
|
34
|
-
.attr('stroke-dasharray', (d) => getLineDashArray(d.dashStyle, d.width))
|
|
34
|
+
.attr('stroke-dasharray', (d) => getLineDashArray(d.dashStyle, d.width))
|
|
35
|
+
.attr('opacity', (d) => d.opacity)
|
|
36
|
+
.attr('cursor', (d) => d.series.cursor);
|
|
35
37
|
let dataLabels = preparedData.reduce((acc, d) => {
|
|
36
38
|
return acc.concat(d.labels);
|
|
37
39
|
}, []);
|
|
@@ -36,7 +36,14 @@ export function renderMarker(selection) {
|
|
|
36
36
|
}
|
|
37
37
|
export function getMarkerVisibility(d) {
|
|
38
38
|
const markerStates = d.point.series.marker.states;
|
|
39
|
-
|
|
39
|
+
let enabled;
|
|
40
|
+
if (d.hovered) {
|
|
41
|
+
enabled = markerStates.hover.enabled && d.hovered;
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
enabled =
|
|
45
|
+
markerStates.normal.enabled || get(d.point.data, 'marker.states.normal.enabled', false);
|
|
46
|
+
}
|
|
40
47
|
return enabled ? '' : 'hidden';
|
|
41
48
|
}
|
|
42
49
|
export function getMarkerHaloVisibility(d) {
|
|
@@ -32,7 +32,8 @@ export function PieSeriesShapes(args) {
|
|
|
32
32
|
return `translate(${x}, ${y})`;
|
|
33
33
|
})
|
|
34
34
|
.style('stroke', (pieData) => pieData.borderColor)
|
|
35
|
-
.style('stroke-width', (pieData) => pieData.borderWidth)
|
|
35
|
+
.style('stroke-width', (pieData) => pieData.borderWidth)
|
|
36
|
+
.attr('cursor', (pieData) => pieData.series.cursor);
|
|
36
37
|
// Render halo appearing outside the hovered slice
|
|
37
38
|
shapesSelection
|
|
38
39
|
.selectAll('halo')
|
|
@@ -68,7 +69,8 @@ export function PieSeriesShapes(args) {
|
|
|
68
69
|
return arcGenerator(d);
|
|
69
70
|
})
|
|
70
71
|
.attr('class', b('segment'))
|
|
71
|
-
.attr('fill', (d) => d.data.color)
|
|
72
|
+
.attr('fill', (d) => d.data.color)
|
|
73
|
+
.attr('opacity', (d) => d.data.opacity);
|
|
72
74
|
shapesSelection
|
|
73
75
|
.selectAll('text')
|
|
74
76
|
.data((pieData) => pieData.labels)
|
|
@@ -114,17 +116,20 @@ export function PieSeriesShapes(args) {
|
|
|
114
116
|
nodes[index].append(customShape);
|
|
115
117
|
}
|
|
116
118
|
});
|
|
119
|
+
const getSelectedSegment = (element) => {
|
|
120
|
+
const datum = select(element).datum();
|
|
121
|
+
const seriesId = get(datum, 'data.series.id', get(datum, 'series.id'));
|
|
122
|
+
return preparedData.reduce((result, pie) => {
|
|
123
|
+
var _a;
|
|
124
|
+
return result || ((_a = pie.segments.find((s) => s.data.series.id === seriesId)) === null || _a === void 0 ? void 0 : _a.data);
|
|
125
|
+
}, undefined);
|
|
126
|
+
};
|
|
117
127
|
const eventName = `hover-shape.pie`;
|
|
118
128
|
const hoverOptions = get(seriesOptions, 'pie.states.hover');
|
|
119
129
|
const inactiveOptions = get(seriesOptions, 'pie.states.inactive');
|
|
120
130
|
svgElement
|
|
121
131
|
.on('mousemove', (e) => {
|
|
122
|
-
const
|
|
123
|
-
const seriesId = get(datum, 'data.series.id', get(datum, 'series.id'));
|
|
124
|
-
const currentSegment = preparedData.reduce((result, pie) => {
|
|
125
|
-
var _a;
|
|
126
|
-
return (result || ((_a = pie.segments.find((s) => s.data.series.id === seriesId)) === null || _a === void 0 ? void 0 : _a.data));
|
|
127
|
-
}, undefined);
|
|
132
|
+
const currentSegment = getSelectedSegment(e.target);
|
|
128
133
|
if (currentSegment) {
|
|
129
134
|
const data = {
|
|
130
135
|
series: {
|
|
@@ -132,13 +137,19 @@ export function PieSeriesShapes(args) {
|
|
|
132
137
|
type: 'pie',
|
|
133
138
|
name: currentSegment.series.name,
|
|
134
139
|
},
|
|
135
|
-
data: currentSegment.series,
|
|
140
|
+
data: currentSegment.series.data,
|
|
136
141
|
};
|
|
137
142
|
dispatcher.call('hover-shape', {}, [data], pointer(e, svgContainer));
|
|
138
143
|
}
|
|
139
144
|
})
|
|
140
145
|
.on('mouseleave', () => {
|
|
141
146
|
dispatcher.call('hover-shape', {}, undefined);
|
|
147
|
+
})
|
|
148
|
+
.on('click', (e) => {
|
|
149
|
+
const selectedSegment = getSelectedSegment(e.target);
|
|
150
|
+
if (selectedSegment) {
|
|
151
|
+
dispatcher.call('click-chart', undefined, { point: selectedSegment.series.data, series: selectedSegment.series }, e);
|
|
152
|
+
}
|
|
142
153
|
});
|
|
143
154
|
dispatcher.on(eventName, (data) => {
|
|
144
155
|
const selectedSeriesId = data === null || data === void 0 ? void 0 : data[0].series.id;
|
|
@@ -22,10 +22,15 @@ export function ScatterSeriesShape(props) {
|
|
|
22
22
|
.data(preparedData, shapeKey)
|
|
23
23
|
.join('g')
|
|
24
24
|
.call(renderMarker)
|
|
25
|
-
.attr('fill', (d) => d.point.data.color || d.point.series.color || '')
|
|
25
|
+
.attr('fill', (d) => d.point.data.color || d.point.series.color || '')
|
|
26
|
+
.attr('opacity', (d) => d.point.opacity)
|
|
27
|
+
.attr('cursor', (d) => d.point.series.cursor);
|
|
28
|
+
const getSelectedPoint = (element) => {
|
|
29
|
+
return select(element).datum();
|
|
30
|
+
};
|
|
26
31
|
svgElement
|
|
27
32
|
.on('mousemove', (e) => {
|
|
28
|
-
const datum =
|
|
33
|
+
const datum = getSelectedPoint(e.target);
|
|
29
34
|
if (!datum) {
|
|
30
35
|
return;
|
|
31
36
|
}
|
|
@@ -42,6 +47,12 @@ export function ScatterSeriesShape(props) {
|
|
|
42
47
|
})
|
|
43
48
|
.on('mouseleave', () => {
|
|
44
49
|
dispatcher.call('hover-shape', {}, undefined);
|
|
50
|
+
})
|
|
51
|
+
.on('click', (e) => {
|
|
52
|
+
const datum = getSelectedPoint(e.target);
|
|
53
|
+
if (datum) {
|
|
54
|
+
dispatcher.call('click-chart', undefined, { point: datum.point.data, series: datum.point.series }, e);
|
|
55
|
+
}
|
|
45
56
|
});
|
|
46
57
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
47
58
|
const inactiveEnabled = inactiveOptions === null || inactiveOptions === void 0 ? void 0 : inactiveOptions.enabled;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
1
2
|
import { getXValue, getYValue } from '../utils';
|
|
2
3
|
const getFilteredLinearScatterData = (data) => {
|
|
3
4
|
return data.filter((d) => typeof d.x === 'number' && typeof d.y === 'number');
|
|
@@ -15,6 +16,7 @@ export const prepareScatterData = (args) => {
|
|
|
15
16
|
series: s,
|
|
16
17
|
x: getXValue({ point: d, xAxis, xScale }),
|
|
17
18
|
y: getYValue({ point: d, yAxis, yScale }),
|
|
19
|
+
opacity: get(d, 'opacity', null),
|
|
18
20
|
},
|
|
19
21
|
hovered: false,
|
|
20
22
|
active: true,
|
|
@@ -18,7 +18,8 @@ export const TreemapSeriesShape = (props) => {
|
|
|
18
18
|
.selectAll('g')
|
|
19
19
|
.data(leaves)
|
|
20
20
|
.join('g')
|
|
21
|
-
.attr('transform', (d) => `translate(${d.x0},${d.y0})`)
|
|
21
|
+
.attr('transform', (d) => `translate(${d.x0},${d.y0})`)
|
|
22
|
+
.attr('cursor', series.cursor);
|
|
22
23
|
const rectSelection = leaf
|
|
23
24
|
.append('rect')
|
|
24
25
|
.attr('id', (d) => d.id || d.name)
|
|
@@ -44,17 +45,24 @@ export const TreemapSeriesShape = (props) => {
|
|
|
44
45
|
.style('font-weight', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontWeight) || null; })
|
|
45
46
|
.style('fill', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontColor) || null; })
|
|
46
47
|
.call(setEllipsisForOverflowTexts, (d) => d.width);
|
|
47
|
-
const
|
|
48
|
+
const getSelectedPart = (node) => {
|
|
49
|
+
const hoveredRect = select(node);
|
|
50
|
+
return hoveredRect.datum();
|
|
51
|
+
};
|
|
52
|
+
const eventName = `hover-shape.treemap`;
|
|
48
53
|
const hoverOptions = get(seriesOptions, 'treemap.states.hover');
|
|
49
54
|
const inactiveOptions = get(seriesOptions, 'treemap.states.inactive');
|
|
50
55
|
svgElement
|
|
51
56
|
.on('mousemove', (e) => {
|
|
52
|
-
const
|
|
53
|
-
const datum = hoveredRect.datum();
|
|
57
|
+
const datum = getSelectedPart(e.target);
|
|
54
58
|
dispatcher.call('hover-shape', {}, [{ data: datum.data, series }], pointer(e, svgContainer));
|
|
55
59
|
})
|
|
56
60
|
.on('mouseleave', () => {
|
|
57
61
|
dispatcher.call('hover-shape', {}, undefined);
|
|
62
|
+
})
|
|
63
|
+
.on('click', (e) => {
|
|
64
|
+
const datum = getSelectedPart(e.target);
|
|
65
|
+
dispatcher.call('click-chart', undefined, { point: datum.data, series }, e);
|
|
58
66
|
});
|
|
59
67
|
dispatcher.on(eventName, (data) => {
|
|
60
68
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
@@ -110,8 +110,10 @@ export const withSplitPane = (ComposedComponent) => {
|
|
|
110
110
|
}
|
|
111
111
|
};
|
|
112
112
|
this.afterCreateCallback = (chart) => {
|
|
113
|
+
var _a, _b;
|
|
113
114
|
chart.tooltip.splitTooltip = true;
|
|
114
115
|
chart.tooltip.getTooltipContainer = this.getTooltipContainer;
|
|
116
|
+
(_b = (_a = this.props).callback) === null || _b === void 0 ? void 0 : _b.call(_a, chart);
|
|
115
117
|
};
|
|
116
118
|
this.setInitialPaneSize = (callback) => {
|
|
117
119
|
if (!this.tooltipContainerRef.current || !this.rootRef.current) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import type { TooltipRenderOptions } from '../../types';
|
|
2
|
-
export declare const getRenderTooltip: (
|
|
1
|
+
import type { TooltipRenderOptions, YagrWidgetData } from '../../types';
|
|
2
|
+
export declare const getRenderTooltip: (userData: YagrWidgetData['data']) => (data: TooltipRenderOptions) => string;
|
|
@@ -7,12 +7,33 @@ const calcOption = (d) => {
|
|
|
7
7
|
})
|
|
8
8
|
: d;
|
|
9
9
|
};
|
|
10
|
+
const getSeriesColorProperty = (args) => {
|
|
11
|
+
var _a;
|
|
12
|
+
const { data, userData, row, rowIndex } = args;
|
|
13
|
+
const userSeries = userData.graphs[rowIndex];
|
|
14
|
+
const lineColor = (_a = data.yagr.getSeriesById(row.id)) === null || _a === void 0 ? void 0 : _a.lineColor;
|
|
15
|
+
let seriesColor = row.color;
|
|
16
|
+
switch (userSeries === null || userSeries === void 0 ? void 0 : userSeries.legendColorKey) {
|
|
17
|
+
case 'lineColor': {
|
|
18
|
+
if (lineColor) {
|
|
19
|
+
seriesColor = lineColor;
|
|
20
|
+
}
|
|
21
|
+
break;
|
|
22
|
+
}
|
|
23
|
+
case 'color':
|
|
24
|
+
default: {
|
|
25
|
+
seriesColor = row.color;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return seriesColor;
|
|
29
|
+
};
|
|
10
30
|
/*
|
|
11
31
|
* Default tooltip renderer.
|
|
12
32
|
* Adapter between native Yagr tooltip config and ChartKit
|
|
13
33
|
* tooltip renderer.
|
|
14
34
|
*/
|
|
15
|
-
export const getRenderTooltip = (
|
|
35
|
+
export const getRenderTooltip = (userData) => (data) => {
|
|
36
|
+
const { timeZone } = userData;
|
|
16
37
|
const cfg = data.yagr.config;
|
|
17
38
|
const timeMultiplier = cfg.chart.timeMultiplier || 1;
|
|
18
39
|
const opts = data.options;
|
|
@@ -41,7 +62,7 @@ export const getRenderTooltip = (timeZone) => (data) => {
|
|
|
41
62
|
activeRowAlwaysFirstInTooltip: rows.length > 1,
|
|
42
63
|
tooltipHeader: dateTime({ input: x / timeMultiplier, timeZone }).format('DD MMMM YYYY HH:mm:ss'),
|
|
43
64
|
shared: true,
|
|
44
|
-
lines: rows.map((row, i) => (Object.assign(Object.assign({}, row), { seriesName: row.name || 'Serie ' + (i + 1), seriesColor: row
|
|
65
|
+
lines: rows.map((row, i) => (Object.assign(Object.assign({}, row), { seriesName: row.name || 'Serie ' + (i + 1), seriesColor: getSeriesColorProperty({ data, userData, row, rowIndex: i }), selectedSeries: row.active, seriesIdx: row.seriesIdx, percentValue: typeof row.transformed === 'number' ? row.transformed.toFixed(1) : '' }))),
|
|
45
66
|
withPercent: calcOption(opts.percent),
|
|
46
67
|
hiddenRowsNumber: hiddenRowsNumber,
|
|
47
68
|
hiddenRowsSum,
|
|
@@ -111,7 +111,7 @@ export const shapeYagrConfig = (args) => {
|
|
|
111
111
|
config.chart = chart;
|
|
112
112
|
if ((_a = config.tooltip) === null || _a === void 0 ? void 0 : _a.show) {
|
|
113
113
|
config.tooltip = config.tooltip || {};
|
|
114
|
-
config.tooltip.render = ((_b = config.tooltip) === null || _b === void 0 ? void 0 : _b.render) || getRenderTooltip(
|
|
114
|
+
config.tooltip.render = ((_b = config.tooltip) === null || _b === void 0 ? void 0 : _b.render) || getRenderTooltip(data);
|
|
115
115
|
if (!config.tooltip.className) {
|
|
116
116
|
// "className" property prevent default yagr styles adding
|
|
117
117
|
config.tooltip.className = 'chartkit-yagr-tooltip';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { MinimalValidConfig, RawSerieData, YagrConfig } from '@gravity-ui/yagr';
|
|
1
|
+
import type { MinimalValidConfig, RawSerieData, SeriesOptions, YagrConfig } from '@gravity-ui/yagr';
|
|
2
2
|
import type Yagr from '@gravity-ui/yagr';
|
|
3
3
|
import { ChartKitProps } from 'src/types';
|
|
4
4
|
export type { default as Yagr } from '@gravity-ui/yagr';
|
|
@@ -10,9 +10,19 @@ export interface CustomTooltipProps {
|
|
|
10
10
|
export type YagrWidgetProps = ChartKitProps<'yagr'> & {
|
|
11
11
|
id: string;
|
|
12
12
|
};
|
|
13
|
+
export type YagrSeriesData<T = Omit<SeriesOptions, 'type'>> = RawSerieData<T> & {
|
|
14
|
+
/**
|
|
15
|
+
* Determines what data value should be used to get a color for tooltip series. Does not work in case of using custom tooltip rendered via `tooltip` property.
|
|
16
|
+
* - `lineColor` indicates that lineColor property should be used
|
|
17
|
+
* - `color` indicates that color property should be used
|
|
18
|
+
*
|
|
19
|
+
* @default 'color'
|
|
20
|
+
*/
|
|
21
|
+
legendColorKey?: 'color' | 'lineColor';
|
|
22
|
+
};
|
|
13
23
|
export type YagrWidgetData = {
|
|
14
24
|
data: {
|
|
15
|
-
graphs:
|
|
25
|
+
graphs: YagrSeriesData[];
|
|
16
26
|
timeline: number[];
|
|
17
27
|
/**
|
|
18
28
|
* Allow to setup timezone for X axis and tooltip's header.
|
|
@@ -19,6 +19,21 @@ export type AreaSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
19
19
|
y?: string | number;
|
|
20
20
|
/** Data label value of the point. If not specified, the y value is used. */
|
|
21
21
|
label?: string | number;
|
|
22
|
+
/** Individual marker options for the point. */
|
|
23
|
+
marker?: {
|
|
24
|
+
/** States for a single point marker. */
|
|
25
|
+
states?: {
|
|
26
|
+
/** The normal state of a single point marker. */
|
|
27
|
+
normal?: {
|
|
28
|
+
/**
|
|
29
|
+
* Enable or disable the point marker.
|
|
30
|
+
*
|
|
31
|
+
* @default false
|
|
32
|
+
* */
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
};
|
|
22
37
|
};
|
|
23
38
|
export type AreaMarkerSymbol = 'circle' | 'square';
|
|
24
39
|
export type AreaMarkerOptions = PointMarkerOptions & {
|
|
@@ -25,6 +25,8 @@ export type BarXSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
25
25
|
category?: string;
|
|
26
26
|
/** Data label value of the bar-x column. If not specified, the y value is used. */
|
|
27
27
|
label?: string | number;
|
|
28
|
+
/** Individual opacity for the bar-x column. */
|
|
29
|
+
opacity?: number;
|
|
28
30
|
};
|
|
29
31
|
export type BarXSeries<T = any> = BaseSeries & {
|
|
30
32
|
type: typeof SeriesType.BarX;
|
|
@@ -19,6 +19,8 @@ export type BarYSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
19
19
|
y?: string | number;
|
|
20
20
|
/** Data label value of the bar. If not specified, the x value is used. */
|
|
21
21
|
label?: string | number;
|
|
22
|
+
/** Individual opacity for the bar. */
|
|
23
|
+
opacity?: number;
|
|
22
24
|
};
|
|
23
25
|
export type BarYSeries<T = any> = BaseSeries & {
|
|
24
26
|
type: typeof SeriesType.BarY;
|
|
@@ -22,6 +22,8 @@ export type BaseSeries = {
|
|
|
22
22
|
* */
|
|
23
23
|
allowOverlap?: boolean;
|
|
24
24
|
};
|
|
25
|
+
/** You can set the cursor to "pointer" if you have click events attached to the series, to signal to the user that the points and lines can be clicked. */
|
|
26
|
+
cursor?: string;
|
|
25
27
|
};
|
|
26
28
|
export type BaseSeriesData<T = any> = {
|
|
27
29
|
/**
|
|
@@ -19,6 +19,13 @@ export type LineSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
19
19
|
y?: string | number;
|
|
20
20
|
/** Data label value of the point. If not specified, the y value is used. */
|
|
21
21
|
label?: string | number;
|
|
22
|
+
marker?: {
|
|
23
|
+
states?: {
|
|
24
|
+
normal?: {
|
|
25
|
+
enabled: boolean;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
};
|
|
22
29
|
};
|
|
23
30
|
export type LineSeries<T = any> = BaseSeries & {
|
|
24
31
|
type: typeof SeriesType.Line;
|
|
@@ -42,4 +49,6 @@ export type LineSeries<T = any> = BaseSeries & {
|
|
|
42
49
|
dashStyle?: `${DashStyle}`;
|
|
43
50
|
/** Option for line cap style */
|
|
44
51
|
linecap?: `${LineCap}`;
|
|
52
|
+
/** Individual opacity for the line. */
|
|
53
|
+
opacity?: number;
|
|
45
54
|
};
|
|
@@ -11,6 +11,8 @@ export type PieSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
11
11
|
visible?: boolean;
|
|
12
12
|
/** Initial data label of the pie segment. If not specified, the value is used. */
|
|
13
13
|
label?: string;
|
|
14
|
+
/** Individual opacity for the pie segment. */
|
|
15
|
+
opacity?: number;
|
|
14
16
|
};
|
|
15
17
|
export type ConnectorShape = 'straight-line' | 'polyline';
|
|
16
18
|
export type ConnectorCurve = 'linear' | 'basic';
|
|
@@ -22,7 +22,10 @@ export type ScatterSeriesData<T = any> = BaseSeriesData<T> & {
|
|
|
22
22
|
* @deprecated use `x` or `y` instead
|
|
23
23
|
*/
|
|
24
24
|
category?: string;
|
|
25
|
+
/** Individual radius for the point. */
|
|
25
26
|
radius?: number;
|
|
27
|
+
/** Individual opacity for the point. */
|
|
28
|
+
opacity?: number;
|
|
26
29
|
};
|
|
27
30
|
export type ScatterSeries<T = any> = BaseSeries & {
|
|
28
31
|
type: typeof SeriesType.Scatter;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/chartkit",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "React component used to render charts based on any sources you need",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": "git@github.com:gravity-ui/ChartKit.git",
|
|
@@ -48,18 +48,19 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@bem-react/classname": "^1.6.0",
|
|
50
50
|
"@gravity-ui/date-utils": "^2.1.0",
|
|
51
|
+
"@gravity-ui/i18n": "^1.0.0",
|
|
51
52
|
"@gravity-ui/yagr": "^4.2.3",
|
|
52
53
|
"afterframe": "^1.0.2",
|
|
53
54
|
"d3": "^7.8.5",
|
|
54
55
|
"lodash": "^4.17.21",
|
|
55
|
-
"react-split-pane": "^0.1.92"
|
|
56
|
+
"react-split-pane": "^0.1.92",
|
|
57
|
+
"tslib": "^2.6.2"
|
|
56
58
|
},
|
|
57
59
|
"devDependencies": {
|
|
58
60
|
"@babel/preset-env": "^7.22.6",
|
|
59
61
|
"@babel/preset-react": "^7.22.5",
|
|
60
62
|
"@babel/preset-typescript": "^7.22.5",
|
|
61
63
|
"@gravity-ui/eslint-config": "^3.1.1",
|
|
62
|
-
"@gravity-ui/i18n": "^1.0.0",
|
|
63
64
|
"@gravity-ui/prettier-config": "^1.1.0",
|
|
64
65
|
"@gravity-ui/stylelint-config": "^4.0.1",
|
|
65
66
|
"@gravity-ui/tsconfig": "^1.0.0",
|