@takaro/lib-components 0.3.3 → 0.4.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/package.json +1 -1
- package/src/components/actions/Dropdown/useDropdown.tsx +8 -1
- package/src/components/charts/echarts/EChartsArea.stories.tsx +139 -0
- package/src/components/charts/echarts/EChartsArea.tsx +139 -0
- package/src/components/charts/echarts/EChartsBar.stories.tsx +141 -0
- package/src/components/charts/echarts/EChartsBar.tsx +133 -0
- package/src/components/charts/echarts/EChartsBase.tsx +265 -0
- package/src/components/charts/echarts/EChartsFunnel.stories.tsx +164 -0
- package/src/components/charts/echarts/EChartsFunnel.tsx +114 -0
- package/src/components/charts/echarts/EChartsHeatmap.stories.tsx +168 -0
- package/src/components/charts/echarts/EChartsHeatmap.tsx +141 -0
- package/src/components/charts/echarts/EChartsLine.stories.tsx +132 -0
- package/src/components/charts/echarts/EChartsLine.tsx +111 -0
- package/src/components/charts/echarts/EChartsPie.stories.tsx +131 -0
- package/src/components/charts/echarts/EChartsPie.tsx +124 -0
- package/src/components/charts/echarts/EChartsRadialBar.stories.tsx +124 -0
- package/src/components/charts/echarts/EChartsRadialBar.tsx +118 -0
- package/src/components/charts/echarts/EChartsScatter.stories.tsx +166 -0
- package/src/components/charts/echarts/EChartsScatter.tsx +135 -0
- package/src/components/charts/echarts/index.ts +26 -0
- package/src/components/charts/index.tsx +26 -0
- package/src/components/feedback/Alert/__snapshots__/Alert.test.tsx.snap +1 -3
- package/src/components/feedback/Alert/index.tsx +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@takaro/lib-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Takaro UI is a simple and customizable component library to build React apps faster within the Takaro eco system",
|
|
6
6
|
"license": "AGPL-3.0-or-later",
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
useTypeahead,
|
|
12
12
|
useClick,
|
|
13
13
|
shift,
|
|
14
|
+
flip,
|
|
14
15
|
} from '@floating-ui/react';
|
|
15
16
|
|
|
16
17
|
export interface UseDropdownOptions {
|
|
@@ -42,7 +43,13 @@ export function useDropdown({
|
|
|
42
43
|
open,
|
|
43
44
|
onOpenChange: setOpen,
|
|
44
45
|
whileElementsMounted: autoUpdate,
|
|
45
|
-
middleware: [
|
|
46
|
+
middleware: [
|
|
47
|
+
offset({ mainAxis: 10 }),
|
|
48
|
+
flip({
|
|
49
|
+
fallbackPlacements: ['top', 'bottom'],
|
|
50
|
+
}),
|
|
51
|
+
shift(),
|
|
52
|
+
],
|
|
46
53
|
});
|
|
47
54
|
|
|
48
55
|
const interactions = useInteractions([
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Meta, StoryFn } from '@storybook/react';
|
|
3
|
+
import { EChartsArea, EChartsAreaProps } from './EChartsArea';
|
|
4
|
+
import { styled } from '../../../styled';
|
|
5
|
+
import { Card } from '../../../components';
|
|
6
|
+
import { faker } from '@faker-js/faker';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Charts/ECharts/Area',
|
|
10
|
+
component: EChartsArea,
|
|
11
|
+
args: {
|
|
12
|
+
smooth: true,
|
|
13
|
+
gradient: true,
|
|
14
|
+
showGrid: true,
|
|
15
|
+
showLegend: true,
|
|
16
|
+
xAxisLabel: 'Date',
|
|
17
|
+
yAxisLabel: 'Revenue ($)',
|
|
18
|
+
title: 'Area Chart Example',
|
|
19
|
+
},
|
|
20
|
+
} as Meta<EChartsAreaProps>;
|
|
21
|
+
|
|
22
|
+
const Wrapper = styled.div`
|
|
23
|
+
height: 500px;
|
|
24
|
+
width: 100%;
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
interface RevenueData {
|
|
28
|
+
date: string;
|
|
29
|
+
revenue: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Generate sample revenue data
|
|
33
|
+
function generateRevenueData(days: number = 30): RevenueData[] {
|
|
34
|
+
const data: RevenueData[] = [];
|
|
35
|
+
const now = new Date();
|
|
36
|
+
const baseValue = 1000;
|
|
37
|
+
|
|
38
|
+
for (let i = days - 1; i >= 0; i--) {
|
|
39
|
+
const date = new Date(now);
|
|
40
|
+
date.setDate(date.getDate() - i);
|
|
41
|
+
|
|
42
|
+
// Add some realistic variation
|
|
43
|
+
const dayOfWeek = date.getDay();
|
|
44
|
+
const weekendBonus = dayOfWeek === 0 || dayOfWeek === 6 ? 300 : 0;
|
|
45
|
+
const randomVariation = faker.number.int({ min: -200, max: 400 });
|
|
46
|
+
const trendGrowth = i * 5; // Slight upward trend
|
|
47
|
+
|
|
48
|
+
data.push({
|
|
49
|
+
date: date.toLocaleDateString(),
|
|
50
|
+
revenue: baseValue + weekendBonus + randomVariation + trendGrowth,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return data;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export const Default: StoryFn<EChartsAreaProps<RevenueData>> = (args) => {
|
|
58
|
+
const data = generateRevenueData();
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Wrapper>
|
|
62
|
+
<EChartsArea<RevenueData>
|
|
63
|
+
{...args}
|
|
64
|
+
data={data}
|
|
65
|
+
xAccessor={(d) => d.date}
|
|
66
|
+
yAccessor={(d) => d.revenue}
|
|
67
|
+
seriesName="Daily Revenue"
|
|
68
|
+
/>
|
|
69
|
+
</Wrapper>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export const NoGradient: StoryFn<EChartsAreaProps<RevenueData>> = (args) => {
|
|
74
|
+
const data = generateRevenueData();
|
|
75
|
+
|
|
76
|
+
return (
|
|
77
|
+
<Wrapper>
|
|
78
|
+
<EChartsArea<RevenueData>
|
|
79
|
+
{...args}
|
|
80
|
+
data={data}
|
|
81
|
+
xAccessor={(d) => d.date}
|
|
82
|
+
yAccessor={(d) => d.revenue}
|
|
83
|
+
seriesName="Revenue"
|
|
84
|
+
gradient={false}
|
|
85
|
+
title="Revenue Trend"
|
|
86
|
+
subtitle="Solid fill area chart"
|
|
87
|
+
/>
|
|
88
|
+
</Wrapper>
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
export const ShopAnalytics: StoryFn = () => {
|
|
93
|
+
const data = generateRevenueData(90);
|
|
94
|
+
|
|
95
|
+
return (
|
|
96
|
+
<Wrapper>
|
|
97
|
+
<Card variant="outline">
|
|
98
|
+
<Card.Title label="Revenue Over Time" />
|
|
99
|
+
<Card.Body>
|
|
100
|
+
<div style={{ height: '400px' }}>
|
|
101
|
+
<EChartsArea
|
|
102
|
+
data={data}
|
|
103
|
+
xAccessor={(d) => d.date}
|
|
104
|
+
yAccessor={(d) => d.revenue}
|
|
105
|
+
seriesName="Revenue"
|
|
106
|
+
smooth={true}
|
|
107
|
+
gradient={true}
|
|
108
|
+
showGrid={true}
|
|
109
|
+
yAxisLabel="Revenue ($)"
|
|
110
|
+
tooltipFormatter={(params: any) => {
|
|
111
|
+
const value = params[0].value;
|
|
112
|
+
return `${params[0].name}<br/>Revenue: $${value.toLocaleString()}`;
|
|
113
|
+
}}
|
|
114
|
+
/>
|
|
115
|
+
</div>
|
|
116
|
+
</Card.Body>
|
|
117
|
+
</Card>
|
|
118
|
+
</Wrapper>
|
|
119
|
+
);
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const StackedArea: StoryFn<EChartsAreaProps<RevenueData>> = (args) => {
|
|
123
|
+
const data = generateRevenueData(20);
|
|
124
|
+
|
|
125
|
+
return (
|
|
126
|
+
<Wrapper>
|
|
127
|
+
<EChartsArea<RevenueData>
|
|
128
|
+
{...args}
|
|
129
|
+
data={data}
|
|
130
|
+
xAccessor={(d) => d.date}
|
|
131
|
+
yAccessor={(d) => d.revenue}
|
|
132
|
+
seriesName="Product Sales"
|
|
133
|
+
stack={true}
|
|
134
|
+
title="Stacked Revenue"
|
|
135
|
+
subtitle="Multiple product categories"
|
|
136
|
+
/>
|
|
137
|
+
</Wrapper>
|
|
138
|
+
);
|
|
139
|
+
};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { FC, useMemo } from 'react';
|
|
2
|
+
import { EChartsOption } from 'echarts';
|
|
3
|
+
import { ResponsiveECharts, EChartsBaseProps } from './EChartsBase';
|
|
4
|
+
import { useTheme } from '../../../hooks';
|
|
5
|
+
|
|
6
|
+
export interface EChartsAreaProps<T = any> extends Omit<EChartsBaseProps, 'option'> {
|
|
7
|
+
data: T[];
|
|
8
|
+
xAccessor: (d: T) => string | number | Date;
|
|
9
|
+
yAccessor: (d: T) => number;
|
|
10
|
+
seriesName?: string;
|
|
11
|
+
smooth?: boolean;
|
|
12
|
+
showGrid?: boolean;
|
|
13
|
+
showLegend?: boolean;
|
|
14
|
+
xAxisLabel?: string;
|
|
15
|
+
yAxisLabel?: string;
|
|
16
|
+
title?: string;
|
|
17
|
+
subtitle?: string;
|
|
18
|
+
gradient?: boolean;
|
|
19
|
+
tooltipFormatter?: (params: any) => string;
|
|
20
|
+
stack?: boolean;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const EChartsArea: FC<EChartsAreaProps> = ({
|
|
24
|
+
data,
|
|
25
|
+
xAccessor,
|
|
26
|
+
yAccessor,
|
|
27
|
+
seriesName = 'Value',
|
|
28
|
+
smooth = true,
|
|
29
|
+
showGrid = true,
|
|
30
|
+
showLegend = false,
|
|
31
|
+
xAxisLabel,
|
|
32
|
+
yAxisLabel,
|
|
33
|
+
title,
|
|
34
|
+
subtitle,
|
|
35
|
+
gradient = true,
|
|
36
|
+
tooltipFormatter,
|
|
37
|
+
stack = false,
|
|
38
|
+
...chartProps
|
|
39
|
+
}) => {
|
|
40
|
+
const theme = useTheme();
|
|
41
|
+
|
|
42
|
+
const option: EChartsOption = useMemo(() => {
|
|
43
|
+
const xData = data.map(xAccessor);
|
|
44
|
+
const yData = data.map(yAccessor);
|
|
45
|
+
|
|
46
|
+
return {
|
|
47
|
+
title: title
|
|
48
|
+
? {
|
|
49
|
+
text: title,
|
|
50
|
+
subtext: subtitle,
|
|
51
|
+
left: 'center',
|
|
52
|
+
}
|
|
53
|
+
: undefined,
|
|
54
|
+
legend: showLegend
|
|
55
|
+
? {
|
|
56
|
+
data: [seriesName],
|
|
57
|
+
top: 30,
|
|
58
|
+
}
|
|
59
|
+
: undefined,
|
|
60
|
+
grid: showGrid
|
|
61
|
+
? {
|
|
62
|
+
left: '3%',
|
|
63
|
+
right: '4%',
|
|
64
|
+
bottom: '3%',
|
|
65
|
+
containLabel: true,
|
|
66
|
+
}
|
|
67
|
+
: undefined,
|
|
68
|
+
tooltip: {
|
|
69
|
+
trigger: 'axis',
|
|
70
|
+
formatter: tooltipFormatter,
|
|
71
|
+
},
|
|
72
|
+
xAxis: {
|
|
73
|
+
type: 'category',
|
|
74
|
+
data: xData,
|
|
75
|
+
name: xAxisLabel,
|
|
76
|
+
nameLocation: 'middle',
|
|
77
|
+
nameGap: 30,
|
|
78
|
+
boundaryGap: false,
|
|
79
|
+
},
|
|
80
|
+
yAxis: {
|
|
81
|
+
type: 'value',
|
|
82
|
+
name: yAxisLabel,
|
|
83
|
+
nameLocation: 'middle',
|
|
84
|
+
nameGap: 50,
|
|
85
|
+
},
|
|
86
|
+
series: [
|
|
87
|
+
{
|
|
88
|
+
name: seriesName,
|
|
89
|
+
type: 'line',
|
|
90
|
+
data: yData,
|
|
91
|
+
smooth: smooth,
|
|
92
|
+
stack: stack ? 'total' : undefined,
|
|
93
|
+
areaStyle: gradient
|
|
94
|
+
? {
|
|
95
|
+
color: {
|
|
96
|
+
type: 'linear',
|
|
97
|
+
x: 0,
|
|
98
|
+
y: 0,
|
|
99
|
+
x2: 0,
|
|
100
|
+
y2: 1,
|
|
101
|
+
colorStops: [
|
|
102
|
+
{
|
|
103
|
+
offset: 0,
|
|
104
|
+
color: theme.colors.primary + '80', // 50% opacity
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
offset: 1,
|
|
108
|
+
color: theme.colors.primary + '10', // 6% opacity
|
|
109
|
+
},
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
: {},
|
|
114
|
+
emphasis: {
|
|
115
|
+
focus: 'series',
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
};
|
|
120
|
+
}, [
|
|
121
|
+
data,
|
|
122
|
+
xAccessor,
|
|
123
|
+
yAccessor,
|
|
124
|
+
seriesName,
|
|
125
|
+
smooth,
|
|
126
|
+
showGrid,
|
|
127
|
+
showLegend,
|
|
128
|
+
xAxisLabel,
|
|
129
|
+
yAxisLabel,
|
|
130
|
+
title,
|
|
131
|
+
subtitle,
|
|
132
|
+
gradient,
|
|
133
|
+
tooltipFormatter,
|
|
134
|
+
stack,
|
|
135
|
+
theme,
|
|
136
|
+
]);
|
|
137
|
+
|
|
138
|
+
return <ResponsiveECharts option={option} {...chartProps} />;
|
|
139
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Meta, StoryFn } from '@storybook/react';
|
|
3
|
+
import { EChartsBar, EChartsBarProps } from './EChartsBar';
|
|
4
|
+
import { styled } from '../../../styled';
|
|
5
|
+
import { Card } from '../../../components';
|
|
6
|
+
import { faker } from '@faker-js/faker';
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
title: 'Charts/ECharts/Bar',
|
|
10
|
+
component: EChartsBar,
|
|
11
|
+
args: {
|
|
12
|
+
horizontal: false,
|
|
13
|
+
showGrid: true,
|
|
14
|
+
showLegend: true,
|
|
15
|
+
xAxisLabel: 'Category',
|
|
16
|
+
yAxisLabel: 'Value',
|
|
17
|
+
title: 'Bar Chart Example',
|
|
18
|
+
colorBy: 'data',
|
|
19
|
+
},
|
|
20
|
+
} as Meta<EChartsBarProps>;
|
|
21
|
+
|
|
22
|
+
const Wrapper = styled.div`
|
|
23
|
+
height: 500px;
|
|
24
|
+
width: 100%;
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
interface CategoryData {
|
|
28
|
+
name: string;
|
|
29
|
+
value: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Generate sample category data
|
|
33
|
+
function generateCategoryData(count: number = 10): CategoryData[] {
|
|
34
|
+
const categories = [
|
|
35
|
+
'Weapons',
|
|
36
|
+
'Armor',
|
|
37
|
+
'Tools',
|
|
38
|
+
'Food',
|
|
39
|
+
'Materials',
|
|
40
|
+
'Potions',
|
|
41
|
+
'Books',
|
|
42
|
+
'Gems',
|
|
43
|
+
'Artifacts',
|
|
44
|
+
'Misc',
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
return categories.slice(0, count).map((name) => ({
|
|
48
|
+
name,
|
|
49
|
+
value: faker.number.int({ min: 10, max: 200 }),
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export const Default: StoryFn<EChartsBarProps<CategoryData>> = (args) => {
|
|
54
|
+
const data = generateCategoryData(8);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<Wrapper>
|
|
58
|
+
<EChartsBar<CategoryData>
|
|
59
|
+
{...args}
|
|
60
|
+
data={data}
|
|
61
|
+
xAccessor={(d) => d.name}
|
|
62
|
+
yAccessor={(d) => d.value}
|
|
63
|
+
seriesName="Sales"
|
|
64
|
+
/>
|
|
65
|
+
</Wrapper>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const HorizontalBar: StoryFn<EChartsBarProps<CategoryData>> = (args) => {
|
|
70
|
+
const data = generateCategoryData(6);
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Wrapper>
|
|
74
|
+
<EChartsBar<CategoryData>
|
|
75
|
+
{...args}
|
|
76
|
+
data={data}
|
|
77
|
+
xAccessor={(d) => d.name}
|
|
78
|
+
yAccessor={(d) => d.value}
|
|
79
|
+
seriesName="Inventory"
|
|
80
|
+
horizontal={true}
|
|
81
|
+
title="Item Inventory"
|
|
82
|
+
subtitle="Current stock levels"
|
|
83
|
+
xAxisLabel="Quantity"
|
|
84
|
+
yAxisLabel=""
|
|
85
|
+
/>
|
|
86
|
+
</Wrapper>
|
|
87
|
+
);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
export const TopSellingItems: StoryFn = () => {
|
|
91
|
+
const products = [
|
|
92
|
+
{ name: 'Diamond Sword', revenue: 15000 },
|
|
93
|
+
{ name: 'Iron Pickaxe', revenue: 12000 },
|
|
94
|
+
{ name: 'Golden Apple', revenue: 9500 },
|
|
95
|
+
{ name: 'Enchanted Book', revenue: 8000 },
|
|
96
|
+
{ name: 'Ender Pearl', revenue: 6500 },
|
|
97
|
+
];
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Wrapper>
|
|
101
|
+
<Card variant="outline">
|
|
102
|
+
<Card.Title label="Top Selling Items" />
|
|
103
|
+
<Card.Body>
|
|
104
|
+
<div style={{ height: '400px' }}>
|
|
105
|
+
<EChartsBar
|
|
106
|
+
data={products}
|
|
107
|
+
xAccessor={(d) => d.name}
|
|
108
|
+
yAccessor={(d) => d.revenue}
|
|
109
|
+
seriesName="Revenue"
|
|
110
|
+
colorBy="data"
|
|
111
|
+
showGrid={true}
|
|
112
|
+
yAxisLabel="Revenue ($)"
|
|
113
|
+
tooltipFormatter={(params: any) => {
|
|
114
|
+
return `${params[0].name}<br/>Revenue: $${params[0].value.toLocaleString()}`;
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
</div>
|
|
118
|
+
</Card.Body>
|
|
119
|
+
</Card>
|
|
120
|
+
</Wrapper>
|
|
121
|
+
);
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export const MonochromeBar: StoryFn<EChartsBarProps<CategoryData>> = (args) => {
|
|
125
|
+
const data = generateCategoryData(12);
|
|
126
|
+
|
|
127
|
+
return (
|
|
128
|
+
<Wrapper>
|
|
129
|
+
<EChartsBar<CategoryData>
|
|
130
|
+
{...args}
|
|
131
|
+
data={data}
|
|
132
|
+
xAccessor={(d) => d.name}
|
|
133
|
+
yAccessor={(d) => d.value}
|
|
134
|
+
seriesName="Activity"
|
|
135
|
+
colorBy="series"
|
|
136
|
+
title="Player Activity by Hour"
|
|
137
|
+
barWidth="60%"
|
|
138
|
+
/>
|
|
139
|
+
</Wrapper>
|
|
140
|
+
);
|
|
141
|
+
};
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { FC, useMemo } from 'react';
|
|
2
|
+
import { EChartsOption } from 'echarts';
|
|
3
|
+
import { ResponsiveECharts, EChartsBaseProps } from './EChartsBase';
|
|
4
|
+
|
|
5
|
+
export interface EChartsBarProps<T = any> extends Omit<EChartsBaseProps, 'option'> {
|
|
6
|
+
data: T[];
|
|
7
|
+
xAccessor: (d: T) => string | number;
|
|
8
|
+
yAccessor: (d: T) => number;
|
|
9
|
+
seriesName?: string;
|
|
10
|
+
horizontal?: boolean;
|
|
11
|
+
showGrid?: boolean;
|
|
12
|
+
showLegend?: boolean;
|
|
13
|
+
xAxisLabel?: string;
|
|
14
|
+
yAxisLabel?: string;
|
|
15
|
+
title?: string;
|
|
16
|
+
subtitle?: string;
|
|
17
|
+
barWidth?: string | number;
|
|
18
|
+
barGap?: string;
|
|
19
|
+
tooltipFormatter?: (params: any) => string;
|
|
20
|
+
colorBy?: 'series' | 'data';
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export const EChartsBar: FC<EChartsBarProps> = ({
|
|
24
|
+
data,
|
|
25
|
+
xAccessor,
|
|
26
|
+
yAccessor,
|
|
27
|
+
seriesName = 'Value',
|
|
28
|
+
horizontal = false,
|
|
29
|
+
showGrid = true,
|
|
30
|
+
showLegend = false,
|
|
31
|
+
xAxisLabel,
|
|
32
|
+
yAxisLabel,
|
|
33
|
+
title,
|
|
34
|
+
subtitle,
|
|
35
|
+
barWidth,
|
|
36
|
+
barGap = '30%',
|
|
37
|
+
tooltipFormatter,
|
|
38
|
+
colorBy = 'series',
|
|
39
|
+
...chartProps
|
|
40
|
+
}) => {
|
|
41
|
+
const option: EChartsOption = useMemo(() => {
|
|
42
|
+
const categories = data.map(xAccessor);
|
|
43
|
+
const values = data.map(yAccessor);
|
|
44
|
+
|
|
45
|
+
const xAxisConfig = {
|
|
46
|
+
type: horizontal ? 'value' : 'category',
|
|
47
|
+
data: horizontal ? undefined : categories,
|
|
48
|
+
name: xAxisLabel,
|
|
49
|
+
nameLocation: 'middle',
|
|
50
|
+
nameGap: 30,
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const yAxisConfig = {
|
|
54
|
+
type: horizontal ? 'category' : 'value',
|
|
55
|
+
data: horizontal ? categories : undefined,
|
|
56
|
+
name: yAxisLabel,
|
|
57
|
+
nameLocation: 'middle',
|
|
58
|
+
nameGap: 50,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
title: title
|
|
63
|
+
? {
|
|
64
|
+
text: title,
|
|
65
|
+
subtext: subtitle,
|
|
66
|
+
left: 'center',
|
|
67
|
+
}
|
|
68
|
+
: undefined,
|
|
69
|
+
legend: showLegend
|
|
70
|
+
? {
|
|
71
|
+
data: [seriesName],
|
|
72
|
+
top: 30,
|
|
73
|
+
}
|
|
74
|
+
: undefined,
|
|
75
|
+
grid: showGrid
|
|
76
|
+
? {
|
|
77
|
+
left: '3%',
|
|
78
|
+
right: '4%',
|
|
79
|
+
bottom: '3%',
|
|
80
|
+
containLabel: true,
|
|
81
|
+
}
|
|
82
|
+
: undefined,
|
|
83
|
+
tooltip: {
|
|
84
|
+
trigger: 'axis',
|
|
85
|
+
axisPointer: {
|
|
86
|
+
type: 'shadow',
|
|
87
|
+
},
|
|
88
|
+
formatter: tooltipFormatter,
|
|
89
|
+
},
|
|
90
|
+
xAxis: xAxisConfig as any,
|
|
91
|
+
yAxis: yAxisConfig as any,
|
|
92
|
+
series: [
|
|
93
|
+
{
|
|
94
|
+
name: seriesName,
|
|
95
|
+
type: 'bar',
|
|
96
|
+
data: values,
|
|
97
|
+
barWidth: barWidth,
|
|
98
|
+
barGap: barGap,
|
|
99
|
+
itemStyle:
|
|
100
|
+
colorBy === 'data'
|
|
101
|
+
? {
|
|
102
|
+
color: (params: any) => {
|
|
103
|
+
const colors = ['#664de5', '#3ccd6A', '#f57c00', '#ff4252', '#06b6d4'];
|
|
104
|
+
return colors[params.dataIndex % colors.length];
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
: undefined,
|
|
108
|
+
emphasis: {
|
|
109
|
+
focus: 'series',
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
};
|
|
114
|
+
}, [
|
|
115
|
+
data,
|
|
116
|
+
xAccessor,
|
|
117
|
+
yAccessor,
|
|
118
|
+
seriesName,
|
|
119
|
+
horizontal,
|
|
120
|
+
showGrid,
|
|
121
|
+
showLegend,
|
|
122
|
+
xAxisLabel,
|
|
123
|
+
yAxisLabel,
|
|
124
|
+
title,
|
|
125
|
+
subtitle,
|
|
126
|
+
barWidth,
|
|
127
|
+
barGap,
|
|
128
|
+
tooltipFormatter,
|
|
129
|
+
colorBy,
|
|
130
|
+
]);
|
|
131
|
+
|
|
132
|
+
return <ResponsiveECharts option={option} {...chartProps} />;
|
|
133
|
+
};
|