Flow Prototype
parent
6665d418b8
commit
00c22ac2be
|
|
@ -0,0 +1,38 @@
|
|||
import { useState } from "react";
|
||||
import ReactFlow, {
|
||||
Background,
|
||||
Controls,
|
||||
ReactFlowInstance,
|
||||
} from "react-flow-renderer";
|
||||
import useStore from "../../lib/FlowEditor/FlowEditorStore";
|
||||
|
||||
const Flow = () => {
|
||||
const [reactFlowInstance, setReactFlowInstance] =
|
||||
useState<ReactFlowInstance>();
|
||||
|
||||
const onInit = (rfi: ReactFlowInstance) => {
|
||||
setReactFlowInstance(rfi);
|
||||
};
|
||||
|
||||
const { nodes, edges, onNodesChange, onEdgesChange, onConnect } = useStore();
|
||||
|
||||
return (
|
||||
<div className="flow h-screen w-full">
|
||||
<ReactFlow
|
||||
nodes={nodes}
|
||||
edges={edges}
|
||||
onNodesChange={onNodesChange}
|
||||
onEdgesChange={onEdgesChange}
|
||||
onConnect={onConnect}
|
||||
onInit={onInit}
|
||||
fitView
|
||||
snapToGrid={true}
|
||||
>
|
||||
<Controls />
|
||||
<Background />
|
||||
</ReactFlow>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Flow;
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
import { DndContext } from "@dnd-kit/core";
|
||||
import { ReactFlowProvider } from "react-flow-renderer";
|
||||
import Flow from "./Flow";
|
||||
import Panel from "./Panel";
|
||||
|
||||
const FlowEditorComponent = () => {
|
||||
return (
|
||||
<DndContext>
|
||||
<Panel />
|
||||
<Flow />
|
||||
</DndContext>
|
||||
);
|
||||
};
|
||||
|
||||
const FlowEditor = () => {
|
||||
return (
|
||||
<div className="flow-editor">
|
||||
<ReactFlowProvider>
|
||||
<FlowEditorComponent />
|
||||
</ReactFlowProvider>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default FlowEditor;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
const Panel = () => {
|
||||
return <aside className="flow-panel"></aside>;
|
||||
};
|
||||
|
||||
export default Panel;
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
import create from "zustand";
|
||||
import {
|
||||
Connection,
|
||||
Edge,
|
||||
EdgeChange,
|
||||
Node,
|
||||
NodeChange,
|
||||
addEdge,
|
||||
OnNodesChange,
|
||||
OnEdgesChange,
|
||||
OnConnect,
|
||||
applyNodeChanges,
|
||||
applyEdgeChanges,
|
||||
XYPosition,
|
||||
} from "react-flow-renderer";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
import initialNodes from "./nodes";
|
||||
import initialEdges from "./edges";
|
||||
|
||||
type FlowEditorStore = {
|
||||
nodes: Node[];
|
||||
edges: Edge[];
|
||||
panelClosed: boolean;
|
||||
onNodesChange: OnNodesChange;
|
||||
onEdgesChange: OnEdgesChange;
|
||||
onConnect: OnConnect;
|
||||
addNode: (type: string, position: XYPosition) => void;
|
||||
togglePanelState: () => void;
|
||||
};
|
||||
|
||||
const useStore = create<FlowEditorStore>((set, get) => ({
|
||||
nodes: initialNodes,
|
||||
edges: initialEdges,
|
||||
panelClosed: false,
|
||||
onNodesChange: (changes: NodeChange[]) => {
|
||||
set({
|
||||
nodes: applyNodeChanges(changes, get().nodes),
|
||||
});
|
||||
},
|
||||
onEdgesChange: (changes: EdgeChange[]) => {
|
||||
set({
|
||||
edges: applyEdgeChanges(changes, get().edges),
|
||||
});
|
||||
},
|
||||
onConnect: (connection: Connection) => {
|
||||
set({
|
||||
edges: addEdge(connection, get().edges),
|
||||
});
|
||||
},
|
||||
addNode: (type: string, position: XYPosition) => {
|
||||
const newNode: Node = {
|
||||
id: `node_${nanoid()}`,
|
||||
type: type,
|
||||
position: position,
|
||||
data: { label: `${type} node` },
|
||||
};
|
||||
set({
|
||||
nodes: get().nodes.concat(newNode),
|
||||
});
|
||||
},
|
||||
togglePanelState: () => {
|
||||
set({
|
||||
panelClosed: !get().panelClosed,
|
||||
});
|
||||
},
|
||||
}));
|
||||
export default useStore;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import { Edge } from "react-flow-renderer";
|
||||
|
||||
const initialEdges: Edge[] = [];
|
||||
|
||||
export default initialEdges;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import { Node } from "react-flow-renderer";
|
||||
|
||||
const initialNodes: Node[] = [
|
||||
{
|
||||
id: "1",
|
||||
type: "input",
|
||||
data: { label: "Старт" },
|
||||
position: { x: 0, y: 0 },
|
||||
},
|
||||
];
|
||||
|
||||
export default initialNodes;
|
||||
|
|
@ -12,7 +12,8 @@
|
|||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-flow-renderer": "^10.3.9",
|
||||
"react-icons": "^4.4.0"
|
||||
"react-icons": "^4.4.0",
|
||||
"zustand": "^4.0.0-rc.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "17.0.4",
|
||||
|
|
@ -4682,6 +4683,22 @@
|
|||
"react-dom": "16 || 17 || 18"
|
||||
}
|
||||
},
|
||||
"node_modules/react-flow-renderer/node_modules/zustand": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
|
||||
"integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
|
||||
"engines": {
|
||||
"node": ">=12.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-icons": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
|
||||
|
|
@ -5888,16 +5905,23 @@
|
|||
}
|
||||
},
|
||||
"node_modules/zustand": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
|
||||
"integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
|
||||
"version": "4.0.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.0.0-rc.1.tgz",
|
||||
"integrity": "sha512-qgcs7zLqBdHu0PuT3GW4WCIY5SgXdsv30GQMu9Qpp1BA2aS+sNS8l4x0hWuyEhjXkN+701aGWawhKDv6oWJAcw==",
|
||||
"dependencies": {
|
||||
"use-sync-external-store": "1.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.7.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"immer": ">=9.0",
|
||||
"react": ">=16.8"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"immer": {
|
||||
"optional": true
|
||||
},
|
||||
"react": {
|
||||
"optional": true
|
||||
}
|
||||
|
|
@ -9124,6 +9148,14 @@
|
|||
"d3-selection": "^3.0.0",
|
||||
"d3-zoom": "^3.0.0",
|
||||
"zustand": "^3.7.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"zustand": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
|
||||
"integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"react-icons": {
|
||||
|
|
@ -10035,10 +10067,12 @@
|
|||
"dev": true
|
||||
},
|
||||
"zustand": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
|
||||
"integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
|
||||
"requires": {}
|
||||
"version": "4.0.0-rc.1",
|
||||
"resolved": "https://registry.npmjs.org/zustand/-/zustand-4.0.0-rc.1.tgz",
|
||||
"integrity": "sha512-qgcs7zLqBdHu0PuT3GW4WCIY5SgXdsv30GQMu9Qpp1BA2aS+sNS8l4x0hWuyEhjXkN+701aGWawhKDv6oWJAcw==",
|
||||
"requires": {
|
||||
"use-sync-external-store": "1.1.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,8 @@
|
|||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-flow-renderer": "^10.3.9",
|
||||
"react-icons": "^4.4.0"
|
||||
"react-icons": "^4.4.0",
|
||||
"zustand": "^4.0.0-rc.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "17.0.4",
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
import FlowEditor from "../components/FlowEditor/FlowEditor";
|
||||
|
||||
const Flow = () => {
|
||||
return "Визуальная среда";
|
||||
return <FlowEditor />;
|
||||
};
|
||||
|
||||
export default Flow;
|
||||
|
|
|
|||
Loading…
Reference in New Issue