diff --git a/docs/useDocs/intro.md b/docs/useDocs/intro.md
index b3bca47..df7342a 100644
--- a/docs/useDocs/intro.md
+++ b/docs/useDocs/intro.md
@@ -6,5 +6,3 @@ group:
title: 为什么选择 ReactFlow ?
description:
---
-
-dsfsaf
diff --git a/docs/useDocs/quickDoc.md b/docs/useDocs/quickDoc.md
index ce0fff5..896bba0 100644
--- a/docs/useDocs/quickDoc.md
+++ b/docs/useDocs/quickDoc.md
@@ -8,4 +8,34 @@ order: 1
description:
---
-asd aws
+## 快速入门
+
+如果您想尽快启动并运行,那么您来对地方了! 此页面将在几分钟内带您从零到一创建一个有效的 ProFlow 应用程序。如果您想深入的了解 ProFlow 的全部内容,请查看示例,或深入了解 API 文档。
+
+## 安装
+
+若要在本地开始,应具备以下几点:
+
+- [Nodejs](https://nodejs.org/en) 安装
+- npm 或其他包管理工具,比如 [yarn](https://yarnpkg.com/) 或 [pnpm](https://pnpm.io/)
+- 以及 [React](https://reactjs.org/)的基础知识
+
+首先启动一个 React 应用,推荐使用 [vite](https://vitejs.dev/), 但选择权在你手中。
+
+```bash
+pnpm create vite@latest my-pro-flow-app --template react
+```
+
+ProFlow 在 npm 上发布为 [@ant-design/pro-flow](https://www.npmjs.com/package/@ant-design/pro-flow) ,推荐使用 pnpm 安装。
+
+```bash
+pnpm i @ant-design/pro-flow -S
+```
+
+最后 React 服务,就可以开始了。
+
+```bash
+pnpm run dev
+```
+
+## 创建第一个 ProFlow
diff --git a/src/Background/demos/double.tsx b/src/Background/demos/double.tsx
new file mode 100644
index 0000000..fb8a8fd
--- /dev/null
+++ b/src/Background/demos/double.tsx
@@ -0,0 +1,26 @@
+import { ProFlow } from '@/index';
+import { createStyles } from 'antd-style';
+import { memo } from 'react';
+import Background, { BackgroundVariant } from '..';
+
+const useStyles = createStyles(({ css }) => ({
+ container: css`
+ width: 100%;
+ height: 600px;
+ `,
+}));
+
+const BackgroundDemo = memo(() => {
+ const { styles } = useStyles();
+
+ return (
+
+ );
+});
+
+export default BackgroundDemo;
diff --git a/src/Background/demos/index.tsx b/src/Background/demos/index.tsx
new file mode 100644
index 0000000..c2ac14a
--- /dev/null
+++ b/src/Background/demos/index.tsx
@@ -0,0 +1,39 @@
+import { ProFlow } from '@/index';
+import { createStyles } from 'antd-style';
+import { memo, useState } from 'react';
+import { Panel } from 'reactflow';
+import Background, { BackgroundVariant } from '..';
+
+const useStyles = createStyles(({ css }) => ({
+ container: css`
+ width: 100%;
+ height: 600px;
+ `,
+}));
+
+const BackgroundDemo = memo(() => {
+ const [variant, setVariant] = useState(BackgroundVariant.Cross);
+ const { styles } = useStyles();
+
+ return (
+
+
+
+ variant:
+
+
+
+
+
+
+
+ );
+});
+
+export default BackgroundDemo;
diff --git a/src/Background/index.md b/src/Background/index.md
new file mode 100644
index 0000000..37614bb
--- /dev/null
+++ b/src/Background/index.md
@@ -0,0 +1,35 @@
+---
+group: 辅助
+title: Background 画布背景
+description: 配合ProFLow组件使用,控制背景展示
+---
+
+## Default
+
+
+
+## Double Background
+
+
+
+## APIs
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| --------- | --------------------------- | ------------------------------------------------------------------------ | ------ | ---- |
+| id | `string` | 如果要显示多个背景,则需要 | - | - |
+| className | `string` | 自定义类名 | - | - |
+| variant | `BackgroundVariant` | 背景图案类型 | - | - |
+| gap | `number \|[number, number]` | 模式之间的差距。您可以传递一个包含两个数字的数组来指定 x 间隙和 y 间隙。 | - | - |
+| size | `number` | ”点“的半径或”十字“的尺寸 | - | - |
+| lineWidth | `number` | ”线“或”十字“的宽度 | - | - |
+| offset | `number` | 图案偏移 | - | - |
+| color | `string` | 图案颜色 | - | - |
+| style | `CSSProperties` | 样式属性 | - | - |
+
+### BackgroundVariant
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | -------- | ---- | ------ | ---- |
+| lines | `string` | 线 | - | - |
+| dots | `string` | 点 | - | - |
+| cross | `string` | 十字 | - | - |
diff --git a/src/Background/index.tsx b/src/Background/index.tsx
new file mode 100644
index 0000000..f48d0a1
--- /dev/null
+++ b/src/Background/index.tsx
@@ -0,0 +1,22 @@
+import { CSSProperties } from 'react';
+import { Background, BackgroundVariant } from 'reactflow';
+
+interface BackgroundProps {
+ variant?: BackgroundVariant;
+ gap?: number | [number, number];
+ size?: number;
+ lineWidth?: number;
+ offset?: number;
+ color?: string;
+ style?: CSSProperties;
+ className?: string;
+ id?: string;
+}
+
+export default (props: BackgroundProps) => {
+ const { gap = 10, color = '#bac3d4' } = props;
+
+ return ;
+};
+
+export { BackgroundVariant };
diff --git a/src/ControlInput/index.md b/src/ControlInput/index.md
index 065e60c..ddfef30 100644
--- a/src/ControlInput/index.md
+++ b/src/ControlInput/index.md
@@ -1,6 +1,6 @@
---
title: ControlInput 可控输入框
-group: 输入控件
+group: 控件
description: 针对编辑场景优化的输入框控件
---
diff --git a/src/EditableText/index.md b/src/EditableText/index.md
index 0abdfd6..006d733 100644
--- a/src/EditableText/index.md
+++ b/src/EditableText/index.md
@@ -1,5 +1,5 @@
---
-group: 输入控件
+group: 控件
title: EditableText 可编辑文本
description: EditableText is a component that allows users to edit text inline. It displays the text in a non-editable state by default, but when the user clicks the edit icon, it switches to an editable input field where the user can make changes. Once the user is done editing, they can click outside the input field or press the enter key to save the changes. The component uses the ControlInput component to display the input field and passes the value and onChange props to it.
---
diff --git a/src/FlowPanel/demos/index.tsx b/src/FlowPanel/demos/index.tsx
new file mode 100644
index 0000000..144fd43
--- /dev/null
+++ b/src/FlowPanel/demos/index.tsx
@@ -0,0 +1,29 @@
+import { ProFlow } from '@/index';
+import { createStyles } from 'antd-style';
+import { memo } from 'react';
+import FlowPanel from '..';
+
+const useStyles = createStyles(({ css }) => ({
+ container: css`
+ width: 100%;
+ height: 600px;
+ `,
+}));
+
+const FlowControllerDemo = memo(() => {
+ const { styles } = useStyles();
+ return (
+
+
+ top-left
+ top-center
+ top-right
+ bottom-left
+ bottom-center
+ bottom-right
+
+
+ );
+});
+
+export default FlowControllerDemo;
diff --git a/src/FlowPanel/index.md b/src/FlowPanel/index.md
new file mode 100644
index 0000000..82ef992
--- /dev/null
+++ b/src/FlowPanel/index.md
@@ -0,0 +1,24 @@
+---
+group: 辅助
+title: FlowPanel 画布面板
+description: 配合ProFLow组件使用,提供一个展示在画布上的面板
+---
+
+## Default
+
+
+
+## APIs
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| --------- | ----------------- | -------------------- | ------ | ---- |
+| className | `string` | 自定义类名 | - | - |
+| visible | `boolean` | 是否展示 | - | - |
+| position | `MiniMapPosition` | 控制器在画布中的坐标 | - | - |
+
+### MiniMapPosition
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | -------- | ------------------------------ | ------ | ---- |
+| x | `number` | x 坐标,正数向左偏移,负数反之 | 0 | - |
+| y | `number` | y 坐标,正数向上偏移,负数反之 | 0 | - |
diff --git a/src/FlowPanel/index.tsx b/src/FlowPanel/index.tsx
new file mode 100644
index 0000000..c4a6e95
--- /dev/null
+++ b/src/FlowPanel/index.tsx
@@ -0,0 +1,16 @@
+import { Panel, PanelPosition } from 'reactflow';
+
+interface PanelProps {
+ position?: PanelPosition;
+ children: React.ReactNode;
+ className?: string;
+ style?: React.CSSProperties;
+}
+
+export default (props: PanelProps) => {
+ const { position = 'top-left', children } = props;
+
+ return {children};
+};
+
+export { PanelPosition };
diff --git a/src/FlowStoreProvider/index.md b/src/FlowStoreProvider/index.md
index 15c8d46..a79fc8a 100644
--- a/src/FlowStoreProvider/index.md
+++ b/src/FlowStoreProvider/index.md
@@ -2,7 +2,7 @@
title: FlowStoreProvider 流数据容器
atomId: FlowStoreProvider
nav: 组件
-group: 容器组件
+group: 辅助
---
# FlowStoreProvider
diff --git a/src/ProFlow/FlowView.tsx b/src/FlowView/FlowView.tsx
similarity index 82%
rename from src/ProFlow/FlowView.tsx
rename to src/FlowView/FlowView.tsx
index 7eb3360..37cb539 100644
--- a/src/ProFlow/FlowView.tsx
+++ b/src/FlowView/FlowView.tsx
@@ -1,10 +1,10 @@
-import { ProFlowProps } from '@/constants';
+import { FlowViewProps } from '@/constants';
import { FC, useContext } from 'react';
import FlowView from '.';
import { FlowViewProvider } from './provider/FlowViewProvider';
import { FlowViewContext } from './provider/provider';
-const ProFlow: FC = (props) => {
+const ProFlow: FC = (props) => {
const { isUseProvider } = useContext(FlowViewContext);
if (isUseProvider) {
diff --git a/src/FlowView/components/DefaultNode.tsx b/src/FlowView/components/DefaultNode.tsx
new file mode 100644
index 0000000..1dce259
--- /dev/null
+++ b/src/FlowView/components/DefaultNode.tsx
@@ -0,0 +1,12 @@
+import { DefaultNodeData } from '@/constants';
+import { FC } from 'react';
+import { useStyles } from '../styles';
+
+const DefaultNode: FC = (props) => {
+ const { styles, cx } = useStyles();
+ const { className, children } = props;
+
+ return {children}
;
+};
+
+export default DefaultNode;
diff --git a/src/ProFlow/constants.tsx b/src/FlowView/constants.tsx
similarity index 88%
rename from src/ProFlow/constants.tsx
rename to src/FlowView/constants.tsx
index 1f1a2d2..e8da36a 100644
--- a/src/ProFlow/constants.tsx
+++ b/src/FlowView/constants.tsx
@@ -1,5 +1,5 @@
import { Node } from 'reactflow';
-import { ProFlowNode, ProFlowNodeData } from '../constants';
+import { DefaultNodeType, FlowNodeType, NodeTypeDataMap } from '../constants';
export enum NodeSelect {
SELECT = 'SELECT',
@@ -15,7 +15,7 @@ export interface InitialNode extends Node {
height?: number;
}
-export interface NodeMapItem {
+export interface NodeMapItem> {
id: string;
key?: string;
left?: string[];
@@ -29,6 +29,7 @@ export interface NodeMapItem {
danger?: boolean;
dangerCount?: number;
type?: 'input' | 'output' | 'default';
+ flowNodeType?: T;
className?: string;
select?: NodeSelect;
isGroup?: boolean;
@@ -38,7 +39,7 @@ export interface NodeMapItem {
qualityScore?: string;
subDanger?: boolean;
logo?: string;
- data: ProFlowNodeData | ProFlowNode[];
+ data: NodeTypeDataMap[T];
nodeType?: string;
zoom?: number;
label?: string;
diff --git a/src/ProFlow/demos/ProFlowDemo.tsx b/src/FlowView/demos/ProFlowDemo.tsx
similarity index 92%
rename from src/ProFlow/demos/ProFlowDemo.tsx
rename to src/FlowView/demos/ProFlowDemo.tsx
index abf8d96..0bc8765 100644
--- a/src/ProFlow/demos/ProFlowDemo.tsx
+++ b/src/FlowView/demos/ProFlowDemo.tsx
@@ -1,4 +1,4 @@
-import { EdgeType, NodeSelect, ProFlowEdge, ProFlowNode } from '@/index';
+import { EdgeType, FlowViewEdge, FlowViewNode, NodeSelect } from '@/index';
import { ProFlow } from '@ant-design/pro-flow';
import { Progress } from 'antd';
import { createStyles } from 'antd-style';
@@ -49,14 +49,13 @@ const DangerLogo = styled.div`
}
`;
-const nodes: ProFlowNode[] = [
+const nodes: FlowViewNode[] = [
{
id: 'a1',
label: '123',
+ type: 'default',
data: {
- title: 'XXX数据源',
- describe: 'cksadjfnf',
- logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*jWDsQ5GTmHMAAAAAAAAAAAAADvuvAQ/original',
+ children: default node, 123123
,
},
},
{
@@ -118,8 +117,8 @@ const nodes: ProFlowNode[] = [
},
{
id: 'd1',
- group: true,
label: '456',
+ type: 'lineageGroup',
data: [
{
id: 'a5',
@@ -181,7 +180,7 @@ const nodes: ProFlowNode[] = [
},
];
-const edges: ProFlowEdge[] = [
+const edges: FlowViewEdge[] = [
{
id: 'a1-b1',
source: 'a1',
@@ -240,11 +239,11 @@ const edges: ProFlowEdge[] = [
];
const ProFlowDemo = () => {
- const [_nodes, setNodes] = useState([...nodes]);
- const [_edges, setEdges] = useState([...edges]);
+ const [_nodes, setNodes] = useState([...nodes]);
+ const [_edges, setEdges] = useState([...edges]);
const { styles } = useStyles();
- const handleHighlight = (node: ProFlowNode) => {
+ const handleHighlight = (node: FlowViewNode) => {
_nodes.forEach((_node) => {
if (_node.id === node.id) {
_node.select = NodeSelect.SELECT;
diff --git a/src/ProFlow/helper.tsx b/src/FlowView/helper.tsx
similarity index 72%
rename from src/ProFlow/helper.tsx
rename to src/FlowView/helper.tsx
index b76a2e1..57392b4 100644
--- a/src/ProFlow/helper.tsx
+++ b/src/FlowView/helper.tsx
@@ -1,9 +1,18 @@
-import BloodNodeGroup from '@/BloodGroupNode';
-import BloodNode from '@/BloodNode';
-import { EdgeType, ProFlowEdge, ProFlowNode, ProFlowNodeData } from '@/constants';
+import LineageNodeGroup from '@/LineageGroupNode';
+import LineageNode from '@/LineageNode';
+import {
+ DefaultNodeData,
+ EdgeType,
+ FlowViewEdge,
+ FlowViewNode,
+ LineageGroupNodeData,
+ LineageNodeData,
+ NodeHandler,
+} from '@/constants';
import Dagre from '@dagrejs/dagre';
import { cx } from 'antd-style';
import { Edge, Node, Position } from 'reactflow';
+import DefaultNode from './components/DefaultNode';
import {
EDGE_DANGER,
EDGE_SELECT,
@@ -18,6 +27,7 @@ import {
NodeSelect,
} from './constants';
+// 这里的type是指节点的连接点在哪里,input是在左边,output是在右边,default是左右两边都有
function getTypeFromEdge(node: NodeMapItem) {
if (node.left?.length && node.right?.length) {
return 'default';
@@ -31,16 +41,18 @@ function getTypeFromEdge(node: NodeMapItem) {
return 'default';
}
-export function convertMappingFrom(nodes: ProFlowNode[], edges: ProFlowEdge[], zoom: number) {
+export function convertMappingFrom(nodes: FlowViewNode[], edges: FlowViewEdge[], zoom: number) {
const mapping: NodeMapping = {};
nodes.forEach((node) => {
+ const { type = 'lineage' } = node;
+
mapping[node.id] = {
id: node.id,
- group: node.group,
- width: node.group ? 355 : 322,
- height: node.group ? 1100 : 85,
+ // width: width ? width : node.group ? 355 : 322,
+ // height: height ? height : node.group ? 1100 : 85,
data: node.data,
select: node.select,
+ flowNodeType: type,
right: [],
left: [],
zoom,
@@ -141,7 +153,7 @@ function getEdgeClsFromNodeSelect(select: NodeSelect) {
// }
// }
-export function getRenderEdges(edges: ProFlowEdge[]) {
+export function getRenderEdges(edges: FlowViewEdge[]) {
return edges.map((edge) => {
const { source, target, select = NodeSelect.DEFAULT, type } = edge;
@@ -161,9 +173,41 @@ export function getRenderEdges(edges: ProFlowEdge[]) {
// })
}
+const NodeComponentHandler: NodeHandler = {
+ default: (node: NodeMapItem) => ,
+ lineage: (node: NodeMapItem) => {
+ const { select = NodeSelect.DEFAULT } = node;
+
+ return (
+
+ );
+ },
+ lineageGroup: (node: NodeMapItem) => {
+ const { select = NodeSelect.DEFAULT } = node;
+
+ return (
+
+ );
+ },
+};
+
export const getRenderData = (
mapping: NodeMapping,
- edges: ProFlowEdge[],
+ edges: FlowViewEdge[],
): {
nodes: Node[];
edges: Edge[];
@@ -174,7 +218,7 @@ export const getRenderData = (
Object.keys(mapping).forEach((id) => {
const node = mapping[id];
- const { select = NodeSelect.DEFAULT } = node;
+ const { flowNodeType } = node;
renderNodes.push({
sourcePosition: Position.Right,
@@ -186,26 +230,7 @@ export const getRenderData = (
height: node.group ? 1100 : 83,
className: cx(INIT_NODE),
data: {
- label: node.group ? (
-
- ) : (
-
- ),
+ label: NodeComponentHandler[flowNodeType!](node),
},
});
});
diff --git a/src/ProFlow/hooks/useFlowView.ts b/src/FlowView/hooks/useFlowView.ts
similarity index 94%
rename from src/ProFlow/hooks/useFlowView.ts
rename to src/FlowView/hooks/useFlowView.ts
index fad59cc..9c6c18c 100644
--- a/src/ProFlow/hooks/useFlowView.ts
+++ b/src/FlowView/hooks/useFlowView.ts
@@ -13,7 +13,7 @@ export const useMiniMap = () => {
const { setMiniMapPosition: setPosition } = useContext(FlowViewContext);
const setMiniMapPosition = (x: number, y: number) => {
- setPosition!([x, y]);
+ setPosition!({ x, y });
};
return {
diff --git a/src/FlowView/index.md b/src/FlowView/index.md
new file mode 100644
index 0000000..b3a38ec
--- /dev/null
+++ b/src/FlowView/index.md
@@ -0,0 +1,90 @@
+---
+group: 画布
+title: FlowView 基础画布容器
+description:
+---
+
+## default
+
+
+
+## API
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ---------- | ----------------- | -------- | ------ | ---- |
+| nodes | `FlowViewNode` | 边数据 | - | - |
+| edges | `FlowViewEdge` | 节点数据 | - | - |
+| className | `string` | 边数据 | - | - |
+| style | `CSSProperties` | 节点数据 | - | - |
+| miniMap | `boolean` | 边数据 | - | - |
+| background | `boolean` | 节点数据 | - | - |
+| children | `React.ReactNode` | 边数据 | - | - |
+
+### FlowViewNode
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | ---------------------------------------------- | ------------ | ------ | ---- |
+| id | `string` | 边数据 | - | - |
+| select | `NodeSelect` | 节点数据 | - | - |
+| data | `NodeTypeDataMap[T]` | 边数据 | - | - |
+| type | `T = 'default' \| 'lineage' \| 'lineageGroup'` | 节点类型() | - | - |
+| label | `string` | 边数据 | - | - |
+| width | `number` | 节点数据 | - | - |
+| height | `number` | 边数据 | - | - |
+
+#### NodeTypeDataMap[T]
+
+```ts
+export interface NodeTypeDataMap {
+ default: DefaultNodeData;
+ lineage: LineageNodeData;
+ lineageGroup: LineageGroupNodeData[];
+}
+```
+
+#### DefaultNodeData
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| --------- | ----------------- | ------ | ------ | ---- |
+| className | `string` | 类名 | - | - |
+| children | `React.ReactNode` | 子组件 | - | - |
+
+#### LineageNodeData
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| --------- | ----------------------------------------------------- | ---- | ------ | ---- |
+| title | `string` | 类名 | - | - |
+| describe | `string` | 描述 | - | - |
+| logo | `string` | logo | - | - |
+| titleSlot | `{ type: 'left' \| 'right', value: React.ReactNode }` | 插槽 | - | - |
+
+#### LineageGroupNodeData
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | ----------------- | ------ | ------ | ---- |
+| id | `string` | 类名 | - | - |
+| data | `LineageNodeData` | 子组件 | - | - |
+
+#### NodeSelect
+
+```ts
+export enum NodeSelect {
+ SELECT = 'SELECT',
+ SUB_SELECT = 'SUB_SELECT',
+ DANGER = 'DANGER',
+ SUB_DANGER = 'SUB_DANGER',
+ WARNING = 'WARNING',
+ SUB_WARNING = 'SUB_WARNING',
+ DEFAULT = 'DEFAULT',
+}
+```
+
+### FlowViewEdge
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | ----------------------------------- | ----------- | ------ | ---- |
+| id | `string` | 唯一 id | - | - |
+| source | `string` | 来源节点 id | - | - |
+| target | `string` | 目标节点 id | - | - |
+| select | `NodeSelect` | 选中状态 | - | - |
+| type | `EdgeType = 'default' \| 'radius' ` | 边缘类型 | - | - |
diff --git a/src/ProFlow/index.tsx b/src/FlowView/index.tsx
similarity index 77%
rename from src/ProFlow/index.tsx
rename to src/FlowView/index.tsx
index 6bf330b..5264cde 100644
--- a/src/ProFlow/index.tsx
+++ b/src/FlowView/index.tsx
@@ -5,9 +5,10 @@ import React, {
useMemo,
type MouseEvent as ReactMouseEvent,
} from 'react';
-import ReactFlow, { Background, BackgroundVariant, Edge, Node, useViewport } from 'reactflow';
+import ReactFlow, { Edge, Node, useViewport } from 'reactflow';
import 'reactflow/dist/style.css';
-import { ProFlowController, ProFlowProps, RadiusEdge } from '../index';
+import Background, { BackgroundVariant } from '../Background';
+import { FlowViewProps, ProFlowController, RadiusEdge } from '../index';
import { convertMappingFrom, getRenderData } from './helper';
import { FlowViewContext } from './provider/provider';
import { useStyles } from './styles';
@@ -16,7 +17,7 @@ const MIN_ZOOM = 0.1;
export const FlowContext = createContext({});
const initFn = () => {};
-const FlowView: React.FC> = (props) => {
+const FlowView: React.FC> = (props) => {
const {
onNodeDragStart = initFn,
onPaneClick = initFn,
@@ -25,6 +26,7 @@ const FlowView: React.FC> = (props) => {
edges,
miniMap = true,
children,
+ background = true,
} = props;
const { styles, cx } = useStyles();
const { zoom } = useViewport();
@@ -53,7 +55,7 @@ const FlowView: React.FC> = (props) => {
// console.log(reactFlowInstance);
const handleNodeDragStart = useCallback(
(event: ReactMouseEvent, node: Node, nodes: Node[]) => {
- // TODO: 应当把事件中的 node 转换为 ProFlowNode 透出给用户
+ // TODO: 应当把事件中的 node 转换为 FlowViewNode 透出给用户
// const {node} = transformNode(node);
onNodeDragStart(event, node, nodes);
},
@@ -62,7 +64,7 @@ const FlowView: React.FC> = (props) => {
const handlePaneClick = useCallback(
(event: ReactMouseEvent) => {
- // TODO: 应当把事件中的 node 转换为 ProFlowNode 透出给用户
+ // TODO: 应当把事件中的 node 转换为 FlowViewNode 透出给用户
// const {node} = transformNode(node);
onPaneClick(event);
},
@@ -71,7 +73,7 @@ const FlowView: React.FC> = (props) => {
const handleNodeClick = useCallback(
(event: ReactMouseEvent, node: Node) => {
- // TODO: 应当把事件中的 node 转换为 ProFlowNode 透出给用户
+ // TODO: 应当把事件中的 node 转换为 FlowViewNode 透出给用户
// const {node} = transformNode(node);
onNodeClick(event, node);
},
@@ -97,14 +99,15 @@ const FlowView: React.FC> = (props) => {
{miniMap && (
)}
-
{children}
+ {background && (
+
+ )}
);
};
diff --git a/src/ProFlow/provider/FlowViewProvider.tsx b/src/FlowView/provider/FlowViewProvider.tsx
similarity index 84%
rename from src/ProFlow/provider/FlowViewProvider.tsx
rename to src/FlowView/provider/FlowViewProvider.tsx
index 2c366b3..39b0c49 100644
--- a/src/ProFlow/provider/FlowViewProvider.tsx
+++ b/src/FlowView/provider/FlowViewProvider.tsx
@@ -1,10 +1,11 @@
+import { MiniMapPosition } from '@/constants';
import { FC, ReactNode, useState } from 'react';
import { ReactFlowProvider, useReactFlow } from 'reactflow';
import { FlowViewContext } from './provider';
// 数据处理层
const ProviderInner: FC<{ children: ReactNode }> = ({ children }) => {
- const [miniMapPosition, setMiniMapPosition] = useState<[number, number]>([0, 0]);
+ const [miniMapPosition, setMiniMapPosition] = useState({ x: 0, y: 0 });
const reactFlowInstance = useReactFlow();
return (
diff --git a/src/ProFlow/provider/provider.ts b/src/FlowView/provider/provider.ts
similarity index 62%
rename from src/ProFlow/provider/provider.ts
rename to src/FlowView/provider/provider.ts
index 5570bfb..1dd70a0 100644
--- a/src/ProFlow/provider/provider.ts
+++ b/src/FlowView/provider/provider.ts
@@ -1,11 +1,12 @@
+import { MiniMapPosition } from '@/constants';
import { createContext } from 'react';
import { ReactFlowInstance } from 'reactflow';
interface FlowViewContextProps {
isUseProvider?: boolean;
reactFlowInstance?: ReactFlowInstance;
- miniMapPosition?: [number, number];
- setMiniMapPosition?: React.Dispatch>;
+ miniMapPosition?: MiniMapPosition;
+ setMiniMapPosition?: React.Dispatch>;
}
export const FlowViewContext = createContext({});
diff --git a/src/FlowView/styles.tsx b/src/FlowView/styles.tsx
new file mode 100644
index 0000000..d513251
--- /dev/null
+++ b/src/FlowView/styles.tsx
@@ -0,0 +1,169 @@
+import { createStyles } from 'antd-style';
+import {
+ EDGE_DANGER,
+ EDGE_SELECT,
+ EDGE_SUB_DANGER,
+ EDGE_SUB_SELECT,
+ EDGE_SUB_WARNING,
+ EDGE_WARNING,
+ INIT_NODE,
+} from './constants';
+
+export const useStyles = createStyles(({ css, cx }) => ({
+ container: css`
+ width: 100%;
+ height: 100%;
+
+ .react-flow__attribution {
+ display: none;
+ }
+
+ .${INIT_NODE} {
+ padding: 0;
+ box-sizing: border-box;
+ width: 320px;
+ height: 83px;
+ border: none;
+ border-radius: 8px;
+ cursor: pointer;
+ z-index: 1;
+ }
+
+ .${EDGE_SELECT} path {
+ stroke: #1677ff;
+ stroke-width: 2;
+ z-index: 100;
+ }
+
+ .${EDGE_SUB_SELECT} path {
+ stroke: #1677ff;
+ stroke-width: 1;
+ z-index: 100;
+ }
+
+ .${EDGE_DANGER} path {
+ stroke: #f7636e;
+ stroke-width: 2;
+ z-index: 100;
+ }
+
+ .${EDGE_SUB_DANGER} path {
+ stroke: #f7636e;
+ stroke-width: 1;
+ z-index: 100;
+ }
+
+ .${EDGE_WARNING} path {
+ stroke: #ef9d3b;
+ stroke-width: 2;
+ z-index: 100;
+ }
+
+ .${EDGE_SUB_WARNING} path {
+ stroke: #ef9d3b;
+ stroke-width: 1;
+ z-index: 100;
+ }
+
+ .selectable:focus {
+ box-shadow: none !important;
+ }
+
+ .selected {
+ box-shadow: none !important;
+ }
+ `,
+ nodeWrap: cx(
+ css`
+ width: 320px;
+ height: 85px;
+ display: flex;
+ z-index: 10 !important;
+ position: absolute;
+ border-radius: 8px;
+ padding: 16px 12px;
+ box-sizing: border-box;
+ /* border: 3px solid white; */
+ flex: 1;
+ background: #ffffff;
+ border: 1px solid rgba(255, 255, 255, 0.04);
+ box-shadow: 0 4px 6px -2px rgba(25, 15, 15, 0.05), 0 0 1px 0 rgba(0, 0, 0, 0.08);
+
+ .img {
+ width: 48px;
+ height: 48px;
+ }
+
+ .content {
+ width: 230px;
+ margin-left: 13px;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+ align-items: flex-start;
+
+ .title {
+ width: 100%;
+ display: flex;
+ flex: 1;
+
+ span {
+ font-size: 16px;
+ color: rgba(0, 0, 0, 85%);
+ line-height: 22px;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-align: left;
+ }
+
+ .dangerLogo {
+ width: 28px;
+ height: 16px;
+ background: #ffeef1;
+ border-radius: 7px;
+ margin-left: 8px;
+ margin-top: 3px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ img {
+ width: 8px;
+ height: 9px;
+ }
+ }
+ }
+
+ .des {
+ font-size: 14px;
+ color: rgba(0, 0, 0, 45%);
+ line-height: 20px;
+ white-space: nowrap;
+ width: 100%;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-align: left;
+ }
+ }
+ `,
+ ),
+ nodeSelected: css`
+ box-shadow: 0 0 0 3px #1677ff, 0 1px 4px 1px rgba(0, 0, 0, 8%) !important;
+ `,
+ nodeSubSelected: css`
+ box-shadow: 0 0 0 1px #1677ff, 0 1px 4px 1px rgba(0, 0, 0, 8%) !important;
+ `,
+ nodeDanger: css`
+ box-shadow: 0 0 0 3px #f7636e, 0 1px 4px 1px rgba(0, 0, 0, 8%);
+ `,
+ nodeSubDanger: css`
+ box-shadow: 0 0 0 1px #f7636e, 0 1px 4px 1px rgba(0, 0, 0, 8%) !important;
+ `,
+ nodeWarning: css`
+ box-shadow: 0 0 0 3px #ef9d3b, 0 1px 4px 1px rgba(0, 0, 0, 8%) !important;
+ `,
+ nodeSubWarning: css`
+ box-shadow: 0 0 0 1px #ef9d3b, 0 1px 4px 1px rgba(0, 0, 0, 8%) !important;
+ `,
+ nodeDefault: css``,
+}));
diff --git a/src/BloodGroupNode/constants.ts b/src/LineageGroupNode/constants.ts
similarity index 100%
rename from src/BloodGroupNode/constants.ts
rename to src/LineageGroupNode/constants.ts
diff --git a/src/LineageGroupNode/demos/index.tsx b/src/LineageGroupNode/demos/index.tsx
new file mode 100644
index 0000000..b985472
--- /dev/null
+++ b/src/LineageGroupNode/demos/index.tsx
@@ -0,0 +1,210 @@
+import { FlowViewEdge, FlowViewNode, NodeSelect } from '@/index';
+import { ProFlow } from '@ant-design/pro-flow';
+import { createStyles } from 'antd-style';
+import { useState } from 'react';
+
+const useStyles = createStyles(({ css }) => ({
+ container: css`
+ width: 100%;
+ height: 600px;
+ .ant-progress-text {
+ text-align: center !important;
+ }
+ `,
+}));
+
+const nodes: FlowViewNode[] = [
+ {
+ id: 'd1',
+ label: 'group1',
+ type: 'lineageGroup',
+ data: [
+ {
+ id: 'a5',
+ data: {
+ title: 'XXX数据源',
+ describe: 'cksadjfnf',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*jWDsQ5GTmHMAAAAAAAAAAAAADvuvAQ/original',
+ },
+ },
+ {
+ id: 'a6',
+ data: {
+ title: 'XXX_API',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*kgyiRKi04eUAAAAAAAAAAAAADvuvAQ/original',
+ describe: 'XXX_XXX_XXX_API',
+ },
+ },
+ {
+ id: 'a7',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ {
+ id: 'a8',
+ data: {
+ title: 'XXX数据源',
+ describe: 'cksadjfnf',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*jWDsQ5GTmHMAAAAAAAAAAAAADvuvAQ/original',
+ },
+ },
+ {
+ id: 'a9',
+ data: {
+ title: 'XXX_API',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*kgyiRKi04eUAAAAAAAAAAAAADvuvAQ/original',
+ describe: 'XXX_XXX_XXX_API',
+ },
+ },
+ {
+ id: 'a10',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ {
+ id: 'a11',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ ],
+ },
+ {
+ id: 'd2',
+ label: 'group2',
+ type: 'lineageGroup',
+ data: [
+ {
+ id: 'a5',
+ data: {
+ title: 'XXX数据源',
+ describe: 'cksadjfnf',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*jWDsQ5GTmHMAAAAAAAAAAAAADvuvAQ/original',
+ },
+ },
+ {
+ id: 'a6',
+ data: {
+ title: 'XXX_API',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*kgyiRKi04eUAAAAAAAAAAAAADvuvAQ/original',
+ describe: 'XXX_XXX_XXX_API',
+ },
+ },
+ {
+ id: 'a7',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ {
+ id: 'a8',
+ data: {
+ title: 'XXX数据源',
+ describe: 'cksadjfnf',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*jWDsQ5GTmHMAAAAAAAAAAAAADvuvAQ/original',
+ },
+ },
+ {
+ id: 'a9',
+ data: {
+ title: 'XXX_API',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*kgyiRKi04eUAAAAAAAAAAAAADvuvAQ/original',
+ describe: 'XXX_XXX_XXX_API',
+ },
+ },
+ {
+ id: 'a10',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ {
+ id: 'a11',
+ data: {
+ title: 'XXXX产品',
+ logo: 'https://mdn.alipayobjects.com/huamei_ntgeqc/afts/img/A*ezaYT4wYRBwAAAAAAAAAAAAADvuvAQ/original',
+ describe: '2031030213014',
+ },
+ },
+ ],
+ },
+];
+
+const edges = [
+ {
+ id: 'b12',
+ source: 'd1',
+ target: 'd2',
+ },
+];
+
+const ProFlowDemo = () => {
+ const [_nodes, setNodes] = useState(nodes);
+ const [_edges, setEdges] = useState(edges);
+ const { styles } = useStyles();
+
+ const handleHighlight = (node: FlowViewNode) => {
+ setNodes(
+ _nodes.map((_node) => {
+ if (_node.id === node.id) {
+ _node.select = NodeSelect.SELECT;
+ }
+ return _node;
+ }),
+ );
+ setEdges(
+ _edges.map((edge) => {
+ if (edge.source === node.id || edge.target === node.id) {
+ edge.select = NodeSelect.SUB_SELECT;
+ }
+ return {
+ ...edge,
+ };
+ }),
+ );
+ };
+
+ const handleUnHighlight = () => {
+ setNodes(
+ _nodes.map((_node) => {
+ _node.select = NodeSelect.DEFAULT;
+ return _node;
+ }),
+ );
+ setEdges(
+ _edges.map((edge) => {
+ edge.select = NodeSelect.DEFAULT;
+ return edge;
+ }),
+ );
+ };
+
+ return (
+
+
handleHighlight(node)}
+ onPaneClick={handleUnHighlight}
+ nodes={_nodes}
+ edges={_edges}
+ >
+
+ );
+};
+
+const FlowDemo = () => {
+ return ;
+};
+
+export default FlowDemo;
diff --git a/src/LineageGroupNode/index.md b/src/LineageGroupNode/index.md
new file mode 100644
index 0000000..6f33a65
--- /dev/null
+++ b/src/LineageGroupNode/index.md
@@ -0,0 +1,25 @@
+---
+group: 节点
+title: LineageGroupNode 血缘组节点
+description: 无法单独使用。在FlowView中将节点类型设置为'lineage'后使用。
+---
+
+## Default
+
+
+
+## API
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| ------ | ----------------- | -------- | ------ | ---- |
+| id | `string` | 节点标题 | - | - |
+| data | `LineageNodeData` | 节点描述 | - | - |
+
+### LineageNodeData
+
+| 属性名 | 类型 | 描述 | 默认值 | 必选 |
+| --------- | --------------------------------------------------- | ------------------------------------------------------------------- | ------ | ---- |
+| title | `string` | 节点标题 | - | - |
+| describe | `string` | 节点描述 | - | - |
+| logo | `string` | 节点 logo 的 url | - | - |
+| titleSlot | `{type: 'left' \| 'right', value: React.ReactNode}` | 标题右侧的插槽,left 跟随在 title 文字结尾处,right 在 title 行尾部 | - | - |
diff --git a/src/BloodGroupNode/index.tsx b/src/LineageGroupNode/index.tsx
similarity index 68%
rename from src/BloodGroupNode/index.tsx
rename to src/LineageGroupNode/index.tsx
index 0216b89..c8ad1da 100644
--- a/src/BloodGroupNode/index.tsx
+++ b/src/LineageGroupNode/index.tsx
@@ -1,22 +1,22 @@
-import { ArtboardTitle, getClsFromSelectType } from '@/BloodNode';
-import { NodeMapItem, NodeSelect } from '@/ProFlow/constants';
-import { ProFlowNode, ProFlowNodeData } from '@/constants';
+import { NodeMapItem, NodeSelect } from '@/FlowView/constants';
+import { ArtboardTitle } from '@/LineageNode';
+import { LineageGroupNodeData, LineageNodeData } from '@/constants';
+import { getClsFromSelectType } from '@/utils';
import { cx } from 'antd-style';
import React from 'react';
import { useStyles } from './styles';
-export interface BloodNodeGroupProps {
+export interface LineageNodeGroupProps {
id?: string;
zoom?: number;
label?: string;
select?: NodeSelect;
- data: ProFlowNode[];
- group: boolean;
+ data: LineageGroupNodeData[];
}
-const convertMappingNode = (nodeList: ProFlowNode[]): NodeMapItem[] => {
- return nodeList.map((node) => {
- return node;
+const convertMappingNode = (nodeList: LineageGroupNodeData[]): NodeMapItem[] => {
+ return nodeList.map((_node) => {
+ return { ..._node, type: 'default', flowNodeType: 'lineage' };
});
};
@@ -35,8 +35,7 @@ const GroupItem = (node: NodeMapItem) => {
);
};
-const BloodNodeGroup: React.FC = ({
- group,
+const LineageNodeGroup: React.FC = ({
data,
select = NodeSelect.SELECT,
zoom = 1,
@@ -44,15 +43,11 @@ const BloodNodeGroup: React.FC = ({
}) => {
const { styles } = useStyles();
- if (!group) {
- return null;
- }
-
- if ((data as ProFlowNode[]).length < 7) {
+ if ((data as LineageGroupNodeData[]).length < 7) {
return 数组长度必须大于等于7!
;
}
- const nodeList = convertMappingNode(data as ProFlowNode[]);
+ const nodeList = convertMappingNode(data as LineageGroupNodeData[]);
return (
<>
@@ -63,7 +58,7 @@ const BloodNodeGroup: React.FC = ({
)}
{nodeList!.map((_node, index) => {
- const data = _node.data as ProFlowNodeData;
+ const data = _node.data as LineageNodeData;
_node.position = {
x: 0,
y: 100 * index,
@@ -86,4 +81,4 @@ const BloodNodeGroup: React.FC
= ({
);
};
-export default BloodNodeGroup;
+export default LineageNodeGroup;
diff --git a/src/BloodGroupNode/styles.ts b/src/LineageGroupNode/styles.ts
similarity index 100%
rename from src/BloodGroupNode/styles.ts
rename to src/LineageGroupNode/styles.ts
diff --git a/src/BloodNode/demos/DataViewList.tsx b/src/LineageNode/demos/DataViewList.tsx
similarity index 100%
rename from src/BloodNode/demos/DataViewList.tsx
rename to src/LineageNode/demos/DataViewList.tsx
diff --git a/src/LineageNode/demos/index.tsx b/src/LineageNode/demos/index.tsx
new file mode 100644
index 0000000..ee81fa3
--- /dev/null
+++ b/src/LineageNode/demos/index.tsx
@@ -0,0 +1,168 @@
+import { FlowViewEdge, FlowViewNode, NodeSelect } from '@/index';
+import { ProFlow } from '@ant-design/pro-flow';
+import { Progress } from 'antd';
+import { createStyles } from 'antd-style';
+import React, { useState } from 'react';
+import styled from 'styled-components';
+
+const useStyles = createStyles(({ css }) => ({
+ container: css`
+ width: 100%;
+ height: 600px;
+ .ant-progress-text {
+ text-align: center !important;
+ }
+ `,
+}));
+
+const ApiScore: React.FC<{ score: number }> = ({ score }) => {
+ return (
+