@gravity-ui/chartkit 4.15.0 → 4.17.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 +7 -0
- package/build/constants/widget-data.js +8 -0
- package/build/plugins/d3/renderer/components/Legend.js +19 -1
- package/build/plugins/d3/renderer/components/styles.css +4 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepareSeries.js +7 -4
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +8 -3
- package/build/plugins/d3/renderer/hooks/useSeries/utils.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useSeries/utils.js +5 -6
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +16 -9
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +3 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +1 -0
- package/build/plugins/d3/renderer/utils/index.js +1 -0
- package/build/plugins/d3/renderer/utils/symbol.d.ts +5 -0
- package/build/plugins/d3/renderer/utils/symbol.js +36 -0
- package/build/types/widget-data/legend.d.ts +8 -0
- package/build/types/widget-data/scatter.d.ts +2 -2
- package/package.json +3 -2
|
@@ -19,6 +19,13 @@ export declare enum DashStyle {
|
|
|
19
19
|
ShortDot = "ShortDot",
|
|
20
20
|
Solid = "Solid"
|
|
21
21
|
}
|
|
22
|
+
export declare enum SymbolType {
|
|
23
|
+
Circle = "circle",
|
|
24
|
+
Diamond = "diamond",
|
|
25
|
+
Square = "square",
|
|
26
|
+
Triangle = "triangle",
|
|
27
|
+
TriangleDown = "triangle-down"
|
|
28
|
+
}
|
|
22
29
|
export declare enum LineCap {
|
|
23
30
|
Butt = "butt",
|
|
24
31
|
Round = "round",
|
|
@@ -20,6 +20,14 @@ export var DashStyle;
|
|
|
20
20
|
DashStyle["ShortDot"] = "ShortDot";
|
|
21
21
|
DashStyle["Solid"] = "Solid";
|
|
22
22
|
})(DashStyle || (DashStyle = {}));
|
|
23
|
+
export var SymbolType;
|
|
24
|
+
(function (SymbolType) {
|
|
25
|
+
SymbolType["Circle"] = "circle";
|
|
26
|
+
SymbolType["Diamond"] = "diamond";
|
|
27
|
+
SymbolType["Square"] = "square";
|
|
28
|
+
SymbolType["Triangle"] = "triangle";
|
|
29
|
+
SymbolType["TriangleDown"] = "triangle-down";
|
|
30
|
+
})(SymbolType || (SymbolType = {}));
|
|
23
31
|
export var LineCap;
|
|
24
32
|
(function (LineCap) {
|
|
25
33
|
LineCap["Butt"] = "butt";
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { select, line as lineGenerator } from 'd3';
|
|
2
|
+
import { symbol, select, line as lineGenerator } from 'd3';
|
|
3
|
+
import { getSymbol } from '../utils';
|
|
3
4
|
import { block } from '../../../../utils/cn';
|
|
4
5
|
import { getLineDashArray } from '../hooks/useShapes/utils';
|
|
5
6
|
const b = block('d3-legend');
|
|
@@ -109,6 +110,23 @@ function renderLegendSymbol(args) {
|
|
|
109
110
|
.style('fill', color);
|
|
110
111
|
break;
|
|
111
112
|
}
|
|
113
|
+
case 'symbol': {
|
|
114
|
+
const y = legend.lineHeight / 2;
|
|
115
|
+
element
|
|
116
|
+
.append('svg:path')
|
|
117
|
+
.attr('d', () => {
|
|
118
|
+
const scatterSymbol = getSymbol(d.symbol.symbolType);
|
|
119
|
+
// D3 takes size as square pixels, so we need to make square pixels size by multiplying
|
|
120
|
+
// https://d3js.org/d3-shape/symbol#symbol
|
|
121
|
+
return symbol(scatterSymbol, d.symbol.width * d.symbol.width)();
|
|
122
|
+
})
|
|
123
|
+
.attr('transform', () => {
|
|
124
|
+
return 'translate(' + x + ',' + y + ')';
|
|
125
|
+
})
|
|
126
|
+
.attr('class', className)
|
|
127
|
+
.style('fill', color);
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
112
130
|
}
|
|
113
131
|
});
|
|
114
132
|
}
|
|
@@ -29,6 +29,10 @@
|
|
|
29
29
|
stroke: var(--g-color-text-hint);
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
+
.chartkit-d3-legend__item-symbol_shape_symbol.chartkit-d3-legend__item-symbol_unselected {
|
|
33
|
+
fill: var(--g-color-text-hint);
|
|
34
|
+
}
|
|
35
|
+
|
|
32
36
|
.chartkit-d3-legend__item-text {
|
|
33
37
|
fill: var(--g-color-text-secondary);
|
|
34
38
|
alignment-baseline: before-edge;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import cloneDeep from 'lodash/cloneDeep';
|
|
2
2
|
import get from 'lodash/get';
|
|
3
|
+
import { getSymbolType } from '../../utils';
|
|
3
4
|
import { prepareLineSeries } from './prepare-line-series';
|
|
4
5
|
import { prepareBarXSeries } from './prepare-bar-x';
|
|
5
6
|
import { prepareBarYSeries } from './prepare-bar-y';
|
|
@@ -8,15 +9,17 @@ import { ChartKitError } from '../../../../../libs';
|
|
|
8
9
|
import { preparePieSeries } from './prepare-pie';
|
|
9
10
|
import { prepareArea } from './prepare-area';
|
|
10
11
|
function prepareAxisRelatedSeries(args) {
|
|
11
|
-
const { colorScale, series, legend } = args;
|
|
12
|
+
const { colorScale, series, legend, index } = args;
|
|
12
13
|
const preparedSeries = cloneDeep(series);
|
|
13
14
|
const name = 'name' in series && series.name ? series.name : '';
|
|
15
|
+
const symbolType = (series.symbolType || getSymbolType(index));
|
|
16
|
+
preparedSeries.symbolType = symbolType;
|
|
14
17
|
preparedSeries.color = 'color' in series && series.color ? series.color : colorScale(name);
|
|
15
18
|
preparedSeries.name = name;
|
|
16
19
|
preparedSeries.visible = get(preparedSeries, 'visible', true);
|
|
17
20
|
preparedSeries.legend = {
|
|
18
21
|
enabled: get(preparedSeries, 'legend.enabled', legend.enabled),
|
|
19
|
-
symbol: prepareLegendSymbol(series),
|
|
22
|
+
symbol: prepareLegendSymbol(series, symbolType),
|
|
20
23
|
};
|
|
21
24
|
return [preparedSeries];
|
|
22
25
|
}
|
|
@@ -36,8 +39,8 @@ export function prepareSeries(args) {
|
|
|
36
39
|
return prepareBarYSeries({ series: series, legend, colorScale });
|
|
37
40
|
}
|
|
38
41
|
case 'scatter': {
|
|
39
|
-
return series.reduce((acc, singleSeries) => {
|
|
40
|
-
acc.push(...prepareAxisRelatedSeries({ series: singleSeries, legend, colorScale }));
|
|
42
|
+
return series.reduce((acc, singleSeries, index) => {
|
|
43
|
+
acc.push(...prepareAxisRelatedSeries({ series: singleSeries, legend, colorScale, index }));
|
|
41
44
|
return acc;
|
|
42
45
|
}, []);
|
|
43
46
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { BarXSeries, BarXSeriesData, BaseTextStyle, ChartKitWidgetLegend, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData, BarYSeries, BarYSeriesData, LineSeries, LineSeriesData, ConnectorShape, ConnectorCurve, PathLegendSymbolOptions, AreaSeries, AreaSeriesData } from '../../../../../types';
|
|
1
|
+
import { BarXSeries, BarXSeriesData, BaseTextStyle, ChartKitWidgetLegend, PieSeries, PieSeriesData, RectLegendSymbolOptions, ScatterSeries, ScatterSeriesData, BarYSeries, BarYSeriesData, LineSeries, LineSeriesData, ConnectorShape, ConnectorCurve, PathLegendSymbolOptions, SymbolLegendSymbolOptions, AreaSeries, AreaSeriesData } from '../../../../../types';
|
|
2
2
|
import type { SeriesOptionsDefaults } from '../../constants';
|
|
3
|
-
import { DashStyle, LineCap } from '../../../../../constants';
|
|
3
|
+
import { DashStyle, LineCap, SymbolType } from '../../../../../constants';
|
|
4
4
|
export type RectLegendSymbol = {
|
|
5
5
|
shape: 'rect';
|
|
6
6
|
} & Required<RectLegendSymbolOptions>;
|
|
@@ -8,7 +8,11 @@ export type PathLegendSymbol = {
|
|
|
8
8
|
shape: 'path';
|
|
9
9
|
strokeWidth: number;
|
|
10
10
|
} & Required<PathLegendSymbolOptions>;
|
|
11
|
-
export type
|
|
11
|
+
export type SymbolLegendSymbol = {
|
|
12
|
+
shape: 'symbol';
|
|
13
|
+
symbolType: SymbolType;
|
|
14
|
+
} & Required<SymbolLegendSymbolOptions>;
|
|
15
|
+
export type PreparedLegendSymbol = RectLegendSymbol | PathLegendSymbol | SymbolLegendSymbol;
|
|
12
16
|
export type PreparedLegend = Required<ChartKitWidgetLegend> & {
|
|
13
17
|
height: number;
|
|
14
18
|
lineHeight: number;
|
|
@@ -53,6 +57,7 @@ type BasePreparedSeries = {
|
|
|
53
57
|
export type PreparedScatterSeries = {
|
|
54
58
|
type: ScatterSeries['type'];
|
|
55
59
|
data: ScatterSeriesData[];
|
|
60
|
+
symbolType: SymbolType;
|
|
56
61
|
} & BasePreparedSeries;
|
|
57
62
|
export type PreparedBarXSeries = {
|
|
58
63
|
type: BarXSeries['type'];
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { PreparedLegendSymbol, PreparedSeries, StackedSeries } from './types';
|
|
2
2
|
import { ChartKitWidgetSeries } from '../../../../../types';
|
|
3
|
+
import { SymbolType } from '../../../../../constants';
|
|
3
4
|
export declare const getActiveLegendItems: (series: PreparedSeries[]) => string[];
|
|
4
5
|
export declare const getAllLegendItems: (series: PreparedSeries[]) => string[];
|
|
5
|
-
export declare function prepareLegendSymbol(series: ChartKitWidgetSeries): PreparedLegendSymbol;
|
|
6
|
+
export declare function prepareLegendSymbol(series: ChartKitWidgetSeries, symbolType?: SymbolType): PreparedLegendSymbol;
|
|
6
7
|
export declare function getSeriesStackId(series: StackedSeries): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import memoize from 'lodash/memoize';
|
|
2
|
-
import { DEFAULT_LEGEND_SYMBOL_PADDING, DEFAULT_LEGEND_SYMBOL_SIZE } from './constants';
|
|
3
2
|
import { getRandomCKId } from '../../../../../utils';
|
|
3
|
+
import { DEFAULT_LEGEND_SYMBOL_PADDING, DEFAULT_LEGEND_SYMBOL_SIZE } from './constants';
|
|
4
|
+
import { SymbolType } from '../../../../../constants';
|
|
4
5
|
export const getActiveLegendItems = (series) => {
|
|
5
6
|
return series.reduce((acc, s) => {
|
|
6
7
|
if (s.legend.enabled && s.visible) {
|
|
@@ -12,15 +13,13 @@ export const getActiveLegendItems = (series) => {
|
|
|
12
13
|
export const getAllLegendItems = (series) => {
|
|
13
14
|
return series.map((s) => s.name);
|
|
14
15
|
};
|
|
15
|
-
export function prepareLegendSymbol(series) {
|
|
16
|
+
export function prepareLegendSymbol(series, symbolType) {
|
|
16
17
|
var _a;
|
|
17
18
|
const symbolOptions = ((_a = series.legend) === null || _a === void 0 ? void 0 : _a.symbol) || {};
|
|
18
|
-
const symbolHeight = (symbolOptions === null || symbolOptions === void 0 ? void 0 : symbolOptions.height) || DEFAULT_LEGEND_SYMBOL_SIZE;
|
|
19
19
|
return {
|
|
20
|
-
shape: '
|
|
20
|
+
shape: 'symbol',
|
|
21
|
+
symbolType: symbolType || SymbolType.Circle,
|
|
21
22
|
width: (symbolOptions === null || symbolOptions === void 0 ? void 0 : symbolOptions.width) || DEFAULT_LEGEND_SYMBOL_SIZE,
|
|
22
|
-
height: symbolHeight,
|
|
23
|
-
radius: (symbolOptions === null || symbolOptions === void 0 ? void 0 : symbolOptions.radius) || symbolHeight / 2,
|
|
24
23
|
padding: (symbolOptions === null || symbolOptions === void 0 ? void 0 : symbolOptions.padding) || DEFAULT_LEGEND_SYMBOL_PADDING,
|
|
25
24
|
};
|
|
26
25
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import get from 'lodash/get';
|
|
3
|
-
import { color, pointer, select } from 'd3';
|
|
3
|
+
import { symbol, color, pointer, select } from 'd3';
|
|
4
4
|
import { block } from '../../../../../../utils/cn';
|
|
5
|
-
import { extractD3DataFromNode, isNodeContainsD3Data } from '../../../utils';
|
|
5
|
+
import { extractD3DataFromNode, isNodeContainsD3Data, getSymbol } from '../../../utils';
|
|
6
6
|
import { shapeKey } from '../utils';
|
|
7
|
+
import { SymbolType } from '../../../../../../constants';
|
|
7
8
|
export { prepareScatterData } from './prepare-data';
|
|
8
9
|
const b = block('d3-scatter');
|
|
9
|
-
const DEFAULT_SCATTER_POINT_RADIUS = 4;
|
|
10
10
|
const EMPTY_SELECTION = null;
|
|
11
11
|
const isNodeContainsScatterData = (node) => {
|
|
12
12
|
return isNodeContainsD3Data(node);
|
|
@@ -22,13 +22,20 @@ export function ScatterSeriesShape(props) {
|
|
|
22
22
|
const hoverOptions = get(seriesOptions, 'scatter.states.hover');
|
|
23
23
|
const inactiveOptions = get(seriesOptions, 'scatter.states.inactive');
|
|
24
24
|
const selection = svgElement
|
|
25
|
-
.selectAll('
|
|
25
|
+
.selectAll('path')
|
|
26
26
|
.data(preparedData, shapeKey)
|
|
27
|
-
.join((enter) => enter.append('
|
|
28
|
-
.attr('
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
.join((enter) => enter.append('path').attr('class', b('point')), (update) => update, (exit) => exit.remove())
|
|
28
|
+
.attr('d', (d) => {
|
|
29
|
+
const symbolType = d.series.symbolType || SymbolType.Circle;
|
|
30
|
+
const scatterSymbol = getSymbol(symbolType);
|
|
31
|
+
// D3 takes size as square pixels, so we need to make square pixels size by multiplying
|
|
32
|
+
// https://d3js.org/d3-shape/symbol#symbol
|
|
33
|
+
return symbol(scatterSymbol, d.size * d.size)();
|
|
34
|
+
})
|
|
35
|
+
.attr('transform', (d) => {
|
|
36
|
+
return 'translate(' + d.cx + ',' + d.cy + ')';
|
|
37
|
+
})
|
|
38
|
+
.attr('fill', (d) => d.data.color || d.series.color || '');
|
|
32
39
|
svgElement
|
|
33
40
|
.on('mousemove', (e) => {
|
|
34
41
|
const point = e.target;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { getXValue, getYValue } from '../utils';
|
|
2
|
+
const DEFAULT_SCATTER_POINT_SIZE = 7;
|
|
2
3
|
const getFilteredLinearScatterData = (data) => {
|
|
3
4
|
return data.filter((d) => typeof d.x === 'number' && typeof d.y === 'number');
|
|
4
5
|
};
|
|
@@ -9,6 +10,7 @@ export const prepareScatterData = (args) => {
|
|
|
9
10
|
? s.data
|
|
10
11
|
: getFilteredLinearScatterData(s.data);
|
|
11
12
|
filteredData.forEach((d) => {
|
|
13
|
+
const size = d.radius ? d.radius * 2 : DEFAULT_SCATTER_POINT_SIZE;
|
|
12
14
|
acc.push({
|
|
13
15
|
data: d,
|
|
14
16
|
series: s,
|
|
@@ -17,6 +19,7 @@ export const prepareScatterData = (args) => {
|
|
|
17
19
|
hovered: false,
|
|
18
20
|
active: true,
|
|
19
21
|
id: acc.length - 1,
|
|
22
|
+
size,
|
|
20
23
|
});
|
|
21
24
|
});
|
|
22
25
|
return acc;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { symbolDiamond2, symbolCircle, symbolSquare, symbolTriangle2 } from 'd3';
|
|
2
|
+
import { SymbolType } from '../../../../constants';
|
|
3
|
+
export const getSymbolType = (index) => {
|
|
4
|
+
const scatterStyles = Object.values(SymbolType);
|
|
5
|
+
return scatterStyles[index % scatterStyles.length];
|
|
6
|
+
};
|
|
7
|
+
// This is an inverted triangle
|
|
8
|
+
// Based on https://github.com/d3/d3-shape/blob/main/src/symbol/triangle2.js
|
|
9
|
+
const sqrt3 = Math.sqrt(3);
|
|
10
|
+
const triangleDown = {
|
|
11
|
+
draw: (context, size) => {
|
|
12
|
+
const s = Math.sqrt(size) * 0.6824;
|
|
13
|
+
const t = s / 2;
|
|
14
|
+
const u = (s * sqrt3) / 2;
|
|
15
|
+
context.moveTo(0, s);
|
|
16
|
+
context.lineTo(u, -t);
|
|
17
|
+
context.lineTo(-u, -t);
|
|
18
|
+
context.closePath();
|
|
19
|
+
},
|
|
20
|
+
};
|
|
21
|
+
export const getSymbol = (symbolType) => {
|
|
22
|
+
switch (symbolType) {
|
|
23
|
+
case SymbolType.Diamond:
|
|
24
|
+
return symbolDiamond2;
|
|
25
|
+
case SymbolType.Circle:
|
|
26
|
+
return symbolCircle;
|
|
27
|
+
case SymbolType.Square:
|
|
28
|
+
return symbolSquare;
|
|
29
|
+
case SymbolType.Triangle:
|
|
30
|
+
return symbolTriangle2;
|
|
31
|
+
case SymbolType.TriangleDown:
|
|
32
|
+
return triangleDown;
|
|
33
|
+
default:
|
|
34
|
+
return symbolCircle;
|
|
35
|
+
}
|
|
36
|
+
};
|
|
@@ -58,3 +58,11 @@ export type PathLegendSymbolOptions = BaseLegendSymbol & {
|
|
|
58
58
|
* */
|
|
59
59
|
width?: number;
|
|
60
60
|
};
|
|
61
|
+
export type SymbolLegendSymbolOptions = BaseLegendSymbol & {
|
|
62
|
+
/**
|
|
63
|
+
* The pixel width of the symbol for series types that use a symbol in the legend
|
|
64
|
+
*
|
|
65
|
+
* @default 8
|
|
66
|
+
* */
|
|
67
|
+
width?: number;
|
|
68
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SeriesType } from '../../constants';
|
|
1
|
+
import { SeriesType, SymbolType } from '../../constants';
|
|
2
2
|
import type { BaseSeries, BaseSeriesData } from './base';
|
|
3
3
|
import type { ChartKitWidgetLegend, RectLegendSymbolOptions } from './legend';
|
|
4
4
|
export type ScatterSeriesData<T = any> = BaseSeriesData<T> & {
|
|
@@ -32,7 +32,7 @@ export type ScatterSeries<T = any> = BaseSeries & {
|
|
|
32
32
|
/** The main color of the series (hex, rgba) */
|
|
33
33
|
color?: string;
|
|
34
34
|
/** A predefined shape or symbol for the dot */
|
|
35
|
-
|
|
35
|
+
symbolType?: `${SymbolType}`;
|
|
36
36
|
/** Individual series legend options. Has higher priority than legend options in widget data */
|
|
37
37
|
legend?: ChartKitWidgetLegend & {
|
|
38
38
|
symbol?: RectLegendSymbolOptions;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gravity-ui/chartkit",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.17.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,7 +48,7 @@
|
|
|
48
48
|
"dependencies": {
|
|
49
49
|
"@bem-react/classname": "^1.6.0",
|
|
50
50
|
"@gravity-ui/date-utils": "^1.4.1",
|
|
51
|
-
"@gravity-ui/yagr": "^4.
|
|
51
|
+
"@gravity-ui/yagr": "^4.2.0",
|
|
52
52
|
"afterframe": "^1.0.2",
|
|
53
53
|
"d3": "^7.8.5",
|
|
54
54
|
"lodash": "^4.17.21",
|
|
@@ -125,6 +125,7 @@
|
|
|
125
125
|
"docs:start:ru": "cd ./documentation && npm run start:ru",
|
|
126
126
|
"docs:build": "cd ./documentation && npm run build",
|
|
127
127
|
"docs:serve": "cd ./documentation && npm run serve",
|
|
128
|
+
"docs:deploy": "cd ./documentation && npm run deploy",
|
|
128
129
|
"prepublishOnly": "npm run build"
|
|
129
130
|
},
|
|
130
131
|
"husky": {
|