Skip to content

Commit e3e26f8

Browse files
committed
feat(echarts): sankey
1 parent 7b64b05 commit e3e26f8

File tree

16 files changed

+707
-7
lines changed

16 files changed

+707
-7
lines changed

packages/react-charts/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/next
2+
/components

packages/react-charts/package.json

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,13 @@
55
"main": "dist/js/index.js",
66
"module": "dist/esm/index.js",
77
"types": "dist/esm/index.d.ts",
8+
"typesVersions": {
9+
"*": {
10+
"next": [
11+
"dist/esm/next/index.d.ts"
12+
]
13+
}
14+
},
815
"patternfly:src": "src/",
916
"sideEffects": [
1017
"*.css",
@@ -30,6 +37,7 @@
3037
"dependencies": {
3138
"@patternfly/react-styles": "workspace:^",
3239
"@patternfly/react-tokens": "workspace:^",
40+
"echarts": "^5.5.1",
3341
"hoist-non-react-statics": "^3.3.2",
3442
"lodash": "^4.17.21",
3543
"tslib": "^2.6.3",
@@ -56,10 +64,12 @@
5664
"react-dom": "^17 || ^18"
5765
},
5866
"scripts": {
59-
"clean": "rimraf dist",
60-
"build:single:packages": "node ../../scripts/build-single-packages.js --config single-packages.config.json"
67+
"build:single:packages": "node ../../scripts/build-single-packages.js --config single-packages.config.json",
68+
"clean": "rimraf dist components next",
69+
"subpaths": "node ../../scripts/exportSubpaths.js --config subpaths.config.json"
6170
},
6271
"devDependencies": {
72+
"@types/echarts": "^4.9.22",
6373
"@types/lodash": "^4.17.6",
6474
"fs-extra": "^11.2.0"
6575
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"packageName": "@patternfly/react-charts",
3-
"exclude": ["dist/esm/deprecated/index.js", "dist/esm/next/index.js"]
3+
"exclude": ["dist/esm/deprecated/index.js"]
44
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import * as React from 'react';
2+
import { render } from '@testing-library/react';
3+
import { Sankey } from './Sankey';
4+
5+
const data = [
6+
{
7+
name: 'a'
8+
},
9+
{
10+
name: 'b'
11+
},
12+
{
13+
name: 'a1'
14+
},
15+
{
16+
name: 'a2'
17+
},
18+
{
19+
name: 'b1'
20+
},
21+
{
22+
name: 'c'
23+
}
24+
];
25+
26+
const links = [
27+
{
28+
source: 'a',
29+
target: 'a1',
30+
value: 5
31+
},
32+
{
33+
source: 'a',
34+
target: 'a2',
35+
value: 3
36+
},
37+
{
38+
source: 'b',
39+
target: 'b1',
40+
value: 8
41+
},
42+
{
43+
source: 'a',
44+
target: 'b1',
45+
value: 3
46+
},
47+
{
48+
source: 'b1',
49+
target: 'a1',
50+
value: 1
51+
},
52+
{
53+
source: 'b1',
54+
target: 'c',
55+
value: 2
56+
}
57+
];
58+
59+
test('renders component data', () => {
60+
const { asFragment } = render(<Sankey series={[{ data, links }]} />);
61+
expect(asFragment()).toMatchSnapshot();
62+
});
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import * as React from 'react';
2+
import * as echarts from 'echarts';
3+
import { useRef } from 'react';
4+
// import { BarChart, SankeyChart } from 'echarts/charts';
5+
// import { CanvasRenderer } from 'echarts/renderers';
6+
7+
// import {
8+
// TitleComponent,
9+
// TooltipComponent,
10+
// GridComponent,
11+
// DatasetComponent,
12+
// TransformComponent
13+
// } from 'echarts/components';
14+
15+
// Register the required components
16+
// echarts.use([
17+
// BarChart,
18+
// SankeyChart,
19+
// TitleComponent,
20+
// TooltipComponent,
21+
// GridComponent,
22+
// DatasetComponent,
23+
// TransformComponent,
24+
// LabelLayout,
25+
// UniversalTransition,
26+
// CanvasRenderer
27+
// ]);
28+
29+
import { theme } from './theme';
30+
31+
/**
32+
*/
33+
export interface SankeyProps {
34+
height?: number;
35+
id?: string;
36+
lineStyle?: any;
37+
series: any[];
38+
title?: any;
39+
tooltip?: any;
40+
width?: number;
41+
}
42+
43+
export const Sankey: React.FunctionComponent<SankeyProps> = ({
44+
height,
45+
id,
46+
lineStyle = {
47+
color: 'source',
48+
opacity: 0.6
49+
},
50+
series,
51+
title,
52+
tooltip = {
53+
trigger: 'item',
54+
triggerOn: 'mousemove'
55+
},
56+
width
57+
}: SankeyProps) => {
58+
const containerRef = useRef<HTMLDivElement>();
59+
const echart = useRef<echarts.ECharts>();
60+
61+
React.useEffect(() => {
62+
echarts.registerTheme('pf-v5-sankey', theme);
63+
echart.current = echarts.init(containerRef.current, 'pf-v5-sankey'); // renderer: 'svg'
64+
65+
const newSeries = series.map((serie: any) => ({
66+
emphasis: {
67+
focus: 'adjacency'
68+
},
69+
layout: 'none',
70+
lineStyle,
71+
type: 'sankey',
72+
...serie
73+
}));
74+
75+
echart.current.setOption({
76+
series: newSeries,
77+
title,
78+
tooltip
79+
});
80+
}, [containerRef, lineStyle, series, title, tooltip]);
81+
82+
React.useEffect(() => {
83+
echart?.current.resize();
84+
}, [height, width]);
85+
86+
const getSize = () => ({
87+
...(height && { height: `${height}px` }),
88+
...(width && { width: `${width}px` })
89+
});
90+
91+
return <div id={id} ref={containerRef} style={getSize()} />;
92+
};
93+
Sankey.displayName = 'Sankey';
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import React from 'react';
2+
import { Sankey } from '@patternfly/react-charts/next';
3+
import { getResizeObserver } from '@patternfly/react-core';
4+
5+
export const FormBasic: React.FunctionComponent = () => {
6+
const data = [
7+
{
8+
name: 'a'
9+
},
10+
{
11+
name: 'b'
12+
},
13+
{
14+
name: 'a1'
15+
},
16+
{
17+
name: 'a2'
18+
},
19+
{
20+
name: 'b1'
21+
},
22+
{
23+
name: 'c'
24+
}
25+
];
26+
27+
const links = [
28+
{
29+
source: 'a',
30+
target: 'a1',
31+
value: 5
32+
},
33+
{
34+
source: 'a',
35+
target: 'a2',
36+
value: 3
37+
},
38+
{
39+
source: 'b',
40+
target: 'b1',
41+
value: 8
42+
},
43+
{
44+
source: 'a',
45+
target: 'b1',
46+
value: 3
47+
},
48+
{
49+
source: 'b1',
50+
target: 'a1',
51+
value: 1
52+
},
53+
{
54+
source: 'b1',
55+
target: 'c',
56+
value: 2
57+
}
58+
];
59+
60+
// let observer = () => {};
61+
const containerRef = React.useRef<HTMLDivElement>();
62+
const [width, setWidth] = React.useState(0);
63+
64+
React.useEffect(() => {
65+
const handleResize = () => {
66+
if (containerRef.current && containerRef.current.clientWidth) {
67+
setWidth(containerRef.current.clientWidth);
68+
}
69+
};
70+
let observer = () => {};
71+
observer = getResizeObserver(containerRef.current, handleResize);
72+
73+
return () => {
74+
observer();
75+
};
76+
}, [containerRef, width]);
77+
78+
return (
79+
<div ref={containerRef}>
80+
<Sankey
81+
height={400}
82+
series={[{ data, links }]}
83+
title={{
84+
subtext: 'Data From lisachristina1234 on GitHub',
85+
left: 'center'
86+
}}
87+
width={width}
88+
/>
89+
</div>
90+
);
91+
};
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
---
2+
id: Sankey
3+
section: charts
4+
propComponents: [
5+
'Sankey',
6+
]
7+
hideDarkMode: true
8+
beta: true
9+
---
10+
11+
## Introduction
12+
Note: PatternFly React charts live in its own package at [@patternfly/react-charts](https://www.npmjs.com/package/@patternfly/react-charts)!
13+
14+
PatternFly React charts are based on the [Apache ECharts](https://echarts.apache.org/) chart library, along with additional functionality, custom components, and theming for PatternFly. This provides a collection of React based components you can use to build PatternFly patterns with consistent markup, styling, and behavior.
15+
16+
## Examples
17+
### Basic
18+
19+
```ts file="./Basic.tsx"
20+
21+
```
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Sankey';

0 commit comments

Comments
 (0)