diff --git a/cypress/integration/flow/stress.spec.js b/cypress/integration/flow/stress.spec.js new file mode 100644 index 00000000..e289ef11 --- /dev/null +++ b/cypress/integration/flow/stress.spec.js @@ -0,0 +1,10 @@ +describe('Stress Graph Rendering', () => { + it('renders a graph', () => { + cy.visit('/stress'); + + cy.get('.react-flow__renderer'); + + cy.get('.react-flow__node').should('have.length', 100); + cy.get('.react-flow__edge').should('have.length', 99); + }); +}); diff --git a/example/public/index.html b/example/public/index.html index c240d2ca..b8f90c04 100644 --- a/example/public/index.html +++ b/example/public/index.html @@ -4,40 +4,12 @@ - - - - - - - React App + + + React Flow Examples
- diff --git a/package-lock.json b/package-lock.json index ab3eab03..5535f23c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1079,12 +1079,6 @@ "figures": "^1.7.0" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -1104,40 +1098,6 @@ "supports-color": "^2.0.0" } }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -1617,9 +1577,9 @@ "integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==" }, "@types/react": { - "version": "16.9.9", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.9.tgz", - "integrity": "sha512-L+AudFJkDukk+ukInYvpoAPyJK5q1GanFOINOJnM0w6tUgITuWvJ4jyoBPFL7z4/L8hGLd+K/6xR5uUjXu0vVg==", + "version": "16.9.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.11.tgz", + "integrity": "sha512-UBT4GZ3PokTXSWmdgC/GeCGEJXE5ofWyibCcecRLUVN2ZBpXQGVgQGtG2foS7CrTKFKlQVVswLvf7Js6XA/CVQ==", "dev": true, "requires": { "@types/prop-types": "*", @@ -1627,9 +1587,9 @@ } }, "@types/react-dom": { - "version": "16.9.2", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.2.tgz", - "integrity": "sha512-hgPbBoI1aTSTvZwo8HYw35UaTldW6n2ETLvHAcfcg1FaOuBV3olmyCe5eMpx2WybWMBPv0MdU2t5GOcQhP+3zA==", + "version": "16.9.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.3.tgz", + "integrity": "sha512-FUuZKXPr9qlzUT9lhuzrZgLjH63TvNn28Ch3MvKG4B+F52zQtO8DtE0Opbncy3xaucNZM2WIPfuNTgkbKx5Brg==", "dev": true, "requires": { "@types/react": "*" @@ -1644,6 +1604,12 @@ "@types/node": "*" } }, + "@types/sizzle": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.2.tgz", + "integrity": "sha512-7EJYyKTL7tFR8+gDbB6Wwz/arpGa0Mywk1TJbNzKzHtzbwVmY4HR9WqS5VV7dsBUKQmPNr192jHr/VpBluj/hg==", + "dev": true + }, "@welldone-software/why-did-you-render": { "version": "3.3.8", "resolved": "https://registry.npmjs.org/@welldone-software/why-did-you-render/-/why-did-you-render-3.3.8.tgz", @@ -1690,6 +1656,12 @@ "integrity": "sha1-06ioOzGapneTZisT52HHkRQiMG4=", "dev": true }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", + "dev": true + }, "ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -1811,56 +1783,56 @@ "dev": true }, "autoprefixer": { - "version": "9.6.5", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.6.5.tgz", - "integrity": "sha512-rGd50YV8LgwFQ2WQp4XzOTG69u1qQsXn0amww7tjqV5jJuNazgFKYEVItEBngyyvVITKOg20zr2V+9VsrXJQ2g==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.7.0.tgz", + "integrity": "sha512-j2IRvaCfrUxIiZun9ba4mhJ2omhw4OY88/yVzLO+lHhGBumAAK72PgM6gkbSN8iregPOn1ZlxGkmZh2CQ7X4AQ==", "dev": true, "requires": { - "browserslist": "^4.7.0", - "caniuse-lite": "^1.0.30000999", + "browserslist": "^4.7.2", + "caniuse-lite": "^1.0.30001004", "chalk": "^2.4.2", "normalize-range": "^0.1.2", "num2fraction": "^1.2.2", - "postcss": "^7.0.18", + "postcss": "^7.0.19", "postcss-value-parser": "^4.0.2" }, "dependencies": { "browserslist": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.0.tgz", - "integrity": "sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA==", + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.7.2.tgz", + "integrity": "sha512-uZavT/gZXJd2UTi9Ov7/Z340WOSQ3+m1iBVRUknf+okKxonL9P83S3ctiBDtuRmRu8PiCHjqyueqQ9HYlJhxiw==", "dev": true, "requires": { - "caniuse-lite": "^1.0.30000989", - "electron-to-chromium": "^1.3.247", - "node-releases": "^1.1.29" + "caniuse-lite": "^1.0.30001004", + "electron-to-chromium": "^1.3.295", + "node-releases": "^1.1.38" } }, "caniuse-lite": { - "version": "1.0.30000999", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000999.tgz", - "integrity": "sha512-1CUyKyecPeksKwXZvYw0tEoaMCo/RwBlXmEtN5vVnabvO0KPd9RQLcaAuR9/1F+KDMv6esmOFWlsXuzDk+8rxg==", + "version": "1.0.30001005", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001005.tgz", + "integrity": "sha512-g78miZm1Z5njjYR216a5812oPiLgV1ssndgGxITHWUopmjUrCswMisA0a2kSB7a0vZRox6JOKhM51+efmYN8Mg==", "dev": true }, "electron-to-chromium": { - "version": "1.3.282", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.282.tgz", - "integrity": "sha512-irSaDeCGgfMu1OA30bhqIBr+dx+pDJjRbwCpob7YWqVZbzXblybNzPGklVnWqv4EXxbkEAzQYqiNCqNTgu00lQ==", + "version": "1.3.296", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.296.tgz", + "integrity": "sha512-s5hv+TSJSVRsxH190De66YHb50pBGTweT9XGWYu/LMR20KX6TsjFzObo36CjVAzM+PUeeKSBRtm/mISlCzeojQ==", "dev": true }, "node-releases": { - "version": "1.1.35", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.35.tgz", - "integrity": "sha512-JGcM/wndCN/2elJlU0IGdVEJQQnJwsLbgPCFd2pY7V0mxf17bZ0Gb/lgOtL29ZQhvEX5shnVhxQyZz3ex94N8w==", + "version": "1.1.39", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.39.tgz", + "integrity": "sha512-8MRC/ErwNCHOlAFycy9OPca46fQYUjbJRDcZTHVWIGXIjYLM73k70vv3WkYutVnM4cCo4hE0MqBVVZjP6vjISA==", "dev": true, "requires": { "semver": "^6.3.0" } }, "postcss": { - "version": "7.0.18", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.18.tgz", - "integrity": "sha512-/7g1QXXgegpF+9GJj4iN7ChGF40sYuGYJ8WZu8DZWnmhQ/G36hfdk3q9LBJmoK+lZ+yzZ5KYpOoxq7LF1BxE8g==", + "version": "7.0.21", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.21.tgz", + "integrity": "sha512-uIFtJElxJo29QC753JzhidoAhvp/e/Exezkdhfmt8AymWT6/5B7W1WmponYWkHk2eg6sONyTch0A3nkMPun3SQ==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -2479,6 +2451,21 @@ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" }, + "cli-cursor": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", + "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", + "dev": true, + "requires": { + "restore-cursor": "^1.0.1" + } + }, + "cli-spinners": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", + "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", + "dev": true + }, "cli-truncate": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-0.2.1.tgz", @@ -2999,13 +2986,14 @@ "dev": true }, "cypress": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-3.4.1.tgz", - "integrity": "sha512-1HBS7t9XXzkt6QHbwfirWYty8vzxNMawGj1yI+Fu6C3/VZJ8UtUngMW6layqwYZzLTZV8tiDpdCNBypn78V4Dg==", + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/cypress/-/cypress-3.5.0.tgz", + "integrity": "sha512-I1iSReD2C8CTP6s4BvQky4gEqHBnKLmhBIqFyCUZdj6BQ6ZDxGnmIbQPM5g79E2iP60KTIbTK99ZPSDVtsNUUg==", "dev": true, "requires": { "@cypress/listr-verbose-renderer": "0.4.1", "@cypress/xvfb": "1.2.4", + "@types/sizzle": "2.3.2", "arch": "2.1.1", "bluebird": "3.5.0", "cachedir": "1.3.0", @@ -3032,16 +3020,11 @@ "request-progress": "3.0.0", "supports-color": "5.5.0", "tmp": "0.1.0", + "untildify": "3.0.3", "url": "0.11.0", "yauzl": "2.10.0" }, "dependencies": { - "ci-info": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", - "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", - "dev": true - }, "commander": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", @@ -3078,15 +3061,6 @@ "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", "dev": true }, - "is-ci": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", - "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", - "dev": true, - "requires": { - "ci-info": "^1.5.0" - } - }, "lodash": { "version": "4.17.15", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz", @@ -3814,7 +3788,8 @@ "ansi-regex": { "version": "2.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -3835,12 +3810,14 @@ "balanced-match": { "version": "1.0.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, "dev": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3855,17 +3832,20 @@ "code-point-at": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "concat-map": { "version": "0.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -3982,7 +3962,8 @@ "inherits": { "version": "2.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -3994,6 +3975,7 @@ "version": "1.0.0", "bundled": true, "dev": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -4008,6 +3990,7 @@ "version": "3.0.4", "bundled": true, "dev": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4015,12 +3998,14 @@ "minimist": { "version": "0.0.8", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "minipass": { "version": "2.3.5", "bundled": true, "dev": true, + "optional": true, "requires": { "safe-buffer": "^5.1.2", "yallist": "^3.0.0" @@ -4039,6 +4024,7 @@ "version": "0.5.1", "bundled": true, "dev": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -4119,7 +4105,8 @@ "number-is-nan": { "version": "1.0.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -4131,6 +4118,7 @@ "version": "1.4.0", "bundled": true, "dev": true, + "optional": true, "requires": { "wrappy": "1" } @@ -4216,7 +4204,8 @@ "safe-buffer": { "version": "5.1.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -4252,6 +4241,7 @@ "version": "1.0.2", "bundled": true, "dev": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -4271,6 +4261,7 @@ "version": "3.0.1", "bundled": true, "dev": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -4314,12 +4305,14 @@ "wrappy": { "version": "1.0.2", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "yallist": { "version": "3.0.3", "bundled": true, - "dev": true + "dev": true, + "optional": true } } }, @@ -4377,9 +4370,9 @@ } }, "glob": { - "version": "7.1.4", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", - "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "version": "7.1.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.5.tgz", + "integrity": "sha512-J9dlskqUXK1OeTOYBEn5s8aMukWMwWfs+rPTn/jn50Ux4MNXVhubL1wu/j2t+H4NVI+cXEcCaYellqaPVGXNqQ==", "dev": true, "requires": { "fs.realpath": "^1.0.0", @@ -4716,6 +4709,23 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz", "integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==" }, + "is-ci": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz", + "integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==", + "dev": true, + "requires": { + "ci-info": "^1.5.0" + }, + "dependencies": { + "ci-info": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz", + "integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==", + "dev": true + } + } + }, "is-color-stop": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz", @@ -5119,12 +5129,6 @@ "strip-ansi": "^3.0.1" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5144,21 +5148,6 @@ "supports-color": "^2.0.0" } }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "cli-spinners": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-0.1.2.tgz", - "integrity": "sha1-u3ZNiOGF+54eaiofGXcjGPYF4xw=", - "dev": true - }, "log-symbols": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-1.0.2.tgz", @@ -5168,43 +5157,6 @@ "chalk": "^1.0.0" } }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "ora": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", - "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", - "dev": true, - "requires": { - "chalk": "^1.1.1", - "cli-cursor": "^1.0.2", - "cli-spinners": "^0.1.2", - "object-assign": "^4.0.1" - } - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5235,12 +5187,6 @@ "strip-ansi": "^3.0.1" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5275,15 +5221,6 @@ "chalk": "^1.0.0" } }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5304,12 +5241,6 @@ "figures": "^1.7.0" }, "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, "ansi-styles": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", @@ -5329,40 +5260,6 @@ "supports-color": "^2.0.0" } }, - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, "supports-color": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", @@ -5468,33 +5365,6 @@ "requires": { "ansi-escapes": "^1.0.0", "cli-cursor": "^1.0.2" - }, - "dependencies": { - "cli-cursor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-1.0.2.tgz", - "integrity": "sha1-ZNo/fValRBLll5S9Ytw1KV6PKYc=", - "dev": true, - "requires": { - "restore-cursor": "^1.0.1" - } - }, - "onetime": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", - "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", - "dev": true - }, - "restore-cursor": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", - "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", - "dev": true, - "requires": { - "exit-hook": "^1.0.0", - "onetime": "^1.0.0" - } - } } }, "loose-envify": { @@ -6007,6 +5877,45 @@ "integrity": "sha1-0YXAQlz9652h0YKQi2W1wCOP67M=", "dev": true }, + "ora": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/ora/-/ora-0.2.3.tgz", + "integrity": "sha1-N1J9Igrc1Tw5tzVx11QVbV22V6Q=", + "dev": true, + "requires": { + "chalk": "^1.1.1", + "cli-cursor": "^1.0.2", + "cli-spinners": "^0.1.2", + "object-assign": "^4.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", + "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", + "dev": true + }, + "chalk": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", + "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", + "dev": true, + "requires": { + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" + } + }, + "supports-color": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", + "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", + "dev": true + } + } + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -6791,9 +6700,9 @@ "dev": true }, "react": { - "version": "16.10.2", - "resolved": "https://registry.npmjs.org/react/-/react-16.10.2.tgz", - "integrity": "sha512-MFVIq0DpIhrHFyqLU0S3+4dIcBhhOvBE8bJ/5kHPVOVaGdo0KuiQzpcjCPsf585WvhypqtrMILyoE2th6dT+Lw==", + "version": "16.11.0", + "resolved": "https://registry.npmjs.org/react/-/react-16.11.0.tgz", + "integrity": "sha512-M5Y8yITaLmU0ynd0r1Yvfq98Rmll6q8AxaEe88c8e7LxO8fZ2cNgmFt0aGAS9wzf1Ao32NKXtCl+/tVVtkxq6g==", "dev": true, "requires": { "loose-envify": "^1.1.0", @@ -6802,9 +6711,9 @@ } }, "react-draggable": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.0.3.tgz", - "integrity": "sha512-4vD6zms+9QGeZ2RQXzlUBw8PBYUXy+dzYX5r22idjp9YwQKIIvD/EojL0rbjS1GK4C3P0rAJnmKa8gDQYWUDyA==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.1.0.tgz", + "integrity": "sha512-Or/qe70cfymshqoC8Lsp0ukTzijJObehb7Vfl7tb5JRxoV+b6PDkOGoqYaWBzZ59k9dH/bwraLGsnlW78/3vrA==", "requires": { "classnames": "^2.2.5", "prop-types": "^15.6.0" @@ -7063,6 +6972,24 @@ "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", "dev": true }, + "restore-cursor": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-1.0.1.tgz", + "integrity": "sha1-NGYfRohjJ/7SmRR5FSJS35LapUE=", + "dev": true, + "requires": { + "exit-hook": "^1.0.0", + "onetime": "^1.0.0" + }, + "dependencies": { + "onetime": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + } + } + }, "ret": { "version": "0.1.15", "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", @@ -7082,18 +7009,18 @@ "dev": true }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", "dev": true, "requires": { "glob": "^7.1.3" } }, "rollup": { - "version": "1.25.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.25.1.tgz", - "integrity": "sha512-K8ytdEzMa6anHSnfTIs2BLB+NXlQ4qmWwdNHBpYQNWCbZAzj+DRVk7+ssbLSgddwpFW1nThr2GElR+jASF2NPA==", + "version": "1.26.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.26.0.tgz", + "integrity": "sha512-5HljNYn9icFvXX+Oe97qY5TWvnWhKqgGT0HGeWWqFPx7w7+Anzg7dfHMtUif7YYy6QxAgynDSwK6uxbgcrVUxw==", "dev": true, "requires": { "@types/estree": "*", @@ -7441,9 +7368,9 @@ "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" }, "scheduler": { - "version": "0.16.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.16.2.tgz", - "integrity": "sha512-BqYVWqwz6s1wZMhjFvLfVR5WXP7ZY32M/wYPo04CcuPM7XZEbV2TBNW7Z0UkguPTl0dWMA59VbNXxK6q+pHItg==", + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.17.0.tgz", + "integrity": "sha512-7rro8Io3tnCPuY4la/NuI5F2yfESpnfZyT6TtkXnSWVkcu0BCDJ+8gk5ozUaFaxpIyNuWAPXrH0yFcSi28fnDA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -7979,23 +7906,6 @@ "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", "strip-ansi": "^3.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - } } }, "string_decoder": { @@ -8007,6 +7917,15 @@ "safe-buffer": "~5.1.0" } }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, "strip-eof": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", @@ -8322,6 +8241,12 @@ } } }, + "untildify": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/untildify/-/untildify-3.0.3.tgz", + "integrity": "sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==", + "dev": true + }, "upath": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", diff --git a/package.json b/package.json index 3f2ceb47..1297faf9 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "d3-zoom": "^1.8.3", "easy-peasy": "^3.1.0", "fast-deep-equal": "^3.0.0-beta.2", - "react-draggable": "^4.0.3", + "react-draggable": "^4.1.0", "resize-observer": "^1.0.0", - "scheduler": "^0.16.2" + "scheduler": "^0.17.0" }, "devDependencies": { "@babel/core": "^7.6.4", @@ -22,18 +22,18 @@ "@babel/preset-react": "^7.6.3", "@types/classnames": "^2.2.9", "@types/d3": "^5.7.2", - "@types/react": "^16.9.9", - "@types/react-dom": "^16.9.2", - "autoprefixer": "^9.6.5", + "@types/react": "^16.9.11", + "@types/react-dom": "^16.9.3", + "autoprefixer": "^9.7.0", "babel-loader": "^8.0.6", "babel-preset-react-app": "^9.0.2", - "cypress": "^3.4.1", + "cypress": "^3.5.0", "husky": "^3.0.9", "postcss-nested": "^4.1.2", "prettier": "1.18.2", "prop-types": "^15.7.2", - "react": "^16.10.2", - "rollup": "^1.25.1", + "react": "^16.11.0", + "rollup": "^1.26.0", "rollup-plugin-babel": "^4.3.3", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-commonjs": "^10.1.0", @@ -57,7 +57,7 @@ "scripts": { "build": "rollup -c --environment NODE_ENV:production", "start": "rollup -w -c", - "dev": "cd example && npm start", + "dev": "npm start & cd example && npm start", "build:example": "npm install && cd example && npm install && npm run build", "dev:wait": "start-server-and-test dev http-get://localhost:3000", "cy:run": "cypress run", diff --git a/src/components/Nodes/utils.ts b/src/components/Nodes/utils.ts new file mode 100644 index 00000000..82d9322e --- /dev/null +++ b/src/components/Nodes/utils.ts @@ -0,0 +1,41 @@ +import { HandleElement, Position } from '../../types'; +import { getDimensions } from '../../utils'; + +export const getHandleBounds = ( + selector: string, + nodeElement: HTMLDivElement, + parentBounds: ClientRect | DOMRect, + k: number +): HandleElement[] | null => { + const handles = nodeElement.querySelectorAll(selector); + + if (!handles || !handles.length) { + return null; + } + + const handlesArray = Array.from(handles) as HTMLDivElement[]; + + return handlesArray.map( + (handle): HandleElement => { + const bounds = handle.getBoundingClientRect(); + const dimensions = getDimensions(handle); + const nodeIdAttr = handle.getAttribute('data-nodeid'); + const handlePosition = (handle.getAttribute('data-handlepos') as unknown) as Position; + const nodeIdSplitted = nodeIdAttr ? nodeIdAttr.split('__') : null; + + let handleId = null; + + if (nodeIdSplitted) { + handleId = (nodeIdSplitted.length ? nodeIdSplitted[1] : nodeIdSplitted) as string; + } + + return { + id: handleId, + position: handlePosition, + x: (bounds.left - parentBounds.left) * (1 / k), + y: (bounds.top - parentBounds.top) * (1 / k), + ...dimensions, + }; + } + ); +}; diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index 1589bf0d..ee491c9a 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -3,58 +3,9 @@ import { DraggableCore } from 'react-draggable'; import cx from 'classnames'; import { ResizeObserver } from 'resize-observer'; -import { getDimensions } from '../../utils'; import { Provider } from '../../contexts/NodeIdContext'; import store from '../../store'; -import { - Node, - XYPosition, - HandleElement, - Position, - Transform, - ElementId, - NodeComponentProps, - WrapNodeProps, -} from '../../types'; - -const getHandleBounds = ( - selector: string, - nodeElement: HTMLDivElement, - parentBounds: ClientRect | DOMRect, - k: number -): HandleElement[] | null => { - const handles = nodeElement.querySelectorAll(selector); - - if (!handles || !handles.length) { - return null; - } - - const handlesArray = Array.from(handles) as HTMLDivElement[]; - - return handlesArray.map( - (handle): HandleElement => { - const bounds = handle.getBoundingClientRect(); - const dimensions = getDimensions(handle); - const nodeIdAttr = handle.getAttribute('data-nodeid'); - const handlePosition = (handle.getAttribute('data-handlepos') as unknown) as Position; - const nodeIdSplitted = nodeIdAttr ? nodeIdAttr.split('__') : null; - - let handleId = null; - - if (nodeIdSplitted) { - handleId = (nodeIdSplitted.length ? nodeIdSplitted[1] : nodeIdSplitted) as string; - } - - return { - id: handleId, - position: handlePosition, - x: (bounds.left - parentBounds.left) * (1 / k), - y: (bounds.top - parentBounds.top) * (1 / k), - ...dimensions, - }; - } - ); -}; +import { Node, XYPosition, Transform, ElementId, NodeComponentProps, WrapNodeProps } from '../../types'; const onStart = ( evt: MouseEvent, @@ -141,7 +92,6 @@ export default (NodeComponent: ComponentType) => { const nodeElement = useRef(null); const [offset, setOffset] = useState({ x: 0, y: 0 }); const [isDragging, setDragging] = useState(false); - const position = { x: xPos, y: yPos }; const nodeClasses = cx('react-flow__node', { selected }); const nodeStyle = { @@ -154,14 +104,7 @@ export default (NodeComponent: ComponentType) => { return; } - const storeState = store.getState(); - const bounds = nodeElement.current.getBoundingClientRect(); - const dimensions = getDimensions(nodeElement.current); - const handleBounds = { - source: getHandleBounds('.source', nodeElement.current, bounds, storeState.transform[2]), - target: getHandleBounds('.target', nodeElement.current, bounds, storeState.transform[2]), - }; - store.dispatch.updateNodeData({ id, ...dimensions, handleBounds }); + store.dispatch.updateNodeDimensions({ id, nodeElement: nodeElement.current }); }; useEffect(() => { @@ -184,7 +127,7 @@ export default (NodeComponent: ComponentType) => { } return; - }, [nodeElement.current]); + }, []); return ( { + return nodes.reduce((res, node) => { const startPosition = { x: node.__rg.position.x || node.position.x, - y: node.__rg.position.y || node.position.x, + y: node.__rg.position.y || node.position.y, }; res[node.id] = startPosition; @@ -30,21 +35,26 @@ export default memo(() => { selectedNodesBbox: s.selectedNodesBbox, selectedElements: s.selectedElements, snapToGrid: s.snapToGrid, - snapGrid: s.snapGrid + snapGrid: s.snapGrid, + nodes: s.nodes, })); const updateNodePos = useStoreActions(a => a.updateNodePos); - const [x, y, k] = state.transform; + const [tx, ty, tScale] = state.transform; const position = state.selectedNodesBbox; const grid = (state.snapToGrid ? state.snapGrid : [1, 1])! as [number, number]; const onStart = (evt: MouseEvent) => { const scaledClient: XYPosition = { - x: evt.clientX * (1 / k), - y: evt.clientY * (1 / k), + x: evt.clientX / tScale, + y: evt.clientY / tScale, }; - const offsetX: number = scaledClient.x - position.x - x; - const offsetY: number = scaledClient.y - position.y - y; - const nextStartPositions = getStartPositions(state.selectedElements); + 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 nextStartPositions = getStartPositions(selectedNodes); if (nextStartPositions) { setOffset({ x: offsetX, y: offsetY }); @@ -54,24 +64,14 @@ export default memo(() => { const onDrag = (evt: MouseEvent) => { const scaledClient: XYPosition = { - x: evt.clientX * (1 / k), - y: evt.clientY * (1 / k), + x: evt.clientX / tScale, + 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 - - x, - y: - startPositions[node.id].y + - scaledClient.y - - position.y - - offset.y - - y, + 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 }); @@ -82,11 +82,11 @@ export default memo(() => {
onStart(evt as MouseEvent)} onDrag={evt => onDrag(evt as MouseEvent)} diff --git a/src/components/UserSelection/index.tsx b/src/components/UserSelection/index.tsx index ab68c9ad..6984377b 100644 --- a/src/components/UserSelection/index.tsx +++ b/src/components/UserSelection/index.tsx @@ -1,3 +1,7 @@ +/** + * The user selection rectangle gets displayed when a user drags the mouse while pressing shift + */ + import React, { useEffect, useRef, useState, memo } from 'react'; import { useStoreActions } from '../../store/hooks'; diff --git a/src/store/index.ts b/src/store/index.ts index 603b4e5d..2beaf69d 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -2,6 +2,9 @@ import { createStore, Action, action } from 'easy-peasy'; import isEqual from 'fast-deep-equal'; import { Selection as D3Selection, ZoomBehavior } from 'd3'; +import { getDimensions } from '../utils'; +import { getHandleBounds } from '../components/Nodes/utils'; + import { getNodesInside, getConnectedEdges, getRectOfNodes } from '../utils/graph'; import { ElementId, @@ -14,7 +17,6 @@ import { XYPosition, OnConnectFunc, SelectionRect, - HandleElement, } from '../types'; type TransformXYK = { @@ -28,14 +30,9 @@ type NodePosUpdate = { pos: XYPosition; }; -type NodeUpdate = { +type NodeDimensionUpdate = { id: ElementId; - width: number; - height: number; - handleBounds: { - source: HandleElement[] | null; - target: HandleElement[] | null; - }; + nodeElement: HTMLDivElement; }; type SelectionUpdate = { @@ -86,7 +83,7 @@ export interface StoreModel { setEdges: Action; - updateNodeData: Action; + updateNodeDimensions: Action; updateNodePos: Action; @@ -134,7 +131,7 @@ const storeModel: StoreModel = { connectionPosition: { x: 0, y: 0 }, snapGrid: [16, 16], - snapToGrid: true, + snapToGrid: false, isInteractive: true, @@ -152,12 +149,30 @@ const storeModel: StoreModel = { state.edges = edges; }), - updateNodeData: action((state, { id, ...data }) => { + updateNodeDimensions: action((state, { id, nodeElement }) => { + const bounds = nodeElement.getBoundingClientRect(); + const dimensions = getDimensions(nodeElement); + const matchingNode = state.nodes.find(n => n.id === id); + + // only update when size change + if ( + !matchingNode || + (matchingNode.__rg.width === dimensions.width && matchingNode.__rg.height === dimensions.height) + ) { + return; + } + + const handleBounds = { + source: getHandleBounds('.source', nodeElement, bounds, state.transform[2]), + target: getHandleBounds('.target', nodeElement, bounds, state.transform[2]), + }; + state.nodes.forEach(n => { if (n.id === id) { n.__rg = { ...n.__rg, - ...data, + ...dimensions, + handleBounds, }; } }); @@ -211,7 +226,6 @@ const storeModel: StoreModel = { state.selection = selection; state.nodesSelectionActive = true; state.selectedNodesBbox = selectedNodesBbox; - state.nodesSelectionActive = true; }), setSelectedElements: action((state, elements) => {