13
README.md
13
README.md
@@ -97,6 +97,9 @@ const BasicFlow = () => <ReactFlow elements={elements} />;
|
||||
- `onMoveStart()`: called when user starts panning or zooming
|
||||
- `onMoveEnd()`: called when user ends panning or zooming
|
||||
- `onSelectionChange(elements: Elements)`: called when user selects one or multiple elements
|
||||
- `onSelectionDragStart(evt: MouseEvent, nodes: Node[])`: called when user starts to drag a selection
|
||||
- `onSelectionDrag(evt: MouseEvent, nodes: Node[])`: called when user drags a selection
|
||||
- `onSelectionDragStop(evt: MouseEvent, nodes: Node[])`: called when user stops to drag a selection
|
||||
- `onPaneClick(event: MouseEvent)`: called when user clicks directly on the canvas
|
||||
- `onPaneContextMenu(event: MouseEvent)`: called when user does a right-click on the canvas
|
||||
|
||||
@@ -230,6 +233,10 @@ Your custom nodes are wrapped so that the basic functions like dragging or selec
|
||||
- `sourcePosition`: string
|
||||
- `targetPosition`: string
|
||||
|
||||
### Prevent dragging
|
||||
|
||||
If you have controls inside your custom node that should not drag the node you can add the class name `nodrag`.
|
||||
|
||||
## Handle Component
|
||||
|
||||
We export a `Handle` component as a helper for your custom nodes:
|
||||
@@ -422,6 +429,7 @@ const FlowWithMiniMap = () => (
|
||||
|
||||
- `nodeColor`: string or function - If you pass a color as a string all nodes will get that color. If you pass a function you can return a color depending on the passed node.
|
||||
- `nodeBorderRadius`: number
|
||||
- `nodeClassName`: string or function for adding an additional class to the nodes inside the mini map
|
||||
- `maskColor`: string
|
||||
- `style`: css properties
|
||||
- `className`: additional class name
|
||||
@@ -568,6 +576,11 @@ Returns all direct child nodes of the passed node
|
||||
|
||||
`getOutgoers = (node: Node, elements: Elements): Node[]`
|
||||
|
||||
### getConnectedEdges
|
||||
|
||||
Returns all edges that are connected to the passed nodes
|
||||
|
||||
`getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[]`
|
||||
|
||||
You can use these function as seen in [this example](/example/src/Overview/index.js#L40-L41) or use your own ones.
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ import ReactFlow, { removeElements, addEdge, MiniMap, Controls, Background, isNo
|
||||
|
||||
const onNodeDragStart = (event, node) => console.log('drag start', node);
|
||||
const onNodeDragStop = (event, node) => console.log('drag stop', node);
|
||||
const onSelectionDrag = (event, nodes) => console.log('selection drag', nodes);
|
||||
const onSelectionDragStart = (event, nodes) => console.log('selection drag start', nodes);
|
||||
const onSelectionDragStop = (event, nodes) => console.log('selection drag stop', nodes);
|
||||
const onElementClick = (event, element) => console.log(`${isNode(element) ? 'node' : 'edge'} click:`, element);
|
||||
const onSelectionChange = (elements) => console.log('selection change', elements);
|
||||
const onLoad = (reactFlowInstance) => {
|
||||
@@ -120,6 +123,9 @@ const OverviewFlow = () => {
|
||||
onConnect={onConnect}
|
||||
onNodeDragStart={onNodeDragStart}
|
||||
onNodeDragStop={onNodeDragStop}
|
||||
onSelectionDragStart={onSelectionDragStart}
|
||||
onSelectionDrag={onSelectionDrag}
|
||||
onSelectionDragStop={onSelectionDragStop}
|
||||
onSelectionChange={onSelectionChange}
|
||||
onMoveEnd={onMoveEnd}
|
||||
onLoad={onLoad}
|
||||
|
||||
139
package-lock.json
generated
139
package-lock.json
generated
@@ -57,16 +57,16 @@
|
||||
}
|
||||
},
|
||||
"@babel/core": {
|
||||
"version": "7.11.1",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.1.tgz",
|
||||
"integrity": "sha512-XqF7F6FWQdKGGWAzGELL+aCO1p+lRY5Tj5/tbT3St1G8NaH70jhhDIKknIZaDans0OQBG5wRAldROLHSt44BgQ==",
|
||||
"version": "7.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.4.tgz",
|
||||
"integrity": "sha512-5deljj5HlqRXN+5oJTY7Zs37iH3z3b++KjiKtIsJy1NrjOOVSEaJHEetLBhyu0aQOSNNZ/0IuEAan9GzRuDXHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/code-frame": "^7.10.4",
|
||||
"@babel/generator": "^7.11.0",
|
||||
"@babel/generator": "^7.11.4",
|
||||
"@babel/helper-module-transforms": "^7.11.0",
|
||||
"@babel/helpers": "^7.10.4",
|
||||
"@babel/parser": "^7.11.1",
|
||||
"@babel/parser": "^7.11.4",
|
||||
"@babel/template": "^7.10.4",
|
||||
"@babel/traverse": "^7.11.0",
|
||||
"@babel/types": "^7.11.0",
|
||||
@@ -90,9 +90,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/generator": {
|
||||
"version": "7.11.0",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.0.tgz",
|
||||
"integrity": "sha512-fEm3Uzw7Mc9Xi//qU20cBKatTfs2aOtKqmvy/Vm7RkJEGFQ4xc9myCfbXxqK//ZS8MR/ciOHw6meGASJuKmDfQ==",
|
||||
"version": "7.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.4.tgz",
|
||||
"integrity": "sha512-Rn26vueFx0eOoz7iifCN2UHT6rGtnkSGWSoDRIy8jZN3B91PzeSULbswfLoOWuTuAcNwpG/mxy+uCTDnZ9Mp1g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@babel/types": "^7.11.0",
|
||||
@@ -191,9 +191,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz",
|
||||
"integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==",
|
||||
"version": "7.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
|
||||
"integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
@@ -1531,9 +1531,9 @@
|
||||
}
|
||||
},
|
||||
"@babel/parser": {
|
||||
"version": "7.11.3",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.3.tgz",
|
||||
"integrity": "sha512-REo8xv7+sDxkKvoxEywIdsNFiZLybwdI7hcT5uEPyQrSMB4YQ973BfC9OOrD/81MaIjh6UxdulIQXkjmiH3PcA==",
|
||||
"version": "7.11.4",
|
||||
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.4.tgz",
|
||||
"integrity": "sha512-MggwidiH+E9j5Sh8pbrX5sJvMcsqS5o+7iB42M9/k0CD63MjYbdP4nhSh7uB5wnv2/RVzTZFTxzF/kIa5mrCqA==",
|
||||
"dev": true
|
||||
},
|
||||
"@babel/template": {
|
||||
@@ -4240,9 +4240,9 @@
|
||||
}
|
||||
},
|
||||
"@octokit/types": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.4.0.tgz",
|
||||
"integrity": "sha512-D/uotqF69M50OIlwMqgyIg9PuLT2daOiBAYF0P40I2ekFA2ESwwBY5dxZe/UhXdPvIbNKDzuZmQrO7rMpuFbcg==",
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-5.4.1.tgz",
|
||||
"integrity": "sha512-OlMlSySBJoJ6uozkr/i03nO5dlYQyE05vmQNZhAh9MyO4DPBP88QlwsDVLmVjIMFssvIZB6WO0ctIGMRG+xsJQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/node": ">= 8"
|
||||
@@ -4277,9 +4277,9 @@
|
||||
}
|
||||
},
|
||||
"@sindresorhus/is": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.1.tgz",
|
||||
"integrity": "sha512-tLnujxFtfH7F+i5ghUfgGlJsvyCKvUnSMFMlWybFdX9/DdX8svb4Zwx1gV0gkkVCHXtmPSetoAR3QlKfOld6Tw==",
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-3.1.2.tgz",
|
||||
"integrity": "sha512-JiX9vxoKMmu8Y3Zr2RVathBL1Cdu4Nt4MuNWemt1Nc06A0RAin9c5FArkhGsyMBWfCu4zj+9b+GxtjAnE4qqLQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@svgr/babel-plugin-add-jsx-attribute": {
|
||||
@@ -6952,70 +6952,69 @@
|
||||
}
|
||||
},
|
||||
"d3-color": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-1.4.0.tgz",
|
||||
"integrity": "sha512-TzNPeJy2+iEepfiL92LAAB7fvnp/dV2YwANPVHdDWmYMm23qIJBYww3qT8I8C1wXrmrg4UWs7BKc2tKIgyjzHg=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-color/-/d3-color-2.0.0.tgz",
|
||||
"integrity": "sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ=="
|
||||
},
|
||||
"d3-dispatch": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.5.tgz",
|
||||
"integrity": "sha512-vwKx+lAqB1UuCeklr6Jh1bvC4SZgbSqbkGBLClItFBIYH4vqDJCA7qfoy14lXmJdnBOdxndAMxjCbImJYW7e6g=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-2.0.0.tgz",
|
||||
"integrity": "sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA=="
|
||||
},
|
||||
"d3-drag": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-1.2.4.tgz",
|
||||
"integrity": "sha512-ICPurDETFAelF1CTHdIyiUM4PsyZLaM+7oIBhmyP+cuVjze5vDZ8V//LdOFjg0jGnFIZD/Sfmk0r95PSiu78rw==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-drag/-/d3-drag-2.0.0.tgz",
|
||||
"integrity": "sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==",
|
||||
"requires": {
|
||||
"d3-dispatch": "1",
|
||||
"d3-selection": "1"
|
||||
"d3-dispatch": "1 - 2",
|
||||
"d3-selection": "2"
|
||||
}
|
||||
},
|
||||
"d3-ease": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-1.0.5.tgz",
|
||||
"integrity": "sha512-Ct1O//ly5y5lFM9YTdu+ygq7LleSgSE4oj7vUt9tPLHUi8VCV7QoizGpdWRWAwCO9LdYzIrQDg97+hGVdsSGPQ=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-2.0.0.tgz",
|
||||
"integrity": "sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ=="
|
||||
},
|
||||
"d3-interpolate": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-1.3.2.tgz",
|
||||
"integrity": "sha512-NlNKGopqaz9qM1PXh9gBF1KSCVh+jSFErrSlD/4hybwoNX/gt1d8CDbDW+3i+5UOHhjC6s6nMvRxcuoMVNgL2w==",
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-2.0.1.tgz",
|
||||
"integrity": "sha512-c5UhwwTs/yybcmTpAVqwSFl6vrQ8JZJoT5F7xNFK9pymv5C0Ymcc9/LIJHtYIggg/yS9YHw8i8O8tgb9pupjeQ==",
|
||||
"requires": {
|
||||
"d3-color": "1"
|
||||
"d3-color": "1 - 2"
|
||||
}
|
||||
},
|
||||
"d3-selection": {
|
||||
"version": "1.4.2",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-1.4.2.tgz",
|
||||
"integrity": "sha512-SJ0BqYihzOjDnnlfyeHT0e30k0K1+5sR3d5fNueCNeuhZTnGw4M4o8mqJchSwgKMXCNFo+e2VTChiSJ0vYtXkg=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-2.0.0.tgz",
|
||||
"integrity": "sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA=="
|
||||
},
|
||||
"d3-timer": {
|
||||
"version": "1.0.9",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.9.tgz",
|
||||
"integrity": "sha512-rT34J5HnQUHhcLvhSB9GjCkN0Ddd5Y8nCwDBG2u6wQEeYxT/Lf51fTFFkldeib/sE/J0clIe0pnCfs6g/lRbyg=="
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-2.0.0.tgz",
|
||||
"integrity": "sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA=="
|
||||
},
|
||||
"d3-transition": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-1.2.0.tgz",
|
||||
"integrity": "sha512-VJ7cmX/FPIPJYuaL2r1o1EMHLttvoIuZhhuAlRoOxDzogV8iQS6jYulDm3xEU3TqL80IZIhI551/ebmCMrkvhw==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-2.0.0.tgz",
|
||||
"integrity": "sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==",
|
||||
"requires": {
|
||||
"d3-color": "1",
|
||||
"d3-dispatch": "1",
|
||||
"d3-ease": "1",
|
||||
"d3-interpolate": "1",
|
||||
"d3-selection": "^1.1.0",
|
||||
"d3-timer": "1"
|
||||
"d3-color": "1 - 2",
|
||||
"d3-dispatch": "1 - 2",
|
||||
"d3-ease": "1 - 2",
|
||||
"d3-interpolate": "1 - 2",
|
||||
"d3-timer": "1 - 2"
|
||||
}
|
||||
},
|
||||
"d3-zoom": {
|
||||
"version": "1.8.3",
|
||||
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-1.8.3.tgz",
|
||||
"integrity": "sha512-VoLXTK4wvy1a0JpH2Il+F2CiOhVu7VRXWF5M/LroMIh3/zBAC3WAt7QoIvPibOavVo20hN6/37vwAsdBejLyKQ==",
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/d3-zoom/-/d3-zoom-2.0.0.tgz",
|
||||
"integrity": "sha512-fFg7aoaEm9/jf+qfstak0IYpnesZLiMX6GZvXtUSdv8RH2o4E2qeelgdU09eKS6wGuiGMfcnMI0nTIqWzRHGpw==",
|
||||
"requires": {
|
||||
"d3-dispatch": "1",
|
||||
"d3-drag": "1",
|
||||
"d3-interpolate": "1",
|
||||
"d3-selection": "1",
|
||||
"d3-transition": "1"
|
||||
"d3-dispatch": "1 - 2",
|
||||
"d3-drag": "2",
|
||||
"d3-interpolate": "1 - 2",
|
||||
"d3-selection": "2",
|
||||
"d3-transition": "2"
|
||||
}
|
||||
},
|
||||
"dashdash": {
|
||||
@@ -11038,9 +11037,9 @@
|
||||
}
|
||||
},
|
||||
"release-it": {
|
||||
"version": "13.6.8",
|
||||
"resolved": "https://registry.npmjs.org/release-it/-/release-it-13.6.8.tgz",
|
||||
"integrity": "sha512-LY3dZEzAVRBdie0DMG0kdV4DWMTVPM+hvc5O5EmY0qIf+zPuMVu9QXS19La6KBhCI4kVhpwm7VZ8B7YMXTBKLA==",
|
||||
"version": "13.6.9",
|
||||
"resolved": "https://registry.npmjs.org/release-it/-/release-it-13.6.9.tgz",
|
||||
"integrity": "sha512-bZEJBMCHiBPzKVZzCTYaGo+lYpunsX1/LSL1bO5RJ2+7G1glC91G5KIs29zgfHJEQfzE0q3tTEVV+b6gscGKvw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@iarna/toml": "2.2.5",
|
||||
@@ -11354,9 +11353,9 @@
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "2.26.4",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.4.tgz",
|
||||
"integrity": "sha512-6+qsGuP0MXGd7vlYmk72utm1MrgZj5GfXibGL+cRkKQ9+ZL/BnFThDl0D5bcl7AqlzMjAQXRAwZX1HVm22M/4Q==",
|
||||
"version": "2.26.5",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.5.tgz",
|
||||
"integrity": "sha512-rCyFG3ZtQdnn9YwfuAVH0l/Om34BdO5lwCA0W6Hq+bNB21dVEBbCRxhaHOmu1G7OBFDWytbzAC104u7rxHwGjA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fsevents": "~2.1.2"
|
||||
@@ -12364,9 +12363,9 @@
|
||||
}
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.9.7",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.7.tgz",
|
||||
"integrity": "sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw==",
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz",
|
||||
"integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==",
|
||||
"dev": true
|
||||
},
|
||||
"uglify-js": {
|
||||
|
||||
12
package.json
12
package.json
@@ -27,15 +27,15 @@
|
||||
"dependencies": {
|
||||
"@welldone-software/why-did-you-render": "^4.3.1",
|
||||
"classcat": "^4.1.0",
|
||||
"d3-selection": "^1.4.2",
|
||||
"d3-zoom": "^1.8.3",
|
||||
"d3-selection": "^2.0.0",
|
||||
"d3-zoom": "^2.0.0",
|
||||
"easy-peasy": "^3.3.1",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
"react-draggable": "^4.4.3",
|
||||
"resize-observer": "^1.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.11.1",
|
||||
"@babel/core": "^7.11.4",
|
||||
"@babel/preset-env": "^7.11.0",
|
||||
"@babel/preset-react": "^7.10.4",
|
||||
"@svgr/rollup": "^5.4.0",
|
||||
@@ -51,8 +51,8 @@
|
||||
"prettier": "2.0.5",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "^16.13.1",
|
||||
"release-it": "^13.6.8",
|
||||
"rollup": "^2.26.4",
|
||||
"release-it": "^13.6.9",
|
||||
"rollup": "^2.26.5",
|
||||
"rollup-plugin-babel": "^4.4.0",
|
||||
"rollup-plugin-bundle-size": "^1.0.3",
|
||||
"rollup-plugin-commonjs": "^10.1.0",
|
||||
@@ -66,7 +66,7 @@
|
||||
"rollup-plugin-typescript2": "^0.27.2",
|
||||
"rollup-plugin-uglify": "^6.0.4",
|
||||
"start-server-and-test": "^1.11.3",
|
||||
"typescript": "^3.9.7"
|
||||
"typescript": "^4.0.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": "^16.13.1"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import React, { memo, CSSProperties } from 'react';
|
||||
import cc from 'classcat';
|
||||
|
||||
interface MiniMapNodeProps {
|
||||
x: number;
|
||||
@@ -6,17 +7,18 @@ interface MiniMapNodeProps {
|
||||
width: number;
|
||||
height: number;
|
||||
color: string;
|
||||
className: string;
|
||||
borderRadius: number;
|
||||
style?: CSSProperties;
|
||||
}
|
||||
|
||||
const MiniMapNode = ({ x, y, width, height, style, color, borderRadius }: MiniMapNodeProps) => {
|
||||
const MiniMapNode = ({ x, y, width, height, style, color, className, borderRadius }: MiniMapNodeProps) => {
|
||||
const { background, backgroundColor } = style || {};
|
||||
const fill = (color || background || backgroundColor) as string;
|
||||
|
||||
return (
|
||||
<rect
|
||||
className="react-flow__minimap-node"
|
||||
className={cc(['react-flow__minimap-node', className])}
|
||||
x={x}
|
||||
y={y}
|
||||
rx={borderRadius}
|
||||
|
||||
@@ -12,6 +12,7 @@ type StringFunc = (node: Node) => string;
|
||||
|
||||
interface MiniMapProps extends React.HTMLAttributes<SVGSVGElement> {
|
||||
nodeColor?: string | StringFunc;
|
||||
nodeClassName?: string | StringFunc;
|
||||
nodeBorderRadius?: number;
|
||||
maskColor?: string;
|
||||
}
|
||||
@@ -23,6 +24,7 @@ const MiniMap = ({
|
||||
style = { backgroundColor: '#f8f8f8' },
|
||||
className,
|
||||
nodeColor = '#ddd',
|
||||
nodeClassName = '',
|
||||
nodeBorderRadius = 5,
|
||||
maskColor = 'rgba(10, 10, 10, .25)',
|
||||
}: MiniMapProps) => {
|
||||
@@ -35,6 +37,7 @@ const MiniMap = ({
|
||||
const elementWidth = (style.width || defaultWidth)! as number;
|
||||
const elementHeight = (style.height || defaultHeight)! as number;
|
||||
const nodeColorFunc = (nodeColor instanceof Function ? nodeColor : () => nodeColor) as StringFunc;
|
||||
const nodeClassNameFunc = (nodeClassName instanceof Function ? nodeClassName : () => nodeClassName) as StringFunc;
|
||||
const hasNodes = nodes && nodes.length;
|
||||
const bb = getRectOfNodes(nodes);
|
||||
const viewBB: Rect = {
|
||||
@@ -73,6 +76,7 @@ const MiniMap = ({
|
||||
width={node.__rf.width}
|
||||
height={node.__rf.height}
|
||||
style={node.style}
|
||||
className={nodeClassNameFunc(node)}
|
||||
color={nodeColorFunc(node)}
|
||||
borderRadius={nodeBorderRadius}
|
||||
/>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* made a selectio with on or several nodes
|
||||
*/
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, MouseEvent } from 'react';
|
||||
import ReactDraggable from 'react-draggable';
|
||||
|
||||
import { useStoreState, useStoreActions } from '../../store/hooks';
|
||||
@@ -27,7 +27,13 @@ function getStartPositions(nodes: Node[]): StartPositions {
|
||||
}, startPositions);
|
||||
}
|
||||
|
||||
export default () => {
|
||||
export interface NodesSelectionProps {
|
||||
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDrag?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDragStop?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
}
|
||||
|
||||
export default ({ onSelectionDragStart, onSelectionDrag, onSelectionDragStop }: NodesSelectionProps) => {
|
||||
const [offset, setOffset] = useState<XYPosition>({ x: 0, y: 0 });
|
||||
const [startPositions, setStartPositions] = useState<StartPositions>({});
|
||||
|
||||
@@ -61,6 +67,10 @@ export default () => {
|
||||
|
||||
const nextStartPositions = getStartPositions(selectedNodes);
|
||||
|
||||
if (onSelectionDragStart) {
|
||||
onSelectionDragStart(event, selectedNodes);
|
||||
}
|
||||
|
||||
if (nextStartPositions) {
|
||||
setOffset({ x: offsetX, y: offsetY });
|
||||
setStartPositions(nextStartPositions);
|
||||
@@ -74,7 +84,17 @@ export default () => {
|
||||
};
|
||||
|
||||
if (selectedElements) {
|
||||
selectedElements.filter(isNode).forEach((node) => {
|
||||
const selectedNodes = selectedElements ? selectedElements.filter(isNode) : [];
|
||||
|
||||
if (onSelectionDrag) {
|
||||
const selectionNodes = selectedNodes.map(
|
||||
(selectedNode) => nodes.find((node) => node.id === selectedNode.id)! as Node
|
||||
);
|
||||
|
||||
onSelectionDrag(event, selectionNodes);
|
||||
}
|
||||
|
||||
selectedNodes.forEach((node) => {
|
||||
const pos: XYPosition = {
|
||||
x: startPositions[node.id].x + scaledClient.x - selectedNodesBbox.x - offset.x - tX,
|
||||
y: startPositions[node.id].y + scaledClient.y - selectedNodesBbox.y - offset.y - tY,
|
||||
@@ -85,6 +105,16 @@ export default () => {
|
||||
}
|
||||
};
|
||||
|
||||
const onStop = (event: MouseEvent) => {
|
||||
if (selectedElements && onSelectionDragStop) {
|
||||
const selectedNodes = selectedElements
|
||||
? selectedElements.filter(isNode).map((selectedNode) => nodes.find((node) => node.id === selectedNode.id)!)
|
||||
: [];
|
||||
|
||||
onSelectionDragStop(event, selectedNodes);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className="react-flow__nodesselection"
|
||||
@@ -97,6 +127,7 @@ export default () => {
|
||||
grid={grid}
|
||||
onStart={(event) => onStart(event as MouseEvent)}
|
||||
onDrag={(event) => onDrag(event as MouseEvent)}
|
||||
onStop={(event) => onStop(event as MouseEvent)}
|
||||
>
|
||||
<div
|
||||
className="react-flow__nodesselection-rect"
|
||||
|
||||
@@ -46,6 +46,9 @@ export interface GraphViewProps {
|
||||
onMoveEnd?: (flowTransform?: FlowTransform) => void;
|
||||
onPaneClick?: (event: MouseEvent) => void;
|
||||
onPaneContextMenu?: (event: MouseEvent) => void;
|
||||
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDrag?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDragStop?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
selectionKeyCode: number;
|
||||
nodeTypes: NodeTypesType;
|
||||
edgeTypes: EdgeTypesType;
|
||||
@@ -84,6 +87,9 @@ const GraphView = ({
|
||||
onNodeContextMenu,
|
||||
onNodeDragStart,
|
||||
onNodeDragStop,
|
||||
onSelectionDragStart,
|
||||
onSelectionDrag,
|
||||
onSelectionDragStop,
|
||||
connectionLineType,
|
||||
connectionLineStyle,
|
||||
selectionKeyCode,
|
||||
@@ -262,7 +268,13 @@ const GraphView = ({
|
||||
markerEndId={markerEndId}
|
||||
/>
|
||||
<UserSelection selectionKeyPressed={selectionKeyPressed} />
|
||||
{nodesSelectionActive && <NodesSelection />}
|
||||
{nodesSelectionActive && (
|
||||
<NodesSelection
|
||||
onSelectionDragStart={onSelectionDragStart}
|
||||
onSelectionDrag={onSelectionDrag}
|
||||
onSelectionDragStop={onSelectionDragStop}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className="react-flow__zoompane"
|
||||
onClick={onZoomPaneClick}
|
||||
|
||||
@@ -53,6 +53,9 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
|
||||
onMoveStart?: (flowTransform?: FlowTransform) => void;
|
||||
onMoveEnd?: (flowTransform?: FlowTransform) => void;
|
||||
onSelectionChange?: (elements: Elements | null) => void;
|
||||
onSelectionDragStart?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDrag?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onSelectionDragStop?: (event: MouseEvent, nodes: Node[]) => void;
|
||||
onPaneClick?: (event: MouseEvent) => void;
|
||||
onPaneContextMenu?: (event: MouseEvent) => void;
|
||||
nodeTypes: NodeTypesType;
|
||||
@@ -103,6 +106,9 @@ const ReactFlow = ({
|
||||
onNodeDragStart,
|
||||
onNodeDragStop,
|
||||
onSelectionChange,
|
||||
onSelectionDragStart,
|
||||
onSelectionDrag,
|
||||
onSelectionDragStop,
|
||||
connectionLineType,
|
||||
connectionLineStyle,
|
||||
deleteKeyCode,
|
||||
@@ -175,6 +181,9 @@ const ReactFlow = ({
|
||||
paneMoveable={paneMoveable}
|
||||
onPaneClick={onPaneClick}
|
||||
onPaneContextMenu={onPaneContextMenu}
|
||||
onSelectionDragStart={onSelectionDragStart}
|
||||
onSelectionDrag={onSelectionDrag}
|
||||
onSelectionDragStop={onSelectionDragStop}
|
||||
/>
|
||||
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
|
||||
{children}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { useEffect, useRef, MutableRefObject } from 'react';
|
||||
import { event } from 'd3-selection';
|
||||
|
||||
import { useStoreState, useStoreActions } from '../store/hooks';
|
||||
import { FlowTransform } from '../types';
|
||||
@@ -53,7 +52,7 @@ export default ({
|
||||
if (selectionKeyPressed) {
|
||||
d3Zoom.on('zoom', null);
|
||||
} else {
|
||||
d3Zoom.on('zoom', () => {
|
||||
d3Zoom.on('zoom', (event: any) => {
|
||||
updateTransform(event.transform);
|
||||
|
||||
if (onMove) {
|
||||
@@ -68,7 +67,7 @@ export default ({
|
||||
useEffect(() => {
|
||||
if (d3Zoom) {
|
||||
if (onMoveStart) {
|
||||
d3Zoom.on('start', () => {
|
||||
d3Zoom.on('start', (event: any) => {
|
||||
if (viewChanged(prevTransform.current, event.transform)) {
|
||||
const flowTransform = eventToFlowTransform(event.transform);
|
||||
prevTransform.current = flowTransform;
|
||||
@@ -85,7 +84,7 @@ export default ({
|
||||
useEffect(() => {
|
||||
if (d3Zoom) {
|
||||
if (onMoveEnd) {
|
||||
d3Zoom.on('end', () => {
|
||||
d3Zoom.on('end', (event: any) => {
|
||||
if (viewChanged(prevTransform.current, event.transform)) {
|
||||
const flowTransform = eventToFlowTransform(event.transform);
|
||||
prevTransform.current = flowTransform;
|
||||
@@ -101,7 +100,7 @@ export default ({
|
||||
|
||||
useEffect(() => {
|
||||
if (d3Zoom) {
|
||||
d3Zoom.filter(() => {
|
||||
d3Zoom.filter((event: any) => {
|
||||
if (!paneMoveable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export { getBezierPath } from './components/Edges/BezierEdge';
|
||||
export { getSmoothStepPath } from './components/Edges/SmoothStepEdge';
|
||||
export { getMarkerEnd, getCenter as getEdgeCenter } from './components/Edges/utils';
|
||||
|
||||
export { isNode, isEdge, removeElements, addEdge, getOutgoers } from './utils/graph';
|
||||
export { isNode, isEdge, removeElements, addEdge, getOutgoers, getConnectedEdges } from './utils/graph';
|
||||
|
||||
export * from './additional-components';
|
||||
export * from './types';
|
||||
|
||||
Reference in New Issue
Block a user