From 27e033ed1687491596d7bda049614dc93f2054dc Mon Sep 17 00:00:00 2001 From: xwj02155382 Date: Tue, 15 Apr 2025 18:14:14 +0800 Subject: [PATCH 01/12] feat: add canvas subpackage --- packages/studio-graph-canvas/.fatherrc.js | 4 + packages/studio-graph-canvas/.npmrc | 1 + packages/studio-graph-canvas/CHANGELOG.md | 137 ++++++ packages/studio-graph-canvas/README.md | 3 + packages/studio-graph-canvas/index.html | 18 + packages/studio-graph-canvas/index.tsx | 13 + packages/studio-graph-canvas/package.json | 55 +++ packages/studio-graph-canvas/src/app.tsx | 59 +++ .../src/elements/arrow-marker/index.tsx | 53 +++ .../src/elements/connection-line/index.tsx | 26 ++ .../src/elements/edge-types/graph-edge.tsx | 92 ++++ .../src/elements/edge-types/index.ts | 7 + .../src/elements/edge-types/label.tsx | 106 +++++ .../src/elements/edge-types/loop-edge.tsx | 67 +++ .../src/elements/edge-types/table-edge.tsx | 41 ++ .../src/elements/edge-types/useStyle.ts | 19 + .../src/elements/edge-types/utils.ts | 192 ++++++++ .../src/elements/forceLayout.tsx | 46 ++ .../studio-graph-canvas/src/elements/index.ts | 15 + .../src/elements/node-types/arrow.tsx | 8 + .../src/elements/node-types/graph-node.tsx | 162 +++++++ .../src/elements/node-types/index.ts | 8 + .../src/elements/node-types/table-node.tsx | 80 ++++ .../src/elements/processEdges.tsx | 126 ++++++ .../src/hooks/useInteractive.ts | 186 ++++++++ packages/studio-graph-canvas/src/index.tsx | 4 + .../studio-graph-canvas/src/store/index.ts | 91 ++++ packages/studio-graph-canvas/src/style.ts | 410 ++++++++++++++++++ .../studio-graph-canvas/src/types/index.ts | 55 +++ .../studio-graph-canvas/src/utils/index.ts | 28 ++ packages/studio-graph-canvas/tsconfig.json | 23 + packages/studio-graph-canvas/vite.config.ts | 37 ++ 32 files changed, 2172 insertions(+) create mode 100644 packages/studio-graph-canvas/.fatherrc.js create mode 100644 packages/studio-graph-canvas/.npmrc create mode 100644 packages/studio-graph-canvas/CHANGELOG.md create mode 100644 packages/studio-graph-canvas/README.md create mode 100644 packages/studio-graph-canvas/index.html create mode 100644 packages/studio-graph-canvas/index.tsx create mode 100644 packages/studio-graph-canvas/package.json create mode 100644 packages/studio-graph-canvas/src/app.tsx create mode 100644 packages/studio-graph-canvas/src/elements/arrow-marker/index.tsx create mode 100644 packages/studio-graph-canvas/src/elements/connection-line/index.tsx create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/graph-edge.tsx create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/index.ts create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/label.tsx create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/loop-edge.tsx create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/table-edge.tsx create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/useStyle.ts create mode 100644 packages/studio-graph-canvas/src/elements/edge-types/utils.ts create mode 100644 packages/studio-graph-canvas/src/elements/forceLayout.tsx create mode 100644 packages/studio-graph-canvas/src/elements/index.ts create mode 100644 packages/studio-graph-canvas/src/elements/node-types/arrow.tsx create mode 100644 packages/studio-graph-canvas/src/elements/node-types/graph-node.tsx create mode 100644 packages/studio-graph-canvas/src/elements/node-types/index.ts create mode 100644 packages/studio-graph-canvas/src/elements/node-types/table-node.tsx create mode 100644 packages/studio-graph-canvas/src/elements/processEdges.tsx create mode 100644 packages/studio-graph-canvas/src/hooks/useInteractive.ts create mode 100644 packages/studio-graph-canvas/src/index.tsx create mode 100644 packages/studio-graph-canvas/src/store/index.ts create mode 100644 packages/studio-graph-canvas/src/style.ts create mode 100644 packages/studio-graph-canvas/src/types/index.ts create mode 100644 packages/studio-graph-canvas/src/utils/index.ts create mode 100644 packages/studio-graph-canvas/tsconfig.json create mode 100644 packages/studio-graph-canvas/vite.config.ts diff --git a/packages/studio-graph-canvas/.fatherrc.js b/packages/studio-graph-canvas/.fatherrc.js new file mode 100644 index 000000000..c4f694d60 --- /dev/null +++ b/packages/studio-graph-canvas/.fatherrc.js @@ -0,0 +1,4 @@ +export default { + esm: { output: 'es' }, + cjs: { output: 'lib' }, +}; diff --git a/packages/studio-graph-canvas/.npmrc b/packages/studio-graph-canvas/.npmrc new file mode 100644 index 000000000..6ab414d06 --- /dev/null +++ b/packages/studio-graph-canvas/.npmrc @@ -0,0 +1 @@ +registry=http://registry.anpm.alibaba-inc.com \ No newline at end of file diff --git a/packages/studio-graph-canvas/CHANGELOG.md b/packages/studio-graph-canvas/CHANGELOG.md new file mode 100644 index 000000000..f545529bd --- /dev/null +++ b/packages/studio-graph-canvas/CHANGELOG.md @@ -0,0 +1,137 @@ +# @graphscope/studtio-graph-editor + +## 0.1.13 + +### Patch Changes + +- update site GS_ENGINE_TYPE window +- Updated dependencies + - @graphscope/studio-components@0.1.19 + +## 0.1.12 + +### Patch Changes + +- update website +- Updated dependencies + - @graphscope/studio-components@0.1.18 + +## 0.1.11 + +### Patch Changes + +- update website +- Updated dependencies + - @graphscope/studio-components@0.1.17 + +## 0.1.10 + +### Patch Changes + +- update website +- Updated dependencies + - @graphscope/studio-components@0.1.16 + +## 0.1.9 + +### Patch Changes + +- update website +- Updated dependencies + - @graphscope/studio-components@0.1.15 + +## 0.1.8 + +### Patch Changes + +- update studio graph +- Updated dependencies + - @graphscope/studio-components@0.1.14 + +## 0.1.7 + +### Patch Changes + +- update website +- Updated dependencies + - @graphscope/studio-components@0.1.13 + +## 0.1.6 + +### Patch Changes + +- update studio graph +- Updated dependencies + - @graphscope/studio-components@0.1.12 + +## 0.1.5 + +### Patch Changes + +- Updated dependencies + - @graphscope/studio-components@0.1.11 + +## 0.1.4 + +### Patch Changes + +- update studio-graph +- Updated dependencies + - @graphscope/studio-components@0.1.10 + +## 0.1.3 + +### Patch Changes + +- update studio +- Updated dependencies + - @graphscope/studio-components@0.1.9 + +## 0.1.2 + +### Patch Changes + +- update site +- Updated dependencies + - @graphscope/studio-components@0.1.8 + +## 0.1.1 + +### Patch Changes + +- Updated dependencies + - @graphscope/studio-components@0.1.7 + +## 0.1.4 + +### Patch Changes + +- update +- Updated dependencies + - @graphscope/studio-components@0.1.4 + - @graphscope/studio-importor@0.1.4 + +## 0.1.3 + +### Patch Changes + +- Updated dependencies + - @graphscope/studio-components@0.1.3 + - @graphscope/studio-importor@0.1.3 + +## 0.1.2 + +### Patch Changes + +- Updated dependencies + - @graphscope/studio-components@0.1.2 + - @graphscope/studio-importor@0.1.2 + +## 0.1.1 + +### Patch Changes + +- First Release +- Updated dependencies + - @graphscope/studio-components@0.1.1 + - @graphscope/studio-importor@0.1.1 diff --git a/packages/studio-graph-canvas/README.md b/packages/studio-graph-canvas/README.md new file mode 100644 index 000000000..b87570d29 --- /dev/null +++ b/packages/studio-graph-canvas/README.md @@ -0,0 +1,3 @@ +# Studio Graph Editor + +- warning: 目前还没有对 `Table-Node` 进行 `API` 支持。 \ No newline at end of file diff --git a/packages/studio-graph-canvas/index.html b/packages/studio-graph-canvas/index.html new file mode 100644 index 000000000..c96f69e74 --- /dev/null +++ b/packages/studio-graph-canvas/index.html @@ -0,0 +1,18 @@ + + + + + + Studio Graph Editor + + + +
+ + + diff --git a/packages/studio-graph-canvas/index.tsx b/packages/studio-graph-canvas/index.tsx new file mode 100644 index 000000000..806c38413 --- /dev/null +++ b/packages/studio-graph-canvas/index.tsx @@ -0,0 +1,13 @@ +import * as React from 'react'; +import GraphEditor from './src/index'; +import { createRoot } from 'react-dom/client'; + +interface IAppProps {} +const DrawGraph: React.FunctionComponent = props => { + return ( + + ); +}; + +// ReactDOM.render(, document.getElementById('root') as HTMLElement); +createRoot(document.getElementById('root')!).render(); diff --git a/packages/studio-graph-canvas/package.json b/packages/studio-graph-canvas/package.json new file mode 100644 index 000000000..788aaa845 --- /dev/null +++ b/packages/studio-graph-canvas/package.json @@ -0,0 +1,55 @@ +{ + "name": "@graphscope/studio-graph-canvas", + "version": "0.1.13", + "description": "", + "main": "lib/index.js", + "module": "es/index.js", + "types": "lib/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/GraphScope/portal.git" + }, + "files": [ + "es", + "lib", + "dist" + ], + "publishConfig": { + "access": "public", + "registry": "https://registry.npmjs.org/" + }, + "scripts": { + "start": "father dev", + "build": "father build", + "start:site": "vite dev", + "build:site": "vite build && tsc" + }, + "peerDependencies": { + "react": "18.2.0", + "react-dom": "18.2.0" + }, + "dependencies": { + "@graphscope/studio-components": "workspace:*", + "@graphscope/use-zustand": "workspace:*", + "antd": "^5.22.2", + "d3-force": "latest", + "dagre": "latest", + "html-to-image": "^1.11.11", + "immer": "^10.1.1", + "lodash": "^4.17.21", + "react-intl": "^6.6.1", + "reactflow": "latest", + "rxjs": "^7.8.1", + "uuid": "^9.0.1", + "valtio": "2.0.0-rc.1", + "zustand": "^4.5.5" + }, + "devDependencies": { + "@types/d3-force": "latest", + "@types/lodash": "^4.14.202", + "@vitejs/plugin-react": "^4.2.1", + "vite": "^5.4.16" + }, + "author": "", + "license": "ISC" +} diff --git a/packages/studio-graph-canvas/src/app.tsx b/packages/studio-graph-canvas/src/app.tsx new file mode 100644 index 000000000..1c97c56cb --- /dev/null +++ b/packages/studio-graph-canvas/src/app.tsx @@ -0,0 +1,59 @@ +import React from 'react'; +import { ReactFlow, ReactFlowProvider, applyNodeChanges } from 'reactflow'; +import useInteractive from './hooks/useInteractive'; +import { nodeTypes } from './elements/node-types'; +import { edgeTypes } from './elements/edge-types'; +import ArrowMarker from './elements/arrow-marker'; +import ConnectionLine from './elements/connection-line'; +import { theme } from 'antd'; +import type { ImportorProps } from './types'; + +const GraphCanvas: React.FC = ({ children, ...props }) => { + const { + nodes, + edges, + nodePositionChange, + onDoubleClick, + onEdgesChange, + onNodesChange, + onConnectStart, + onConnectEnd, + onReactFlowInit, + } = useInteractive(); + const { token } = theme.useToken(); + + const _nodes = nodePositionChange.length === 0 ? nodes : applyNodeChanges(nodePositionChange, nodes); + return ( +
+
+ + + {children} + +
+
+ ); +}; +export default (props: ImportorProps & { children?: React.ReactNode }) => { + return ( + + + + ); +}; diff --git a/packages/studio-graph-canvas/src/elements/arrow-marker/index.tsx b/packages/studio-graph-canvas/src/elements/arrow-marker/index.tsx new file mode 100644 index 000000000..74b689c49 --- /dev/null +++ b/packages/studio-graph-canvas/src/elements/arrow-marker/index.tsx @@ -0,0 +1,53 @@ +import React, { useEffect } from 'react'; + +import { theme } from 'antd'; + +interface IArrowMarkerProps { + selectedColor?: string; + color?: string; +} + +const ArrowMarker: React.FunctionComponent = props => { + const { token } = theme.useToken(); + const { selectedColor = token.colorPrimary, color = token.colorText } = props; + + return ( + + + + + + + + + + + + + + ); +}; + +export default ArrowMarker; diff --git a/packages/studio-graph-canvas/src/elements/connection-line/index.tsx b/packages/studio-graph-canvas/src/elements/connection-line/index.tsx new file mode 100644 index 000000000..93f7f8cde --- /dev/null +++ b/packages/studio-graph-canvas/src/elements/connection-line/index.tsx @@ -0,0 +1,26 @@ +import React from 'react'; + +export default ({ fromX, fromY, toX, toY }) => { + return ( + + + + + ); +}; diff --git a/packages/studio-graph-canvas/src/elements/edge-types/graph-edge.tsx b/packages/studio-graph-canvas/src/elements/edge-types/graph-edge.tsx new file mode 100644 index 000000000..6cf4786c7 --- /dev/null +++ b/packages/studio-graph-canvas/src/elements/edge-types/graph-edge.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { useCallback } from 'react'; +import { useStore } from 'reactflow'; +import type { EdgeProps } from 'reactflow'; +import { + getEdgeParams, + getBezierPointsWithOffsetsCorrected, + getControlPoint, + getSmoothPath, + calculateDegree, +} from './utils'; +import { useGraphStore } from '../../store'; +import LoopEdge from './loop-edge'; +import Label from './label'; +import { useStudioProvier } from '@graphscope/studio-components'; + +function GraphEdge(props: EdgeProps) { + const { id, source, target, style, data } = props; + const { _extra, label, filelocation, disabled } = data || {}; + const { offset = 0 } = _extra || {}; + const sourceNode = useStore(useCallback(store => store.nodeInternals.get(source), [source])); + const targetNode = useStore(useCallback(store => store.nodeInternals.get(target), [target])); + const { store } = useGraphStore(); + const { currentId, theme } = store; + const { isLight } = useStudioProvier(); + if (!sourceNode || !targetNode) { + return null; + } + const isLoop = source === target; + if (isLoop) { + return ; + } + + const isSelected = id === currentId; + + const { sx: sourceX, sy: sourceY, tx: targetX, ty: targetY } = getEdgeParams(sourceNode, targetNode); + + const controlPoint = getControlPoint({ sourceX, sourceY, targetX, targetY, offset }); + + const { P1, P2 } = getBezierPointsWithOffsetsCorrected({ + sourceX, + sourceY, + targetX, + targetY, + offset, + }); + + const [edgePath] = getSmoothPath({ + source: { + x: sourceX, + y: sourceY, + }, + target: { + x: targetX, + y: targetY, + }, + P1: P1, + P2: controlPoint, + P3: P2, + }); + + /** 计算标签和标签背景的旋转角度 */ + let degree = calculateDegree({ x: sourceX, y: sourceY }, { x: targetX, y: targetY }); + const getStroke = () => { + if (!isLight) { + return isSelected ? theme.primaryColor : '#d7d7d7'; + } + return isSelected ? theme.primaryColor : '#000'; + }; + return ( + <> + +