Skip to content

Commit a91b938

Browse files
committed
Init commit
0 parents  commit a91b938

15 files changed

+384
-0
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
.DS_Store
2+
node_modules

README.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# @strawberry-vis/g2-rect
2+
3+
A lightweight React Component for @antv/g2.
4+
5+
## Installing
6+
7+
```bash
8+
npm install @strawberry-vis/g2-rect
9+
```
10+
11+
```jsx
12+
import React, { useState } from "react";
13+
import { Chart } from "@strawberry-vis/g2-rect";
14+
15+
export function Card() {
16+
return (
17+
<Chart
18+
options={{
19+
type: "interval",
20+
data: [
21+
{ genre: "Sports", sold: 275 },
22+
{ genre: "Strategy", sold: 115 },
23+
{ genre: "Action", sold: 120 },
24+
{ genre: "Shooter", sold: 350 },
25+
{ genre: "Other", sold: 150 },
26+
],
27+
encode: { x: "genre", y: "sold" },
28+
}}
29+
/>
30+
);
31+
}
32+
```
33+
34+
## API Reference
35+
36+
<a name="props-options" href="#props-options">#</a> props.**options**
37+
38+
```js
39+
import React, { useState } from "react";
40+
import { Chart } from "@strawberry-vis/g2-rect";
41+
42+
export function Card() {
43+
const [options, setOptions] = useState({
44+
type: "interval",
45+
data: [
46+
{ genre: "Sports", sold: 275 },
47+
{ genre: "Strategy", sold: 115 },
48+
{ genre: "Action", sold: 120 },
49+
{ genre: "Shooter", sold: 350 },
50+
{ genre: "Other", sold: 150 },
51+
],
52+
encode: { x: "genre", y: "sold" },
53+
});
54+
55+
function onClick() {
56+
setOptions({ ...options, data: options.data.slice(0, 2) });
57+
}
58+
59+
return (
60+
<div>
61+
<Chart options={options} />
62+
<button onClick={onClick}>Update Options</button>
63+
</div>
64+
);
65+
}
66+
```
67+
68+
<a name="props-chartref" href="#props-chartref">#</a> props.**chartRef**
69+
70+
```js
71+
import React, { useRef, useEffect } from "react";
72+
import { Chart } from "@strawberry-vis/g2-rect";
73+
74+
export function Card() {
75+
const chartRef = useRef();
76+
77+
useEffect(() => {
78+
const chart = chartRef.current;
79+
chart.on("afterrender", () => {});
80+
}, []);
81+
82+
return <Chart options={options} chartRef={chartRef} />;
83+
}
84+
```

package.json

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"name": "@strawberry-vis/g2-rect",
3+
"version": "0.0.1",
4+
"description": "The lightweight React Component for @antv/g2.",
5+
"main": "index.js",
6+
"scripts": {
7+
"dev": "vite dev"
8+
},
9+
"author": {
10+
"name": "pearmini",
11+
"url": "https://github.com/pearmini"
12+
},
13+
"license": "ISC",
14+
"dependencies": {
15+
"@antv/g2": "^5.0.22",
16+
"react": "^18.2.0"
17+
},
18+
"devDependencies": {
19+
"@antv/g-svg": "^1.10.14",
20+
"@types/react": "^18.2.21",
21+
"@types/react-dom": "^18.2.7",
22+
"jsdom": "^22.1.0",
23+
"react-dom": "^18.2.0",
24+
"vite": "^4.4.9"
25+
}
26+
}

src/Chart.tsx

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import React, {
2+
useRef,
3+
useState,
4+
useEffect,
5+
useImperativeHandle,
6+
forwardRef,
7+
CSSProperties,
8+
} from "react";
9+
import { Chart as G2Chart, G2Spec, ChartOptions } from "@antv/g2";
10+
11+
export type ChartRef = G2Chart | undefined;
12+
13+
export type ChartProps = {
14+
spec: G2Spec;
15+
options?: ChartOptions;
16+
style?: CSSProperties;
17+
onInit?: () => void;
18+
};
19+
20+
export const Chart = forwardRef<ChartRef, ChartProps>((props, ref) => {
21+
const { spec, style, onInit, options } = props;
22+
const containerRef = useRef<HTMLDivElement>(null);
23+
const chartRef = useRef<G2Chart>();
24+
const [init, setInit] = useState(false);
25+
26+
useEffect(() => {
27+
if (containerRef.current) {
28+
chartRef.current = new G2Chart({
29+
...options,
30+
container: containerRef.current,
31+
});
32+
setInit(true);
33+
}
34+
return () => {
35+
if (chartRef.current) chartRef.current.destroy();
36+
};
37+
}, []);
38+
39+
useEffect(() => {
40+
if (init) onInit?.();
41+
}, [init]);
42+
43+
useEffect(() => {
44+
if (chartRef.current && spec) {
45+
chartRef.current.options(spec);
46+
chartRef.current.render();
47+
}
48+
}, [spec]);
49+
50+
useImperativeHandle(ref, () => chartRef.current, [init]);
51+
52+
return <div ref={containerRef} style={style}></div>;
53+
});

src/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { Chart, type ChartProps, type ChartRef } from "./Chart";

test/demos/chart-options.tsx

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import React from "react";
2+
import { Renderer } from "@antv/g-svg";
3+
import { Chart } from "../../src";
4+
import { render } from "./render";
5+
6+
function Demo() {
7+
return (
8+
<Chart
9+
options={{ renderer: new Renderer() }}
10+
spec={{
11+
type: "interval",
12+
data: [
13+
{ genre: "Sports", sold: 275 },
14+
{ genre: "Strategy", sold: 115 },
15+
{ genre: "Action", sold: 120 },
16+
{ genre: "Shooter", sold: 350 },
17+
{ genre: "Other", sold: 150 },
18+
],
19+
encode: { x: "genre", y: "sold" },
20+
}}
21+
/>
22+
);
23+
}
24+
25+
export const chartOptions = render(Demo);

