Merge pull request #248 from wbkd/develop

Develop
This commit is contained in:
Moritz
2020-05-25 13:59:54 +02:00
committed by GitHub
15 changed files with 188 additions and 262 deletions
+2
View File
@@ -67,10 +67,12 @@ const BasicFlow = () => (
- `elements`: array of [nodes](#nodes) and [edges](#edges) *(required)*
- `onElementClick`: element click handler
- `onElementsRemove`: element remove handler
- `onNodeDragStart`: node drag start handler
- `onNodeDragStop`: node drag stop handler
- `onConnect`: connect handler
- `onLoad`: editor load handler
- `onMove`: move handler
- `onSelectionChange`: fired when element selection changes
- `nodeTypes`: object with [node types](#node-types--custom-nodes)
- `edgeTypes`: object with [edge types](#edge-types--custom-edges)
- `style`: css style passed to the wrapper
+10 -63
View File
@@ -1,68 +1,15 @@
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
## React Flow Examples
## Available Scripts
The examples are deployed here: https://react-flow.netlify.app/
In the project directory, you can run:
### Installation
### `yarn start`
```
npm install
```
Runs the app in the development mode.<br />
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
### Start Dev Server
The page will reload if you make edits.<br />
You will also see any lint errors in the console.
### `yarn test`
Launches the test runner in the interactive watch mode.<br />
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
### `yarn build`
Builds the app for production to the `build` folder.<br />
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.<br />
Your app is ready to be deployed!
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
### `yarn eject`
**Note: this is a one-way operation. Once you `eject`, you cant go back!**
If you arent satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
Instead, it will copy all the configuration files and the transitive dependencies (Webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point youre on your own.
You dont have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldnt feel obligated to use this feature. However we understand that this tool wouldnt be useful if you couldnt customize it when you are ready for it.
## Learn More
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
To learn React, check out the [React documentation](https://reactjs.org/).
### Code Splitting
This section has moved here: https://facebook.github.io/create-react-app/docs/code-splitting
### Analyzing the Bundle Size
This section has moved here: https://facebook.github.io/create-react-app/docs/analyzing-the-bundle-size
### Making a Progressive Web App
This section has moved here: https://facebook.github.io/create-react-app/docs/making-a-progressive-web-app
### Advanced Configuration
This section has moved here: https://facebook.github.io/create-react-app/docs/advanced-configuration
### Deployment
This section has moved here: https://facebook.github.io/create-react-app/docs/deployment
### `yarn build` fails to minify
This section has moved here: https://facebook.github.io/create-react-app/docs/troubleshooting#npm-run-build-fails-to-minify
```
npm start
```
+4
View File
@@ -2,8 +2,10 @@ import React, { useState } from 'react';
import ReactFlow, { removeElements, addEdge, MiniMap, Controls } from 'react-flow-renderer';
const onNodeDragStart = node => console.log('drag start', node);
const onNodeDragStop = node => console.log('drag stop', node);
const onElementClick = element => console.log('click', element);
const onSelectionChange = elements => console.log('selection change', elements);
const onLoad = (graph) => {
console.log('graph loaded:', graph);
graph.fitView();
@@ -50,7 +52,9 @@ const OverviewFlow = () => {
onElementClick={onElementClick}
onElementsRemove={onElementsRemove}
onConnect={onConnect}
onNodeDragStart={onNodeDragStart}
onNodeDragStop={onNodeDragStop}
onSelectionChange={onSelectionChange}
style={{ width: '100%', height: '100%' }}
onLoad={onLoad}
connectionLineStyle={{ stroke: '#ddd', strokeWidth: 2 }}
+78 -138
View File
@@ -3393,18 +3393,6 @@
"defer-to-connect": "^2.0.0"
}
},
"@types/blob-util": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@types/blob-util/-/blob-util-1.3.3.tgz",
"integrity": "sha512-4ahcL/QDnpjWA2Qs16ZMQif7HjGP2cw3AGjHabybjw7Vm1EKu+cfQN1D78BaZbS1WJNa1opSMF5HNMztx7lR0w==",
"dev": true
},
"@types/bluebird": {
"version": "3.5.29",
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.29.tgz",
"integrity": "sha512-kmVtnxTuUuhCET669irqQmPAez4KFnFVKvpleVRyfC3g+SHD1hIkFZcWLim9BVcwUBLO59o8VZE4yGCmTif8Yw==",
"dev": true
},
"@types/cacheable-request": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.1.tgz",
@@ -3417,22 +3405,6 @@
"@types/responselike": "*"
}
},
"@types/chai": {
"version": "4.2.7",
"resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.2.7.tgz",
"integrity": "sha512-luq8meHGYwvky0O7u0eQZdA7B4Wd9owUCqvbw2m3XCrCU8mplYOujMBbvyS547AxJkC+pGnd0Cm15eNxEUNU8g==",
"dev": true
},
"@types/chai-jquery": {
"version": "1.1.40",
"resolved": "https://registry.npmjs.org/@types/chai-jquery/-/chai-jquery-1.1.40.tgz",
"integrity": "sha512-mCNEZ3GKP7T7kftKeIs7QmfZZQM7hslGSpYzKbOlR2a2HCFf9ph4nlMRA9UnuOETeOQYJVhJQK7MwGqNZVyUtQ==",
"dev": true,
"requires": {
"@types/chai": "*",
"@types/jquery": "*"
}
},
"@types/classnames": {
"version": "2.2.10",
"resolved": "https://registry.npmjs.org/@types/classnames/-/classnames-2.2.10.tgz",
@@ -3723,15 +3695,6 @@
"integrity": "sha512-c3Xy026kOF7QOTn00hbIllV1dLR9hG9NkSrLQgCVs8NF6sBU+VGWjD3wLPhmh1TYAc7ugCFsvHYMN4VcBN1U1A==",
"dev": true
},
"@types/jquery": {
"version": "3.3.31",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.3.31.tgz",
"integrity": "sha512-Lz4BAJihoFw5nRzKvg4nawXPzutkv7wmfQ5121avptaSIXlDNJCUuxZxX/G+9EVidZGuO0UBlk+YjKbwRKJigg==",
"dev": true,
"requires": {
"@types/sizzle": "*"
}
},
"@types/keyv": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.1.tgz",
@@ -3741,24 +3704,6 @@
"@types/node": "*"
}
},
"@types/lodash": {
"version": "4.14.149",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.149.tgz",
"integrity": "sha512-ijGqzZt/b7BfzcK9vTrS6MFljQRPn5BFWOx8oE0GYxribu6uV+aA9zZuXI1zc/etK9E8nrgdoF2+LgUw7+9tJQ==",
"dev": true
},
"@types/minimatch": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.3.tgz",
"integrity": "sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA==",
"dev": true
},
"@types/mocha": {
"version": "5.2.7",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-5.2.7.tgz",
"integrity": "sha512-NYrtPht0wGzhwe9+/idPaBB+TqkY9AhTvOLMkThm0IoEfLaiVQZwBwyJ5puCkO3AUCWrmcoePjp2mbFocKy4SQ==",
"dev": true
},
"@types/node": {
"version": "12.7.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.12.tgz",
@@ -3820,22 +3765,12 @@
"@types/node": "*"
}
},
"@types/sinon": {
"version": "7.5.1",
"resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-7.5.1.tgz",
"integrity": "sha512-EZQUP3hSZQyTQRfiLqelC9NMWd1kqLcmQE0dMiklxBkgi84T+cHOhnKpgk4NnOWpGX863yE6+IaGnOXUNFqDnQ==",
"@types/sinonjs__fake-timers": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.1.tgz",
"integrity": "sha512-yYezQwGWty8ziyYLdZjwxyMb0CZR49h8JALHGrxjQHWlqGgc8kLdHEgWrgL0uZ29DMvEVBDnHU2Wg36zKSIUtA==",
"dev": true
},
"@types/sinon-chai": {
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/@types/sinon-chai/-/sinon-chai-3.2.3.tgz",
"integrity": "sha512-TOUFS6vqS0PVL1I8NGVSNcFaNJtFoyZPXZ5zur+qlhDfOmQECZZM4H4kKgca6O8L+QceX/ymODZASfUfn+y4yQ==",
"dev": true,
"requires": {
"@types/chai": "*",
"@types/sinon": "*"
}
},
"@types/sizzle": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz",
@@ -3843,9 +3778,9 @@
"dev": true
},
"@welldone-software/why-did-you-render": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/@welldone-software/why-did-you-render/-/why-did-you-render-4.2.1.tgz",
"integrity": "sha512-Q1jH++Sx0F09bU2eTEzAPuBxPiv/uxzgFfWMX1G8LqT4xzdGOrr287DD3lsfPpGLDLx9sqL8jMc0RoxorRewUg==",
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@welldone-software/why-did-you-render/-/why-did-you-render-4.2.2.tgz",
"integrity": "sha512-v08t2WXFQdnxkPodXzbPeho3FwgrlwzjwxasN+8A1LSZnkcxJpYvOF8/z+OySqehC44JT6oPB1KEnBVMrebHdw==",
"requires": {
"lodash": "^4"
}
@@ -5102,9 +5037,9 @@
}
},
"commander": {
"version": "2.20.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.1.tgz",
"integrity": "sha512-cCuLsMhJeWQ/ZpsFTbE765kvVfoeSddc4nU3up4fV+fDBcfUXnbITJ+JzhkdjzOqhURjZgujxaioam4RM9yGUg==",
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
"dev": true
},
"common-tags": {
@@ -5540,24 +5475,15 @@
"dev": true
},
"cypress": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-4.5.0.tgz",
"integrity": "sha512-2A4g5FW5d2fHzq8HKUGAMVTnW6P8nlWYQALiCoGN4bqBLvgwhYM/oG9oKc2CS6LnvgHFiKivKzpm9sfk3uU3zQ==",
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/cypress/-/cypress-4.6.0.tgz",
"integrity": "sha512-vIPXAceRP+Nxvnm/O9ruY9EQaRGmVVybtk9F1sfC9mH3067YbitrdBTynaaLuHFj90p9e0U2ZCV7OkX4x4V/Wg==",
"dev": true,
"requires": {
"@cypress/listr-verbose-renderer": "0.4.1",
"@cypress/request": "2.88.5",
"@cypress/xvfb": "1.2.4",
"@types/blob-util": "1.3.3",
"@types/bluebird": "3.5.29",
"@types/chai": "4.2.7",
"@types/chai-jquery": "1.1.40",
"@types/jquery": "3.3.31",
"@types/lodash": "4.14.149",
"@types/minimatch": "3.0.3",
"@types/mocha": "5.2.7",
"@types/sinon": "7.5.1",
"@types/sinon-chai": "3.2.3",
"@types/sinonjs__fake-timers": "6.0.1",
"@types/sizzle": "2.3.2",
"arch": "2.1.1",
"bluebird": "3.7.2",
@@ -5635,12 +5561,6 @@
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A==",
"dev": true
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"pretty-bytes": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.3.0.tgz",
@@ -6260,21 +6180,6 @@
"ms": "2.0.0"
}
},
"minimist": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
"dev": true
},
"mkdirp": {
"version": "0.5.5",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
"dev": true,
"requires": {
"minimist": "^1.2.5"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -10139,9 +10044,9 @@
}
},
"rollup": {
"version": "2.10.2",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.10.2.tgz",
"integrity": "sha512-tivFM8UXBlYOUqpBYD3pRktYpZvK/eiCQ190eYlrAyrpE/lzkyG2gbawroNdbwmzyUc7Y4eT297xfzv0BDh9qw==",
"version": "2.10.9",
"resolved": "https://registry.npmjs.org/rollup/-/rollup-2.10.9.tgz",
"integrity": "sha512-dY/EbjiWC17ZCUSyk14hkxATAMAShkMsD43XmZGWjLrgFj15M3Dw2kEkA9ns64BiLFm9PKN6vTQw8neHwK74eg==",
"dev": true,
"requires": {
"fsevents": "~2.1.2"
@@ -10402,32 +10307,61 @@
}
},
"rollup-plugin-terser": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-5.3.0.tgz",
"integrity": "sha512-XGMJihTIO3eIBsVGq7jiNYOdDMb3pVxuzY0uhOE/FM4x/u9nQgr3+McsjzqBn3QfHIpNSZmFnpoKAwHBEcsT7g==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz",
"integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==",
"dev": true,
"requires": {
"@babel/code-frame": "^7.5.5",
"jest-worker": "^24.9.0",
"rollup-pluginutils": "^2.8.2",
"serialize-javascript": "^2.1.2",
"terser": "^4.6.2"
"@babel/code-frame": "^7.8.3",
"jest-worker": "^26.0.0",
"serialize-javascript": "^3.0.0",
"terser": "^4.7.0"
},
"dependencies": {
"rollup-pluginutils": {
"version": "2.8.2",
"resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz",
"integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==",
"@babel/code-frame": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
"integrity": "sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g==",
"dev": true,
"requires": {
"estree-walker": "^0.6.1"
"@babel/highlight": "^7.8.3"
}
},
"serialize-javascript": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-2.1.2.tgz",
"integrity": "sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ==",
"@babel/highlight": {
"version": "7.9.0",
"resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.9.0.tgz",
"integrity": "sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ==",
"dev": true,
"requires": {
"@babel/helper-validator-identifier": "^7.9.0",
"chalk": "^2.0.0",
"js-tokens": "^4.0.0"
}
},
"has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"dev": true
},
"jest-worker": {
"version": "26.0.0",
"resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.0.0.tgz",
"integrity": "sha512-pPaYa2+JnwmiZjK9x7p9BoZht+47ecFCDFA/CJxspHzeDvQcfVBLWzCiWyo+EGrSiQMWZtCFo9iSvMZnAAo8vw==",
"dev": true,
"requires": {
"merge-stream": "^2.0.0",
"supports-color": "^7.0.0"
}
},
"supports-color": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
"integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==",
"dev": true,
"requires": {
"has-flag": "^4.0.0"
}
}
}
},
@@ -10608,6 +10542,12 @@
}
}
},
"serialize-javascript": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.0.0.tgz",
"integrity": "sha512-skZcHYw2vEX4bw90nAr2iTTsz6x2SrHEnfxgKYmZlvJYBEZrvbKtobJWlQ20zczKb3bsHHXXTYt48zBA7ni9cw==",
"dev": true
},
"shallow-clone": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-0.1.2.tgz",
@@ -10705,9 +10645,9 @@
"dev": true
},
"source-map-support": {
"version": "0.5.16",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.16.tgz",
"integrity": "sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ==",
"version": "0.5.19",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz",
"integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==",
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
@@ -11020,9 +10960,9 @@
"dev": true
},
"terser": {
"version": "4.6.6",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.6.6.tgz",
"integrity": "sha512-4lYPyeNmstjIIESr/ysHg2vUPRGf2tzF9z2yYwnowXVuVzLEamPN1Gfrz7f8I9uEPuHcbFlW4PLIAsJoxXyJ1g==",
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/terser/-/terser-4.7.0.tgz",
"integrity": "sha512-Lfb0RiZcjRDXCC3OSHJpEkxJ9Qeqs6mp2v4jf2MHfy8vGERmVDuvjXdd/EnP5Deme5F2yBRBymKmKHCBg2echw==",
"dev": true,
"requires": {
"commander": "^2.20.0",
@@ -11144,9 +11084,9 @@
}
},
"typescript": {
"version": "3.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.2.tgz",
"integrity": "sha512-q2ktq4n/uLuNNShyayit+DTobV2ApPEo/6so68JaD5ojvc/6GClBipedB9zNWYxRSAlZXAe405Rlijzl6qDiSw==",
"version": "3.9.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.3.tgz",
"integrity": "sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==",
"dev": true
},
"uglify-js": {
+5 -5
View File
@@ -23,7 +23,7 @@
"release": "release-it"
},
"dependencies": {
"@welldone-software/why-did-you-render": "^4.2.1",
"@welldone-software/why-did-you-render": "^4.2.2",
"classnames": "^2.2.6",
"d3-selection": "^1.4.1",
"d3-zoom": "^1.8.3",
@@ -44,13 +44,13 @@
"autoprefixer": "^9.8.0",
"babel-loader": "^8.1.0",
"babel-preset-react-app": "^9.1.2",
"cypress": "^4.5.0",
"cypress": "^4.6.0",
"postcss-nested": "^4.2.1",
"prettier": "2.0.5",
"prop-types": "^15.7.2",
"react": "^16.13.1",
"release-it": "^13.6.1",
"rollup": "^2.10.2",
"rollup": "^2.10.9",
"rollup-plugin-babel": "^4.4.0",
"rollup-plugin-bundle-size": "^1.0.3",
"rollup-plugin-commonjs": "^10.1.0",
@@ -60,11 +60,11 @@
"rollup-plugin-postcss": "^3.1.1",
"rollup-plugin-replace": "^2.2.0",
"rollup-plugin-serve": "^1.0.1",
"rollup-plugin-terser": "^5.3.0",
"rollup-plugin-terser": "^6.1.0",
"rollup-plugin-typescript2": "^0.27.1",
"rollup-plugin-uglify": "^6.0.4",
"start-server-and-test": "^1.11.0",
"typescript": "^3.9.2"
"typescript": "^3.9.3"
},
"peerDependencies": {
"react": "^16.13.1"
+20 -13
View File
@@ -12,7 +12,7 @@ const getMouseEvent = (evt: MouseEvent | TouchEvent) =>
const onStart = (
evt: MouseEvent | TouchEvent,
onClick: (node: Node) => void,
onDragStart: (node: Node) => void,
id: ElementId,
type: string,
data: any,
@@ -26,13 +26,14 @@ const onStart = (
x: startEvt.clientX * (1 / transform[2]),
y: startEvt.clientY * (1 / transform[2]),
};
const offsetX = scaledClient.x - position.x - transform[0];
const offsetY = scaledClient.y - position.y - transform[1];
const node = { id, type, position, data };
store.dispatch.setSelectedElements({ id, type } as Node);
setOffset({ x: offsetX, y: offsetY });
onClick(node);
onDragStart(node);
};
const onDrag = (
@@ -60,7 +61,8 @@ const onDrag = (
};
const onStop = (
onNodeDragStop: (node: Node) => void,
onDragStop: (node: Node) => void,
onClick: (node: Node) => void,
isDragging: boolean,
setDragging: (isDragging: boolean) => void,
id: ElementId,
@@ -68,15 +70,19 @@ const onStop = (
position: XYPosition,
data: any
): void => {
if (isDragging) {
setDragging(false);
onNodeDragStop({
id,
type,
position,
data,
} as Node);
const node = {
id,
type,
position,
data,
} as Node;
if (!isDragging) {
return onClick(node);
}
setDragging(false);
onDragStop(node);
};
export default (NodeComponent: ComponentType<NodeComponentProps>) => {
@@ -90,6 +96,7 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
yPos,
selected,
onClick,
onNodeDragStart,
onNodeDragStop,
style,
isInteractive,
@@ -139,9 +146,9 @@ export default (NodeComponent: ComponentType<NodeComponentProps>) => {
return (
<DraggableCore
onStart={(evt) => onStart(evt as MouseEvent, onClick, id, type, data, setOffset, transform, position)}
onStart={(evt) => onStart(evt as MouseEvent, onNodeDragStart, id, type, data, setOffset, transform, position)}
onDrag={(evt) => onDrag(evt as MouseEvent, setDragging, id, offset, transform)}
onStop={() => onStop(onNodeDragStop, isDragging, setDragging, id, type, position, data)}
onStop={() => onStop(onNodeDragStop, onClick, isDragging, setDragging, id, type, position, data)}
scale={transform[2]}
disabled={!isInteractive}
cancel=".nodrag"
+14 -10
View File
@@ -50,9 +50,11 @@ export default memo(() => {
};
const offsetX: number = scaledClient.x - position.x - tx;
const offsetY: number = scaledClient.y - position.y - ty;
const selectedNodes = (state.selectedElements.filter(isNode) as Node[]).map(
(selectedNode) => state.nodes.find((node) => node.id === selectedNode.id)! as Node
);
const selectedNodes = state.selectedElements
? (state.selectedElements.filter(isNode) as Node[]).map(
(selectedNode) => state.nodes.find((node) => node.id === selectedNode.id)! as Node
)
: [];
const nextStartPositions = getStartPositions(selectedNodes);
@@ -68,14 +70,16 @@ export default memo(() => {
y: evt.clientY / tScale,
};
(state.selectedElements.filter(isNode) as Node[]).forEach((node) => {
const pos: XYPosition = {
x: startPositions[node.id].x + scaledClient.x - position.x - offset.x - tx,
y: startPositions[node.id].y + scaledClient.y - position.y - offset.y - ty,
};
if (state.selectedElements) {
(state.selectedElements.filter(isNode) as Node[]).forEach((node) => {
const pos: XYPosition = {
x: startPositions[node.id].x + scaledClient.x - position.x - offset.x - tx,
y: startPositions[node.id].y + scaledClient.y - position.y - offset.y - ty,
};
updateNodePos({ id: node.id, pos });
});
updateNodePos({ id: node.id, pos });
});
}
};
return (
+22
View File
@@ -0,0 +1,22 @@
import { useEffect } from 'react';
import { Elements } from '../../types';
import { useStoreState } from '../../store/hooks';
interface SelectionListenerProps {
onSelectionChange: (elements: Elements | null) => void;
}
// This is just a helper component for calling the onSelectionChange listener.
// As soon as easy-peasy has implemented the effectOn hook, we can remove this compeonent
// and use the hook instead. https://github.com/ctrlplusb/easy-peasy/pull/459
export default ({ onSelectionChange }: SelectionListenerProps) => {
const selectedElements = useStoreState((s) => s.selectedElements);
useEffect(() => {
onSelectionChange(selectedElements);
}, [selectedElements]);
return null;
};
+4 -4
View File
@@ -117,7 +117,7 @@ function renderEdge(
edge: Edge,
props: EdgeRendererProps,
nodes: Node[],
selectedElements: Elements,
selectedElements: Elements | null,
isInteractive: boolean
) {
const [sourceId, sourceHandleId] = edge.source.split('__');
@@ -154,9 +154,9 @@ function renderEdge(
targetPosition
);
const isSelected = (selectedElements as Edge[]).some(
(elm) => isEdge(elm) && elm.source === sourceId && elm.target === targetId
);
const isSelected = selectedElements
? (selectedElements as Edge[]).some((elm) => isEdge(elm) && elm.source === sourceId && elm.target === targetId)
: false;
return (
<EdgeComponent
+3
View File
@@ -19,6 +19,7 @@ export interface GraphViewProps {
elements: Elements;
onElementClick: (element: Node | Edge) => void;
onElementsRemove: (elements: Elements) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onConnect: (connection: Connection | Edge) => void;
onLoad: OnLoadFunc;
@@ -46,6 +47,7 @@ const GraphView = memo(
onMove,
onLoad,
onElementClick,
onNodeDragStart,
onNodeDragStop,
connectionLineType,
connectionLineStyle,
@@ -140,6 +142,7 @@ const GraphView = memo(
nodeTypes={nodeTypes}
onElementClick={onElementClick}
onNodeDragStop={onNodeDragStop}
onNodeDragStart={onNodeDragStart}
onlyRenderVisibleNodes={onlyRenderVisibleNodes}
/>
<EdgeRenderer
+4 -2
View File
@@ -7,6 +7,7 @@ import { Node, Transform, NodeTypesType, WrapNodeProps, Elements, Edge } from '.
interface NodeRendererProps {
nodeTypes: NodeTypesType;
onElementClick: (element: Node | Edge) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onlyRenderVisibleNodes?: boolean;
}
@@ -15,7 +16,7 @@ function renderNode(
node: Node,
props: NodeRendererProps,
transform: Transform,
selectedElements: Elements,
selectedElements: Elements | null,
isInteractive: boolean
) {
const nodeType = node.type || 'default';
@@ -24,7 +25,7 @@ function renderNode(
console.warn(`No node type found for type "${nodeType}". Using fallback type "default".`);
}
const isSelected = selectedElements.some(({ id }) => id === node.id);
const isSelected = selectedElements ? selectedElements.some(({ id }) => id === node.id) : false;
return (
<NodeComponent
@@ -35,6 +36,7 @@ function renderNode(
xPos={node.__rg.position.x}
yPos={node.__rg.position.y}
onClick={props.onElementClick}
onNodeDragStart={props.onNodeDragStart}
onNodeDragStop={props.onNodeDragStop}
transform={transform}
selected={isSelected}
+8 -1
View File
@@ -14,6 +14,7 @@ import DefaultNode from '../../components/Nodes/DefaultNode';
import InputNode from '../../components/Nodes/InputNode';
import OutputNode from '../../components/Nodes/OutputNode';
import { createNodeTypes } from '../NodeRenderer/utils';
import SelectionListener from '../../components/SelectionListener';
import BezierEdge from '../../components/Edges/BezierEdge';
import StraightEdge from '../../components/Edges/StraightEdge';
import StepEdge from '../../components/Edges/StepEdge';
@@ -27,10 +28,12 @@ export interface ReactFlowProps extends Omit<HTMLAttributes<HTMLDivElement>, 'on
elements: Elements;
onElementClick: (element: Node | Edge) => void;
onElementsRemove: (elements: Elements) => void;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
onConnect: (connection: Edge | Connection) => void;
onLoad: OnLoadFunc;
onMove: () => void;
onSelectionChange: (elements: Elements | null) => void;
nodeTypes: NodeTypesType;
edgeTypes: EdgeTypesType;
connectionLineType: string;
@@ -59,7 +62,9 @@ const ReactFlow = ({
onMove,
onElementsRemove,
onConnect,
onNodeDragStart,
onNodeDragStop,
onSelectionChange,
connectionLineType,
connectionLineStyle,
deleteKeyCode,
@@ -83,6 +88,7 @@ const ReactFlow = ({
onLoad={onLoad}
onMove={onMove}
onElementClick={onElementClick}
onNodeDragStart={onNodeDragStart}
onNodeDragStop={onNodeDragStop}
nodeTypes={nodeTypesParsed}
edgeTypes={edgeTypesParsed}
@@ -102,6 +108,7 @@ const ReactFlow = ({
onlyRenderVisibleNodes={onlyRenderVisibleNodes}
isInteractive={isInteractive}
/>
{onSelectionChange && <SelectionListener onSelectionChange={onSelectionChange} />}
{children}
</StoreProvider>
</div>
@@ -113,6 +120,7 @@ ReactFlow.displayName = 'ReactFlow';
ReactFlow.defaultProps = {
onElementClick: () => {},
onElementsRemove: () => {},
onNodeDragStart: () => {},
onNodeDragStop: () => {},
onConnect: () => {},
onLoad: () => {},
@@ -139,7 +147,6 @@ ReactFlow.defaultProps = {
snapGrid: [16, 16],
onlyRenderVisibleNodes: true,
isInteractive: true,
className: '',
};
export default ReactFlow;
+4 -7
View File
@@ -11,22 +11,19 @@ interface HookParams {
}
export default ({ deleteKeyCode, onElementsRemove }: HookParams): void => {
const state = useStoreState(s => ({
const state = useStoreState((s) => ({
selectedElements: s.selectedElements,
edges: s.edges,
}));
const setNodesSelection = useStoreActions(a => a.setNodesSelection);
const setNodesSelection = useStoreActions((a) => a.setNodesSelection);
const deleteKeyPressed = useKeyPress(deleteKeyCode);
useEffect(() => {
if (deleteKeyPressed && state.selectedElements.length) {
if (deleteKeyPressed && state.selectedElements) {
let elementsToRemove = state.selectedElements;
// we also want to remove the edges if only one node is selected
if (
state.selectedElements.length === 1 &&
!isEdge(state.selectedElements[0])
) {
if (state.selectedElements.length === 1 && !isEdge(state.selectedElements[0])) {
const node = (state.selectedElements[0] as unknown) as Node;
const connectedEdges = getConnectedEdges([node], state.edges);
elementsToRemove = [...state.selectedElements, ...connectedEdges];
+9 -19
View File
@@ -56,7 +56,7 @@ export interface StoreModel {
transform: Transform;
nodes: Node[];
edges: Edge[];
selectedElements: Elements;
selectedElements: Elements | null;
selectedNodesBbox: Rect;
d3Zoom: ZoomBehavior<Element, unknown> | null;
@@ -95,8 +95,6 @@ export interface StoreModel {
setSelectedElements: Action<StoreModel, Elements | Node | Edge>;
updateSelection: Action<StoreModel, SelectionRect>;
updateTransform: Action<StoreModel, TransformXYK>;
updateSize: Action<StoreModel, Dimensions>;
@@ -122,7 +120,7 @@ const storeModel: StoreModel = {
transform: [0, 0, 1],
nodes: [],
edges: [],
selectedElements: [],
selectedElements: null,
selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 },
d3Zoom: null,
@@ -250,8 +248,11 @@ const storeModel: StoreModel = {
const selectedElementsUpdated = !isEqual(nextSelectedElements, state.selectedElements);
state.selection = nextRect;
state.selectedElements = selectedElementsUpdated ? nextSelectedElements : state.selectedElements;
state.userSelectionRect = nextRect;
if (selectedElementsUpdated) {
state.selectedElements = nextSelectedElements.length > 0 ? nextSelectedElements : null;
}
}),
unsetUserSelection: action((state) => {
@@ -261,7 +262,7 @@ const storeModel: StoreModel = {
state.selectionActive = false;
state.userSelectionRect = { ...state.userSelectionRect, draw: false };
state.nodesSelectionActive = false;
state.selectedElements = [];
state.selectedElements = null;
return;
}
@@ -283,7 +284,7 @@ const storeModel: StoreModel = {
setNodesSelection: action((state, { isActive, selection }) => {
if (!isActive || typeof selection === 'undefined') {
state.nodesSelectionActive = false;
state.selectedElements = [];
state.selectedElements = null;
return;
}
@@ -291,7 +292,7 @@ const storeModel: StoreModel = {
if (!selectedNodes.length) {
state.nodesSelectionActive = false;
state.selectedElements = [];
state.selectedElements = null;
return;
}
@@ -311,17 +312,6 @@ const storeModel: StoreModel = {
state.selectedElements = selectedElements;
}),
updateSelection: action((state, selection) => {
const selectedNodes = getNodesInside(state.nodes, selection, state.transform);
const selectedEdges = getConnectedEdges(selectedNodes, state.edges);
const nextSelectedElements = [...selectedNodes, ...selectedEdges];
const selectedElementsUpdated = !isEqual(nextSelectedElements, state.selectedElements);
state.selection = selection;
state.selectedElements = selectedElementsUpdated ? nextSelectedElements : state.selectedElements;
}),
updateTransform: action((state, transform) => {
state.transform = [transform.x, transform.y, transform.k];
}),
+1
View File
@@ -123,6 +123,7 @@ export interface WrapNodeProps {
yPos: number;
isInteractive: boolean;
onClick: (node: Node) => void | undefined;
onNodeDragStart: (node: Node) => void;
onNodeDragStop: (node: Node) => void;
style?: CSSProperties;
sourcePosition?: Position;