@gravity-ui/chartkit 5.0.0 → 5.1.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 +9 -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-line.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-pie.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.js +2 -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 +2 -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 +2 -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 +18 -8
- 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 +12 -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 +10 -3
- 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/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 +1 -1
|
@@ -60,6 +60,15 @@ export const Chart = (props) => {
|
|
|
60
60
|
yScale,
|
|
61
61
|
svgContainer: svgRef.current,
|
|
62
62
|
});
|
|
63
|
+
React.useEffect(() => {
|
|
64
|
+
var _a, _b, _c, _d;
|
|
65
|
+
if ((_b = (_a = data.chart) === null || _a === void 0 ? void 0 : _a.events) === null || _b === void 0 ? void 0 : _b.click) {
|
|
66
|
+
dispatcher.on('click-chart', (_d = (_c = data.chart) === null || _c === void 0 ? void 0 : _c.events) === null || _d === void 0 ? void 0 : _d.click);
|
|
67
|
+
}
|
|
68
|
+
return () => {
|
|
69
|
+
dispatcher.on('click-chart', null);
|
|
70
|
+
};
|
|
71
|
+
}, [dispatcher]);
|
|
63
72
|
const boundsOffsetTop = chart.margin.top;
|
|
64
73
|
const boundsOffsetLeft = chart.margin.left + getWidthOccupiedByYAxis({ preparedAxis: yAxis });
|
|
65
74
|
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
|
};
|
|
@@ -130,6 +130,7 @@ export type PreparedPieSeries = {
|
|
|
130
130
|
};
|
|
131
131
|
};
|
|
132
132
|
renderCustomShape?: PieSeries['renderCustomShape'];
|
|
133
|
+
opacity: number | null;
|
|
133
134
|
} & BasePreparedSeries;
|
|
134
135
|
export type PreparedLineSeries = {
|
|
135
136
|
type: LineSeries['type'];
|
|
@@ -161,6 +162,7 @@ export type PreparedLineSeries = {
|
|
|
161
162
|
};
|
|
162
163
|
dashStyle: DashStyle;
|
|
163
164
|
linecap: LineCap;
|
|
165
|
+
opacity: number | null;
|
|
164
166
|
} & BasePreparedSeries;
|
|
165
167
|
export type PreparedAreaSeries = {
|
|
166
168
|
type: AreaSeries['type'];
|
|
@@ -27,7 +27,8 @@ 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);
|
|
31
32
|
let dataLabels = preparedData.map((d) => d.label).filter(Boolean);
|
|
32
33
|
if (!((_a = preparedData[0]) === null || _a === void 0 ? void 0 : _a.series.dataLabels.allowOverlap)) {
|
|
33
34
|
dataLabels = filterOverlappingLabels(dataLabels);
|
|
@@ -23,7 +23,8 @@ 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);
|
|
27
28
|
const dataLabels = preparedData.filter((d) => d.series.dataLabels.enabled);
|
|
28
29
|
const labelSelection = svgElement
|
|
29
30
|
.selectAll('text')
|
|
@@ -31,7 +31,8 @@ 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);
|
|
35
36
|
let dataLabels = preparedData.reduce((acc, d) => {
|
|
36
37
|
return acc.concat(d.labels);
|
|
37
38
|
}, []);
|
|
@@ -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) {
|
|
@@ -68,7 +68,8 @@ export function PieSeriesShapes(args) {
|
|
|
68
68
|
return arcGenerator(d);
|
|
69
69
|
})
|
|
70
70
|
.attr('class', b('segment'))
|
|
71
|
-
.attr('fill', (d) => d.data.color)
|
|
71
|
+
.attr('fill', (d) => d.data.color)
|
|
72
|
+
.attr('opacity', (d) => d.data.opacity);
|
|
72
73
|
shapesSelection
|
|
73
74
|
.selectAll('text')
|
|
74
75
|
.data((pieData) => pieData.labels)
|
|
@@ -114,17 +115,20 @@ export function PieSeriesShapes(args) {
|
|
|
114
115
|
nodes[index].append(customShape);
|
|
115
116
|
}
|
|
116
117
|
});
|
|
118
|
+
const getSelectedSegment = (element) => {
|
|
119
|
+
const datum = select(element).datum();
|
|
120
|
+
const seriesId = get(datum, 'data.series.id', get(datum, 'series.id'));
|
|
121
|
+
return preparedData.reduce((result, pie) => {
|
|
122
|
+
var _a;
|
|
123
|
+
return result || ((_a = pie.segments.find((s) => s.data.series.id === seriesId)) === null || _a === void 0 ? void 0 : _a.data);
|
|
124
|
+
}, undefined);
|
|
125
|
+
};
|
|
117
126
|
const eventName = `hover-shape.pie`;
|
|
118
127
|
const hoverOptions = get(seriesOptions, 'pie.states.hover');
|
|
119
128
|
const inactiveOptions = get(seriesOptions, 'pie.states.inactive');
|
|
120
129
|
svgElement
|
|
121
130
|
.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);
|
|
131
|
+
const currentSegment = getSelectedSegment(e.target);
|
|
128
132
|
if (currentSegment) {
|
|
129
133
|
const data = {
|
|
130
134
|
series: {
|
|
@@ -132,13 +136,19 @@ export function PieSeriesShapes(args) {
|
|
|
132
136
|
type: 'pie',
|
|
133
137
|
name: currentSegment.series.name,
|
|
134
138
|
},
|
|
135
|
-
data: currentSegment.series,
|
|
139
|
+
data: currentSegment.series.data,
|
|
136
140
|
};
|
|
137
141
|
dispatcher.call('hover-shape', {}, [data], pointer(e, svgContainer));
|
|
138
142
|
}
|
|
139
143
|
})
|
|
140
144
|
.on('mouseleave', () => {
|
|
141
145
|
dispatcher.call('hover-shape', {}, undefined);
|
|
146
|
+
})
|
|
147
|
+
.on('click', (e) => {
|
|
148
|
+
const selectedSegment = getSelectedSegment(e.target);
|
|
149
|
+
if (selectedSegment) {
|
|
150
|
+
dispatcher.call('click-chart', undefined, { point: selectedSegment.series.data, series: selectedSegment.series }, e);
|
|
151
|
+
}
|
|
142
152
|
});
|
|
143
153
|
dispatcher.on(eventName, (data) => {
|
|
144
154
|
const selectedSeriesId = data === null || data === void 0 ? void 0 : data[0].series.id;
|
|
@@ -22,10 +22,14 @@ 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
|
+
const getSelectedPoint = (element) => {
|
|
28
|
+
return select(element).datum();
|
|
29
|
+
};
|
|
26
30
|
svgElement
|
|
27
31
|
.on('mousemove', (e) => {
|
|
28
|
-
const datum =
|
|
32
|
+
const datum = getSelectedPoint(e.target);
|
|
29
33
|
if (!datum) {
|
|
30
34
|
return;
|
|
31
35
|
}
|
|
@@ -42,6 +46,12 @@ export function ScatterSeriesShape(props) {
|
|
|
42
46
|
})
|
|
43
47
|
.on('mouseleave', () => {
|
|
44
48
|
dispatcher.call('hover-shape', {}, undefined);
|
|
49
|
+
})
|
|
50
|
+
.on('click', (e) => {
|
|
51
|
+
const datum = getSelectedPoint(e.target);
|
|
52
|
+
if (datum) {
|
|
53
|
+
dispatcher.call('click-chart', undefined, { point: datum.point.data, series: datum.point.series }, e);
|
|
54
|
+
}
|
|
45
55
|
});
|
|
46
56
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
47
57
|
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,
|
|
@@ -44,17 +44,24 @@ export const TreemapSeriesShape = (props) => {
|
|
|
44
44
|
.style('font-weight', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontWeight) || null; })
|
|
45
45
|
.style('fill', () => { var _a; return ((_a = series.dataLabels.style) === null || _a === void 0 ? void 0 : _a.fontColor) || null; })
|
|
46
46
|
.call(setEllipsisForOverflowTexts, (d) => d.width);
|
|
47
|
-
const
|
|
47
|
+
const getSelectedPart = (node) => {
|
|
48
|
+
const hoveredRect = select(node);
|
|
49
|
+
return hoveredRect.datum();
|
|
50
|
+
};
|
|
51
|
+
const eventName = `hover-shape.treemap`;
|
|
48
52
|
const hoverOptions = get(seriesOptions, 'treemap.states.hover');
|
|
49
53
|
const inactiveOptions = get(seriesOptions, 'treemap.states.inactive');
|
|
50
54
|
svgElement
|
|
51
55
|
.on('mousemove', (e) => {
|
|
52
|
-
const
|
|
53
|
-
const datum = hoveredRect.datum();
|
|
56
|
+
const datum = getSelectedPart(e.target);
|
|
54
57
|
dispatcher.call('hover-shape', {}, [{ data: datum.data, series }], pointer(e, svgContainer));
|
|
55
58
|
})
|
|
56
59
|
.on('mouseleave', () => {
|
|
57
60
|
dispatcher.call('hover-shape', {}, undefined);
|
|
61
|
+
})
|
|
62
|
+
.on('click', (e) => {
|
|
63
|
+
const datum = getSelectedPart(e.target);
|
|
64
|
+
dispatcher.call('click-chart', undefined, { point: datum.data, series }, e);
|
|
58
65
|
});
|
|
59
66
|
dispatcher.on(eventName, (data) => {
|
|
60
67
|
const hoverEnabled = hoverOptions === null || hoverOptions === void 0 ? void 0 : hoverOptions.enabled;
|
|
@@ -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;
|
|
@@ -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