@gravity-ui/chartkit 5.15.0 → 5.16.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/Legend.js +129 -66
- package/build/plugins/d3/renderer/components/styles.css +8 -0
- package/build/plugins/d3/renderer/constants/defaults/legend.d.ts +12 -4
- package/build/plugins/d3/renderer/constants/defaults/legend.js +4 -0
- 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 +8 -6
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-legend.js +58 -11
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-line.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-treemap.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/prepare-waterfall.js +1 -0
- package/build/plugins/d3/renderer/hooks/useSeries/types.d.ts +23 -1
- package/build/plugins/d3/renderer/hooks/useShapes/HtmlLayer.d.ts +8 -0
- package/build/plugins/d3/renderer/hooks/useShapes/HtmlLayer.js +22 -0
- package/build/plugins/d3/renderer/hooks/useShapes/area/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/area/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/area/prepare-data.js +18 -3
- package/build/plugins/d3/renderer/hooks/useShapes/area/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/prepare-data.js +21 -4
- package/build/plugins/d3/renderer/hooks/useShapes/bar-x/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/index.js +18 -23
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/prepare-data.js +44 -3
- package/build/plugins/d3/renderer/hooks/useShapes/bar-y/types.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +7 -7
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/line/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/line/prepare-data.js +17 -1
- package/build/plugins/d3/renderer/hooks/useShapes/line/types.d.ts +2 -1
- package/build/plugins/d3/renderer/hooks/useShapes/pie/index.js +2 -10
- package/build/plugins/d3/renderer/hooks/useShapes/pie/prepare-data.js +0 -1
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter/types.d.ts +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/prepare-data.js +1 -1
- package/build/plugins/d3/renderer/hooks/useShapes/treemap/types.d.ts +2 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.d.ts +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/index.js +5 -2
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/prepare-data.js +1 -0
- package/build/plugins/d3/renderer/hooks/useShapes/waterfall/types.d.ts +2 -1
- package/build/plugins/d3/renderer/types/index.d.ts +3 -1
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.d.ts +5 -4
- package/build/plugins/d3/renderer/utils/axis-generators/bottom.js +11 -7
- package/build/plugins/d3/renderer/utils/axis.d.ts +1 -1
- package/build/plugins/d3/renderer/utils/axis.js +1 -1
- package/build/plugins/d3/renderer/utils/color.d.ts +10 -0
- package/build/plugins/d3/renderer/utils/color.js +43 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +2 -0
- package/build/plugins/d3/renderer/utils/index.js +2 -0
- package/build/plugins/d3/renderer/utils/legend.d.ts +8 -0
- package/build/plugins/d3/renderer/utils/legend.js +23 -0
- package/build/plugins/d3/renderer/utils/text.js +17 -10
- package/build/types/widget-data/bar-x.d.ts +1 -1
- package/build/types/widget-data/legend.d.ts +24 -0
- package/package.json +1 -1
|
@@ -16,7 +16,7 @@ function addDomain(selection, options) {
|
|
|
16
16
|
}
|
|
17
17
|
}
|
|
18
18
|
export function axisBottom(args) {
|
|
19
|
-
const { scale, ticks: { labelFormat, labelsPaddings = 0, labelsMargin = 0, labelsMaxWidth = Infinity, labelsStyle, labelsLineHeight, items: tickItems, count: ticksCount, maxTickCount, rotation, }, domain
|
|
19
|
+
const { scale, ticks: { labelFormat = (value) => String(value), labelsPaddings = 0, labelsMargin = 0, labelsMaxWidth = Infinity, labelsStyle, labelsLineHeight, items: tickItems, count: ticksCount, maxTickCount, rotation = 0, tickColor, }, domain, } = args;
|
|
20
20
|
const offset = getXAxisOffset();
|
|
21
21
|
const position = getXTickPosition({ scale, offset });
|
|
22
22
|
const values = getXAxisItems({ scale, count: ticksCount, maxCount: maxTickCount });
|
|
@@ -25,10 +25,11 @@ export function axisBottom(args) {
|
|
|
25
25
|
style: labelsStyle,
|
|
26
26
|
}).maxHeight;
|
|
27
27
|
return function (selection) {
|
|
28
|
-
var _a, _b;
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
const
|
|
28
|
+
var _a, _b, _c;
|
|
29
|
+
const rect = (_a = selection.node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
30
|
+
const x = (rect === null || rect === void 0 ? void 0 : rect.x) || 0;
|
|
31
|
+
const right = x + domain.size;
|
|
32
|
+
const top = -((_c = (_b = tickItems === null || tickItems === void 0 ? void 0 : tickItems[0]) === null || _b === void 0 ? void 0 : _b[0]) !== null && _c !== void 0 ? _c : 0);
|
|
32
33
|
let transform = `translate(0, ${labelHeight + labelsMargin - top}px)`;
|
|
33
34
|
if (rotation) {
|
|
34
35
|
const labelsOffsetTop = labelHeight * calculateCos(rotation) + labelsMargin - top;
|
|
@@ -39,7 +40,7 @@ export function axisBottom(args) {
|
|
|
39
40
|
transform = `translate(${-labelsOffsetLeft}px, ${labelsOffsetTop}px) rotate(${rotation}deg)`;
|
|
40
41
|
}
|
|
41
42
|
const tickPath = path();
|
|
42
|
-
tickItems.forEach(([start, end]) => {
|
|
43
|
+
tickItems === null || tickItems === void 0 ? void 0 : tickItems.forEach(([start, end]) => {
|
|
43
44
|
tickPath.moveTo(0, start);
|
|
44
45
|
tickPath.lineTo(0, end);
|
|
45
46
|
});
|
|
@@ -49,7 +50,9 @@ export function axisBottom(args) {
|
|
|
49
50
|
.order()
|
|
50
51
|
.join((el) => {
|
|
51
52
|
const tick = el.append('g').attr('class', 'tick');
|
|
52
|
-
tick.append('path')
|
|
53
|
+
tick.append('path')
|
|
54
|
+
.attr('d', tickPath.toString())
|
|
55
|
+
.attr('stroke', tickColor !== null && tickColor !== void 0 ? tickColor : 'currentColor');
|
|
53
56
|
tick.append('text')
|
|
54
57
|
.text(labelFormat)
|
|
55
58
|
.attr('fill', 'currentColor')
|
|
@@ -115,6 +118,7 @@ export function axisBottom(args) {
|
|
|
115
118
|
}
|
|
116
119
|
});
|
|
117
120
|
}
|
|
121
|
+
const { size: domainSize, color: domainColor } = domain;
|
|
118
122
|
selection
|
|
119
123
|
.call(addDomain, { size: domainSize, color: domainColor })
|
|
120
124
|
.style('font-size', (labelsStyle === null || labelsStyle === void 0 ? void 0 : labelsStyle.fontSize) || '');
|
|
@@ -15,7 +15,7 @@ export declare function getXTickPosition({ scale, offset }: {
|
|
|
15
15
|
export declare function getXAxisItems({ scale, count, maxCount, }: {
|
|
16
16
|
scale: AxisScale<AxisDomain>;
|
|
17
17
|
count?: number;
|
|
18
|
-
maxCount
|
|
18
|
+
maxCount?: number;
|
|
19
19
|
}): any;
|
|
20
20
|
export declare function getMaxTickCount({ axis, width }: {
|
|
21
21
|
axis: PreparedAxis;
|
|
@@ -32,7 +32,7 @@ export function getXTickPosition({ scale, offset }) {
|
|
|
32
32
|
}
|
|
33
33
|
export function getXAxisItems({ scale, count, maxCount, }) {
|
|
34
34
|
let values = getScaleTicks(scale, count);
|
|
35
|
-
if (values.length > maxCount) {
|
|
35
|
+
if (maxCount && values.length > maxCount) {
|
|
36
36
|
const step = Math.ceil(values.length / maxCount);
|
|
37
37
|
values = values.filter((_, i) => i % step === 0);
|
|
38
38
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ChartKitWidgetData } from '../../../../types';
|
|
2
|
+
export declare function getDomainForContinuousColorScale(args: {
|
|
3
|
+
series: ChartKitWidgetData['series']['data'];
|
|
4
|
+
}): number[];
|
|
5
|
+
export declare function getDefaultColorStops(size: number): number[];
|
|
6
|
+
export declare function getContinuesColorFn(args: {
|
|
7
|
+
values: number[];
|
|
8
|
+
colors: string[];
|
|
9
|
+
stops?: number[];
|
|
10
|
+
}): (value: number) => string;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { range, scaleLinear } from 'd3';
|
|
2
|
+
export function getDomainForContinuousColorScale(args) {
|
|
3
|
+
const { series } = args;
|
|
4
|
+
const values = series.reduce((acc, s) => {
|
|
5
|
+
switch (s.type) {
|
|
6
|
+
case 'pie': {
|
|
7
|
+
acc.push(...s.data.map((d) => d.value));
|
|
8
|
+
break;
|
|
9
|
+
}
|
|
10
|
+
case 'bar-y': {
|
|
11
|
+
acc.push(...s.data.map((d) => Number(d.x)));
|
|
12
|
+
break;
|
|
13
|
+
}
|
|
14
|
+
case 'scatter':
|
|
15
|
+
case 'bar-x':
|
|
16
|
+
case 'waterfall':
|
|
17
|
+
case 'line':
|
|
18
|
+
case 'area': {
|
|
19
|
+
acc.push(...s.data.map((d) => Number(d.y)));
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
default: {
|
|
23
|
+
throw Error(`The method for calculation a domain for a continuous color scale for the "${s.type}" series is not defined`);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return acc;
|
|
27
|
+
}, []);
|
|
28
|
+
return [Math.min(...values), Math.max(...values)];
|
|
29
|
+
}
|
|
30
|
+
export function getDefaultColorStops(size) {
|
|
31
|
+
return range(size).map((d) => d / size);
|
|
32
|
+
}
|
|
33
|
+
export function getContinuesColorFn(args) {
|
|
34
|
+
const { values, colors, stops: customStops } = args;
|
|
35
|
+
const min = Math.min(...values);
|
|
36
|
+
const max = Math.max(...values);
|
|
37
|
+
const stops = customStops !== null && customStops !== void 0 ? customStops : getDefaultColorStops(colors.length);
|
|
38
|
+
const color = scaleLinear(stops, colors);
|
|
39
|
+
return (value) => {
|
|
40
|
+
const colorValue = (value - min) / (max - min);
|
|
41
|
+
return color(colorValue);
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -6,8 +6,10 @@ export * from './text';
|
|
|
6
6
|
export * from './time';
|
|
7
7
|
export * from './axis';
|
|
8
8
|
export * from './labels';
|
|
9
|
+
export * from './legend';
|
|
9
10
|
export * from './symbol';
|
|
10
11
|
export * from './series';
|
|
12
|
+
export * from './color';
|
|
11
13
|
export declare const CHART_SERIES_WITH_VOLUME_ON_Y_AXIS: ChartKitWidgetSeries['type'][];
|
|
12
14
|
export declare const CHART_SERIES_WITH_VOLUME_ON_X_AXIS: ChartKitWidgetSeries['type'][];
|
|
13
15
|
export type AxisDirection = 'x' | 'y';
|
|
@@ -12,8 +12,10 @@ export * from './text';
|
|
|
12
12
|
export * from './time';
|
|
13
13
|
export * from './axis';
|
|
14
14
|
export * from './labels';
|
|
15
|
+
export * from './legend';
|
|
15
16
|
export * from './symbol';
|
|
16
17
|
export * from './series';
|
|
18
|
+
export * from './color';
|
|
17
19
|
const CHARTS_WITHOUT_AXIS = ['pie', 'treemap'];
|
|
18
20
|
export const CHART_SERIES_WITH_VOLUME_ON_Y_AXIS = [
|
|
19
21
|
'bar-x',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Selection } from 'd3';
|
|
2
|
+
export declare function createGradientRect(container: Selection<SVGGElement, unknown, null, undefined>, args: {
|
|
3
|
+
x?: number;
|
|
4
|
+
y?: number;
|
|
5
|
+
width: number;
|
|
6
|
+
height: number;
|
|
7
|
+
interpolator: (value: number) => string;
|
|
8
|
+
}): Selection<SVGImageElement, unknown, null, undefined>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export function createGradientRect(container, args) {
|
|
2
|
+
const { x = 0, y = 0, width, height, interpolator } = args;
|
|
3
|
+
const n = 256;
|
|
4
|
+
const canvas = document.createElement('canvas');
|
|
5
|
+
canvas.width = n;
|
|
6
|
+
canvas.height = 1;
|
|
7
|
+
const context = canvas.getContext('2d');
|
|
8
|
+
if (!context) {
|
|
9
|
+
throw Error("Couldn't get canvas context");
|
|
10
|
+
}
|
|
11
|
+
for (let i = 0, j = n - 1; i < n; ++i) {
|
|
12
|
+
context.fillStyle = interpolator(i / j);
|
|
13
|
+
context.fillRect(i, 0, 1, height);
|
|
14
|
+
}
|
|
15
|
+
return container
|
|
16
|
+
.append('image')
|
|
17
|
+
.attr('preserveAspectRatio', 'none')
|
|
18
|
+
.attr('height', height)
|
|
19
|
+
.attr('width', width)
|
|
20
|
+
.attr('x', x)
|
|
21
|
+
.attr('y', y)
|
|
22
|
+
.attr('xlink:href', canvas.toDataURL());
|
|
23
|
+
}
|
|
@@ -64,7 +64,7 @@ function renderLabels(selection, { labels, style = {}, attrs = {}, }) {
|
|
|
64
64
|
return text;
|
|
65
65
|
}
|
|
66
66
|
export function getLabelsSize({ labels, style, rotation, html, }) {
|
|
67
|
-
var _a, _b, _c
|
|
67
|
+
var _a, _b, _c;
|
|
68
68
|
if (!labels.filter(Boolean).length) {
|
|
69
69
|
return { maxHeight: 0, maxWidth: 0 };
|
|
70
70
|
}
|
|
@@ -75,12 +75,19 @@ export function getLabelsSize({ labels, style, rotation, html, }) {
|
|
|
75
75
|
let labelWrapper;
|
|
76
76
|
if (html) {
|
|
77
77
|
labelWrapper = container.append('div').style('position', 'absolute').node();
|
|
78
|
-
labels.
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
78
|
+
const { height, width } = labels.reduce((acc, l) => {
|
|
79
|
+
var _a, _b;
|
|
80
|
+
if (labelWrapper) {
|
|
81
|
+
labelWrapper.innerHTML = l;
|
|
82
|
+
}
|
|
83
|
+
const rect = labelWrapper === null || labelWrapper === void 0 ? void 0 : labelWrapper.getBoundingClientRect();
|
|
84
|
+
return {
|
|
85
|
+
width: Math.max(acc.width, (_a = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _a !== void 0 ? _a : 0),
|
|
86
|
+
height: Math.max(acc.height, (_b = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _b !== void 0 ? _b : 0),
|
|
87
|
+
};
|
|
88
|
+
}, { height: 0, width: 0 });
|
|
89
|
+
result.maxWidth = width;
|
|
90
|
+
result.maxHeight = height;
|
|
84
91
|
}
|
|
85
92
|
else {
|
|
86
93
|
const svg = container.append('svg');
|
|
@@ -90,9 +97,9 @@ export function getLabelsSize({ labels, style, rotation, html, }) {
|
|
|
90
97
|
.attr('text-anchor', rotation > 0 ? 'start' : 'end')
|
|
91
98
|
.style('transform', `rotate(${rotation}deg)`);
|
|
92
99
|
}
|
|
93
|
-
const rect = (
|
|
94
|
-
result.maxWidth = (
|
|
95
|
-
result.maxHeight = (
|
|
100
|
+
const rect = (_a = svg.select('g').node()) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
|
|
101
|
+
result.maxWidth = (_b = rect === null || rect === void 0 ? void 0 : rect.width) !== null && _b !== void 0 ? _b : 0;
|
|
102
|
+
result.maxHeight = (_c = rect === null || rect === void 0 ? void 0 : rect.height) !== null && _c !== void 0 ? _c : 0;
|
|
96
103
|
}
|
|
97
104
|
container.remove();
|
|
98
105
|
return result;
|
|
@@ -49,7 +49,7 @@ export type BarXSeries<T = any> = BaseSeries & {
|
|
|
49
49
|
* @default true
|
|
50
50
|
* */
|
|
51
51
|
grouping?: boolean;
|
|
52
|
-
dataLabels?: ChartKitWidgetSeriesOptions['dataLabels'] & {
|
|
52
|
+
dataLabels?: BaseSeries['dataLabels'] & ChartKitWidgetSeriesOptions['dataLabels'] & {
|
|
53
53
|
/**
|
|
54
54
|
* Whether to align the data label inside or outside the box
|
|
55
55
|
*
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import type { BaseTextStyle } from './base';
|
|
2
2
|
export type ChartKitWidgetLegend = {
|
|
3
3
|
enabled?: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Different types for different color schemes.
|
|
6
|
+
* If the color scheme is continuous, a gradient legend will be drawn.
|
|
7
|
+
* Otherwise, samples for different point values
|
|
8
|
+
*
|
|
9
|
+
* @default 'discrete'
|
|
10
|
+
*/
|
|
11
|
+
type?: 'discrete' | 'continuous';
|
|
4
12
|
/**
|
|
5
13
|
* The horizontal alignment of the legend box within the chart area.
|
|
6
14
|
*
|
|
@@ -21,6 +29,22 @@ export type ChartKitWidgetLegend = {
|
|
|
21
29
|
* @default 15
|
|
22
30
|
*/
|
|
23
31
|
margin?: number;
|
|
32
|
+
title?: {
|
|
33
|
+
text?: string;
|
|
34
|
+
/** CSS styles for the title */
|
|
35
|
+
style?: Partial<BaseTextStyle>;
|
|
36
|
+
/** The distance(in pixels) between the main content of the legend and its title
|
|
37
|
+
*
|
|
38
|
+
* Defaults to 4 for horizontal axes, 8 for vertical.
|
|
39
|
+
* */
|
|
40
|
+
margin?: number;
|
|
41
|
+
};
|
|
42
|
+
colorScale?: {
|
|
43
|
+
stops?: number[];
|
|
44
|
+
colors: string[];
|
|
45
|
+
domain?: number[];
|
|
46
|
+
};
|
|
47
|
+
width?: number;
|
|
24
48
|
};
|
|
25
49
|
export type BaseLegendSymbol = {
|
|
26
50
|
/**
|
package/package.json
CHANGED