From 7981230a57ae1d7864e6bc576cc430379642d25e Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 5 Nov 2020 17:56:10 +0100 Subject: [PATCH 01/61] fix(panOnScroll): use deltaX instead of wheelDeltaX event prop --- src/container/ZoomPane/index.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 1c9da121..1c790fb5 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -78,8 +78,8 @@ const ZoomPane = ({ d3Zoom.translateBy( d3Selection, - (event.wheelDeltaX / currentZoom) * panOnScrollSpeed, - (event.wheelDeltaY / currentZoom) * panOnScrollSpeed + (event.deltaX / currentZoom) * panOnScrollSpeed, + (event.deltaY / currentZoom) * panOnScrollSpeed ); }) .on('wheel.zoom', null); From c9267a1a2850ccec6eec1e716708f4eea5a3b512 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 5 Nov 2020 17:59:00 +0100 Subject: [PATCH 02/61] 7.1.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9b70a680..de6ce961 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.0", + "version": "7.1.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 82f6a2e6..de03e2ec 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.0", + "version": "7.1.1", "main": "dist/ReactFlow.js", "module": "dist/ReactFlow.esm.js", "types": "dist/index.d.ts", From b13308877151caa0bc8e1d2fc320c18de930ea4f Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 05:05:53 +0000 Subject: [PATCH 03/61] chore(deps-dev): bump @babel/preset-react from 7.12.1 to 7.12.5 Bumps [@babel/preset-react](https://github.com/babel/babel/tree/HEAD/packages/babel-preset-react) from 7.12.1 to 7.12.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.12.5/packages/babel-preset-react) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 39 ++++++++++++++++++++++++++++----------- package.json | 2 +- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index de6ce961..ba187fac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -887,9 +887,9 @@ } }, "@babel/plugin-transform-react-jsx": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.1.tgz", - "integrity": "sha512-RmKejwnT0T0QzQUzcbP5p1VWlpnP8QHtdhEtLG55ZDQnJNalbF3eeDyu3dnGKvGzFIQiBzFhBYTwvv435p9Xpw==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.12.5.tgz", + "integrity": "sha512-2xkcPqqrYiOQgSlM/iwto1paPijjsDbUynN13tI6bosDz/jOW3CRzYguIE8wKX32h+msbBM22Dv5fwrFkUOZjQ==", "dev": true, "requires": { "@babel/helper-builder-react-jsx": "^7.10.4", @@ -899,9 +899,9 @@ } }, "@babel/plugin-transform-react-jsx-development": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.1.tgz", - "integrity": "sha512-IilcGWdN1yNgEGOrB96jbTplRh+V2Pz1EoEwsKsHfX1a/L40cUYuD71Zepa7C+ujv7kJIxnDftWeZbKNEqZjCQ==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.12.5.tgz", + "integrity": "sha512-1JJusg3iPgsZDthyWiCr3KQiGs31ikU/mSf2N2dSYEAO0GEImmVUbWf0VoSDGDFTAn5Dj4DUiR6SdIXHY7tELA==", "dev": true, "requires": { "@babel/helper-builder-react-jsx-experimental": "^7.12.1", @@ -1132,15 +1132,15 @@ } }, "@babel/preset-react": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.1.tgz", - "integrity": "sha512-euCExymHCi0qB9u5fKw7rvlw7AZSjw/NaB9h7EkdTt5+yHRrXdiRTh7fkG3uBPpJg82CqLfp1LHLqWGSCrab+g==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.5.tgz", + "integrity": "sha512-jcs++VPrgyFehkMezHtezS2BpnUlR7tQFAyesJn1vGTO9aTFZrgIQrA5YydlTwxbcjMwkFY6i04flCigRRr3GA==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.10.4", "@babel/plugin-transform-react-display-name": "^7.12.1", - "@babel/plugin-transform-react-jsx": "^7.12.1", - "@babel/plugin-transform-react-jsx-development": "^7.12.1", + "@babel/plugin-transform-react-jsx": "^7.12.5", + "@babel/plugin-transform-react-jsx-development": "^7.12.5", "@babel/plugin-transform-react-jsx-self": "^7.12.1", "@babel/plugin-transform-react-jsx-source": "^7.12.1", "@babel/plugin-transform-react-pure-annotations": "^7.12.1" @@ -2324,6 +2324,23 @@ "@babel/runtime": "7.12.1", "babel-plugin-macros": "2.8.0", "babel-plugin-transform-react-remove-prop-types": "0.4.24" + }, + "dependencies": { + "@babel/preset-react": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.12.1.tgz", + "integrity": "sha512-euCExymHCi0qB9u5fKw7rvlw7AZSjw/NaB9h7EkdTt5+yHRrXdiRTh7fkG3uBPpJg82CqLfp1LHLqWGSCrab+g==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.10.4", + "@babel/plugin-transform-react-display-name": "^7.12.1", + "@babel/plugin-transform-react-jsx": "^7.12.1", + "@babel/plugin-transform-react-jsx-development": "^7.12.1", + "@babel/plugin-transform-react-jsx-self": "^7.12.1", + "@babel/plugin-transform-react-jsx-source": "^7.12.1", + "@babel/plugin-transform-react-pure-annotations": "^7.12.1" + } + } } }, "balanced-match": { diff --git a/package.json b/package.json index de03e2ec..5d93b144 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@babel/core": "^7.12.3", "@babel/plugin-transform-runtime": "^7.12.1", "@babel/preset-env": "^7.12.1", - "@babel/preset-react": "^7.12.1", + "@babel/preset-react": "^7.12.5", "@rollup/plugin-babel": "^5.2.1", "@rollup/plugin-commonjs": "^16.0.0", "@rollup/plugin-node-resolve": "^10.0.0", From 39edf2055b2e3bb9d54be2514e80b427353112c6 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 05:06:59 +0000 Subject: [PATCH 04/61] chore(deps-dev): bump rollup from 2.33.0 to 2.33.1 Bumps [rollup](https://github.com/rollup/rollup) from 2.33.0 to 2.33.1. - [Release notes](https://github.com/rollup/rollup/releases) - [Changelog](https://github.com/rollup/rollup/blob/master/CHANGELOG.md) - [Commits](https://github.com/rollup/rollup/compare/v2.33.0...v2.33.1) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index de6ce961..5cce51d2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7394,9 +7394,9 @@ } }, "rollup": { - "version": "2.33.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.0.tgz", - "integrity": "sha512-7jFrmKgQj1GOWlC8rExHaPcv2SQnWMv1BFUyH/xWS5w80h6132wBUWp/qTvQkAbnlqGvi13T6iP2kHo9Sb2HxA==", + "version": "2.33.1", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.33.1.tgz", + "integrity": "sha512-uY4O/IoL9oNW8MMcbA5hcOaz6tZTMIh7qJHx/tzIJm+n1wLoY38BLn6fuy7DhR57oNFLMbDQtDeJoFURt5933w==", "dev": true, "requires": { "fsevents": "~2.1.2" diff --git a/package.json b/package.json index de03e2ec..0dc1225d 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,7 @@ "prop-types": "^15.7.2", "react": "^16.14.0", "release-it": "^14.2.1", - "rollup": "^2.33.0", + "rollup": "^2.33.1", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-postcss": "^3.1.8", "rollup-plugin-typescript2": "^0.29.0", From 62cf898217cf9c46c0674b95a75b390e4790bc71 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 05:07:42 +0000 Subject: [PATCH 05/61] chore(deps-dev): bump @types/d3 from 5.16.3 to 6.0.0 Bumps [@types/d3](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/d3) from 5.16.3 to 6.0.0. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/d3) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 287 +++++++++++++++++++++++----------------------- package.json | 2 +- 2 files changed, 145 insertions(+), 144 deletions(-) diff --git a/package-lock.json b/package-lock.json index de6ce961..b2fe2060 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1711,263 +1711,264 @@ "dev": true }, "@types/d3": { - "version": "5.16.3", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-5.16.3.tgz", - "integrity": "sha512-s3wrhYhu25XZQ5p1hI9gEMSX5bx7lg9hAmi0+i5r3v75Gz1zRTgB2Q0psx+SO+4K0AO/PPJ1pnHCz64pANN/4w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@types/d3/-/d3-6.0.0.tgz", + "integrity": "sha512-nggAKM2OHRm2M+ZOfnU0i6AWJ6P77DsyNJhBGvDo1h/WPrlVsltAw6oqLrb2R6V/yFNGaNKWL2hCfYs2Nh5+ig==", "dev": true, "requires": { - "@types/d3-array": "^1", - "@types/d3-axis": "^1", - "@types/d3-brush": "^1", - "@types/d3-chord": "^1", - "@types/d3-collection": "*", - "@types/d3-color": "^1", - "@types/d3-contour": "^1", - "@types/d3-dispatch": "^1", - "@types/d3-drag": "^1", - "@types/d3-dsv": "^1", - "@types/d3-ease": "^1", - "@types/d3-fetch": "^1", - "@types/d3-force": "^1", - "@types/d3-format": "^1", - "@types/d3-geo": "^1", - "@types/d3-hierarchy": "^1", - "@types/d3-interpolate": "^1", - "@types/d3-path": "^1", - "@types/d3-polygon": "^1", - "@types/d3-quadtree": "^1", - "@types/d3-random": "^1", - "@types/d3-scale": "^2", - "@types/d3-scale-chromatic": "^1", - "@types/d3-selection": "^1", - "@types/d3-shape": "^1", - "@types/d3-time": "^1", - "@types/d3-time-format": "^2", - "@types/d3-timer": "^1", - "@types/d3-transition": "^1", - "@types/d3-voronoi": "*", - "@types/d3-zoom": "^1" + "@types/d3-array": "*", + "@types/d3-axis": "*", + "@types/d3-brush": "*", + "@types/d3-chord": "*", + "@types/d3-color": "*", + "@types/d3-contour": "*", + "@types/d3-delaunay": "*", + "@types/d3-dispatch": "*", + "@types/d3-drag": "*", + "@types/d3-dsv": "*", + "@types/d3-ease": "*", + "@types/d3-fetch": "*", + "@types/d3-force": "*", + "@types/d3-format": "*", + "@types/d3-geo": "*", + "@types/d3-hierarchy": "*", + "@types/d3-interpolate": "*", + "@types/d3-path": "*", + "@types/d3-polygon": "*", + "@types/d3-quadtree": "*", + "@types/d3-random": "*", + "@types/d3-scale": "*", + "@types/d3-scale-chromatic": "*", + "@types/d3-selection": "*", + "@types/d3-shape": "*", + "@types/d3-time": "*", + "@types/d3-time-format": "*", + "@types/d3-timer": "*", + "@types/d3-transition": "*", + "@types/d3-zoom": "*" } }, "@types/d3-array": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-1.2.8.tgz", - "integrity": "sha512-wWV0wT6oLUGprrOR5LMK7Dh8EBiondhnqINsvazv6UucYfTdb2oaFF4knlqzZV2RKB9ZC9G7G1Iojt8b/wolsw==", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-2.5.1.tgz", + "integrity": "sha512-SA4BkFg930fGpKNXudWsVi3dwsGc/ujMktUGXCNF+13wuEpt8IoNbGj06JluEvrWeznQxI3dExrRzZbRqMNONQ==", "dev": true }, "@types/d3-axis": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-1.0.14.tgz", - "integrity": "sha512-wZAKX/dtFT5t5iuCaiU0QL0BWB19TE6h7C7kgfBVyoka7zidQWvf8E9zQTJ5bNPBQxd0+JmplNqwy1M8O8FOjA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-2.0.0.tgz", + "integrity": "sha512-gUdlEwGBLl3tXGiBnBNmNzph9W3bCfa4tBgWZD60Z1eDQKTY4zyCAcZ3LksignGfKawYatmDYcBdjJ5h/54sqA==", "dev": true, "requires": { - "@types/d3-selection": "^1" + "@types/d3-selection": "*" } }, "@types/d3-brush": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-1.1.4.tgz", - "integrity": "sha512-2t8CgWaha9PsPdSZJ9m6Jl4awqf3DGIXek2e7gfheyfP2R0a/18MX+wuLHx+LyI1Ad7lxDsPWcswKD0XhQEjmg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-2.1.0.tgz", + "integrity": "sha512-rLQqxQeXWF4ArXi81GlV8HBNwJw9EDpz0jcWvvzv548EDE4tXrayBTOHYi/8Q4FZ/Df8PGXFzxpAVQmJMjOtvQ==", "dev": true, "requires": { - "@types/d3-selection": "^1" + "@types/d3-selection": "*" } }, "@types/d3-chord": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-1.0.10.tgz", - "integrity": "sha512-U6YojfET6ITL1/bUJo+/Lh3pMV9XPAfOWwbshl3y3RlgAX9VO/Bxa13IMAylZIDY4VsA3Gkh29kZP1AcAeyoYA==", - "dev": true - }, - "@types/d3-collection": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-collection/-/d3-collection-1.0.9.tgz", - "integrity": "sha512-Oeaor3M3YjN+GH9dYXY3iKeTVTlNVNveLpvb3coDTIcIklVluP9aze++ByNfkZHDeu7eaQTWBloBeoPQNtrG7w==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-2.0.0.tgz", + "integrity": "sha512-3nHsLY7lImpZlM/hrPeDqqW2a+lRXXoHsG54QSurDGihZAIE/doQlohs0evoHrWOJqXyn4A4xbSVEtXnMEZZiw==", "dev": true }, "@types/d3-color": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-1.4.1.tgz", - "integrity": "sha512-xkPLi+gbgUU9ED6QX4g6jqYL2KCB0/3AlM+ncMGqn49OgH0gFMY/ITGqPF8HwEiLzJaC+2L0I+gNwBgABv1Pvg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-2.0.0.tgz", + "integrity": "sha512-Bs0maTeU47rdZT+n42iQ0C4gnbnJlIDJkqHFtIsDx2tPPITDeoSdIrm+00UYXzegzArYC2GsG80eHNMwz08IAw==", "dev": true }, "@types/d3-contour": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-1.3.1.tgz", - "integrity": "sha512-wWwsM/3NfKTRBdH00cSf+XlsaHlNTkvH66PgDedobyvKQZ4sJrXXpr16LXvDnAal4B67v8JGrWDgyx6dqqKLuQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-2.0.0.tgz", + "integrity": "sha512-PS9UO6zBQqwHXsocbpdzZFONgK1oRUgWtjjh/iz2vM06KaXLInLiKZ9e3OLBRerc1cU2uJYpO+8zOnb6frvCGQ==", "dev": true, "requires": { - "@types/d3-array": "^1", + "@types/d3-array": "*", "@types/geojson": "*" } }, + "@types/d3-delaunay": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-5.3.0.tgz", + "integrity": "sha512-gJYcGxLu0xDZPccbUe32OUpeaNtd1Lz0NYJtko6ZLMyG2euF4pBzrsQXms67LHZCDFzzszw+dMhSL/QAML3bXw==", + "dev": true + }, "@types/d3-dispatch": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-1.0.9.tgz", - "integrity": "sha512-zJ44YgjqALmyps+II7b1mZLhrtfV/FOxw9owT87mrweGWcg+WK5oiJX2M3SYJ0XUAExBduarysfgbR11YxzojQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-2.0.0.tgz", + "integrity": "sha512-Sh0KW6z/d7uxssD7K4s4uCSzlEG/+SP+U47q098NVdOfFvUKNTvKAIV4XqjxsUuhE/854ARAREHOxkr9gQOCyg==", "dev": true }, "@types/d3-drag": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-1.2.5.tgz", - "integrity": "sha512-7NeTnfolst1Js3Vs7myctBkmJWu6DMI3k597AaHUX98saHjHWJ6vouT83UrpE+xfbSceHV+8A0JgxuwgqgmqWw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-2.0.0.tgz", + "integrity": "sha512-VaUJPjbMnDn02tcRqsHLRAX5VjcRIzCjBfeXTLGe6QjMn5JccB5Cz4ztMRXMJfkbC45ovgJFWuj6DHvWMX1thA==", "dev": true, "requires": { - "@types/d3-selection": "^1" + "@types/d3-selection": "*" } }, "@types/d3-dsv": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-1.2.1.tgz", - "integrity": "sha512-LLmJmjiqp/fTNEdij5bIwUJ6P6TVNk5hKM9/uk5RPO2YNgEu9XvKO0dJ7Iqd3psEdmZN1m7gB1bOsjr4HmO2BA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-2.0.0.tgz", + "integrity": "sha512-wYqy7T8tQ/DmocwxmlPujllLI5fg3lb6/FrVVWkLUD+NsRV+kcE4nbRZg10G9yjJ8pK2ZXqu+VP5jQbN13uNRQ==", "dev": true }, "@types/d3-ease": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-1.0.10.tgz", - "integrity": "sha512-fMFTCzd8DOwruE9zlu2O8ci5ct+U5jkGcDS+cH+HCidnJlDs0MZ+TuSVCFtEzh4E5MasItwy+HvgoFtxPHa5Cw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-2.0.0.tgz", + "integrity": "sha512-6aZrTyX5LG+ptofVHf+gTsThLRY1nhLotJjgY4drYqk1OkJMu2UvuoZRlPw2fffjRHeYepue3/fxTufqKKmvsA==", "dev": true }, "@types/d3-fetch": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-1.2.2.tgz", - "integrity": "sha512-rtFs92GugtV/NpiJQd0WsmGLcg52tIL0uF0bKbbJg231pR9JEb6HT4AUwrtuLq3lOeKdLBhsjV14qb0pMmd0Aw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-2.0.0.tgz", + "integrity": "sha512-WnLepGtxepFfXRdPI8I5FTgNiHn9p4vMTTqaNCzJJfAswXx0rOY2jjeolzEU063em3iJmGZ+U79InnEeFOrCRw==", "dev": true, "requires": { - "@types/d3-dsv": "^1" + "@types/d3-dsv": "*" } }, "@types/d3-force": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-1.2.2.tgz", - "integrity": "sha512-TN7KO7sk0tJauedIt0q20RQRFo4V3v97pJKO/TDK40X3LaPM1aXRM2+zFF+nRMtseEiszg4KffudhjR8a3+4cg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-2.1.0.tgz", + "integrity": "sha512-LGDtC2YADu8OBniq9EBx/MOsXsMcJbEkmfSpXuz6oVdRamB+3CLCiq5EKFPEILGZQckkilGFq1ZTJ7kc289k+Q==", "dev": true }, "@types/d3-format": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.4.1.tgz", - "integrity": "sha512-ss9G2snEKmp2In5Z3T0Jpqv8QaDBc2xHltBw83KjnV5B5w+Iwphbvq5ph/Xnu4d03fmmsdt+o1aWch379rxIbA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-2.0.0.tgz", + "integrity": "sha512-uagdkftxnGkO4pZw5jEYOM5ZnZOEsh7z8j11Qxk85UkB2RzfUUxRl7R9VvvJZHwKn8l+x+rpS77Nusq7FkFmIg==", "dev": true }, "@types/d3-geo": { - "version": "1.12.1", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-1.12.1.tgz", - "integrity": "sha512-8+gyGFyMCXIHtnMNKQDT++tZ4XYFXgiP5NK7mcv34aYXA16GQFiBBITjKzxghpO8QNVceOd9rUn1JY92WLNGQw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-2.0.0.tgz", + "integrity": "sha512-DHHgYXW36lnAEQMYU2udKVOxxljHrn2EdOINeSC9jWCAXwOnGn7A19B8sNsHqgpu4F7O2bSD7//cqBXD3W0Deg==", "dev": true, "requires": { "@types/geojson": "*" } }, "@types/d3-hierarchy": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-1.1.7.tgz", - "integrity": "sha512-fvht6DOYKzqmXjMb/+xfgkmrWM4SD7rMA/ZbM+gGwr9ZTuIDfky95J8CARtaJo/ExeWyS0xGVdL2gqno2zrQ0Q==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-2.0.0.tgz", + "integrity": "sha512-YxdskUvwzqggpnSnDQj4KVkicgjpkgXn/g/9M9iGsiToLS3nG6Ytjo1FoYhYVAAElV/fJBGVL3cQ9Hb7tcv+lw==", "dev": true }, "@types/d3-interpolate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-1.4.2.tgz", - "integrity": "sha512-ylycts6llFf8yAEs1tXzx2loxxzDZHseuhPokrqKprTQSTcD3JbJI1omZP1rphsELZO3Q+of3ff0ZS7+O6yVzg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-2.0.0.tgz", + "integrity": "sha512-Wt1v2zTlEN8dSx8hhx6MoOhWQgTkz0Ukj7owAEIOF2QtI0e219paFX9rf/SLOr/UExWb1TcUzatU8zWwFby6gg==", "dev": true, "requires": { - "@types/d3-color": "^1" + "@types/d3-color": "*" } }, "@types/d3-path": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz", - "integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-2.0.0.tgz", + "integrity": "sha512-tXcR/9OtDdeCIsyl6eTNHC3XOAOdyc6ceF3QGBXOd9jTcK+ex/ecr00p9L9362e/op3UEPpxrToi1FHrtTSj7Q==", "dev": true }, "@types/d3-polygon": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-1.0.8.tgz", - "integrity": "sha512-1TOJPXCBJC9V3+K3tGbTqD/CsqLyv/YkTXAcwdsZzxqw5cvpdnCuDl42M4Dvi8XzMxZNCT9pL4ibrK2n4VmAcw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-2.0.0.tgz", + "integrity": "sha512-fISnMd8ePED1G4aa4V974Jmt+ajHSgPoxMa2D0ULxMybpx0Vw4WEzhQEaMIrL3hM8HVRcKTx669I+dTy/4PhAw==", "dev": true }, "@types/d3-quadtree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-1.0.8.tgz", - "integrity": "sha512-FuqYiexeSQZlc+IcGAVK8jSJKDFKHcSf/jx8rqJUUVx6rzv7ecQiXKyatrLHHh3W4CAvgNeVI23JKgk4+x2wFg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-2.0.0.tgz", + "integrity": "sha512-YZuJuGBnijD0H+98xMJD4oZXgv/umPXy5deu3IimYTPGH3Kr8Th6iQUff0/6S80oNBD7KtOuIHwHUCymUiRoeQ==", "dev": true }, "@types/d3-random": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-1.1.3.tgz", - "integrity": "sha512-XXR+ZbFCoOd4peXSMYJzwk0/elP37WWAzS/DG+90eilzVbUSsgKhBcWqylGWe+lA2ubgr7afWAOBaBxRgMUrBQ==", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-2.2.0.tgz", + "integrity": "sha512-Hjfj9m68NmYZzushzEG7etPvKH/nj9b9s9+qtkNG3/dbRBjQZQg1XS6nRuHJcCASTjxXlyXZnKu2gDxyQIIu9A==", "dev": true }, "@types/d3-scale": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-2.2.4.tgz", - "integrity": "sha512-wkQXT+IfgfAnKB5rtS1qMJg3FS32r1rVFHvqtiqk8pX8o5aQR3VwX1P7ErHjzNIicTlkWsaMiUTrYB+E75HFeA==", + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-3.2.1.tgz", + "integrity": "sha512-j+FryQSVk3GHLqjOX/RsHwGHg4XByJ0xIO1ASBTgzhE9o1tgeV4kEWLOzMzJRembKalflk5F03lEkM+4V6LDrQ==", "dev": true, "requires": { - "@types/d3-time": "^1" + "@types/d3-time": "*" } }, "@types/d3-scale-chromatic": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-1.5.1.tgz", - "integrity": "sha512-7FtJYrmXTEWLykShjYhoGuDNR/Bda0+tstZMkFj4RRxUEryv16AGh3be21tqg84B6KfEwiZyEpBcTyPyU+GWjg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-2.0.0.tgz", + "integrity": "sha512-Y62+2clOwZoKua84Ha0xU77w7lePiaBoTjXugT4l8Rd5LAk+Mn/ZDtrgs087a+B5uJ3jYUHHtKw5nuEzp0WBHw==", "dev": true }, "@types/d3-selection": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-1.4.3.tgz", - "integrity": "sha512-GjKQWVZO6Sa96HiKO6R93VBE8DUW+DDkFpIMf9vpY5S78qZTlRRSNUsHr/afDpF7TvLDV7VxrUFOWW7vdIlYkA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-2.0.0.tgz", + "integrity": "sha512-EF0lWZ4tg7oDFg4YQFlbOU3936e3a9UmoQ2IXlBy1+cv2c2Pv7knhKUzGlH5Hq2sF/KeDTH1amiRPey2rrLMQA==", "dev": true }, "@types/d3-shape": { - "version": "1.3.4", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-1.3.4.tgz", - "integrity": "sha512-fxmOjs+UqNQGpztD5BOo+KriE0jLFrBP4Ct++0QExv/xfDOT1cpcMxgsZ+5qPmnR0t+GjbwAe1Um1PHpv3G4oA==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-2.0.0.tgz", + "integrity": "sha512-NLzD02m5PiD1KLEDjLN+MtqEcFYn4ZL9+Rqc9ZwARK1cpKZXd91zBETbe6wpBB6Ia0D0VZbpmbW3+BsGPGnCpA==", "dev": true, "requires": { "@types/d3-path": "^1" + }, + "dependencies": { + "@types/d3-path": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-1.0.9.tgz", + "integrity": "sha512-NaIeSIBiFgSC6IGUBjZWcscUJEq7vpVu7KthHN8eieTV9d9MqkSOZLH4chq1PmcKy06PNe3axLeKmRIyxJ+PZQ==", + "dev": true + } } }, "@types/d3-time": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-1.1.1.tgz", - "integrity": "sha512-ULX7LoqXTCYtM+tLYOaeAJK7IwCT+4Gxlm2MaH0ErKLi07R5lh8NHCAyWcDkCCmx1AfRcBEV6H9QE9R25uP7jw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-2.0.0.tgz", + "integrity": "sha512-Abz8bTzy8UWDeYs9pCa3D37i29EWDjNTjemdk0ei1ApYVNqulYlGUKip/jLOpogkPSsPz/GvZCYiC7MFlEk0iQ==", "dev": true }, "@types/d3-time-format": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.3.1.tgz", - "integrity": "sha512-fck0Z9RGfIQn3GJIEKVrp15h9m6Vlg0d5XXeiE/6+CQiBmMDZxfR21XtjEPuDeg7gC3bBM0SdieA5XF3GW1wKA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-3.0.0.tgz", + "integrity": "sha512-UpLg1mn/8PLyjr+J/JwdQJM/GzysMvv2CS8y+WYAL5K0+wbvXv/pPSLEfdNaprCZsGcXTxPsFMy8QtkYv9ueew==", "dev": true }, "@types/d3-timer": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-1.0.10.tgz", - "integrity": "sha512-ZnAbquVqy+4ZjdW0cY6URp+qF/AzTVNda2jYyOzpR2cPT35FTXl78s15Bomph9+ckOiI1TtkljnWkwbIGAb6rg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-2.0.0.tgz", + "integrity": "sha512-l6stHr1VD1BWlW6u3pxrjLtJfpPZq9I3XmKIQtq7zHM/s6fwEtI1Yn6Sr5/jQTrUDCC5jkS6gWqlFGCDArDqNg==", "dev": true }, "@types/d3-transition": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-1.3.1.tgz", - "integrity": "sha512-U9CpMlTL/NlqdGXBlHYxTZwbmy/vN1cFv8TuAIFPX+xOW/1iChbeJBY2xmINhDQfkGJbgkH4IovafCwI1ZDrgg==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-2.0.0.tgz", + "integrity": "sha512-UJDzI98utcZQUJt3uIit/Ho0/eBIANzrWJrTmi4+TaKIyWL2iCu7ShP0o4QajCskhyjOA7C8+4CE3b1YirTzEQ==", "dev": true, "requires": { - "@types/d3-selection": "^1" + "@types/d3-selection": "*" } }, - "@types/d3-voronoi": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@types/d3-voronoi/-/d3-voronoi-1.1.9.tgz", - "integrity": "sha512-DExNQkaHd1F3dFPvGA/Aw2NGyjMln6E9QzsiqOcBgnE+VInYnFBHBBySbZQts6z6xD+5jTfKCP7M4OqMyVjdwQ==", - "dev": true - }, "@types/d3-zoom": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-1.8.2.tgz", - "integrity": "sha512-rU0LirorUxkLxEHSzkFs7pPC0KWsxRGc0sHrxEDR0/iQq+7/xpNkKuuOOwthlgvOtpOvtTLJ2JFOD6Kr0Si4Uw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@types/d3-zoom/-/d3-zoom-2.0.0.tgz", + "integrity": "sha512-daL0PJm4yT0ISTGa7p2lHX0kvv9FO/IR1ooWbHR/7H4jpbaKiLux5FslyS/OvISPiJ5SXb4sOqYhO6fMB6hKRw==", "dev": true, "requires": { - "@types/d3-interpolate": "^1", - "@types/d3-selection": "^1" + "@types/d3-interpolate": "*", + "@types/d3-selection": "*" } }, "@types/estree": { diff --git a/package.json b/package.json index de03e2ec..e96a8ab3 100644 --- a/package.json +++ b/package.json @@ -47,7 +47,7 @@ "@rollup/plugin-replace": "^2.3.4", "@svgr/rollup": "^5.4.0", "@types/classnames": "^2.2.11", - "@types/d3": "^5.16.3", + "@types/d3": "^6.0.0", "@types/react": "^16.9.55", "@types/react-dom": "^16.9.9", "autoprefixer": "^9.8.6", From cf34c8f48e80928eba9b23d99c7251437da85e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Mon, 9 Nov 2020 12:39:21 +0100 Subject: [PATCH 06/61] fix(panOnScroll): normalize scroll speed in different browsers closes #665 --- src/container/ZoomPane/index.tsx | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 1c790fb5..9fe19301 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -75,11 +75,16 @@ const ZoomPane = ({ event.stopImmediatePropagation(); const currentZoom = d3Selection.property('__zoom').k || 1; + // increase scroll speed in firefox + // firefox: deltaMode === 1; chrome: deltaMode === 0 + const deltaNormalize = event.deltaMode === 1 ? 20 : 1; + const deltaX = event.deltaX * deltaNormalize; + const deltaY = event.deltaY * deltaNormalize; d3Zoom.translateBy( d3Selection, - (event.deltaX / currentZoom) * panOnScrollSpeed, - (event.deltaY / currentZoom) * panOnScrollSpeed + (deltaX / currentZoom) * panOnScrollSpeed, + (deltaY / currentZoom) * panOnScrollSpeed ); }) .on('wheel.zoom', null); From c746fdc741a327402750b9aec75e53ef2d109a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Mon, 9 Nov 2020 13:16:33 +0100 Subject: [PATCH 07/61] fix type definition for d3-zoom handler --- src/store/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/store/index.ts b/src/store/index.ts index 36417d4f..263e8b2f 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,6 +1,6 @@ import { createStore, Action, action, Thunk, thunk, computed, Computed } from 'easy-peasy'; import isEqual from 'fast-deep-equal'; -import { Selection as D3Selection, ZoomBehavior, ValueFn } from 'd3'; +import { Selection as D3Selection, ZoomBehavior } from 'd3'; import { zoom, zoomIdentity } from 'd3-zoom'; import { select } from 'd3-selection'; @@ -61,7 +61,7 @@ export interface StoreModel { d3Zoom: ZoomBehavior | null; d3Selection: D3Selection | null; - d3ZoomHandler: ValueFn | undefined; + d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined; d3Initialised: boolean; minZoom: number; maxZoom: number; @@ -165,7 +165,7 @@ export const storeModel: StoreModel = { d3Zoom: null, d3Selection: null, d3Initialised: false, - d3ZoomHandler: () => {}, + d3ZoomHandler: undefined, minZoom: 0.5, maxZoom: 2, translateExtent: [ From a23b05b0dc2e73d811251a9ea215db4ef8c7b5c8 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 12:23:16 +0000 Subject: [PATCH 08/61] chore(deps-dev): bump @types/react from 16.9.55 to 16.9.56 Bumps [@types/react](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/react) from 16.9.55 to 16.9.56. - [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases) - [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/react) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 6 +++--- package.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ed0e3ee..dcf15ecd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2023,9 +2023,9 @@ "dev": true }, "@types/react": { - "version": "16.9.55", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.55.tgz", - "integrity": "sha512-6KLe6lkILeRwyyy7yG9rULKJ0sXplUsl98MGoCfpteXf9sPWFWWMknDcsvubcpaTdBuxtsLF6HDUwdApZL/xIg==", + "version": "16.9.56", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.9.56.tgz", + "integrity": "sha512-gIkl4J44G/qxbuC6r2Xh+D3CGZpJ+NdWTItAPmZbR5mUS+JQ8Zvzpl0ea5qT/ZT3ZNTUcDKUVqV3xBE8wv/DyQ==", "dev": true, "requires": { "@types/prop-types": "*", diff --git a/package.json b/package.json index a04cfe58..0f8096a8 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "@svgr/rollup": "^5.4.0", "@types/classnames": "^2.2.11", "@types/d3": "^6.0.0", - "@types/react": "^16.9.55", + "@types/react": "^16.9.56", "@types/react-dom": "^16.9.9", "autoprefixer": "^9.8.6", "babel-preset-react-app": "^10.0.0", From 71b76b20e51a422271778b4fe90525d11ceb7f79 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2020 12:23:22 +0000 Subject: [PATCH 09/61] chore(deps): bump @babel/runtime from 7.12.1 to 7.12.5 Bumps [@babel/runtime](https://github.com/babel/babel/tree/HEAD/packages/babel-runtime) from 7.12.1 to 7.12.5. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.12.5/packages/babel-runtime) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 15 ++++++++++++--- package.json | 2 +- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1ed0e3ee..914cd020 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1157,9 +1157,9 @@ } }, "@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", + "version": "7.12.5", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.5.tgz", + "integrity": "sha512-plcc+hbExy3McchJCEQG3knOsuh3HH+Prx1P6cLIkET/0dLuQDEnrT+s27Axgc9bqfsmNUNHfscgMUdBpC9xfg==", "requires": { "regenerator-runtime": "^0.13.4" } @@ -2341,6 +2341,15 @@ "@babel/plugin-transform-react-jsx-source": "^7.12.1", "@babel/plugin-transform-react-pure-annotations": "^7.12.1" } + }, + "@babel/runtime": { + "version": "7.12.1", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", + "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", + "dev": true, + "requires": { + "regenerator-runtime": "^0.13.4" + } } } }, diff --git a/package.json b/package.json index a04cfe58..e57b3631 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,7 @@ "release:next": "release-it major --preRelease=next" }, "dependencies": { - "@babel/runtime": "^7.12.1", + "@babel/runtime": "^7.12.5", "@welldone-software/why-did-you-render": "^5.0.0", "classcat": "^4.1.0", "d3-selection": "^2.0.0", From 803a4aea57a3cda0f476a93c946953b670b8a263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Mon, 9 Nov 2020 13:44:40 +0100 Subject: [PATCH 10/61] chore: release v7.1.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 2716c496..85da28c1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.1", + "version": "7.1.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 17dc8272..9b013526 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.1", + "version": "7.1.2", "main": "dist/ReactFlow.js", "module": "dist/ReactFlow.esm.js", "types": "dist/index.d.ts", From cf38388f149dadf3e9981d9b233f7aa1464d2ccd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Mon, 9 Nov 2020 17:23:59 +0100 Subject: [PATCH 11/61] refactor(zoom): move zoom methods into own hook, detatch from store --- example/src/Interaction/index.js | 1 + src/additional-components/Controls/index.tsx | 35 +++--- src/container/GraphView/index.tsx | 11 +- src/container/ReactFlow/Wrapper.tsx | 7 +- src/container/ZoomPane/index.tsx | 32 +++++- src/hooks/useZoomPanHelper.ts | 67 ++++++++++++ src/store/index.ts | 109 ++----------------- src/utils/graph.ts | 29 +---- 8 files changed, 139 insertions(+), 152 deletions(-) create mode 100644 src/hooks/useZoomPanHelper.ts diff --git a/example/src/Interaction/index.js b/example/src/Interaction/index.js index 90819509..39e83887 100644 --- a/example/src/Interaction/index.js +++ b/example/src/Interaction/index.js @@ -50,6 +50,7 @@ const InteractionFlow = () => { onPaneClick={captureZoomClick ? onPaneClick : undefined} onPaneScroll={captureZoomScroll ? onPaneScroll : undefined} onPaneContextMenu={captureZoomClick ? onPaneContextMenu : undefined} + onMoveEnd={(evt) => console.log('on move end', evt)} > diff --git a/src/additional-components/Controls/index.tsx b/src/additional-components/Controls/index.tsx index ae5a53f3..983701e9 100644 --- a/src/additional-components/Controls/index.tsx +++ b/src/additional-components/Controls/index.tsx @@ -10,6 +10,7 @@ import LockIcon from '../../../assets/icons/lock.svg'; import UnlockIcon from '../../../assets/icons/unlock.svg'; import './style.css'; +import useZoomPanHelper from '../../hooks/useZoomPanHelper'; export interface ControlProps extends React.HTMLAttributes { showZoom?: boolean; @@ -33,9 +34,7 @@ const Controls = ({ className, }: ControlProps) => { const setInteractive = useStoreActions((actions) => actions.setInteractive); - const fitView = useStoreActions((actions) => actions.fitView); - const zoomIn = useStoreActions((actions) => actions.zoomIn); - const zoomOut = useStoreActions((actions) => actions.zoomOut); + const { zoomIn, zoomOut, fitView } = useZoomPanHelper(); const isInteractive = useStoreState((s) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable); const mapClasses = cc(['react-flow__controls', className]); @@ -44,20 +43,26 @@ const Controls = ({
{showZoom && ( <> -
{ - zoomIn(); - if (onZoomIn) { - onZoomIn(); - } - }}> +
{ + zoomIn(); + if (onZoomIn) { + onZoomIn(); + } + }} + >
-
{ - zoomOut(); - if (onZoomOut) { - onZoomOut(); - } - }}> +
{ + zoomOut(); + if (onZoomOut) { + onZoomOut(); + } + }} + >
diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index eb68438d..3f9ce248 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -22,6 +22,7 @@ import { OnConnectEndFunc, TranslateExtent, } from '../../types'; +import useZoomPanHelper from '../../hooks/useZoomPanHelper'; export interface GraphViewProps { elements: Elements; @@ -145,10 +146,8 @@ const GraphView = ({ const setMinZoom = useStoreActions((actions) => actions.setMinZoom); const setMaxZoom = useStoreActions((actions) => actions.setMaxZoom); const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent); - const fitView = useStoreActions((actions) => actions.fitView); - const zoom = useStoreActions((actions) => actions.zoom); - const zoomTo = useStoreActions((actions) => actions.zoomTo); const currentStore = useStore(); + const { zoomIn, zoomOut, zoomTo, fitView } = useZoomPanHelper(); useElementUpdater(elements); @@ -157,9 +156,9 @@ const GraphView = ({ if (onLoad) { onLoad({ fitView: (params = { padding: 0.1 }) => fitView(params), - zoomIn: () => zoom(0.2), - zoomOut: () => zoom(-0.2), - zoomTo: (zoomLevel) => zoomTo(zoomLevel), + zoomIn, + zoomOut, + zoomTo, project: onLoadProject(currentStore), getElements: onLoadGetElements(currentStore), setTransform: (transform: FlowTransform) => diff --git a/src/container/ReactFlow/Wrapper.tsx b/src/container/ReactFlow/Wrapper.tsx index c5cc6de0..2081e092 100644 --- a/src/container/ReactFlow/Wrapper.tsx +++ b/src/container/ReactFlow/Wrapper.tsx @@ -1,10 +1,11 @@ import React, { FC } from 'react'; -import { StoreProvider, useStore } from 'easy-peasy'; +import { StoreProvider } from 'easy-peasy'; -import store, { StoreModel } from '../../store'; +import store from '../../store'; +import { useStore } from '../../store/hooks'; const Wrapper: FC = ({ children }) => { - const easyPeasyStore = useStore(); + const easyPeasyStore = useStore(); const isWrapepdWithReactFlowProvider = easyPeasyStore?.getState()?.reactFlowVersion; if (isWrapepdWithReactFlowProvider) { diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 9fe19301..9ff0bc14 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -1,7 +1,11 @@ import React, { useEffect, useRef, ReactNode } from 'react'; +import { zoom, zoomIdentity } from 'd3-zoom'; +import { select } from 'd3-selection'; +import { clamp } from '../../utils'; + import useResizeHandler from '../../hooks/useResizeHandler'; -import { useStoreState, useStoreActions } from '../../store/hooks'; +import { useStoreState, useStoreActions, useStore } from '../../store/hooks'; import { FlowTransform, TranslateExtent } from '../../types'; interface ZoomPaneProps { @@ -55,14 +59,36 @@ const ZoomPane = ({ const d3Selection = useStoreState((s) => s.d3Selection); const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler); - const initD3 = useStoreActions((actions) => actions.initD3); + const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom); const updateTransform = useStoreActions((actions) => actions.updateTransform); + const store = useStore(); useResizeHandler(zoomPane); useEffect(() => { if (zoomPane.current) { - initD3({ zoomPane: zoomPane.current, defaultPosition, defaultZoom, translateExtent }); + // initD3: action((state, { zoomPane, defaultPosition, defaultZoom, translateExtent }) => { + const state = store.getState(); + const currentTranslateExtent = typeof translateExtent !== 'undefined' ? translateExtent : state.translateExtent; + const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(currentTranslateExtent); + const selection = select(zoomPane.current as Element).call(d3ZoomInstance); + + const clampedX = clamp(defaultPosition[0], currentTranslateExtent[0][0], currentTranslateExtent[1][0]); + const clampedY = clamp(defaultPosition[1], currentTranslateExtent[0][1], currentTranslateExtent[1][1]); + const clampedZoom = clamp(defaultZoom, state.minZoom, state.maxZoom); + + const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom); + // selection.property('__zoom', updatedTransform); + + const zoomHandler = selection.on('wheel.zoom'); + + d3ZoomInstance.transform(selection, updatedTransform); + + initD3Zoom({ + d3Zoom: d3ZoomInstance, + d3Selection: selection, + d3ZoomHandler: zoomHandler, + }); } }, []); diff --git a/src/hooks/useZoomPanHelper.ts b/src/hooks/useZoomPanHelper.ts new file mode 100644 index 00000000..239e3514 --- /dev/null +++ b/src/hooks/useZoomPanHelper.ts @@ -0,0 +1,67 @@ +import { useCallback } from 'react'; +import { zoomIdentity } from 'd3-zoom'; +import { useStoreState, useStore } from '../store/hooks'; + +import { clamp } from '../utils'; +import { getRectOfNodes } from '../utils/graph'; +import { FitViewParams } from '../types'; + +export default () => { + const store = useStore(); + const d3Zoom = useStoreState((s) => s.d3Zoom); + const d3Selection = useStoreState((s) => s.d3Selection); + + const zoomIn = useCallback(() => { + if (d3Selection) { + d3Zoom?.scaleBy(d3Selection, 1.2); + } + }, [d3Zoom, d3Selection]); + + const zoomOut = useCallback(() => { + if (d3Selection) { + d3Zoom?.scaleBy(d3Selection, 1 / 1.2); + } + }, [d3Zoom, d3Selection]); + + const zoomTo = useCallback( + (zoomLevel: number) => { + if (d3Selection) { + d3Zoom?.scaleTo(d3Selection, zoomLevel); + } + }, + [d3Zoom, d3Selection] + ); + + const fitView = useCallback( + (options: FitViewParams) => { + const { padding = 0.1 } = options; + const { nodes, width, height, minZoom, maxZoom } = store.getState(); + + if (!d3Selection || !nodes.length) { + return; + } + + const bounds = getRectOfNodes(nodes); + const xZoom = width / (bounds.width * (1 + padding)); + const yZoom = height / (bounds.height * (1 + padding)); + const zoom = Math.min(xZoom, yZoom); + const clampedZoom = clamp(zoom, minZoom, maxZoom); + const boundsCenterX = bounds.x + bounds.width / 2; + const boundsCenterY = bounds.y + bounds.height / 2; + const x = width / 2 - boundsCenterX * clampedZoom; + const y = height / 2 - boundsCenterY * clampedZoom; + const k = clampedZoom; + const transform = zoomIdentity.translate(x, y).scale(k); + + d3Zoom?.transform(d3Selection, transform); + }, + [store, d3Zoom, d3Selection] + ); + + return { + zoomIn, + zoomOut, + zoomTo, + fitView, + }; +}; diff --git a/src/store/index.ts b/src/store/index.ts index 263e8b2f..24685222 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,10 +1,9 @@ import { createStore, Action, action, Thunk, thunk, computed, Computed } from 'easy-peasy'; import isEqual from 'fast-deep-equal'; import { Selection as D3Selection, ZoomBehavior } from 'd3'; -import { zoom, zoomIdentity } from 'd3-zoom'; -import { select } from 'd3-selection'; +import { zoomIdentity } from 'd3-zoom'; -import { getDimensions, clamp } from '../utils'; +import { getDimensions } from '../utils'; import { getHandleBounds } from '../components/Nodes/utils'; import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph'; @@ -26,7 +25,6 @@ import { SetConnectionId, NodePosUpdate, NodeDiffUpdate, - FitViewParams, TranslateExtent, SnapGrid, } from '../types'; @@ -42,11 +40,10 @@ type NodeDimensionUpdate = { nodeElement: HTMLDivElement; }; -type InitD3 = { - zoomPane: Element; - defaultPosition: [number, number]; - defaultZoom: number; - translateExtent?: TranslateExtent; +type InitD3Zoom = { + d3Zoom: ZoomBehavior; + d3Selection: D3Selection; + d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined; }; export interface StoreModel { width: number; @@ -119,7 +116,7 @@ export interface StoreModel { updateSize: Action; - initD3: Action; + initD3Zoom: Action; setMinZoom: Action; setMaxZoom: Action; @@ -142,12 +139,6 @@ export interface StoreModel { updateUserSelection: Action; unsetUserSelection: Action; - fitView: Action; - zoomTo: Action; - zoom: Thunk; - zoomIn: Thunk; - zoomOut: Thunk; - setMultiSelectionActive: Action; } @@ -397,26 +388,10 @@ export const storeModel: StoreModel = { state.height = size.height || 500; }), - initD3: action((state, { zoomPane, defaultPosition, defaultZoom, translateExtent }) => { - const currentTranslateExtent = typeof translateExtent !== 'undefined' ? translateExtent : state.translateExtent; - const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(currentTranslateExtent); - const selection = select(zoomPane).call(d3ZoomInstance); - - const clampedX = clamp(defaultPosition[0], currentTranslateExtent[0][0], currentTranslateExtent[1][0]); - const clampedY = clamp(defaultPosition[1], currentTranslateExtent[0][1], currentTranslateExtent[1][1]); - const clampedZoom = clamp(defaultZoom, state.minZoom, state.maxZoom); - - const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom); - selection.property('__zoom', updatedTransform); - - const defaultHandler = selection.on('wheel.zoom'); - - state.transform[0] = clampedX; - state.transform[1] = clampedY; - state.transform[2] = clampedZoom; - state.d3Zoom = d3ZoomInstance; - state.d3Selection = selection; - state.d3ZoomHandler = defaultHandler; + initD3Zoom: action((state, { d3Zoom, d3Selection, d3ZoomHandler }) => { + state.d3Zoom = d3Zoom; + state.d3Selection = d3Selection; + state.d3ZoomHandler = d3ZoomHandler; state.d3Initialised = true; }), @@ -481,68 +456,6 @@ export const storeModel: StoreModel = { state.elementsSelectable = elementsSelectable; }), - fitView: action((state, payload = { padding: 0.1 }) => { - const { padding } = payload; - const { nodes, width, height, d3Selection, minZoom, maxZoom } = state; - - if (!d3Selection || !nodes.length) { - return; - } - - const bounds = getRectOfNodes(nodes); - const xZoom = width / (bounds.width * (1 + padding)); - const yZoom = height / (bounds.height * (1 + padding)); - const zoom = Math.min(xZoom, yZoom); - const clampedZoom = clamp(zoom, minZoom, maxZoom); - const boundsCenterX = bounds.x + bounds.width / 2; - const boundsCenterY = bounds.y + bounds.height / 2; - const transform = [width / 2 - boundsCenterX * clampedZoom, height / 2 - boundsCenterY * clampedZoom]; - const fittedTransform = zoomIdentity.translate(transform[0], transform[1]).scale(clampedZoom); - - // we need to sync the d3 zoom transform with the fitted transform - d3Selection.property('__zoom', fittedTransform); - - state.transform[0] = fittedTransform.x; - state.transform[1] = fittedTransform.y; - state.transform[2] = fittedTransform.k; - }), - - zoomTo: action((state, zoomLevel) => { - const { d3Selection, transform, minZoom, maxZoom } = state; - const nextZoom = clamp(zoomLevel, minZoom, maxZoom); - - if (d3Selection) { - // we want to zoom in and out to the center of the zoom pane - const center = [state.width / 2, state.height / 2]; - const centerInverted = [(center[0] - transform[0]) / transform[2], (center[1] - transform[1]) / transform[2]]; - const x = center[0] - centerInverted[0] * nextZoom; - const y = center[1] - centerInverted[1] * nextZoom; - const zoomedTransform = zoomIdentity.translate(x, y).scale(nextZoom); - - // we need to sync the d3 zoom transform with the zoomed transform - d3Selection.property('__zoom', zoomedTransform); - - state.transform[0] = zoomedTransform.x; - state.transform[1] = zoomedTransform.y; - state.transform[2] = zoomedTransform.k; - } - }), - - zoom: thunk((actions, amount, helpers) => { - const { transform } = helpers.getState(); - const nextZoom = transform[2] + amount; - - actions.zoomTo(nextZoom); - }), - - zoomIn: thunk((actions) => { - actions.zoom(0.2); - }), - - zoomOut: thunk((actions) => { - actions.zoom(-0.2); - }), - setMultiSelectionActive: action((state, isActive) => { state.multiSelectionActive = isActive; }), diff --git a/src/utils/graph.ts b/src/utils/graph.ts index d39c8f7e..1870a0fb 100644 --- a/src/utils/graph.ts +++ b/src/utils/graph.ts @@ -1,7 +1,6 @@ import { Store } from 'easy-peasy'; - -import store, { StoreModel } from '../store'; -import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, FitViewParams, Box, Connection } from '../types'; +import { StoreModel } from '../store'; +import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, Box, Connection } from '../types'; export const isEdge = (element: Node | Connection | Edge): element is Edge => 'id' in element && 'source' in element && 'target' in element; @@ -106,12 +105,6 @@ export const onLoadProject = (currentStore: Store) => { }; }; -export const project = (position: XYPosition): XYPosition => { - const { transform, snapToGrid, snapGrid } = store.getState(); - - return pointToRendererPoint(position, transform, snapToGrid, snapGrid); -}; - export const parseElement = (element: Node | Edge): Node | Edge => { if (!element.id) { throw new Error('All nodes and edges need to have an id.'); @@ -227,18 +220,6 @@ export const getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[] => { }); }; -export const fitView = (params: FitViewParams = { padding: 0.1 }): void => { - store.getActions().fitView(params); -}; - -const zoom = (amount: number): void => { - store.getActions().zoom(amount); -}; - -export const zoomIn = (): void => zoom(0.2); - -export const zoomOut = (): void => zoom(-0.2); - const parseElements = (nodes: Node[], edges: Edge[]): Elements => { return [ ...nodes.map((node) => { @@ -258,9 +239,3 @@ export const onLoadGetElements = (currentStore: Store) => { return parseElements(nodes, edges); }; }; - -export const getElements = (): Elements => { - const { nodes = [], edges = [] } = store.getState(); - - return parseElements(nodes, edges); -}; From cf87acc89b47776b8cbbd0043433b19074b593d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Mon, 9 Nov 2020 17:29:27 +0100 Subject: [PATCH 12/61] chore: release v8.0.0-next.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 85da28c1..4ca33336 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.2", + "version": "8.0.0-next.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9b013526..e49deab9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "7.1.2", + "version": "8.0.0-next.0", "main": "dist/ReactFlow.js", "module": "dist/ReactFlow.esm.js", "types": "dist/index.d.ts", From 2db5a7bce24f830fab91bdd68e0549f2efe8077e Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 17:48:51 +0100 Subject: [PATCH 13/61] refactor(getElements): use internal node position #603 --- src/utils/graph.ts | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/utils/graph.ts b/src/utils/graph.ts index 1870a0fb..4871ceb5 100644 --- a/src/utils/graph.ts +++ b/src/utils/graph.ts @@ -210,14 +210,9 @@ export const getNodesInside = ( }; export const getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[] => { - const nodeIds = nodes.map((n) => n.id); + const nodeIds = nodes.map((node) => node.id); - return edges.filter((e) => { - const sourceId = e.source.split('__')[0]; - const targetId = e.target.split('__')[0]; - - return nodeIds.includes(sourceId) || nodeIds.includes(targetId); - }); + return edges.filter((edge) => nodeIds.includes(edge.source) || nodeIds.includes(edge.target)); }; const parseElements = (nodes: Node[], edges: Edge[]): Elements => { @@ -225,6 +220,8 @@ const parseElements = (nodes: Node[], edges: Edge[]): Elements => { ...nodes.map((node) => { const n = { ...node }; + n.position = n.__rf.position; + delete n.__rf; return n; }), From 7cc2306975cb0ba2363c8a6626ff223928238470 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 18:17:36 +0100 Subject: [PATCH 14/61] feat(reactflowInstance): add toObject function closes #603 --- example/src/Basic/index.js | 14 ++++++++++---- src/container/GraphView/index.tsx | 3 ++- src/types/index.ts | 9 +++++++++ src/utils/graph.ts | 25 ++++++++++++++++++++++++- 4 files changed, 45 insertions(+), 6 deletions(-) diff --git a/example/src/Basic/index.js b/example/src/Basic/index.js index 841e731e..2b38a838 100644 --- a/example/src/Basic/index.js +++ b/example/src/Basic/index.js @@ -2,7 +2,6 @@ import React, { useState } from 'react'; import ReactFlow, { removeElements, addEdge, isNode, Background } from 'react-flow-renderer'; -const onLoad = (reactFlowInstance) => console.log('flow loaded:', reactFlowInstance); const onNodeDragStop = (event, node) => console.log('drag stop', node); const onElementClick = (event, element) => console.log('click', element); @@ -16,9 +15,11 @@ const initialElements = [ ]; const BasicFlow = () => { + const [rfInstance, setRfInstance] = useState(null); const [elements, setElements] = useState(initialElements); const onElementsRemove = (elementsToRemove) => setElements((els) => removeElements(elementsToRemove, els)); const onConnect = (params) => setElements((els) => addEdge(params, els)); + const onLoad = (reactFlowInstance) => setRfInstance(reactFlowInstance); const updatePos = () => { setElements((elms) => { @@ -38,6 +39,8 @@ const BasicFlow = () => { }); }; + const logToObject = () => console.log(rfInstance.toObject()); + return ( { > - +
+ + +
); }; diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 3f9ce248..7b82778a 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -5,7 +5,7 @@ import FlowRenderer from '../FlowRenderer'; import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; import useElementUpdater from '../../hooks/useElementUpdater'; -import { onLoadProject, onLoadGetElements } from '../../utils/graph'; +import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph'; import { Elements, NodeTypesType, @@ -163,6 +163,7 @@ const GraphView = ({ getElements: onLoadGetElements(currentStore), setTransform: (transform: FlowTransform) => setInitTransform({ x: transform.x, y: transform.y, k: transform.zoom }), + toObject: onLoadToObject(currentStore), }); } diff --git a/src/types/index.ts b/src/types/index.ts index 583d9391..d912f2bc 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -229,8 +229,16 @@ export interface WrapNodeProps { export type FitViewParams = { padding: number; }; + +export type FlowExportObject = { + elements: Elements; + position: [number, number]; + zoom: number; +}; + export type FitViewFunc = (fitViewOptions?: FitViewParams) => void; export type ProjectFunc = (position: XYPosition) => XYPosition; +export type ToObjectFunc = () => FlowExportObject; export type OnLoadParams = { zoomIn: () => void; @@ -240,6 +248,7 @@ export type OnLoadParams = { project: ProjectFunc; getElements: () => Elements; setTransform: (transform: FlowTransform) => void; + toObject: ToObjectFunc; }; export type OnLoadFunc = (params: OnLoadParams) => void; diff --git a/src/utils/graph.ts b/src/utils/graph.ts index 4871ceb5..9285e59a 100644 --- a/src/utils/graph.ts +++ b/src/utils/graph.ts @@ -1,6 +1,17 @@ import { Store } from 'easy-peasy'; import { StoreModel } from '../store'; -import { ElementId, Node, Edge, Elements, Transform, XYPosition, Rect, Box, Connection } from '../types'; +import { + ElementId, + Node, + Edge, + Elements, + Transform, + XYPosition, + Rect, + Box, + Connection, + FlowExportObject, +} from '../types'; export const isEdge = (element: Node | Connection | Edge): element is Edge => 'id' in element && 'source' in element && 'target' in element; @@ -236,3 +247,15 @@ export const onLoadGetElements = (currentStore: Store) => { return parseElements(nodes, edges); }; }; + +export const onLoadToObject = (currentStore: Store) => { + return (): FlowExportObject => { + const { nodes = [], edges = [], transform } = currentStore.getState(); + + return { + elements: parseElements(nodes, edges), + position: [transform[0], transform[1]], + zoom: transform[2], + }; + }; +}; From c7bf8ffbcc6d09f286a101e5f74868663f893893 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 18:27:41 +0100 Subject: [PATCH 15/61] refactor(initD3): pass initial transform --- src/container/GraphView/index.tsx | 6 +++--- src/container/ZoomPane/index.tsx | 9 +++------ src/store/index.ts | 10 ++++++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 7b82778a..72d8f2b8 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -132,7 +132,7 @@ const GraphView = ({ onPaneContextMenu, }: GraphViewProps) => { const isInitialised = useRef(false); - const d3Initialised = useStoreState((state) => state.d3Initialised); + const d3Zoom = useStoreState((state) => state.d3Zoom); const setOnConnect = useStoreActions((actions) => actions.setOnConnect); const setOnConnectStart = useStoreActions((actions) => actions.setOnConnectStart); const setOnConnectStop = useStoreActions((actions) => actions.setOnConnectStop); @@ -152,7 +152,7 @@ const GraphView = ({ useElementUpdater(elements); useEffect(() => { - if (!isInitialised.current && d3Initialised) { + if (!isInitialised.current && d3Zoom) { if (onLoad) { onLoad({ fitView: (params = { padding: 0.1 }) => fitView(params), @@ -169,7 +169,7 @@ const GraphView = ({ isInitialised.current = true; } - }, [d3Initialised, onLoad]); + }, [d3Zoom, onLoad]); useEffect(() => { if (onConnect) { diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 9ff0bc14..4dcaba8b 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -67,7 +67,6 @@ const ZoomPane = ({ useEffect(() => { if (zoomPane.current) { - // initD3: action((state, { zoomPane, defaultPosition, defaultZoom, translateExtent }) => { const state = store.getState(); const currentTranslateExtent = typeof translateExtent !== 'undefined' ? translateExtent : state.translateExtent; const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(currentTranslateExtent); @@ -76,18 +75,16 @@ const ZoomPane = ({ const clampedX = clamp(defaultPosition[0], currentTranslateExtent[0][0], currentTranslateExtent[1][0]); const clampedY = clamp(defaultPosition[1], currentTranslateExtent[0][1], currentTranslateExtent[1][1]); const clampedZoom = clamp(defaultZoom, state.minZoom, state.maxZoom); - const updatedTransform = zoomIdentity.translate(clampedX, clampedY).scale(clampedZoom); - // selection.property('__zoom', updatedTransform); - - const zoomHandler = selection.on('wheel.zoom'); d3ZoomInstance.transform(selection, updatedTransform); initD3Zoom({ d3Zoom: d3ZoomInstance, d3Selection: selection, - d3ZoomHandler: zoomHandler, + d3ZoomHandler: selection.on('wheel.zoom'), + // we need to pass transform because zoom handler is not registered when we set the initial transform + transform: [clampedX, clampedY, clampedZoom], }); } }, []); diff --git a/src/store/index.ts b/src/store/index.ts index 24685222..05e550cf 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -44,6 +44,7 @@ type InitD3Zoom = { d3Zoom: ZoomBehavior; d3Selection: D3Selection; d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined; + transform: Transform; }; export interface StoreModel { width: number; @@ -59,7 +60,6 @@ export interface StoreModel { d3Zoom: ZoomBehavior | null; d3Selection: D3Selection | null; d3ZoomHandler: ((this: Element, event: any, d: unknown) => void) | undefined; - d3Initialised: boolean; minZoom: number; maxZoom: number; translateExtent: TranslateExtent; @@ -155,7 +155,6 @@ export const storeModel: StoreModel = { d3Zoom: null, d3Selection: null, - d3Initialised: false, d3ZoomHandler: undefined, minZoom: 0.5, maxZoom: 2, @@ -388,11 +387,14 @@ export const storeModel: StoreModel = { state.height = size.height || 500; }), - initD3Zoom: action((state, { d3Zoom, d3Selection, d3ZoomHandler }) => { + initD3Zoom: action((state, { d3Zoom, d3Selection, d3ZoomHandler, transform }) => { state.d3Zoom = d3Zoom; state.d3Selection = d3Selection; state.d3ZoomHandler = d3ZoomHandler; - state.d3Initialised = true; + + state.transform[0] = transform[0]; + state.transform[1] = transform[1]; + state.transform[2] = transform[2]; }), setMinZoom: action((state, minZoom) => { From e1ae70e7790596c1684f6f5de3ccd884f602e039 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 19:30:21 +0100 Subject: [PATCH 16/61] refactor(zoomPanHelper): export and simplify --- example/src/Basic/index.js | 5 + src/additional-components/Controls/index.tsx | 59 +++++------- src/container/GraphView/index.tsx | 13 +-- src/container/ZoomPane/index.tsx | 2 +- src/hooks/useZoomPanHelper.ts | 97 +++++++++----------- src/index.ts | 1 + src/store/index.ts | 35 ++----- 7 files changed, 89 insertions(+), 123 deletions(-) diff --git a/example/src/Basic/index.js b/example/src/Basic/index.js index 2b38a838..3395d29b 100644 --- a/example/src/Basic/index.js +++ b/example/src/Basic/index.js @@ -41,6 +41,8 @@ const BasicFlow = () => { const logToObject = () => console.log(rfInstance.toObject()); + const resetTransform = () => rfInstance.setTransform({ x: 0, y: 0, zoom: 1 }); + return ( {
+ diff --git a/src/additional-components/Controls/index.tsx b/src/additional-components/Controls/index.tsx index 983701e9..ca11bfa3 100644 --- a/src/additional-components/Controls/index.tsx +++ b/src/additional-components/Controls/index.tsx @@ -1,4 +1,4 @@ -import React, { memo } from 'react'; +import React, { memo, useCallback } from 'react'; import cc from 'classcat'; import { useStoreState, useStoreActions } from '../../store/hooks'; @@ -39,56 +39,47 @@ const Controls = ({ const isInteractive = useStoreState((s) => s.nodesDraggable && s.nodesConnectable && s.elementsSelectable); const mapClasses = cc(['react-flow__controls', className]); + const onZoomInHandler = useCallback(() => { + zoomIn?.(); + onZoomIn?.(); + }, [zoomIn, onZoomIn]); + + const onZoomOutHandler = useCallback(() => { + zoomOut?.(); + onZoomOut?.(); + }, [zoomOut, onZoomOut]); + + const onFitViewHandler = useCallback(() => { + fitView?.(); + onFitView?.(); + }, [fitView, onFitView]); + + const onInteractiveChangeHandler = useCallback(() => { + setInteractive?.(!isInteractive); + onInteractiveChange?.(!isInteractive); + }, [isInteractive, setInteractive, onInteractiveChange]); + return (
{showZoom && ( <> -
{ - zoomIn(); - if (onZoomIn) { - onZoomIn(); - } - }} - > +
-
{ - zoomOut(); - if (onZoomOut) { - onZoomOut(); - } - }} - > +
)} {showFitView && ( -
{ - fitView({ padding: 0.1 }); - if (onFitView) { - onFitView(); - } - }} - > +
)} {showInteractive && (
{ - setInteractive(!isInteractive); - if (onInteractiveChange) { - onInteractiveChange(!isInteractive); - } - }} + onClick={onInteractiveChangeHandler} > {isInteractive ? : }
diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 72d8f2b8..44c209bd 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -1,6 +1,6 @@ import React, { useEffect, useRef, memo, CSSProperties, MouseEvent, WheelEvent } from 'react'; -import { useStoreState, useStoreActions, useStore } from '../../store/hooks'; +import { useStoreActions, useStore } from '../../store/hooks'; import FlowRenderer from '../FlowRenderer'; import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; @@ -132,7 +132,6 @@ const GraphView = ({ onPaneContextMenu, }: GraphViewProps) => { const isInitialised = useRef(false); - const d3Zoom = useStoreState((state) => state.d3Zoom); const setOnConnect = useStoreActions((actions) => actions.setOnConnect); const setOnConnectStart = useStoreActions((actions) => actions.setOnConnectStart); const setOnConnectStop = useStoreActions((actions) => actions.setOnConnectStop); @@ -142,34 +141,32 @@ const GraphView = ({ const setNodesDraggable = useStoreActions((actions) => actions.setNodesDraggable); const setNodesConnectable = useStoreActions((actions) => actions.setNodesConnectable); const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable); - const setInitTransform = useStoreActions((actions) => actions.setInitTransform); const setMinZoom = useStoreActions((actions) => actions.setMinZoom); const setMaxZoom = useStoreActions((actions) => actions.setMaxZoom); const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent); const currentStore = useStore(); - const { zoomIn, zoomOut, zoomTo, fitView } = useZoomPanHelper(); + const { zoomIn, zoomOut, zoomTo, transform, fitView } = useZoomPanHelper(); useElementUpdater(elements); useEffect(() => { - if (!isInitialised.current && d3Zoom) { + if (!isInitialised.current && zoomIn && zoomOut && zoomTo && transform && fitView) { if (onLoad) { onLoad({ fitView: (params = { padding: 0.1 }) => fitView(params), zoomIn, zoomOut, zoomTo, + setTransform: transform, project: onLoadProject(currentStore), getElements: onLoadGetElements(currentStore), - setTransform: (transform: FlowTransform) => - setInitTransform({ x: transform.x, y: transform.y, k: transform.zoom }), toObject: onLoadToObject(currentStore), }); } isInitialised.current = true; } - }, [d3Zoom, onLoad]); + }, [onLoad, zoomIn, zoomOut, zoomTo, transform, fitView]); useEffect(() => { if (onConnect) { diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 4dcaba8b..3d2d94e3 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -123,7 +123,7 @@ const ZoomPane = ({ d3Zoom.on('zoom', null); } else { d3Zoom.on('zoom', (event: any) => { - updateTransform(event.transform); + updateTransform([event.transform.x, event.transform.y, event.transform.k]); if (onMove) { const flowTransform = eventToFlowTransform(event.transform); diff --git a/src/hooks/useZoomPanHelper.ts b/src/hooks/useZoomPanHelper.ts index 239e3514..b2b5a0e7 100644 --- a/src/hooks/useZoomPanHelper.ts +++ b/src/hooks/useZoomPanHelper.ts @@ -1,67 +1,60 @@ -import { useCallback } from 'react'; +import { useMemo } from 'react'; import { zoomIdentity } from 'd3-zoom'; import { useStoreState, useStore } from '../store/hooks'; import { clamp } from '../utils'; import { getRectOfNodes } from '../utils/graph'; -import { FitViewParams } from '../types'; +import { FitViewParams, FlowTransform } from '../types'; + +const initialHelpers = { + zoomIn: null, + zoomOut: null, + zoomTo: null, + transform: null, + fitView: null, +}; export default () => { const store = useStore(); const d3Zoom = useStoreState((s) => s.d3Zoom); const d3Selection = useStoreState((s) => s.d3Selection); - const zoomIn = useCallback(() => { - if (d3Selection) { - d3Zoom?.scaleBy(d3Selection, 1.2); + const zoomPanHelperFunctions = useMemo(() => { + if (d3Selection && d3Zoom) { + return { + zoomIn: () => d3Zoom.scaleBy(d3Selection, 1.2), + zoomOut: () => d3Zoom.scaleBy(d3Selection, 1 / 1.2), + zoomTo: (zoomLevel: number) => d3Zoom.scaleTo(d3Selection, zoomLevel), + transform: (transform: FlowTransform) => { + const nextTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.zoom); + + d3Zoom.transform(d3Selection, nextTransform); + }, + fitView: (options: FitViewParams = { padding: 0.1 }) => { + const { nodes, width, height, minZoom, maxZoom } = store.getState(); + + if (!nodes.length) { + return; + } + + const bounds = getRectOfNodes(nodes); + const xZoom = width / (bounds.width * (1 + options.padding)); + const yZoom = height / (bounds.height * (1 + options.padding)); + const zoom = Math.min(xZoom, yZoom); + const clampedZoom = clamp(zoom, minZoom, maxZoom); + const boundsCenterX = bounds.x + bounds.width / 2; + const boundsCenterY = bounds.y + bounds.height / 2; + const x = width / 2 - boundsCenterX * clampedZoom; + const y = height / 2 - boundsCenterY * clampedZoom; + const transform = zoomIdentity.translate(x, y).scale(clampedZoom); + + d3Zoom.transform(d3Selection, transform); + }, + }; } + + return initialHelpers; }, [d3Zoom, d3Selection]); - const zoomOut = useCallback(() => { - if (d3Selection) { - d3Zoom?.scaleBy(d3Selection, 1 / 1.2); - } - }, [d3Zoom, d3Selection]); - - const zoomTo = useCallback( - (zoomLevel: number) => { - if (d3Selection) { - d3Zoom?.scaleTo(d3Selection, zoomLevel); - } - }, - [d3Zoom, d3Selection] - ); - - const fitView = useCallback( - (options: FitViewParams) => { - const { padding = 0.1 } = options; - const { nodes, width, height, minZoom, maxZoom } = store.getState(); - - if (!d3Selection || !nodes.length) { - return; - } - - const bounds = getRectOfNodes(nodes); - const xZoom = width / (bounds.width * (1 + padding)); - const yZoom = height / (bounds.height * (1 + padding)); - const zoom = Math.min(xZoom, yZoom); - const clampedZoom = clamp(zoom, minZoom, maxZoom); - const boundsCenterX = bounds.x + bounds.width / 2; - const boundsCenterY = bounds.y + bounds.height / 2; - const x = width / 2 - boundsCenterX * clampedZoom; - const y = height / 2 - boundsCenterY * clampedZoom; - const k = clampedZoom; - const transform = zoomIdentity.translate(x, y).scale(k); - - d3Zoom?.transform(d3Selection, transform); - }, - [store, d3Zoom, d3Selection] - ); - - return { - zoomIn, - zoomOut, - zoomTo, - fitView, - }; + return zoomPanHelperFunctions; }; diff --git a/src/index.ts b/src/index.ts index 3fe2e30e..6ce7ecc2 100644 --- a/src/index.ts +++ b/src/index.ts @@ -9,6 +9,7 @@ export { getSmoothStepPath } from './components/Edges/SmoothStepEdge'; export { getMarkerEnd, getCenter as getEdgeCenter } from './components/Edges/utils'; export { isNode, isEdge, removeElements, addEdge, getOutgoers, getIncomers, getConnectedEdges } from './utils/graph'; +export { default as useZoomPanHelper } from './hooks/useZoomPanHelper'; export * from './additional-components'; export * from './store/hooks'; diff --git a/src/store/index.ts b/src/store/index.ts index 05e550cf..406ac647 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -1,12 +1,11 @@ import { createStore, Action, action, Thunk, thunk, computed, Computed } from 'easy-peasy'; import isEqual from 'fast-deep-equal'; import { Selection as D3Selection, ZoomBehavior } from 'd3'; -import { zoomIdentity } from 'd3-zoom'; import { getDimensions } from '../utils'; +import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph'; import { getHandleBounds } from '../components/Nodes/utils'; -import { getNodesInside, getConnectedEdges, getRectOfNodes, isNode, isEdge } from '../utils/graph'; import { ElementId, Elements, @@ -29,12 +28,6 @@ import { SnapGrid, } from '../types'; -type TransformXYK = { - x: number; - y: number; - k: number; -}; - type NodeDimensionUpdate = { id: ElementId; nodeElement: HTMLDivElement; @@ -110,9 +103,7 @@ export interface StoreModel { setSelectedElements: Action; addSelectedElements: Thunk; - updateTransform: Action; - - setInitTransform: Action; + updateTransform: Action; updateSize: Action; @@ -148,8 +139,8 @@ export const storeModel: StoreModel = { viewportBox: computed((state) => ({ x: 0, y: 0, width: state.width, height: state.height })), transform: [0, 0, 1], elements: [], - nodes: computed((state) => state.elements.filter((el) => isNode(el)) as Node[]), - edges: computed((state) => state.elements.filter((el) => isEdge(el)) as Edge[]), + nodes: computed((state) => state.elements.filter(isNode)), + edges: computed((state) => state.elements.filter(isEdge)), selectedElements: null, selectedNodesBbox: { x: 0, y: 0, width: 0, height: 0 }, @@ -363,21 +354,9 @@ export const storeModel: StoreModel = { }), updateTransform: action((state, transform) => { - state.transform[0] = transform.x; - state.transform[1] = transform.y; - state.transform[2] = transform.k; - }), - - setInitTransform: action((state, transform) => { - state.transform[0] = transform.x; - state.transform[1] = transform.y; - state.transform[2] = transform.k; - - if (state.d3Selection) { - const updatedTransform = zoomIdentity.translate(transform.x, transform.y).scale(transform.k); - // we need to sync the d3 zoom transform with the updated transform - state.d3Selection.property('__zoom', updatedTransform); - } + state.transform[0] = transform[0]; + state.transform[1] = transform[1]; + state.transform[2] = transform[2]; }), updateSize: action((state, size) => { From d06868ecdeb16e80ff55d453035873fad38549a1 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 22:00:26 +0100 Subject: [PATCH 17/61] refactor(graphview): extend react flow props --- src/container/FlowRenderer/index.tsx | 1 + src/container/GraphView/index.tsx | 70 ++++------------------------ src/hooks/useZoomPanHelper.ts | 6 +-- 3 files changed, 14 insertions(+), 63 deletions(-) diff --git a/src/container/FlowRenderer/index.tsx b/src/container/FlowRenderer/index.tsx index 12bec2f5..4127f481 100644 --- a/src/container/FlowRenderer/index.tsx +++ b/src/container/FlowRenderer/index.tsx @@ -20,6 +20,7 @@ interface FlowRendererProps | 'connectionLineType' | 'arrowHeadColor' | 'onlyRenderVisibleNodes' + | 'selectNodesOnDrag' > { children: ReactNode; } diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 44c209bd..c831b367 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useRef, memo, CSSProperties, MouseEvent, WheelEvent } from 'react'; +import React, { useEffect, useRef, memo } from 'react'; import { useStoreActions, useStore } from '../../store/hooks'; import FlowRenderer from '../FlowRenderer'; @@ -6,76 +6,26 @@ import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; import useElementUpdater from '../../hooks/useElementUpdater'; import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph'; -import { - Elements, - NodeTypesType, - EdgeTypesType, - OnLoadFunc, - Node, - Edge, - Connection, - ConnectionLineType, - ConnectionLineComponent, - FlowTransform, - OnConnectStartFunc, - OnConnectStopFunc, - OnConnectEndFunc, - TranslateExtent, -} from '../../types'; import useZoomPanHelper from '../../hooks/useZoomPanHelper'; -export interface GraphViewProps { - elements: Elements; - onElementClick?: (event: MouseEvent, element: Node | Edge) => void; - onElementsRemove?: (elements: Elements) => void; - onNodeMouseEnter?: (event: MouseEvent, node: Node) => void; - onNodeMouseMove?: (event: MouseEvent, node: Node) => void; - onNodeMouseLeave?: (event: MouseEvent, node: Node) => void; - onNodeContextMenu?: (event: MouseEvent, node: Node) => void; - onNodeDragStart?: (event: MouseEvent, node: Node) => void; - onNodeDragStop?: (event: MouseEvent, node: Node) => void; - onConnect?: (connection: Connection | Edge) => void; - onConnectStart?: OnConnectStartFunc; - onConnectStop?: OnConnectStopFunc; - onConnectEnd?: OnConnectEndFunc; - onLoad?: OnLoadFunc; - onMove?: (flowTransform?: FlowTransform) => void; - onMoveStart?: (flowTransform?: FlowTransform) => void; - onMoveEnd?: (flowTransform?: FlowTransform) => void; - onPaneScroll?: (event?: WheelEvent) => 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; - onSelectionContextMenu?: (event: MouseEvent, nodes: Node[]) => void; - selectionKeyCode: number; +import { ReactFlowProps } from '../ReactFlow'; + +import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types'; + +export interface GraphViewProps extends Omit { nodeTypes: NodeTypesType; edgeTypes: EdgeTypesType; - connectionLineType: ConnectionLineType; - connectionLineStyle?: CSSProperties; - connectionLineComponent?: ConnectionLineComponent; + selectionKeyCode: number; deleteKeyCode: number; multiSelectionKeyCode: number; + connectionLineType: ConnectionLineType; snapToGrid: boolean; snapGrid: [number, number]; onlyRenderVisibleNodes: boolean; - nodesDraggable?: boolean; - nodesConnectable?: boolean; - elementsSelectable?: boolean; - selectNodesOnDrag?: boolean; - minZoom?: number; - maxZoom?: number; defaultZoom: number; defaultPosition: [number, number]; - translateExtent?: TranslateExtent; arrowHeadColor: string; - markerEndId?: string; - zoomOnScroll?: boolean; - panOnScroll?: boolean; - panOnScrollSpeed?: number; - zoomOnDoubleClick?: boolean; - paneMoveable?: boolean; + selectNodesOnDrag: boolean; } const GraphView = ({ @@ -114,7 +64,7 @@ const GraphView = ({ nodesDraggable, nodesConnectable, elementsSelectable, - selectNodesOnDrag = true, + selectNodesOnDrag, minZoom, maxZoom, defaultZoom, diff --git a/src/hooks/useZoomPanHelper.ts b/src/hooks/useZoomPanHelper.ts index b2b5a0e7..defb16be 100644 --- a/src/hooks/useZoomPanHelper.ts +++ b/src/hooks/useZoomPanHelper.ts @@ -1,12 +1,12 @@ import { useMemo } from 'react'; import { zoomIdentity } from 'd3-zoom'; -import { useStoreState, useStore } from '../store/hooks'; +import { useStoreState, useStore } from '../store/hooks'; import { clamp } from '../utils'; import { getRectOfNodes } from '../utils/graph'; import { FitViewParams, FlowTransform } from '../types'; -const initialHelpers = { +const initialZoomPanHelper = { zoomIn: null, zoomOut: null, zoomTo: null, @@ -53,7 +53,7 @@ export default () => { }; } - return initialHelpers; + return initialZoomPanHelper; }, [d3Zoom, d3Selection]); return zoomPanHelperFunctions; From 0fbefe5a58f193cdba037aad07a0f5b80c452884 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 9 Nov 2020 22:24:12 +0100 Subject: [PATCH 18/61] refactor(GraphView): reduce amounts of re-renderings --- .../ElementUpdater/index.tsx} | 20 ++++++++++++------- src/container/GraphView/index.tsx | 6 +----- src/container/ReactFlow/index.tsx | 3 ++- src/container/ZoomPane/index.tsx | 2 +- src/hooks/useGlobalKeyHandler.ts | 6 +++--- 5 files changed, 20 insertions(+), 17 deletions(-) rename src/{hooks/useElementUpdater.ts => components/ElementUpdater/index.tsx} (90%) diff --git a/src/hooks/useElementUpdater.ts b/src/components/ElementUpdater/index.tsx similarity index 90% rename from src/hooks/useElementUpdater.ts rename to src/components/ElementUpdater/index.tsx index 0f2bac7c..a84c5c01 100644 --- a/src/hooks/useElementUpdater.ts +++ b/src/components/ElementUpdater/index.tsx @@ -1,16 +1,20 @@ import { useEffect } from 'react'; import isEqual from 'fast-deep-equal'; -import { useStoreState, useStoreActions } from '../store/hooks'; -import { parseElement, isNode, isEdge } from '../utils/graph'; -import { Elements, Node, Edge, FlowElement } from '../types'; +import { useStoreState, useStoreActions } from '../../store/hooks'; +import { parseElement, isNode, isEdge } from '../../utils/graph'; +import { Elements, Node, Edge, FlowElement } from '../../types'; -const useElementUpdater = (propElements: Elements): void => { +interface ElementUpdaterProps { + elements: Elements; +} + +const ElementUpdater = ({ elements }: ElementUpdaterProps) => { const stateElements = useStoreState((state) => state.elements); const setElements = useStoreActions((actions) => actions.setElements); useEffect(() => { - const nextElements: Elements = propElements.map((propElement) => { + const nextElements: Elements = elements.map((propElement) => { const existingElement = stateElements.find((el) => el.id === propElement.id?.toString()); if (existingElement) { @@ -137,7 +141,9 @@ const useElementUpdater = (propElements: Elements): void => { if (elementsChanged) { setElements(nextElements); } - }, [propElements, stateElements]); + }, [elements, stateElements]); + + return null; }; -export default useElementUpdater; +export default ElementUpdater; diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index c831b367..2c870ab3 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -4,7 +4,6 @@ import { useStoreActions, useStore } from '../../store/hooks'; import FlowRenderer from '../FlowRenderer'; import NodeRenderer from '../NodeRenderer'; import EdgeRenderer from '../EdgeRenderer'; -import useElementUpdater from '../../hooks/useElementUpdater'; import { onLoadProject, onLoadGetElements, onLoadToObject } from '../../utils/graph'; import useZoomPanHelper from '../../hooks/useZoomPanHelper'; @@ -12,7 +11,7 @@ import { ReactFlowProps } from '../ReactFlow'; import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types'; -export interface GraphViewProps extends Omit { +export interface GraphViewProps extends Omit { nodeTypes: NodeTypesType; edgeTypes: EdgeTypesType; selectionKeyCode: number; @@ -53,7 +52,6 @@ const GraphView = ({ multiSelectionKeyCode, onElementsRemove, deleteKeyCode, - elements, onConnect, onConnectStart, onConnectStop, @@ -97,8 +95,6 @@ const GraphView = ({ const currentStore = useStore(); const { zoomIn, zoomOut, zoomTo, transform, fitView } = useZoomPanHelper(); - useElementUpdater(elements); - useEffect(() => { if (!isInitialised.current && zoomIn && zoomOut && zoomTo && transform && fitView) { if (onLoad) { diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 533d2100..8a4860b5 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -9,6 +9,7 @@ if (nodeEnv !== 'production') { } import GraphView from '../GraphView'; +import ElementUpdater from '../../components/ElementUpdater'; import DefaultNode from '../../components/Nodes/DefaultNode'; import InputNode from '../../components/Nodes/InputNode'; import OutputNode from '../../components/Nodes/OutputNode'; @@ -189,7 +190,6 @@ const ReactFlow = ({ onElementsRemove={onElementsRemove} deleteKeyCode={deleteKeyCode} multiSelectionKeyCode={multiSelectionKeyCode} - elements={elements} onConnect={onConnect} onConnectStart={onConnectStart} onConnectStop={onConnectStop} @@ -221,6 +221,7 @@ const ReactFlow = ({ onSelectionDragStop={onSelectionDragStop} onSelectionContextMenu={onSelectionContextMenu} /> + {onSelectionChange && } {children} diff --git a/src/container/ZoomPane/index.tsx b/src/container/ZoomPane/index.tsx index 3d2d94e3..e67c253d 100644 --- a/src/container/ZoomPane/index.tsx +++ b/src/container/ZoomPane/index.tsx @@ -55,13 +55,13 @@ const ZoomPane = ({ const zoomPane = useRef(null); const prevTransform = useRef({ x: 0, y: 0, zoom: 0 }); + const store = useStore(); const d3Zoom = useStoreState((s) => s.d3Zoom); const d3Selection = useStoreState((s) => s.d3Selection); const d3ZoomHandler = useStoreState((s) => s.d3ZoomHandler); const initD3Zoom = useStoreActions((actions) => actions.initD3Zoom); const updateTransform = useStoreActions((actions) => actions.updateTransform); - const store = useStore(); useResizeHandler(zoomPane); diff --git a/src/hooks/useGlobalKeyHandler.ts b/src/hooks/useGlobalKeyHandler.ts index a6319b3d..1a719f4c 100644 --- a/src/hooks/useGlobalKeyHandler.ts +++ b/src/hooks/useGlobalKeyHandler.ts @@ -1,6 +1,6 @@ import { useEffect } from 'react'; -import { useStoreState, useStoreActions } from '../store/hooks'; +import { useStore, useStoreActions } from '../store/hooks'; import useKeyPress from './useKeyPress'; import { isNode, getConnectedEdges } from '../utils/graph'; import { Elements } from '../types'; @@ -12,8 +12,7 @@ interface HookParams { } export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: HookParams): void => { - const selectedElements = useStoreState((state) => state.selectedElements); - const edges = useStoreState((state) => state.edges); + const store = useStore(); const unsetNodesSelection = useStoreActions((actions) => actions.unsetNodesSelection); const setMultiSelectionActive = useStoreActions((actions) => actions.setMultiSelectionActive); @@ -23,6 +22,7 @@ export default ({ deleteKeyCode, multiSelectionKeyCode, onElementsRemove }: Hook const multiSelectionKeyPressed = useKeyPress(multiSelectionKeyCode); useEffect(() => { + const { edges, selectedElements } = store.getState(); if (onElementsRemove && deleteKeyPressed && selectedElements) { let elementsToRemove = selectedElements; From e088287370f50ab227ecd16c8c26dd3392f18407 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Tue, 10 Nov 2020 12:58:15 +0100 Subject: [PATCH 19/61] fix(useKeyPress): reset key when window loses focus #641 --- src/hooks/useKeyPress.ts | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hooks/useKeyPress.ts b/src/hooks/useKeyPress.ts index 4fec31f2..6fb340fa 100644 --- a/src/hooks/useKeyPress.ts +++ b/src/hooks/useKeyPress.ts @@ -17,13 +17,19 @@ export default (keyCode: number): boolean => { } }; + const resetHandler = () => { + setKeyPressed(false); + }; + useEffect(() => { window.addEventListener('keydown', downHandler); window.addEventListener('keyup', upHandler); + window.addEventListener('blur', resetHandler); return () => { window.removeEventListener('keydown', downHandler); window.removeEventListener('keyup', upHandler); + window.removeEventListener('blur', resetHandler); }; }, []); From 7cd0d4e5634bc4e282fdd64c0783b90132ecd81b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Tue, 10 Nov 2020 13:01:39 +0100 Subject: [PATCH 20/61] change release:next npm task --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e49deab9..f597600c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "test:all": "npm run test:chrome && npm run test:firefox", "test": "npm run dev:wait test:chrome", "release": "npm run test && release-it", - "release:next": "release-it major --preRelease=next" + "release:next": "release-it --preRelease=next" }, "dependencies": { "@babel/runtime": "^7.12.5", From 965fb2a212fdf3f90cebeb6ad7eecad46c9c8def Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christopher=20Mo=CC=88ller?= Date: Tue, 10 Nov 2020 13:03:10 +0100 Subject: [PATCH 21/61] chore: release v8.0.0-next.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4ca33336..190ccc0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "8.0.0-next.0", + "version": "8.0.0-next.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f597600c..f2cb51e1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "8.0.0-next.0", + "version": "8.0.0-next.1", "main": "dist/ReactFlow.js", "module": "dist/ReactFlow.esm.js", "types": "dist/index.d.ts", From 959216f6fcff68166f865280b19ac225853510b5 Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 10 Nov 2020 14:27:15 +0100 Subject: [PATCH 22/61] refactor(keycodes): allow strings and numbers as key codes --- src/container/GraphView/index.tsx | 8 +++---- src/container/ReactFlow/index.tsx | 13 ++++++----- src/hooks/useGlobalKeyHandler.ts | 6 ++--- src/hooks/useKeyPress.ts | 37 ++++++++++++++++--------------- src/types/index.ts | 2 ++ 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 2c870ab3..1efff10c 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -9,14 +9,14 @@ import useZoomPanHelper from '../../hooks/useZoomPanHelper'; import { ReactFlowProps } from '../ReactFlow'; -import { NodeTypesType, EdgeTypesType, ConnectionLineType } from '../../types'; +import { NodeTypesType, EdgeTypesType, ConnectionLineType, KeyCode } from '../../types'; export interface GraphViewProps extends Omit { nodeTypes: NodeTypesType; edgeTypes: EdgeTypesType; - selectionKeyCode: number; - deleteKeyCode: number; - multiSelectionKeyCode: number; + selectionKeyCode: KeyCode; + deleteKeyCode: KeyCode; + multiSelectionKeyCode: KeyCode; connectionLineType: ConnectionLineType; snapToGrid: boolean; snapGrid: [number, number]; diff --git a/src/container/ReactFlow/index.tsx b/src/container/ReactFlow/index.tsx index 8a4860b5..a4f47765 100644 --- a/src/container/ReactFlow/index.tsx +++ b/src/container/ReactFlow/index.tsx @@ -33,6 +33,7 @@ import { OnConnectStopFunc, OnConnectEndFunc, TranslateExtent, + KeyCode, } from '../../types'; import '../../style.css'; @@ -81,9 +82,9 @@ export interface ReactFlowProps extends Omit, 'on connectionLineType?: ConnectionLineType; connectionLineStyle?: CSSProperties; connectionLineComponent?: ConnectionLineComponent; - deleteKeyCode?: number; - selectionKeyCode?: number; - multiSelectionKeyCode?: number; + deleteKeyCode?: KeyCode; + selectionKeyCode?: KeyCode; + multiSelectionKeyCode?: KeyCode; snapToGrid?: boolean; snapGrid?: [number, number]; onlyRenderVisibleNodes?: boolean; @@ -134,9 +135,9 @@ const ReactFlow = ({ connectionLineType = ConnectionLineType.Bezier, connectionLineStyle, connectionLineComponent, - deleteKeyCode = 8, - selectionKeyCode = 16, - multiSelectionKeyCode = 91, + deleteKeyCode = 'Backspace', + selectionKeyCode = 'Shift', + multiSelectionKeyCode = 'Meta', snapToGrid = false, snapGrid = [15, 15], onlyRenderVisibleNodes = true, diff --git a/src/hooks/useGlobalKeyHandler.ts b/src/hooks/useGlobalKeyHandler.ts index 1a719f4c..d7e392a6 100644 --- a/src/hooks/useGlobalKeyHandler.ts +++ b/src/hooks/useGlobalKeyHandler.ts @@ -3,11 +3,11 @@ import { useEffect } from 'react'; import { useStore, useStoreActions } from '../store/hooks'; import useKeyPress from './useKeyPress'; import { isNode, getConnectedEdges } from '../utils/graph'; -import { Elements } from '../types'; +import { Elements, KeyCode } from '../types'; interface HookParams { - deleteKeyCode: number; - multiSelectionKeyCode: number; + deleteKeyCode: KeyCode; + multiSelectionKeyCode: KeyCode; onElementsRemove?: (elements: Elements) => void; } diff --git a/src/hooks/useKeyPress.ts b/src/hooks/useKeyPress.ts index 6fb340fa..80685137 100644 --- a/src/hooks/useKeyPress.ts +++ b/src/hooks/useKeyPress.ts @@ -1,27 +1,28 @@ import { useState, useEffect } from 'react'; import { isInputDOMNode } from '../utils'; +import { KeyCode } from '../types'; -export default (keyCode: number): boolean => { +export default (keyCode: KeyCode): boolean => { const [keyPressed, setKeyPressed] = useState(false); - function downHandler(event: KeyboardEvent) { - if (event.keyCode === keyCode && !isInputDOMNode(event)) { - setKeyPressed(true); - } - } - - const upHandler = (event: KeyboardEvent) => { - if (event.keyCode === keyCode && !isInputDOMNode(event)) { - setKeyPressed(false); - } - }; - - const resetHandler = () => { - setKeyPressed(false); - }; - useEffect(() => { + const downHandler = (event: KeyboardEvent) => { + if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { + event.preventDefault(); + + setKeyPressed(true); + } + }; + + const upHandler = (event: KeyboardEvent) => { + if (!isInputDOMNode(event) && (event.key === keyCode || event.keyCode === keyCode)) { + setKeyPressed(false); + } + }; + + const resetHandler = () => setKeyPressed(false); + window.addEventListener('keydown', downHandler); window.addEventListener('keyup', upHandler); window.addEventListener('blur', resetHandler); @@ -31,7 +32,7 @@ export default (keyCode: number): boolean => { window.removeEventListener('keyup', upHandler); window.removeEventListener('blur', resetHandler); }; - }, []); + }, [keyCode, setKeyPressed]); return keyPressed; }; diff --git a/src/types/index.ts b/src/types/index.ts index d912f2bc..d0aba74a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -329,3 +329,5 @@ export type FlowTransform = { }; export type TranslateExtent = [[number, number], [number, number]]; + +export type KeyCode = number | string; From 5e28762f53eba2f4f28271c014856b7357e414ea Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 10 Nov 2020 17:06:18 +0100 Subject: [PATCH 23/61] refactor(nodes): don't re-render on pan #677 --- src/components/Nodes/wrapNode.tsx | 4 ++-- src/container/NodeRenderer/index.tsx | 8 ++++---- src/types/index.ts | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index 5e69704b..4e8bfba6 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -12,7 +12,7 @@ export default (NodeComponent: ComponentType) => { id, type, data, - transform, + scale, xPos, yPos, selected, @@ -199,7 +199,7 @@ export default (NodeComponent: ComponentType) => { onStart={onDragStart} onDrag={onDrag} onStop={onDragStop} - scale={transform[2]} + scale={scale} disabled={!isDraggable} cancel=".nodrag" nodeRef={nodeElement} diff --git a/src/container/NodeRenderer/index.tsx b/src/container/NodeRenderer/index.tsx index 66125c1d..8faf9cb6 100644 --- a/src/container/NodeRenderer/index.tsx +++ b/src/container/NodeRenderer/index.tsx @@ -2,7 +2,7 @@ import React, { memo, ComponentType, MouseEvent } from 'react'; import { useStoreState } from '../../store/hooks'; import { getNodesInside } from '../../utils/graph'; -import { Node, Transform, NodeTypesType, WrapNodeProps, Elements, Edge } from '../../types'; +import { Node, NodeTypesType, WrapNodeProps, Elements, Edge } from '../../types'; interface NodeRendererProps { nodeTypes: NodeTypesType; @@ -22,7 +22,7 @@ interface NodeRendererProps { function renderNode( node: Node, props: NodeRendererProps, - transform: Transform, + scale: number, selectedElements: Elements | null, nodesDraggable: boolean, nodesConnectable: boolean, @@ -57,7 +57,7 @@ function renderNode( onContextMenu={props.onNodeContextMenu} onNodeDragStart={props.onNodeDragStart} onNodeDragStop={props.onNodeDragStop} - transform={transform} + scale={scale} selected={isSelected} style={node.style} className={node.className} @@ -93,7 +93,7 @@ const NodeRenderer = (props: NodeRendererProps) => { return (
{renderNodes.map((node) => - renderNode(node, props, transform, selectedElements, nodesDraggable, nodesConnectable, elementsSelectable) + renderNode(node, props, transform[2], selectedElements, nodesDraggable, nodesConnectable, elementsSelectable) )}
); diff --git a/src/types/index.ts b/src/types/index.ts index d0aba74a..9f428d2f 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -201,7 +201,7 @@ export interface WrapNodeProps { type: string; data: any; selected: boolean; - transform: Transform; + scale: number; xPos: number; yPos: number; isSelectable: boolean; From 8bba855a1721c13fe13e8ecd052f91cb1061a5d3 Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 10 Nov 2020 17:06:58 +0100 Subject: [PATCH 24/61] 8.0.0-next.2 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 190ccc0a..6262176a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "8.0.0-next.1", + "version": "8.0.0-next.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index f2cb51e1..102687af 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-flow-renderer", - "version": "8.0.0-next.1", + "version": "8.0.0-next.2", "main": "dist/ReactFlow.js", "module": "dist/ReactFlow.esm.js", "types": "dist/index.d.ts", From ae6ce3cd0583bd18d59bd677020d7e82d0e1a59e Mon Sep 17 00:00:00 2001 From: moklick Date: Tue, 10 Nov 2020 17:56:19 +0100 Subject: [PATCH 25/61] feat(panOnScroll): add mode options free, vertical and horizontal --- example/src/Interaction/index.js | 20 +++++++++++++++++++- src/container/FlowRenderer/index.tsx | 2 ++ src/container/GraphView/index.tsx | 2 ++ src/container/ReactFlow/index.tsx | 4 ++++ src/container/ZoomPane/index.tsx | 10 ++++++---- src/types/index.ts | 6 ++++++ 6 files changed, 39 insertions(+), 5 deletions(-) diff --git a/example/src/Interaction/index.js b/example/src/Interaction/index.js index 39e83887..c60589ff 100644 --- a/example/src/Interaction/index.js +++ b/example/src/Interaction/index.js @@ -17,6 +17,7 @@ const onElementClick = (event, element) => console.log('click', element); const onPaneClick = (event) => console.log('onPaneClick', event); const onPaneScroll = (event) => console.log('onPaneScroll', event); const onPaneContextMenu = (event) => console.log('onPaneContextMenu', event); +const onMoveEnd = (event) => console.log('onMoveEnd', event); const InteractionFlow = () => { const [elements, setElements] = useState(initialElements); @@ -27,6 +28,7 @@ const InteractionFlow = () => { const [isConnectable, setIsConnectable] = useState(false); const [zoomOnScroll, setZoomOnScroll] = useState(false); const [panOnScroll, setPanOnScroll] = useState(false); + const [panOnScrollMode, setPanOnScrollMode] = useState('free'); const [zoomOnDoubleClick, setZoomOnDoubleClick] = useState(false); const [paneMoveable, setPaneMoveable] = useState(true); const [captureZoomClick, setCaptureZoomClick] = useState(false); @@ -41,6 +43,7 @@ const InteractionFlow = () => { nodesDraggable={isDraggable} zoomOnScroll={zoomOnScroll} panOnScroll={panOnScroll} + panOnScrollMode={panOnScrollMode} zoomOnDoubleClick={zoomOnDoubleClick} onConnect={onConnect} onElementClick={captureElementClick ? onElementClick : undefined} @@ -50,7 +53,7 @@ const InteractionFlow = () => { onPaneClick={captureZoomClick ? onPaneClick : undefined} onPaneScroll={captureZoomScroll ? onPaneScroll : undefined} onPaneContextMenu={captureZoomClick ? onPaneContextMenu : undefined} - onMoveEnd={(evt) => console.log('on move end', evt)} + onMoveEnd={onMoveEnd} > @@ -116,6 +119,21 @@ const InteractionFlow = () => { />
+
+ +