@gravity-ui/chartkit 3.1.2 → 3.2.0-beta.1
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/__stories__/bar/category.stories.d.ts +4 -0
- package/build/plugins/d3/__stories__/bar/category.stories.js +75 -0
- package/build/plugins/d3/__stories__/bar/datetime.stories.d.ts +4 -0
- package/build/plugins/d3/__stories__/bar/datetime.stories.js +71 -0
- package/build/plugins/d3/__stories__/bar/linear.stories.d.ts +4 -0
- package/build/plugins/d3/__stories__/bar/linear.stories.js +74 -0
- package/build/plugins/d3/__stories__/penguins.json +3098 -0
- package/build/plugins/d3/__stories__/scatter/LinearCategories.stories.d.ts +4 -0
- package/build/plugins/d3/__stories__/scatter/LinearCategories.stories.js +103 -0
- package/build/plugins/d3/__stories__/scatter/Timestamp.stories.d.ts +4 -0
- package/build/plugins/d3/__stories__/scatter/Timestamp.stories.js +91 -0
- package/build/plugins/d3/index.d.ts +7 -0
- package/build/plugins/d3/index.js +10 -0
- package/build/plugins/d3/renderer/D3Widget.d.ts +15 -0
- package/build/plugins/d3/renderer/D3Widget.js +40 -0
- package/build/plugins/d3/renderer/components/AxisX.d.ts +10 -0
- package/build/plugins/d3/renderer/components/AxisX.js +68 -0
- package/build/plugins/d3/renderer/components/AxisY.d.ts +10 -0
- package/build/plugins/d3/renderer/components/AxisY.js +73 -0
- package/build/plugins/d3/renderer/components/Chart.d.ts +10 -0
- package/build/plugins/d3/renderer/components/Chart.js +64 -0
- package/build/plugins/d3/renderer/components/Legend.d.ts +12 -0
- package/build/plugins/d3/renderer/components/Legend.js +66 -0
- package/build/plugins/d3/renderer/components/Title.d.ts +7 -0
- package/build/plugins/d3/renderer/components/Title.js +8 -0
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.d.ts +10 -0
- package/build/plugins/d3/renderer/components/Tooltip/DefaultContent.js +21 -0
- package/build/plugins/d3/renderer/components/Tooltip/index.d.ts +12 -0
- package/build/plugins/d3/renderer/components/Tooltip/index.js +53 -0
- package/build/plugins/d3/renderer/components/index.d.ts +1 -0
- package/build/plugins/d3/renderer/components/index.js +1 -0
- package/build/plugins/d3/renderer/components/styles.css +61 -0
- package/build/plugins/d3/renderer/constants.d.ts +1 -0
- package/build/plugins/d3/renderer/constants.js +22 -0
- package/build/plugins/d3/renderer/hooks/index.d.ts +10 -0
- package/build/plugins/d3/renderer/hooks/index.js +10 -0
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.d.ts +17 -0
- package/build/plugins/d3/renderer/hooks/useChartDimensions/index.js +13 -0
- package/build/plugins/d3/renderer/hooks/useChartEvents/index.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartEvents/index.js +15 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.d.ts +8 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/chart.js +60 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/constants.js +3 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/index.d.ts +3 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/index.js +32 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.d.ts +6 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/legend.js +7 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/title.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/title.js +17 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/tooltip.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/tooltip.js +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/types.d.ts +33 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/types.js +1 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/utils.js +18 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/x-axis.js +29 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.d.ts +5 -0
- package/build/plugins/d3/renderer/hooks/useChartOptions/y-axis.js +35 -0
- package/build/plugins/d3/renderer/hooks/useLegend/index.d.ts +13 -0
- package/build/plugins/d3/renderer/hooks/useLegend/index.js +28 -0
- package/build/plugins/d3/renderer/hooks/useScales/index.d.ts +17 -0
- package/build/plugins/d3/renderer/hooks/useScales/index.js +106 -0
- package/build/plugins/d3/renderer/hooks/useSeries/index.d.ts +14 -0
- package/build/plugins/d3/renderer/hooks/useSeries/index.js +23 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar.d.ts +16 -0
- package/build/plugins/d3/renderer/hooks/useShapes/bar.js +75 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.d.ts +19 -0
- package/build/plugins/d3/renderer/hooks/useShapes/index.js +44 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.d.ts +18 -0
- package/build/plugins/d3/renderer/hooks/useShapes/scatter.js +62 -0
- package/build/plugins/d3/renderer/hooks/useTooltip/index.d.ts +13 -0
- package/build/plugins/d3/renderer/hooks/useTooltip/index.js +19 -0
- package/build/plugins/d3/renderer/hooks/useTooltip/types.d.ts +7 -0
- package/build/plugins/d3/renderer/hooks/useTooltip/types.js +1 -0
- package/build/plugins/d3/renderer/utils/index.d.ts +18 -0
- package/build/plugins/d3/renderer/utils/index.js +71 -0
- package/build/plugins/d3/types.d.ts +4 -0
- package/build/plugins/d3/types.js +1 -0
- package/build/types/widget-data/axis.d.ts +24 -0
- package/build/types/widget-data/axis.js +1 -0
- package/build/types/widget-data/bar.d.ts +31 -0
- package/build/types/widget-data/bar.js +1 -0
- package/build/types/widget-data/base.d.ts +15 -0
- package/build/types/widget-data/base.js +1 -0
- package/build/types/widget-data/chart.d.ts +9 -0
- package/build/types/widget-data/chart.js +1 -0
- package/build/types/widget-data/index.d.ts +28 -0
- package/build/types/widget-data/index.js +10 -0
- package/build/types/widget-data/legend.d.ts +3 -0
- package/build/types/widget-data/legend.js +1 -0
- package/build/types/widget-data/pie.d.ts +10 -0
- package/build/types/widget-data/pie.js +1 -0
- package/build/types/widget-data/scatter.d.ts +20 -0
- package/build/types/widget-data/scatter.js +1 -0
- package/build/types/widget-data/series.d.ts +18 -0
- package/build/types/widget-data/series.js +1 -0
- package/build/types/widget-data/title.d.ts +5 -0
- package/build/types/widget-data/title.js +1 -0
- package/build/types/widget-data/tooltip.d.ts +12 -0
- package/build/types/widget-data/tooltip.js +1 -0
- package/build/types/widget.d.ts +5 -0
- package/package.json +7 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { TooltipHoveredData } from '../../../../../types/widget-data';
|
|
3
|
+
import type { PointerPosition, PreparedAxis, PreparedTooltip } from '../../hooks';
|
|
4
|
+
type TooltipProps = {
|
|
5
|
+
tooltip: PreparedTooltip;
|
|
6
|
+
xAxis: PreparedAxis;
|
|
7
|
+
yAxis: PreparedAxis;
|
|
8
|
+
hovered?: TooltipHoveredData;
|
|
9
|
+
pointerPosition?: PointerPosition;
|
|
10
|
+
};
|
|
11
|
+
export declare const Tooltip: (props: TooltipProps) => React.JSX.Element | null;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import block from 'bem-cn-lite';
|
|
3
|
+
import { DefaultContent } from './DefaultContent';
|
|
4
|
+
const b = block('chartkit-d3-tooltip');
|
|
5
|
+
const POINTER_OFFSET_X = 20;
|
|
6
|
+
export const Tooltip = (props) => {
|
|
7
|
+
const { hovered, pointerPosition, tooltip, xAxis, yAxis } = props;
|
|
8
|
+
const ref = React.useRef(null);
|
|
9
|
+
const size = React.useMemo(() => {
|
|
10
|
+
if (ref.current && hovered) {
|
|
11
|
+
const { width, height } = ref.current.getBoundingClientRect();
|
|
12
|
+
return { width, height };
|
|
13
|
+
}
|
|
14
|
+
return undefined;
|
|
15
|
+
}, [hovered, pointerPosition]);
|
|
16
|
+
const position = React.useMemo(() => {
|
|
17
|
+
if (hovered && pointerPosition && size) {
|
|
18
|
+
const { clientWidth } = document.documentElement;
|
|
19
|
+
const { width, height } = size;
|
|
20
|
+
const [pointerLeft, pointetTop] = pointerPosition;
|
|
21
|
+
const outOfRightBoudary = pointerLeft + width + POINTER_OFFSET_X >= clientWidth;
|
|
22
|
+
const outOfTopBoundary = pointetTop - height / 2 <= 0;
|
|
23
|
+
const left = outOfRightBoudary
|
|
24
|
+
? pointerLeft - width - POINTER_OFFSET_X
|
|
25
|
+
: pointerLeft + POINTER_OFFSET_X;
|
|
26
|
+
const top = outOfTopBoundary ? 0 : pointetTop - height / 2;
|
|
27
|
+
return { left, top };
|
|
28
|
+
}
|
|
29
|
+
else if (hovered && pointerPosition) {
|
|
30
|
+
return { left: -1000, top: -1000 };
|
|
31
|
+
}
|
|
32
|
+
return undefined;
|
|
33
|
+
}, [hovered, pointerPosition, size]);
|
|
34
|
+
const content = React.useMemo(() => {
|
|
35
|
+
if (tooltip.renderer && hovered) {
|
|
36
|
+
return tooltip.renderer({ hovered });
|
|
37
|
+
}
|
|
38
|
+
else if (hovered) {
|
|
39
|
+
return React.createElement(DefaultContent, { hovered: hovered, xAxis: xAxis, yAxis: yAxis });
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}, [hovered, tooltip, xAxis, yAxis]);
|
|
43
|
+
if (!position || !hovered) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
const { left, top } = position;
|
|
47
|
+
const style = {
|
|
48
|
+
position: 'absolute',
|
|
49
|
+
top,
|
|
50
|
+
left: left,
|
|
51
|
+
};
|
|
52
|
+
return (React.createElement("div", { ref: ref, className: b(), style: style }, content));
|
|
53
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Chart } from './Chart';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Chart } from './Chart';
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
.chartkit-d3-axis .domain {
|
|
2
|
+
stroke: var(--g-color-line-generic-active);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
.chartkit-d3-axis .tick text {
|
|
6
|
+
color: var(--g-color-text-secondary);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
.chartkit-d3-axis .tick line {
|
|
10
|
+
stroke: var(--g-color-line-generic);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.chartkit-d3-axis__title {
|
|
14
|
+
fill: var(--g-color-text-secondary);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.chartkit-d3-legend__item {
|
|
18
|
+
cursor: pointer;
|
|
19
|
+
user-select: none;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.chartkit-d3-legend__item-text {
|
|
23
|
+
fill: var(--g-color-text-secondary);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.chartkit-d3-legend__item-text_unselected {
|
|
27
|
+
fill: var(--g-color-text-hint);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.chartkit-d3-legend__item-text:hover {
|
|
31
|
+
fill: var(--g-color-text-complementary);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
.chartkit-d3-scatter__point {
|
|
35
|
+
stroke-width: 1px;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.chartkit-d3_hovered .chartkit-d3-scatter__point {
|
|
39
|
+
opacity: 0.5;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.chartkit-d3-scatter__point:hover {
|
|
43
|
+
stroke: #fff;
|
|
44
|
+
opacity: 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.chartkit-d3-title {
|
|
48
|
+
font-size: var(--g-text-subheader-2-font-size);
|
|
49
|
+
font-weight: var(--g-text-subheader-font-weight);
|
|
50
|
+
fill: var(--g-color-text-primary);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.chartkit-d3-tooltip {
|
|
54
|
+
position: absolute;
|
|
55
|
+
padding: 10px 14px;
|
|
56
|
+
background-color: var(--g-color-infographics-tooltip-bg);
|
|
57
|
+
border: 1px solid var(--g-color-line-generic);
|
|
58
|
+
border-radius: 3px;
|
|
59
|
+
box-shadow: 0 2px 12px var(--g-color-sfx-shadow);
|
|
60
|
+
z-index: 100001;
|
|
61
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const DEFAULT_PALETTE: string[];
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export const DEFAULT_PALETTE = [
|
|
2
|
+
'#4DA2F1',
|
|
3
|
+
'#FF3D64',
|
|
4
|
+
'#8AD554',
|
|
5
|
+
'#FFC636',
|
|
6
|
+
'#FFB9DD',
|
|
7
|
+
'#84D1EE',
|
|
8
|
+
'#FF91A1',
|
|
9
|
+
'#54A520',
|
|
10
|
+
'#DB9100',
|
|
11
|
+
'#BA74B3',
|
|
12
|
+
'#1F68A9',
|
|
13
|
+
'#ED65A9',
|
|
14
|
+
'#0FA08D',
|
|
15
|
+
'#FF7E00',
|
|
16
|
+
'#E8B0A4',
|
|
17
|
+
'#52A6C5',
|
|
18
|
+
'#BE2443',
|
|
19
|
+
'#70C1AF',
|
|
20
|
+
'#FFB46C',
|
|
21
|
+
'#DCA3D7',
|
|
22
|
+
];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './useChartDimensions';
|
|
2
|
+
export * from './useChartEvents';
|
|
3
|
+
export * from './useChartOptions';
|
|
4
|
+
export * from './useChartOptions/types';
|
|
5
|
+
export * from './useLegend';
|
|
6
|
+
export * from './useScales';
|
|
7
|
+
export * from './useSeries';
|
|
8
|
+
export * from './useShapes';
|
|
9
|
+
export * from './useTooltip';
|
|
10
|
+
export * from './useTooltip/types';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export * from './useChartDimensions';
|
|
2
|
+
export * from './useChartEvents';
|
|
3
|
+
export * from './useChartOptions';
|
|
4
|
+
export * from './useChartOptions/types';
|
|
5
|
+
export * from './useLegend';
|
|
6
|
+
export * from './useScales';
|
|
7
|
+
export * from './useSeries';
|
|
8
|
+
export * from './useShapes';
|
|
9
|
+
export * from './useTooltip';
|
|
10
|
+
export * from './useTooltip/types';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ChartMargin } from '../../../../../types/widget-data';
|
|
2
|
+
import type { ChartOptions, PreparedAxis, PreparedTitle } from '../useChartOptions/types';
|
|
3
|
+
type Args = {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
margin: ChartMargin;
|
|
7
|
+
legend: ChartOptions['legend'];
|
|
8
|
+
title?: PreparedTitle;
|
|
9
|
+
xAxis?: PreparedAxis;
|
|
10
|
+
yAxis?: PreparedAxis[];
|
|
11
|
+
};
|
|
12
|
+
export declare const useChartDimensions: (args: Args) => {
|
|
13
|
+
boundsWidth: number;
|
|
14
|
+
boundsHeight: number;
|
|
15
|
+
legendHeight: number;
|
|
16
|
+
};
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const LEGEND_LINE_HEIGHT = 15;
|
|
2
|
+
export const useChartDimensions = (args) => {
|
|
3
|
+
const { margin, legend, title, width, height, xAxis, yAxis } = args;
|
|
4
|
+
const legendHeight = legend.enabled ? LEGEND_LINE_HEIGHT : 0;
|
|
5
|
+
const titleHeight = (title === null || title === void 0 ? void 0 : title.height) || 0;
|
|
6
|
+
const xAxisTitleHeight = (xAxis === null || xAxis === void 0 ? void 0 : xAxis.title.height) || 0;
|
|
7
|
+
const yAxisTitleHeight = (yAxis === null || yAxis === void 0 ? void 0 : yAxis.reduce((acc, axis) => {
|
|
8
|
+
return acc + (axis.title.height || 0);
|
|
9
|
+
}, 0)) || 0;
|
|
10
|
+
const boundsWidth = width - margin.right - margin.left - yAxisTitleHeight;
|
|
11
|
+
const boundsHeight = height - margin.top - margin.bottom - legendHeight - titleHeight - xAxisTitleHeight;
|
|
12
|
+
return { boundsWidth, boundsHeight, legendHeight };
|
|
13
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const useChartEvents = () => {
|
|
3
|
+
const [chartHovered, setChartHovered] = React.useState(false);
|
|
4
|
+
const handleMouseEnter = React.useCallback(() => {
|
|
5
|
+
setChartHovered(true);
|
|
6
|
+
}, []);
|
|
7
|
+
const handleMouseLeave = React.useCallback(() => {
|
|
8
|
+
setChartHovered(false);
|
|
9
|
+
}, []);
|
|
10
|
+
return {
|
|
11
|
+
chartHovered,
|
|
12
|
+
handleMouseEnter,
|
|
13
|
+
handleMouseLeave,
|
|
14
|
+
};
|
|
15
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
|
+
import type { PreparedAxis, PreparedChart } from './types';
|
|
3
|
+
export declare const getPreparedChart: (args: {
|
|
4
|
+
chart: ChartKitWidgetData['chart'];
|
|
5
|
+
series: ChartKitWidgetData['series'];
|
|
6
|
+
preparedXAxis: PreparedAxis;
|
|
7
|
+
preparedY1Axis: PreparedAxis;
|
|
8
|
+
}) => PreparedChart;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { select, max } from 'd3';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
import { formatAxisTickLabel, getDomainDataYBySeries } from '../../utils';
|
|
4
|
+
import { getHorisontalSvgTextDimensions } from './utils';
|
|
5
|
+
const AXIS_WIDTH = 1;
|
|
6
|
+
const getAxisLabelMaxWidth = (args) => {
|
|
7
|
+
const { axis, series } = args;
|
|
8
|
+
let maxDomainValue;
|
|
9
|
+
let width = 0;
|
|
10
|
+
switch (axis.type) {
|
|
11
|
+
case 'category': {
|
|
12
|
+
const yCatigories = get(axis, 'categories', []);
|
|
13
|
+
maxDomainValue = [...yCatigories].sort((c1, c2) => c2.length - c1.length)[0];
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
case 'datetime': {
|
|
17
|
+
const yTimestamps = get(axis, 'timestamps');
|
|
18
|
+
const domain = yTimestamps || getDomainDataYBySeries(series);
|
|
19
|
+
maxDomainValue = max(domain);
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
case 'linear': {
|
|
23
|
+
const domain = getDomainDataYBySeries(series);
|
|
24
|
+
maxDomainValue = max(domain);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const formattedValue = formatAxisTickLabel({
|
|
28
|
+
axisType: axis.type,
|
|
29
|
+
value: maxDomainValue,
|
|
30
|
+
dateFormat: axis.labels.dateFormat,
|
|
31
|
+
numberFormat: axis.labels.numberFormat,
|
|
32
|
+
});
|
|
33
|
+
select(document.body)
|
|
34
|
+
.append('text')
|
|
35
|
+
.style('font-size', axis.labels.style.fontSize)
|
|
36
|
+
.text(formattedValue)
|
|
37
|
+
.each(function () {
|
|
38
|
+
width = this.getBoundingClientRect().width;
|
|
39
|
+
})
|
|
40
|
+
.remove();
|
|
41
|
+
return width;
|
|
42
|
+
};
|
|
43
|
+
export const getPreparedChart = (args) => {
|
|
44
|
+
const { chart, series, preparedXAxis, preparedY1Axis } = args;
|
|
45
|
+
const marginBottom = get(chart, 'margin.bottom', 0) +
|
|
46
|
+
preparedXAxis.labels.padding +
|
|
47
|
+
getHorisontalSvgTextDimensions({ text: 'Tmp', style: preparedXAxis.labels.style });
|
|
48
|
+
const marginLeft = get(chart, 'margin.left', AXIS_WIDTH) +
|
|
49
|
+
preparedY1Axis.labels.padding +
|
|
50
|
+
getAxisLabelMaxWidth({ axis: preparedY1Axis, series: series.data }) +
|
|
51
|
+
(preparedY1Axis.title.height || 0);
|
|
52
|
+
return {
|
|
53
|
+
margin: {
|
|
54
|
+
top: get(chart, 'margin.top', 0),
|
|
55
|
+
right: get(chart, 'margin.right', 0),
|
|
56
|
+
bottom: marginBottom,
|
|
57
|
+
left: marginLeft,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getPreparedChart } from './chart';
|
|
3
|
+
import { getPreparedLegend } from './legend';
|
|
4
|
+
import { getPreparedTitle } from './title';
|
|
5
|
+
import { getPreparedTooltip } from './tooltip';
|
|
6
|
+
import { getPreparedXAxis } from './x-axis';
|
|
7
|
+
import { getPreparedYAxis } from './y-axis';
|
|
8
|
+
export const useChartOptions = (args) => {
|
|
9
|
+
const { chart, series, legend, title, tooltip, xAxis, yAxis } = args;
|
|
10
|
+
const options = React.useMemo(() => {
|
|
11
|
+
const preparedTitle = getPreparedTitle({ title });
|
|
12
|
+
const preparedTooltip = getPreparedTooltip({ tooltip });
|
|
13
|
+
const preparedLegend = getPreparedLegend({ legend, series });
|
|
14
|
+
const preparedYAxis = getPreparedYAxis({ yAxis });
|
|
15
|
+
const preparedXAxis = getPreparedXAxis({ xAxis });
|
|
16
|
+
const preparedChart = getPreparedChart({
|
|
17
|
+
chart,
|
|
18
|
+
series,
|
|
19
|
+
preparedXAxis,
|
|
20
|
+
preparedY1Axis: preparedYAxis[0],
|
|
21
|
+
});
|
|
22
|
+
return {
|
|
23
|
+
chart: preparedChart,
|
|
24
|
+
legend: preparedLegend,
|
|
25
|
+
title: preparedTitle,
|
|
26
|
+
tooltip: preparedTooltip,
|
|
27
|
+
xAxis: preparedXAxis,
|
|
28
|
+
yAxis: preparedYAxis,
|
|
29
|
+
};
|
|
30
|
+
}, [chart, legend, title, tooltip, series, xAxis, yAxis]);
|
|
31
|
+
return options;
|
|
32
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ChartKitWidgetData } from '../../../../../types/widget-data';
|
|
2
|
+
import type { PreparedLegend } from './types';
|
|
3
|
+
export declare const getPreparedLegend: (args: {
|
|
4
|
+
legend: ChartKitWidgetData['legend'];
|
|
5
|
+
series: ChartKitWidgetData['series'];
|
|
6
|
+
}) => PreparedLegend;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { getHorisontalSvgTextDimensions } from './utils';
|
|
3
|
+
const DEFAULT_TITLE_FONT_SIZE = '15px';
|
|
4
|
+
const TITLE_PADDINGS = 8 * 2;
|
|
5
|
+
export const getPreparedTitle = ({ title, }) => {
|
|
6
|
+
const titleText = get(title, 'text');
|
|
7
|
+
const titleStyle = {
|
|
8
|
+
fontSize: get(title, 'style.fontSize', DEFAULT_TITLE_FONT_SIZE),
|
|
9
|
+
};
|
|
10
|
+
const titleHeight = titleText
|
|
11
|
+
? getHorisontalSvgTextDimensions({ text: titleText, style: titleStyle }) + TITLE_PADDINGS
|
|
12
|
+
: 0;
|
|
13
|
+
const preparedTitle = titleText
|
|
14
|
+
? { text: titleText, style: titleStyle, height: titleHeight }
|
|
15
|
+
: undefined;
|
|
16
|
+
return preparedTitle;
|
|
17
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { BaseTextStyle, ChartKitWidgetData, ChartKitWidgetAxis, ChartKitWidgetAxisType, ChartKitWidgetAxisLabels, ChartKitWidgetLegend, ChartMargin } from '../../../../../types/widget-data';
|
|
2
|
+
type PreparedAxisLabels = Omit<ChartKitWidgetAxisLabels, 'enabled' | 'padding' | 'style'> & Required<Pick<ChartKitWidgetAxisLabels, 'enabled' | 'padding'>> & {
|
|
3
|
+
style: BaseTextStyle;
|
|
4
|
+
};
|
|
5
|
+
export type PreparedChart = {
|
|
6
|
+
margin: ChartMargin;
|
|
7
|
+
};
|
|
8
|
+
export type PreparedLegend = Required<ChartKitWidgetLegend>;
|
|
9
|
+
export type PreparedAxis = Omit<ChartKitWidgetAxis, 'type' | 'labels'> & {
|
|
10
|
+
type: ChartKitWidgetAxisType;
|
|
11
|
+
labels: PreparedAxisLabels;
|
|
12
|
+
title: {
|
|
13
|
+
height: number;
|
|
14
|
+
text: string;
|
|
15
|
+
style: BaseTextStyle;
|
|
16
|
+
};
|
|
17
|
+
min?: number;
|
|
18
|
+
};
|
|
19
|
+
export type PreparedTitle = ChartKitWidgetData['title'] & {
|
|
20
|
+
height: number;
|
|
21
|
+
};
|
|
22
|
+
export type PreparedTooltip = ChartKitWidgetData['tooltip'] & {
|
|
23
|
+
enabled: boolean;
|
|
24
|
+
};
|
|
25
|
+
export type ChartOptions = {
|
|
26
|
+
chart: PreparedChart;
|
|
27
|
+
legend: PreparedLegend;
|
|
28
|
+
tooltip: PreparedTooltip;
|
|
29
|
+
xAxis: PreparedAxis;
|
|
30
|
+
yAxis: PreparedAxis[];
|
|
31
|
+
title?: PreparedTitle;
|
|
32
|
+
};
|
|
33
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { select } from 'd3';
|
|
2
|
+
import get from 'lodash/get';
|
|
3
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE } from './constants';
|
|
4
|
+
export const getHorisontalSvgTextDimensions = (args) => {
|
|
5
|
+
const { text, style } = args;
|
|
6
|
+
const textSelection = select(document.body).append('text').text(text);
|
|
7
|
+
const fontSize = get(style, 'fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE);
|
|
8
|
+
let height = 0;
|
|
9
|
+
if (fontSize) {
|
|
10
|
+
textSelection.style('font-size', fontSize);
|
|
11
|
+
}
|
|
12
|
+
textSelection
|
|
13
|
+
.each(function () {
|
|
14
|
+
height = this.getBoundingClientRect().height;
|
|
15
|
+
})
|
|
16
|
+
.remove();
|
|
17
|
+
return height;
|
|
18
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from './constants';
|
|
3
|
+
import { getHorisontalSvgTextDimensions } from './utils';
|
|
4
|
+
export const getPreparedXAxis = ({ xAxis }) => {
|
|
5
|
+
const titleText = get(xAxis, 'title.text', '');
|
|
6
|
+
const titleStyle = {
|
|
7
|
+
fontSize: get(xAxis, 'title.style.fontSize', DEFAULT_AXIS_TITLE_FONT_SIZE),
|
|
8
|
+
};
|
|
9
|
+
const preparedXAxis = {
|
|
10
|
+
type: get(xAxis, 'type', 'linear'),
|
|
11
|
+
labels: {
|
|
12
|
+
enabled: get(xAxis, 'labels.enabled', true),
|
|
13
|
+
padding: get(xAxis, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
|
|
14
|
+
dateFormat: get(xAxis, 'labels.dateFormat'),
|
|
15
|
+
numberFormat: get(xAxis, 'labels.numberFormat'),
|
|
16
|
+
style: { fontSize: get(xAxis, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE) },
|
|
17
|
+
},
|
|
18
|
+
categories: get(xAxis, 'categories'),
|
|
19
|
+
timestamps: get(xAxis, 'timestamps'),
|
|
20
|
+
title: {
|
|
21
|
+
text: titleText,
|
|
22
|
+
style: titleStyle,
|
|
23
|
+
height: titleText
|
|
24
|
+
? getHorisontalSvgTextDimensions({ text: titleText, style: titleStyle })
|
|
25
|
+
: 0,
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
return preparedXAxis;
|
|
29
|
+
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import get from 'lodash/get';
|
|
2
|
+
import { DEFAULT_AXIS_LABEL_FONT_SIZE, DEFAULT_AXIS_LABEL_PADDING, DEFAULT_AXIS_TITLE_FONT_SIZE, } from './constants';
|
|
3
|
+
import { getHorisontalSvgTextDimensions } from './utils';
|
|
4
|
+
export const getPreparedYAxis = ({ yAxis }) => {
|
|
5
|
+
// FIXME: add support for n axises
|
|
6
|
+
const yAxis1 = yAxis === null || yAxis === void 0 ? void 0 : yAxis[0];
|
|
7
|
+
const y1LabelsStyle = {
|
|
8
|
+
fontSize: get(yAxis1, 'labels.style.fontSize', DEFAULT_AXIS_LABEL_FONT_SIZE),
|
|
9
|
+
};
|
|
10
|
+
const y1TitleText = get(yAxis1, 'title.text', '');
|
|
11
|
+
const y1TitleStyle = {
|
|
12
|
+
fontSize: get(yAxis1, 'title.style.fontSize', DEFAULT_AXIS_TITLE_FONT_SIZE),
|
|
13
|
+
};
|
|
14
|
+
const preparedY1Axis = {
|
|
15
|
+
type: get(yAxis1, 'type', 'linear'),
|
|
16
|
+
labels: {
|
|
17
|
+
enabled: get(yAxis1, 'labels.enabled', true),
|
|
18
|
+
padding: get(yAxis1, 'labels.padding', DEFAULT_AXIS_LABEL_PADDING),
|
|
19
|
+
dateFormat: get(yAxis1, 'labels.dateFormat'),
|
|
20
|
+
numberFormat: get(yAxis1, 'labels.numberFormat'),
|
|
21
|
+
style: y1LabelsStyle,
|
|
22
|
+
},
|
|
23
|
+
categories: get(yAxis1, 'categories'),
|
|
24
|
+
timestamps: get(yAxis1, 'timestamps'),
|
|
25
|
+
title: {
|
|
26
|
+
text: y1TitleText,
|
|
27
|
+
style: y1TitleStyle,
|
|
28
|
+
height: y1TitleText
|
|
29
|
+
? getHorisontalSvgTextDimensions({ text: y1TitleText, style: y1TitleStyle })
|
|
30
|
+
: 0,
|
|
31
|
+
},
|
|
32
|
+
min: get(yAxis1, 'min'),
|
|
33
|
+
};
|
|
34
|
+
return [preparedY1Axis];
|
|
35
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
|
|
2
|
+
export type OnLegendItemClick = (data: {
|
|
3
|
+
name: string;
|
|
4
|
+
metaKey: boolean;
|
|
5
|
+
}) => void;
|
|
6
|
+
type Args = {
|
|
7
|
+
series: ChartKitWidgetSeries[];
|
|
8
|
+
};
|
|
9
|
+
export declare const useLegend: (args: Args) => {
|
|
10
|
+
activeLegendItems: string[];
|
|
11
|
+
handleLegendItemClick: OnLegendItemClick;
|
|
12
|
+
};
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { getVisibleSeriesNames } from '../../utils';
|
|
3
|
+
export const useLegend = (args) => {
|
|
4
|
+
const { series } = args;
|
|
5
|
+
const [activeLegendItems, setActiveLegendItems] = React.useState(getVisibleSeriesNames(series));
|
|
6
|
+
const handleLegendItemClick = React.useCallback(({ name, metaKey }) => {
|
|
7
|
+
const onlyItemSelected = activeLegendItems.length === 1 && activeLegendItems.includes(name);
|
|
8
|
+
let nextActiveLegendItems;
|
|
9
|
+
if (metaKey && activeLegendItems.includes(name)) {
|
|
10
|
+
nextActiveLegendItems = activeLegendItems.filter((item) => item !== name);
|
|
11
|
+
}
|
|
12
|
+
else if (metaKey && !activeLegendItems.includes(name)) {
|
|
13
|
+
nextActiveLegendItems = activeLegendItems.concat(name);
|
|
14
|
+
}
|
|
15
|
+
else if (onlyItemSelected) {
|
|
16
|
+
nextActiveLegendItems = getVisibleSeriesNames(series);
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
nextActiveLegendItems = [name];
|
|
20
|
+
}
|
|
21
|
+
setActiveLegendItems(nextActiveLegendItems);
|
|
22
|
+
}, [series, activeLegendItems]);
|
|
23
|
+
// FIXME: remove effect. It initiates extra rerender
|
|
24
|
+
React.useEffect(() => {
|
|
25
|
+
setActiveLegendItems(getVisibleSeriesNames(series));
|
|
26
|
+
}, [series]);
|
|
27
|
+
return { activeLegendItems, handleLegendItemClick };
|
|
28
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { ScaleBand, ScaleLinear, ScaleTime } from 'd3';
|
|
2
|
+
import type { ChartKitWidgetSeries } from '../../../../../types/widget-data';
|
|
3
|
+
import type { ChartOptions } from '../useChartOptions/types';
|
|
4
|
+
export type ChartScale = ScaleLinear<number, number> | ScaleBand<string> | ScaleTime<number, number>;
|
|
5
|
+
type Args = {
|
|
6
|
+
boundsWidth: number;
|
|
7
|
+
boundsHeight: number;
|
|
8
|
+
series: ChartKitWidgetSeries[];
|
|
9
|
+
xAxis: ChartOptions['xAxis'];
|
|
10
|
+
yAxis: ChartOptions['yAxis'];
|
|
11
|
+
};
|
|
12
|
+
type ReturnValue = {
|
|
13
|
+
xScale: ChartScale;
|
|
14
|
+
yScale: ChartScale;
|
|
15
|
+
};
|
|
16
|
+
export declare const useScales: (args: Args) => ReturnValue;
|
|
17
|
+
export {};
|