test/demos/chart-ref.tsx

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import React, { useRef } from "react";
2+
import { Chart, ChartRef } from "../../src";
3+
import { render } from "./render";
4+
5+
function Demo() {
6+
const chartRef = useRef<ChartRef>(null);
7+
8+
function onInit() {
9+
const chart = chartRef.current;
10+
if (chart) {
11+
chart.on("afterrender", () => {
12+
chart.emit("element:highlight", {
13+
data: {
14+
data: { genre: "Sports" },
15+
},
16+
});
17+
});
18+
}
19+
}
20+
21+
return (
22+
<Chart
23+
ref={chartRef}
24+
spec={{
25+
type: "interval",
26+
data: [
27+
{ genre: "Sports", sold: 275 },
28+
{ genre: "Strategy", sold: 115 },
29+
{ genre: "Action", sold: 120 },
30+
{ genre: "Shooter", sold: 350 },
31+
{ genre: "Other", sold: 150 },
32+
],
33+
encode: { x: "genre", y: "sold" },
34+
state: { active: { fill: "red" } },
35+
interaction: { elementHighlight: true },
36+
}}
37+
onInit={onInit}
38+
/>
39+
);
40+
}
41+
42+
export const chartRef = render(Demo);

test/demos/chart-spec.tsx

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from "react";
2+
import { Chart } from "../../src";
3+
import { render } from "./render";
4+
5+
function Demo() {
6+
return (
7+
<Chart
8+
spec={{
9+
type: "interval",
10+
data: [
11+
{ genre: "Sports", sold: 275 },
12+
{ genre: "Strategy", sold: 115 },
13+
{ genre: "Action", sold: 120 },
14+
{ genre: "Shooter", sold: 350 },
15+
{ genre: "Other", sold: 150 },
16+
],
17+
encode: { x: "genre", y: "sold" },
18+
}}
19+
/>
20+
);
21+
}
22+
23+
export const chartSpec = render(Demo);

test/demos/chart-style.tsx

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from "react";
2+
import { Chart } from "../../src";
3+
import { render } from "./render";
4+
5+
function Demo() {
6+
return (
7+
<Chart
8+
spec={{
9+
type: "interval",
10+
autoFit: true,
11+
data: [
12+
{ genre: "Sports", sold: 275 },
13+
{ genre: "Strategy", sold: 115 },
14+
{ genre: "Action", sold: 120 },
15+
{ genre: "Shooter", sold: 350 },
16+
{ genre: "Other", sold: 150 },
17+
],
18+
encode: { x: "genre", y: "sold" },
19+
}}
20+
style={{
21+
width: 800,
22+
height: 600,
23+
background: "#eee",
24+
padding: "1em",
25+
borderRadius: "0.5em",
26+
}}
27+
/>
28+
);
29+
}
30+
31+
export const chartStyle = render(Demo);

test/demos/chart-update.tsx

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import React, { useState } from "react";
2+
import { Chart } from "../../src";
3+
import { render } from "./render";
4+
5+
function Demo() {
6+
const data = [
7+
{ genre: "Sports", sold: 275 },
8+
{ genre: "Strategy", sold: 115 },
9+
{ genre: "Action", sold: 120 },
10+
{ genre: "Shooter", sold: 350 },
11+
{ genre: "Other", sold: 150 },
12+
];
13+
14+
const [options, setOptions] = useState({
15+
type: "interval",
16+
data,
17+
encode: { x: "genre", y: "sold", color: "genre" },
18+
});
19+
20+
function onClick() {
21+
setOptions({
22+
...options,
23+
data: data.sort(() => Math.random() - 0.5),
24+
});
25+
}
26+
27+
return (
28+
<>
29+
<Chart spec={options} />
30+
<button onClick={onClick}>Update</button>
31+
</>
32+
);
33+
}
34+
35+
export const chartUpdate = render(Demo);

test/demos/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export { chartSpec } from "./chart-spec";
2+
export { chartUpdate } from "./chart-update";
3+
export { chartStyle } from "./chart-style";
4+
export { chartRef } from "./chart-ref";
5+
export { chartOptions } from "./chart-options";

test/demos/render.tsx

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import React from "react";
2+
import { createRoot } from "react-dom/client";
3+
4+
export function render(Demo) {
5+
return () => {
6+
const container = document.createElement("div");
7+
const root = createRoot(container);
8+
root.render(<Demo />);
9+
return container;
10+
};
11+
}

test/index.html

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
<html>
2+
<script type="module" src="./main.ts"></script>
3+
</html>

test/main.ts

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import * as demos from "./demos";
2+
3+
const select = document.createElement("select");
4+
select.style.margin = "1em";
5+
select.onchange = onChange;
6+
select.style.display = "block";
7+
document.body.append(select);
8+
9+
const options = Object.keys(demos).map((d) => {
10+
const option = document.createElement("option");
11+
option.textContent = d;
12+
option.value = d;
13+
return option;
14+
});
15+
options.forEach((d) => select.append(d));
16+
17+
const initialValue = new URL(location as any).searchParams.get(
18+
"name"
19+
) as string;
20+
if (demos[initialValue]) select.value = initialValue;
21+
22+
let node;
23+
render();
24+
25+
function render() {
26+
if (node) node.remove();
27+
const demo = demos[select.value];
28+
node = demo();
29+
document.body.append(node);
30+
}
31+
32+
function onChange() {
33+
const { value } = select;
34+
history.pushState({ value }, "", `?name=${value}`);
35+
render();
36+
}

0 commit comments

Comments
 (0)