From 79c18aa59d84410f2d003965e921cff12d8b259c Mon Sep 17 00:00:00 2001 From: Aaron Date: Thu, 18 Apr 2024 10:05:05 +0800 Subject: [PATCH] feat: add HTML node, g node, react node (#5654) * feat(elements): add html node * fix: fix issue that unexpected invoke sequence cause exception * refactor: adjust exports * feat(react): create g6-extension-react * test: update test case * chore: update dependencies * fix: fix cr issue * chore: adjust jest config --- packages/g6-extension-3d/package.json | 2 +- .../__tests__/demos/g-node.tsx | 112 +++++++++ .../__tests__/demos/graph.tsx | 24 ++ .../__tests__/demos/index.tsx | 3 + .../__tests__/demos/react-node.tsx | 166 +++++++++++++ .../g6-extension-react/__tests__/index.html | 17 ++ .../g6-extension-react/__tests__/main.tsx | 47 ++++ .../__tests__/unit/default.spec.ts | 5 + packages/g6-extension-react/jest.config.js | 8 + packages/g6-extension-react/package.json | 54 ++++ packages/g6-extension-react/rollup.config.mjs | 30 +++ .../src/elements/g/index.ts | 4 + .../src/elements/g/node.tsx | 36 +++ .../src/elements/g/shapes.ts | 1 + .../g6-extension-react/src/elements/index.ts | 2 + .../src/elements/react/index.ts | 3 + .../src/elements/react/node.tsx | 36 +++ .../g6-extension-react/src/graph/graph.tsx | 44 ++++ .../g6-extension-react/src/graph/index.ts | 1 + packages/g6-extension-react/src/index.ts | 18 ++ .../g6-extension-react/tsconfig.build.json | 7 + packages/g6-extension-react/tsconfig.json | 12 + .../g6-extension-react/tsconfig.test.json | 7 + packages/g6-extension-react/vite.config.js | 16 ++ .../__tests__/bugs/continuous-invoke.spec.ts | 13 + .../g6/__tests__/demos/element-node-html.ts | 34 +++ packages/g6/__tests__/demos/index.ts | 1 + packages/g6/__tests__/unit/registry.spec.ts | 10 +- packages/g6/jest.config.js | 1 + packages/g6/src/constants/events/animation.ts | 4 - packages/g6/src/elements/nodes/base-node.ts | 4 +- packages/g6/src/elements/nodes/html.ts | 230 ++++++++++++++++++ packages/g6/src/elements/nodes/index.ts | 2 + packages/g6/src/exports.ts | 8 +- packages/g6/src/registry/build-in.ts | 6 +- packages/g6/src/runtime/graph.ts | 21 +- packages/g6/src/runtime/index.ts | 7 - 37 files changed, 967 insertions(+), 29 deletions(-) create mode 100644 packages/g6-extension-react/__tests__/demos/g-node.tsx create mode 100644 packages/g6-extension-react/__tests__/demos/graph.tsx create mode 100644 packages/g6-extension-react/__tests__/demos/index.tsx create mode 100644 packages/g6-extension-react/__tests__/demos/react-node.tsx create mode 100644 packages/g6-extension-react/__tests__/index.html create mode 100644 packages/g6-extension-react/__tests__/main.tsx create mode 100644 packages/g6-extension-react/__tests__/unit/default.spec.ts create mode 100644 packages/g6-extension-react/jest.config.js create mode 100644 packages/g6-extension-react/package.json create mode 100644 packages/g6-extension-react/rollup.config.mjs create mode 100644 packages/g6-extension-react/src/elements/g/index.ts create mode 100644 packages/g6-extension-react/src/elements/g/node.tsx create mode 100644 packages/g6-extension-react/src/elements/g/shapes.ts create mode 100644 packages/g6-extension-react/src/elements/index.ts create mode 100644 packages/g6-extension-react/src/elements/react/index.ts create mode 100644 packages/g6-extension-react/src/elements/react/node.tsx create mode 100644 packages/g6-extension-react/src/graph/graph.tsx create mode 100644 packages/g6-extension-react/src/graph/index.ts create mode 100644 packages/g6-extension-react/src/index.ts create mode 100644 packages/g6-extension-react/tsconfig.build.json create mode 100644 packages/g6-extension-react/tsconfig.json create mode 100644 packages/g6-extension-react/tsconfig.test.json create mode 100644 packages/g6-extension-react/vite.config.js create mode 100644 packages/g6/__tests__/bugs/continuous-invoke.spec.ts create mode 100644 packages/g6/__tests__/demos/element-node-html.ts create mode 100644 packages/g6/src/elements/nodes/html.ts delete mode 100644 packages/g6/src/runtime/index.ts diff --git a/packages/g6-extension-3d/package.json b/packages/g6-extension-3d/package.json index d0b52319c7e..213195ce213 100644 --- a/packages/g6-extension-3d/package.json +++ b/packages/g6-extension-3d/package.json @@ -42,7 +42,7 @@ "devDependencies": { "@antv/g": "^5.18.25", "@antv/g-canvas": "^1.11.27", - "@antv/g6": "^5.0.0-beta.30" + "@antv/g6": "workspace:*" }, "peerDependencies": { "@antv/g": "^5.18.25", diff --git a/packages/g6-extension-react/__tests__/demos/g-node.tsx b/packages/g6-extension-react/__tests__/demos/g-node.tsx new file mode 100644 index 00000000000..2d13d64b652 --- /dev/null +++ b/packages/g6-extension-react/__tests__/demos/g-node.tsx @@ -0,0 +1,112 @@ +import type { NodeData } from '@antv/g6'; +import { ExtensionCategory, register } from '@antv/g6'; +import { GNode, Group, Image, Rect, Text } from '../../src'; +import { Graph } from '../../src/graph'; + +register(ExtensionCategory.NODE, 'g', GNode); + +type Datum = { + name: string; + type: 'module' | 'process'; + status: 'success' | 'error'; + success: number; + time: number; + failure: number; +}; + +const Node = ({ data, size }: { data: NodeData; size: [number, number] }) => { + const [width, height] = size; + + const { name, type, status, success, time, failure } = data.data as Datum; + const color = status === 'success' ? '#30BF78' : '#F4664A'; + const radius = 4; + + const titleMap = { + success: 'Success', + time: 'Time', + failure: 'Failure', + }; + + const format = (cat: string, value: number) => { + if (cat === 'success') return `${value}%`; + if (cat === 'time') return `${value}min`; + return value.toString(); + }; + + const highlight = (cat: string, value: number) => { + if (cat === 'success') { + if (value >= 90) return 'green'; + if (value < 60) return 'red'; + return 'gray'; + } + if (cat === 'time') { + if (value <= 10) return 'green'; + if (value >= 30) return 'red'; + return 'gray'; + } + if (value >= 20) return 'red'; + if (value >= 5) return 'orange'; + return 'gray'; + }; + + return ( + + + + + + + + {Object.entries({ success, time, failure }).map(([key, value], index) => ( + + + + + ))} + + + + ); +}; + +export const GNodeDemo = () => { + return ( + , + }, + }, + behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'], + }} + /> + ); +}; diff --git a/packages/g6-extension-react/__tests__/demos/graph.tsx b/packages/g6-extension-react/__tests__/demos/graph.tsx new file mode 100644 index 00000000000..7eb229bbbd3 --- /dev/null +++ b/packages/g6-extension-react/__tests__/demos/graph.tsx @@ -0,0 +1,24 @@ +import { Graph } from '../../src/graph'; + +export const G6Graph = () => { + return ( + { + console.log('render'); + }} + onDestroy={() => { + console.log('destroy'); + }} + /> + ); +}; diff --git a/packages/g6-extension-react/__tests__/demos/index.tsx b/packages/g6-extension-react/__tests__/demos/index.tsx new file mode 100644 index 00000000000..a2cef959628 --- /dev/null +++ b/packages/g6-extension-react/__tests__/demos/index.tsx @@ -0,0 +1,3 @@ +export * from './g-node'; +export * from './graph'; +export * from './react-node'; diff --git a/packages/g6-extension-react/__tests__/demos/react-node.tsx b/packages/g6-extension-react/__tests__/demos/react-node.tsx new file mode 100644 index 00000000000..597f4ef84a0 --- /dev/null +++ b/packages/g6-extension-react/__tests__/demos/react-node.tsx @@ -0,0 +1,166 @@ +import { DatabaseFilled } from '@ant-design/icons'; +import type { Graph as G6Graph, G6Spec, NodeData } from '@antv/g6'; +import { ExtensionCategory, register } from '@antv/g6'; +import { Badge, Button, Flex, Form, Input, Layout, Select, Table, Tag, Typography } from 'antd'; +import { useRef, useState } from 'react'; +import { ReactNode } from '../../src'; +import { Graph } from '../../src/graph'; + +const { Content, Footer } = Layout; +const { Text } = Typography; + +register(ExtensionCategory.NODE, 'react', ReactNode); + +type Datum = { + name: string; + status: 'success' | 'error' | 'warning'; + type: 'local' | 'remote'; + url: string; +}; + +const Node = ({ data, onChange }: { data: NodeData; onChange?: (value: string) => void }) => { + const { status, type } = data.data as Datum; + + return ( + + + + + Server + {type} + + + + {data.id} + + + *URL: + + { + const url = event.target.value; + onChange?.(url); + }} + /> + + + ); +}; + +export const ReactNodeDemo = () => { + const graphRef = useRef(null); + + const [form] = Form.useForm(); + const isValidUrl = (url: string) => { + return /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_+.~#?&//=]*)/.test( + url, + ); + }; + + const [options, setOptions] = useState({ + data: { + nodes: [ + { + id: 'local-server-1', + data: { status: 'success', type: 'local', url: 'http://localhost:3000' }, + style: { x: 50, y: 50 }, + }, + { + id: 'remote-server-1', + data: { status: 'warning', type: 'remote' }, + style: { x: 350, y: 50 }, + }, + ], + }, + node: { + style: { + type: 'react', + size: [240, 100], + component: (data: NodeData) => ( + { + setOptions((prev) => { + if (!graphRef.current || graphRef.current.destroyed) return prev; + const nodes = graphRef.current.getNodeData(); + const index = nodes.findIndex((node) => node.id === data.id); + const node = nodes[index]; + const datum = { + ...node.data, + url, + status: url === '' ? 'warning' : isValidUrl(url) ? 'success' : 'error', + } as Datum; + nodes[index] = { ...node, data: datum }; + return { ...prev, data: { ...prev.data, nodes } }; + }); + }} + /> + ), + }, + }, + behaviors: ['drag-element', 'zoom-canvas', 'drag-canvas'], + }); + + return ( + + + (graphRef.current = graph)} /> + +