Skip to content
This repository was archived by the owner on Mar 17, 2024. It is now read-only.

Commit 1a307ca

Browse files
committed
add web module by using wasm
1 parent e2a875a commit 1a307ca

File tree

6 files changed

+6128
-90
lines changed

6 files changed

+6128
-90
lines changed

.storybook/config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { wasmFolder } from '@hpcc-js/wasm';
2+
3+
wasmFolder('https://unpkg.com/@hpcc-js/wasm/dist/');

.storybook/main.js

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module.exports = {
2+
stories: ['../src/**/*.stories.[tj]sx'],
3+
webpackFinal: async config => {
4+
config.module.rules.push({
5+
test: /\.(ts|tsx)$/,
6+
use: [
7+
{
8+
loader: require.resolve('ts-loader'),
9+
},
10+
],
11+
});
12+
config.resolve.extensions.push('.ts', '.tsx');
13+
return config;
14+
},
15+
};

package.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,26 +29,36 @@
2929
"scripts": {
3030
"build": "rollup -c",
3131
"test": "jest",
32-
"lint": "eslint -c .eslintrc.json --ext ts,tsx src"
32+
"lint": "eslint -c .eslintrc.json --ext ts,tsx src",
33+
"storybook": "start-storybook -p 9000"
3334
},
3435
"peerDependencies": {
36+
"@hpcc-js/wasm": "^0.3.13",
3537
"react": ">=16.8.0",
3638
"react-dom": ">=16.8.0",
3739
"ts-graphviz": ">=0.10.0"
3840
},
41+
"peerDependenciesMeta": {
42+
"@hpcc-js/wasm": {
43+
"optional": true
44+
}
45+
},
3946
"dependencies": {
4047
"prop-types": "^15.7.2",
4148
"react-reconciler": "^0.24.0"
4249
},
4350
"devDependencies": {
51+
"@hpcc-js/wasm": "^0.3.13",
4452
"@rollup/plugin-commonjs": "^11.1.0",
53+
"@storybook/react": "^5.3.18",
4554
"@testing-library/react-hooks": "^3.2.1",
4655
"@types/prop-types": "^15.7.3",
4756
"@types/react": "^16.9.17",
4857
"@types/react-dom": "^16.9.4",
4958
"@types/react-reconciler": "^0.18.0",
5059
"@typescript-eslint/eslint-plugin": "^2.28.0",
5160
"@typescript-eslint/parser": "^2.28.0",
61+
"babel-loader": "^8.1.0",
5262
"eslint": "^6.8.0",
5363
"eslint-config-airbnb": "^18.1.0",
5464
"eslint-config-prettier": "^6.10.1",
@@ -69,6 +79,7 @@
6979
"rollup-plugin-typescript2": "^0.27.0",
7080
"ts-graphviz": "^0.10.0",
7181
"ts-jest": "^25.3.1",
82+
"ts-loader": "^7.0.2",
7283
"typescript": "^3.8.2"
7384
}
7485
}

src/web/Graphviz.stories.tsx

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React, { FC, useState, useEffect } from 'react';
2+
import { Graphviz } from './Graphviz';
3+
import { Digraph } from '../components/Digraph';
4+
import { Node } from '../components/Node';
5+
import { Edge } from '../components/Edge';
6+
import { Subgraph } from '../components/Subgraph';
7+
import { DOT } from '../components/HtmlLike';
8+
9+
export default { title: 'Graphviz' };
10+
11+
export const Example: FC = () => (
12+
<Graphviz>
13+
<Digraph
14+
rankdir="TB"
15+
edge={{
16+
color: 'blue',
17+
fontcolor: 'blue',
18+
}}
19+
node={{
20+
shape: 'none',
21+
}}
22+
>
23+
<Node
24+
id="nodeA"
25+
shape="none"
26+
label={
27+
<DOT.TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
28+
<DOT.TR>
29+
<DOT.TD>left</DOT.TD>
30+
<DOT.TD PORT="m">middle</DOT.TD>
31+
<DOT.TD PORT="r">right</DOT.TD>
32+
</DOT.TR>
33+
</DOT.TABLE>
34+
}
35+
/>
36+
37+
<Subgraph id="cluster" label="Cluster" labeljust="l">
38+
<Node id="nodeB" label="This is label for nodeB." />
39+
</Subgraph>
40+
<Edge targets={['nodeB', 'nodeA:m']} comment="Edge from node A to B" label={<DOT.B>A to B</DOT.B>} />
41+
</Digraph>
42+
</Graphviz>
43+
);
44+
45+
const shapes = [
46+
'box',
47+
'polygon',
48+
'ellipse',
49+
'oval',
50+
'circle',
51+
'egg',
52+
'triangle',
53+
'parallelogram',
54+
'house',
55+
'pentagon',
56+
'hexagon',
57+
];
58+
59+
export const CircoAnime: FC = () => {
60+
const [nodes, setNodes] = useState<string[]>(['n0', 'n1']);
61+
const [i, setI] = useState<number>(2);
62+
useEffect(() => {
63+
const interval = setInterval(() => {
64+
setNodes([...nodes, `n${i}`]);
65+
setI(i + 1);
66+
}, 2000);
67+
return (): void => {
68+
clearInterval(interval);
69+
};
70+
}, [nodes, i, setNodes, setI]);
71+
return (
72+
<Graphviz engine="circo">
73+
<Digraph>
74+
{nodes.map((n, j) => (
75+
<Node id={n} key={n} shape={shapes[j % shapes.length]} />
76+
))}
77+
<Edge targets={nodes} />
78+
<Edge targets={[`n${i - 1}`, 'n0']} />
79+
</Digraph>
80+
</Graphviz>
81+
);
82+
};

src/web/Graphviz.tsx

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/* eslint-disable react/prop-types */
2+
import React, { FC, ReactElement, useRef, useMemo, useEffect } from 'react';
3+
import { graphviz } from '@hpcc-js/wasm';
4+
import { renderToDot } from '../renderer/render';
5+
6+
type Engine = 'circo' | 'dot' | 'fdp' | 'neato' | 'osage' | 'patchwork' | 'twopi';
7+
interface Image {
8+
path: string;
9+
width: string;
10+
height: string;
11+
}
12+
interface File {
13+
path: string;
14+
data: string;
15+
}
16+
17+
type Props = {
18+
children: ReactElement;
19+
engine?: Engine;
20+
images?: Image[];
21+
files?: File[];
22+
};
23+
24+
export const Graphviz: FC<Props> = ({ children, engine, images, files }) => {
25+
const ref = useRef<HTMLDivElement>(null);
26+
const dot = useMemo(() => renderToDot(children), [children]);
27+
useEffect(() => {
28+
const render = async (): Promise<void> => {
29+
const result = await graphviz.layout(dot, 'svg', engine, { images, files });
30+
if (ref.current) {
31+
ref.current.innerHTML = result;
32+
}
33+
};
34+
render();
35+
}, [dot, engine, images, files]);
36+
return <div ref={ref} />;
37+
};
38+
39+
Graphviz.defaultProps = {
40+
images: [],
41+
files: [],
42+
};

0 commit comments

Comments
 (0)