From 35b423aacb0b2543d1d66ef620508d0276f0b01d Mon Sep 17 00:00:00 2001 From: moklick Date: Sun, 20 Dec 2020 13:33:18 +0100 Subject: [PATCH] chore(examples): add layouting --- example/package-lock.json | 76 ++++++++++++++++------- example/package.json | 1 + example/src/DragNDrop/dnd.css | 4 -- example/src/Layouting/index.js | 68 ++++++++++++++++++++ example/src/Layouting/initial-elements.js | 67 ++++++++++++++++++++ example/src/Layouting/layouting.css | 11 ++++ example/src/index.js | 5 ++ 7 files changed, 207 insertions(+), 25 deletions(-) create mode 100644 example/src/Layouting/index.js create mode 100644 example/src/Layouting/initial-elements.js create mode 100644 example/src/Layouting/layouting.css diff --git a/example/package-lock.json b/example/package-lock.json index 0bcbd71b..263ad951 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -9,6 +9,7 @@ "version": "0.1.0", "dependencies": { "@craco/craco": "^5.7.0", + "dagre": "^0.8.5", "localforage": "^1.9.0", "react-dom": "^17.0.1", "react-flow-renderer": "file:..", @@ -18,7 +19,7 @@ }, "..": { "name": "react-flow-renderer", - "version": "8.2.1", + "version": "8.2.2", "license": "MIT", "dependencies": { "@babel/runtime": "^7.12.5", @@ -30,10 +31,10 @@ "react-draggable": "^4.4.3" }, "devDependencies": { - "@babel/core": "^7.12.9", - "@babel/plugin-transform-runtime": "^7.12.1", - "@babel/preset-env": "^7.12.7", - "@babel/preset-react": "^7.12.7", + "@babel/core": "^7.12.10", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.12.10", + "@babel/preset-react": "^7.12.10", "@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-commonjs": "^17.0.0", "@rollup/plugin-node-resolve": "^11.0.0", @@ -44,11 +45,11 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "@types/resize-observer-browser": "^0.1.4", - "autoprefixer": "^10.0.4", + "autoprefixer": "^10.1.0", "babel-preset-react-app": "^10.0.0", - "cypress": "^6.0.1", - "postcss": "^8.1.14", - "postcss-nested": "^5.0.2", + "cypress": "^6.1.0", + "postcss": "^8.2.1", + "postcss-nested": "^5.0.3", "prettier": "2.2.1", "prop-types": "^15.7.2", "react": "^17.0.1", @@ -58,7 +59,7 @@ "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-typescript2": "^0.29.0", "start-server-and-test": "^1.11.6", - "typescript": "^4.1.2" + "typescript": "^4.1.3" }, "peerDependencies": { "react": "16 || 17" @@ -4562,6 +4563,15 @@ "type": "^1.0.1" } }, + "node_modules/dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "dependencies": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, "node_modules/damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", @@ -6852,6 +6862,14 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, + "node_modules/graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "dependencies": { + "lodash": "^4.17.15" + } + }, "node_modules/growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -20298,6 +20316,15 @@ "type": "^1.0.1" } }, + "dagre": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/dagre/-/dagre-0.8.5.tgz", + "integrity": "sha512-/aTqmnRta7x7MCCpExk7HQL2O4owCT2h8NT//9I1OQ9vt29Pa0BzSAkR5lwFUcQ7491yVi/3CXU9jQ5o0Mn2Sw==", + "requires": { + "graphlib": "^2.1.8", + "lodash": "^4.17.15" + } + }, "damerau-levenshtein": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.6.tgz", @@ -22226,6 +22253,14 @@ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==" }, + "graphlib": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/graphlib/-/graphlib-2.1.8.tgz", + "integrity": "sha512-jcLLfkpoVGmH7/InMC/1hIvOPSUh38oJtGhvrOFGzioE1DZ+0YW16RgmOJhHiuWTvGiJQ9Z1Ik43JvkRPRvE+A==", + "requires": { + "lodash": "^4.17.15" + } + }, "growly": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/growly/-/growly-1.3.0.tgz", @@ -26789,10 +26824,10 @@ "react-flow-renderer": { "version": "file:..", "requires": { - "@babel/core": "^7.12.9", - "@babel/plugin-transform-runtime": "^7.12.1", - "@babel/preset-env": "^7.12.7", - "@babel/preset-react": "^7.12.7", + "@babel/core": "^7.12.10", + "@babel/plugin-transform-runtime": "^7.12.10", + "@babel/preset-env": "^7.12.10", + "@babel/preset-react": "^7.12.10", "@babel/runtime": "^7.12.5", "@rollup/plugin-babel": "^5.2.2", "@rollup/plugin-commonjs": "^17.0.0", @@ -26804,16 +26839,16 @@ "@types/react": "^17.0.0", "@types/react-dom": "^17.0.0", "@types/resize-observer-browser": "^0.1.4", - "autoprefixer": "^10.0.4", + "autoprefixer": "^10.1.0", "babel-preset-react-app": "^10.0.0", "classcat": "^4.1.0", - "cypress": "^6.0.1", + "cypress": "^6.1.0", "d3-selection": "^2.0.0", "d3-zoom": "^2.0.0", "easy-peasy": "^4.0.1", "fast-deep-equal": "^3.1.3", - "postcss": "^8.1.14", - "postcss-nested": "^5.0.2", + "postcss": "^8.2.1", + "postcss-nested": "^5.0.3", "prettier": "2.2.1", "prop-types": "^15.7.2", "react": "^17.0.1", @@ -26824,7 +26859,7 @@ "rollup-plugin-postcss": "^4.0.0", "rollup-plugin-typescript2": "^0.29.0", "start-server-and-test": "^1.11.6", - "typescript": "^4.1.2" + "typescript": "^4.1.3" }, "dependencies": { "@babel/core": { @@ -26851,8 +26886,7 @@ } }, "@babel/plugin-transform-runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", + "version": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.12.1.tgz", "integrity": "sha512-Ac/H6G9FEIkS2tXsZjL4RAdS3L3WHxci0usAnz7laPWUmFiGtj7tIASChqKZMHTSQTQY6xDbOq+V1/vIq3QrWg==", "dev": true, "requires": { diff --git a/example/package.json b/example/package.json index 51de568a..329f9590 100644 --- a/example/package.json +++ b/example/package.json @@ -4,6 +4,7 @@ "private": true, "dependencies": { "@craco/craco": "^5.7.0", + "dagre": "^0.8.5", "localforage": "^1.9.0", "react-dom": "^17.0.1", "react-flow-renderer": "file:..", diff --git a/example/src/DragNDrop/dnd.css b/example/src/DragNDrop/dnd.css index 9067f699..2e47d278 100644 --- a/example/src/DragNDrop/dnd.css +++ b/example/src/DragNDrop/dnd.css @@ -40,10 +40,6 @@ height: 100%; } -.dndflow .selectall { - margin-top: 10px; -} - @media screen and (min-width: 768px) { .dndflow { flex-direction: row; diff --git a/example/src/Layouting/index.js b/example/src/Layouting/index.js new file mode 100644 index 00000000..1d094e63 --- /dev/null +++ b/example/src/Layouting/index.js @@ -0,0 +1,68 @@ +import React, { useEffect, useState } from 'react'; +import ReactFlow, { ReactFlowProvider, addEdge, removeElements, Controls, isNode } from 'react-flow-renderer'; +import dagre from 'dagre'; + +import initialElements from './initial-elements'; + +import './layouting.css'; + +const dagreGraph = new dagre.graphlib.Graph(); +dagreGraph.setDefaultEdgeLabel(() => ({})); + +const LayoutFlow = () => { + const [elements, setElements] = useState(initialElements); + const onConnect = (params) => setElements((els) => addEdge(params, els)); + const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els)); + + const onLayout = (direction) => { + const isHorizontal = direction === 'LR'; + dagreGraph.setGraph({ rankdir: direction }); + + elements.forEach((el) => { + if (isNode(el)) { + dagreGraph.setNode(el.id, { width: 150, height: 50 }); + } else { + dagreGraph.setEdge(el.source, el.target); + } + }); + + dagre.layout(dagreGraph); + + const layoutedElements = elements.map((el) => { + if (isNode(el)) { + const nodeWithPosition = dagreGraph.node(el.id); + el.targetPosition = isHorizontal ? 'left' : 'top'; + el.sourcePosition = isHorizontal ? 'right' : 'bottom'; + // we need to pass a slighltiy different position in order to notify react flow about the change + // @TODO how can we change the position handling so that we dont need this hack? + el.position = { x: nodeWithPosition.x + Math.random() / 1000, y: nodeWithPosition.y }; + } + + return el; + }); + + setElements(layoutedElements); + }; + + useEffect(() => { + onLayout('TB'); + }, []); + + return ( +
+ + + + +
+ + +
+
+
+ ); +}; + +export default LayoutFlow; diff --git a/example/src/Layouting/initial-elements.js b/example/src/Layouting/initial-elements.js new file mode 100644 index 00000000..d615b409 --- /dev/null +++ b/example/src/Layouting/initial-elements.js @@ -0,0 +1,67 @@ +const position = { x: 0, y: 0 }; + +export default [ + { + id: '1', + type: 'input', + data: { label: 'input' }, + position, + }, + { + id: '2', + data: { label: 'node 2' }, + position, + }, + { + id: '2a', + data: { label: 'node 2a' }, + position, + }, + { + id: '2b', + data: { label: 'node 2b' }, + position, + }, + { + id: '2c', + data: { label: 'node 2c' }, + position, + }, + { + id: '2d', + data: { label: 'node 2d' }, + position, + }, + { + id: '3', + data: { label: 'node 3' }, + position, + }, + { + id: '4', + data: { label: 'node 4' }, + position, + }, + { + id: '5', + data: { label: 'node 5' }, + position, + }, + { + id: '6', + type: 'output', + data: { label: 'output' }, + position, + }, + { id: '7', type: 'output', data: { label: 'output' }, position: { x: 400, y: 450 } }, + { id: 'e12', source: '1', target: '2', type: 'smoothstep' }, + { id: 'e13', source: '1', target: '3', type: 'smoothstep' }, + { id: 'e22a', source: '2', target: '2a', type: 'smoothstep' }, + { id: 'e22b', source: '2', target: '2b', type: 'smoothstep' }, + { id: 'e22c', source: '2', target: '2c', type: 'smoothstep' }, + { id: 'e2c2d', source: '2c', target: '2d', type: 'smoothstep' }, + + { id: 'e45', source: '4', target: '5', type: 'smoothstep' }, + { id: 'e56', source: '5', target: '6', type: 'smoothstep' }, + { id: 'e57', source: '5', target: '7', type: 'smoothstep' }, +]; diff --git a/example/src/Layouting/layouting.css b/example/src/Layouting/layouting.css new file mode 100644 index 00000000..6d248b22 --- /dev/null +++ b/example/src/Layouting/layouting.css @@ -0,0 +1,11 @@ +.layoutflow { + flex-grow: 1; + position: relative; +} + +.layoutflow .controls { + position: absolute; + right: 10px; + top: 10px; + z-index: 10; +} diff --git a/example/src/index.js b/example/src/index.js index 6a1011c7..5ec5f662 100644 --- a/example/src/index.js +++ b/example/src/index.js @@ -19,6 +19,7 @@ import UpdatableEdge from './UpdatableEdge'; import UpdateNode from './UpdateNode'; import SaveRestore from './SaveRestore'; import DragNDrop from './DragNDrop'; +import Layout from './Layouting'; import './index.css'; @@ -91,6 +92,10 @@ const routes = [ path: '/drag-and-drop', component: DragNDrop, }, + { + path: '/layouting', + component: Layout, + }, ]; const Header = withRouter(({ history, location }) => {