From c9afbcdfbd3f96294154567c12f3c13624d8d657 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:08:55 +0000 Subject: [PATCH 1/8] chore(deps-dev): bump rollup-plugin-terser from 7.0.1 to 7.0.2 Bumps [rollup-plugin-terser](https://github.com/TrySound/rollup-plugin-terser) from 7.0.1 to 7.0.2. - [Release notes](https://github.com/TrySound/rollup-plugin-terser/releases) - [Commits](https://github.com/TrySound/rollup-plugin-terser/compare/v7.0.1...v7.0.2) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 12 ++++++------ package.json | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package-lock.json b/package-lock.json index 354cae18..a41f8262 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11640,9 +11640,9 @@ } }, "rollup-plugin-terser": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.1.tgz", - "integrity": "sha512-HL0dgzSxBYG/Ly9i/E5Sc+PuKKZ0zBzk11VmLCfdUtpqH4yYqkLclPkTqRy85FU9246yetImOClaQ/ufnj08vg==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-7.0.2.tgz", + "integrity": "sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", @@ -12257,9 +12257,9 @@ "dev": true }, "terser": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.2.1.tgz", - "integrity": "sha512-/AOtjRtAMNGO0fIF6m8HfcvXTw/2AKpsOzDn36tA5RfhRdeXyb4RvHxJ5Pah7iL6dFkLk+gOnCaNHGwJPl6TrQ==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.3.0.tgz", + "integrity": "sha512-XTT3D3AwxC54KywJijmY2mxZ8nJiEjBHVYzq8l9OaYuRFWeQNBwvipuzzYEP4e+/AVcd1hqG/CqgsdIRyT45Fg==", "dev": true, "requires": { "commander": "^2.20.0", diff --git a/package.json b/package.json index 7ec040b5..de1d7494 100644 --- a/package.json +++ b/package.json @@ -62,7 +62,7 @@ "rollup-plugin-postcss": "^3.1.8", "rollup-plugin-replace": "^2.2.0", "rollup-plugin-serve": "^1.0.4", - "rollup-plugin-terser": "^7.0.1", + "rollup-plugin-terser": "^7.0.2", "rollup-plugin-typescript2": "^0.27.2", "rollup-plugin-uglify": "^6.0.4", "start-server-and-test": "^1.11.3", From d66694e2bc99f8a9c5c852962b81db4457f1ec9d Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:09:59 +0000 Subject: [PATCH 2/8] chore(deps-dev): bump @babel/core from 7.11.5 to 7.11.6 Bumps [@babel/core](https://github.com/babel/babel/tree/HEAD/packages/babel-core) from 7.11.5 to 7.11.6. - [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.11.6/packages/babel-core) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 27 ++++++++++++++++----------- package.json | 2 +- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index 354cae18..799c9c2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -63,13 +63,13 @@ } }, "@babel/core": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.5.tgz", - "integrity": "sha512-fsEANVOcZHzrsV6dMVWqpSeXClq3lNbYrfFGme6DE25FQWe7pyeYpXyx9guqUnpy466JLzZ8z4uwSr2iv60V5Q==", + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", + "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", "dev": true, "requires": { "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", + "@babel/generator": "^7.11.6", "@babel/helper-module-transforms": "^7.11.0", "@babel/helpers": "^7.10.4", "@babel/parser": "^7.11.5", @@ -83,7 +83,7 @@ "lodash": "^4.17.19", "resolve": "^1.3.2", "semver": "^5.4.1", - "source-map": "^0.6.1" + "source-map": "^0.5.0" }, "dependencies": { "@babel/code-frame": { @@ -95,6 +95,17 @@ "@babel/highlight": "^7.10.4" } }, + "@babel/generator": { + "version": "7.11.6", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", + "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", + "dev": true, + "requires": { + "@babel/types": "^7.11.5", + "jsesc": "^2.5.1", + "source-map": "^0.5.0" + } + }, "@babel/helper-member-expression-to-functions": { "version": "7.11.0", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", @@ -212,12 +223,6 @@ "lodash": "^4.17.19", "to-fast-properties": "^2.0.0" } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true } } }, diff --git a/package.json b/package.json index 7ec040b5..bc6a489e 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "resize-observer": "^1.0.0" }, "devDependencies": { - "@babel/core": "^7.11.5", + "@babel/core": "^7.11.6", "@babel/preset-env": "^7.11.5", "@babel/preset-react": "^7.10.4", "@svgr/rollup": "^5.4.0", From 2505ef0879cf35ce404a874e1b6e2ea485280f25 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:15:42 +0000 Subject: [PATCH 3/8] chore(deps-dev): bump rollup from 2.26.9 to 2.26.10 Bumps [rollup](https://github.com/rollup/rollup) from 2.26.9 to 2.26.10. - [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.26.9...v2.26.10) 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 a41f8262..10324321 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11377,9 +11377,9 @@ } }, "rollup": { - "version": "2.26.9", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.9.tgz", - "integrity": "sha512-XIiWYLayLqV+oY4S2Lub/shJq4uk/QQLwWToYCL4LjZbYHbFK3czea4UDVRUJu+zNmKmxq5Zb/OG7c5HSvH2TQ==", + "version": "2.26.10", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.26.10.tgz", + "integrity": "sha512-dUnjCWOA0h9qNX6qtcHidyatz8FAFZxVxt1dbcGtKdlJkpSxGK3G9+DLCYvtZr9v94D129ij9zUhG+xbRoqepw==", "dev": true, "requires": { "fsevents": "~2.1.2" diff --git a/package.json b/package.json index de1d7494..9f378048 100644 --- a/package.json +++ b/package.json @@ -52,7 +52,7 @@ "prop-types": "^15.7.2", "react": "^16.13.1", "release-it": "^13.7.1", - "rollup": "^2.26.9", + "rollup": "^2.26.10", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-bundle-size": "^1.0.3", "rollup-plugin-commonjs": "^10.1.0", From 9bff0a04db682f54f142dc294d23a7a13acec805 Mon Sep 17 00:00:00 2001 From: "dependabot-preview[bot]" <27856297+dependabot-preview[bot]@users.noreply.github.com> Date: Mon, 7 Sep 2020 05:28:44 +0000 Subject: [PATCH 4/8] chore(deps-dev): bump release-it from 13.7.1 to 14.0.2 Bumps [release-it](https://github.com/release-it/release-it) from 13.7.1 to 14.0.2. - [Release notes](https://github.com/release-it/release-it/releases) - [Changelog](https://github.com/release-it/release-it/blob/master/CHANGELOG.md) - [Commits](https://github.com/release-it/release-it/compare/13.7.1...14.0.2) Signed-off-by: dependabot-preview[bot] --- package-lock.json | 139 ++++------------------------------------------ package.json | 2 +- 2 files changed, 13 insertions(+), 128 deletions(-) diff --git a/package-lock.json b/package-lock.json index e9d3600f..273f8fef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4149,9 +4149,9 @@ } }, "@octokit/plugin-paginate-rest": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.3.1.tgz", - "integrity": "sha512-81A+ONLpcSX7vWxnEmVZteQPNsbdeScSVUqjgMYPSk1trzG69iYkhS42wPRWtN0nYw6OEmT48DNeQCjHeyroYw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.3.2.tgz", + "integrity": "sha512-PjHbMhKryxClCrmfvRpGaKCTxUcHIf2zirWRV9SMGf0EmxD/rFew/abSqbMiLl9uQgRZvqtTyCRMGMlUv1ZsBg==", "dev": true, "requires": { "@octokit/types": "^5.3.0" @@ -6109,12 +6109,6 @@ "supports-color": "^5.3.0" } }, - "changelog-filename-regex": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/changelog-filename-regex/-/changelog-filename-regex-1.1.2.tgz", - "integrity": "sha512-kpOfKlZ9x2UpeC4at6FAXHLKfi/JEUqUqkPCb1JUCa5FnNbJIzOHRM9RfeQ1QDcpj+Gxuc/UoHqASgmEeFDejQ==", - "dev": true - }, "chardet": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", @@ -7123,15 +7117,6 @@ "object-keys": "^1.0.12" } }, - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -7162,26 +7147,6 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, - "detect-repo-changelog": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/detect-repo-changelog/-/detect-repo-changelog-1.0.1.tgz", - "integrity": "sha1-whCMu/CWTae8B0ZFtq0dO4CmvW0=", - "dev": true, - "requires": { - "changelog-filename-regex": "^1.1.0", - "is-regular-file": "^1.0.1", - "lodash.find": "^4.6.0", - "pify": "^2.3.0" - }, - "dependencies": { - "pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", - "dev": true - } - } - }, "dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -8316,9 +8281,9 @@ } }, "rxjs": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.2.tgz", - "integrity": "sha512-BHdBMVoWC2sL26w//BCu3YzKT4s2jip/WhwsGEDmeKYBhKDZeYezVUnHatYB7L85v5xs0BAQmg6BEYJEKxBabg==", + "version": "6.6.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.3.tgz", + "integrity": "sha512-trsQc+xYYXZ3urjOiJOuCOa5N3jAZ3eiSpQB5hIT8zGlL2QfnHLJ2r7GMkBGuIausdJN1OneaI6gQlsqNHHmZQ==", "dev": true, "requires": { "tslib": "^1.9.0" @@ -8365,15 +8330,6 @@ "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY=", "dev": true }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, "is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", @@ -8424,32 +8380,12 @@ "rgba-regex": "^1.0.0" } }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "requires": { - "kind-of": "^6.0.0" - } - }, "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", "dev": true }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - }, "is-directory": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", @@ -8571,12 +8507,6 @@ "has": "^1.0.3" } }, - "is-regular-file": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regular-file/-/is-regular-file-1.1.1.tgz", - "integrity": "sha512-+1U3MZrVwC4HM6VUKk3L5fiHtNd2d9kayzEJhmQ+B+uIBPE/p8Fy8QVdkx0HIr3o9J5TOKJY40eI5GfTfBqbdA==", - "dev": true - }, "is-resolvable": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", @@ -8796,12 +8726,6 @@ "json-buffer": "3.0.1" } }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, "latest-version": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/latest-version/-/latest-version-5.1.0.tgz", @@ -9044,12 +8968,6 @@ "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=", "dev": true }, - "lodash.find": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.find/-/lodash.find-4.6.0.tgz", - "integrity": "sha1-ywcE1Hq3F4n/oN6Ll92Sb7iLE7E=", - "dev": true - }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -9423,9 +9341,9 @@ "dev": true }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==", + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", "dev": true }, "node-releases": { @@ -11107,9 +11025,9 @@ } }, "release-it": { - "version": "13.7.1", - "resolved": "https://registry.npmjs.org/release-it/-/release-it-13.7.1.tgz", - "integrity": "sha512-OAupGLMZJBGrGRJmb8RvZ8ZQAQquKlkGGYvgRrJmkHE+jnGdf+YSvEmItBv08CwhDcwCyXdTkkN/rJ2Flt68+g==", + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/release-it/-/release-it-14.0.2.tgz", + "integrity": "sha512-YJEI8z/cl0gXuVN3a4n/oZ9LYjR9tzEiuUbUROMKG172tzrIDPILT48CR3PQ0fpTGqGimraNFCZrTFiZWqP4pA==", "dev": true, "requires": { "@iarna/toml": "2.2.5", @@ -11119,7 +11037,6 @@ "cosmiconfig": "7.0.0", "debug": "4.1.1", "deprecated-obj": "2.0.0", - "detect-repo-changelog": "1.0.1", "execa": "4.0.3", "find-up": "5.0.0", "form-data": "3.0.0", @@ -11136,11 +11053,9 @@ "parse-json": "5.1.0", "semver": "7.3.2", "shelljs": "0.8.4", - "supports-color": "7.2.0", "update-notifier": "4.1.1", "url-join": "4.0.1", "uuid": "8.3.0", - "window-size": "1.1.1", "yaml": "1.10.0", "yargs-parser": "19.0.4" }, @@ -12692,36 +12607,6 @@ "string-width": "^4.0.0" } }, - "window-size": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/window-size/-/window-size-1.1.1.tgz", - "integrity": "sha512-5D/9vujkmVQ7pSmc0SCBmHXbkv6eaHwXEx65MywhmUMsI8sGqJ972APq1lotfcwMKPFLuCFfL8xGHLIp7jaBmA==", - "dev": true, - "requires": { - "define-property": "^1.0.0", - "is-number": "^3.0.0" - }, - "dependencies": { - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "^3.0.2" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, "windows-release": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/windows-release/-/windows-release-4.0.0.tgz", diff --git a/package.json b/package.json index d3590183..6530422e 100644 --- a/package.json +++ b/package.json @@ -51,7 +51,7 @@ "prettier": "2.1.1", "prop-types": "^15.7.2", "react": "^16.13.1", - "release-it": "^13.7.1", + "release-it": "^14.0.2", "rollup": "^2.26.10", "rollup-plugin-babel": "^4.4.0", "rollup-plugin-bundle-size": "^1.0.3", From ae91e84f67f3c6189386dd507729a077eee3c950 Mon Sep 17 00:00:00 2001 From: moklick Date: Mon, 7 Sep 2020 12:35:36 +0200 Subject: [PATCH 5/8] docs(readme): cleanup --- README.md | 55 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 29 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 2f3f6e7f..aa541672 100644 --- a/README.md +++ b/README.md @@ -31,10 +31,10 @@ React Flow is a library for building node-based graphs. You can easily implement ## Key Features * **Easy to use:** Seamless zooming & panning behaviour and single and multi-selections of elements -* **Customizable:** Different [node](#node-types--custom-nodes) and [edge types](#edge-types--custom-edges) and support for custom nodes with multiple handles and edges +* **Customizable:** Different [node](#node-types--custom-nodes) and [edge types](#edge-types--custom-edges) and support for custom nodes with multiple handles and custom edges * **Fast rendering:** Only nodes that have changed are re-rendered and only those that are in the viewport are displayed -* **Utils:** Snap-to-grid, background styles and graph [helper functions](#helper-functions) -* **Components:** [Background, Minimap and graph controls](#components) +* **Utils:** Snap-to-grid and graph [helper functions](#helper-functions) +* **Components:** [Background, Minimap and Controls](#components) * **Reliable**: Written in [Typescript](https://www.typescriptlang.org/) and tested with [cypress](https://www.cypress.io/) In order to make this library as flexible as possible we don’t do any state updates besides the positions. This means that you need to pass the functions to remove an element or connect nodes by yourself. You can implement your own ones or use the helper functions that come with the library. @@ -80,7 +80,7 @@ const BasicFlow = () => ; - `onlyRenderVisibleNodes`: default: `true` #### Event Handlers -- `onElementClick(event: MouseEvent, element: Node | Edge)`: called when user clicks node or edge click +- `onElementClick(event: MouseEvent, element: Node | Edge)`: called when user clicks node or edge - `onElementsRemove(elements: Elements)`: called when user removes node or edge - `onNodeDragStart(event: MouseEvent, node: Node)`: node drag start - `onNodeDragStop(event: MouseEvent, node: Node)`: node drag stop @@ -93,21 +93,21 @@ const BasicFlow = () => ; - `onConnectStop(event: MouseEvent)`: called when user stops to drag connection line - `onConnectEnd(event: MouseEvent)`: called after user stops or connects nodes - `onLoad(reactFlowInstance)`: called after flow is initialized -- `onMove()`: called when user is panning or zooming -- `onMoveStart()`: called when user starts panning or zooming -- `onMoveEnd()`: called when user ends panning or zooming +- `onMove(flowTransform: FlowTransform)`: called when user is panning or zooming +- `onMoveStart(flowTransform: FlowTransform)`: called when user starts panning or zooming +- `onMoveEnd(flowTransform: FlowTransform)`: called when user ends panning or zooming - `onSelectionChange(elements: Elements)`: called when user selects one or multiple elements - `onSelectionDragStart(evt: MouseEvent, nodes: Node[])`: called when user starts to drag a selection - `onSelectionDrag(evt: MouseEvent, nodes: Node[])`: called when user drags a selection - `onSelectionDragStop(evt: MouseEvent, nodes: Node[])`: called when user stops to drag a selection - `onPaneClick(event: MouseEvent)`: called when user clicks directly on the canvas - `onPaneContextMenu(event: MouseEvent)`: called when user does a right-click on the canvas -- `onPaneScroll(event: WheelEvent)`: called when user scrolls pane (only works when `zoomOnScroll` is set to `false) +- `onPaneScroll(event: WheelEvent)`: called when user scrolls pane (only works when `zoomOnScroll` is set to `false) #### Interaction -- `nodesDraggable`: default: `true`. This applies to all nodes. You can also change the behavior of a specific node with the `draggable` node option. -- `nodesConnectable`: default: `true`. This applies to all nodes. You can also change the behavior of a specific node with the `connectable` node option. -- `elementsSelectable`: default: `true`. This applies to all elements. You can also change the behavior of a specific node with the `selectable` node option. +- `nodesDraggable`: default: `true`. This applies to all nodes. You can also change the behavior of a specific node with the `draggable` node option +- `nodesConnectable`: default: `true`. This applies to all nodes. You can also change the behavior of a specific node with the `connectable` node option +- `elementsSelectable`: default: `true`. This applies to all elements. You can also change the behavior of a specific node with the `selectable` node option - `zoomOnScroll`: default: `true` - `zoomOnDoubleClick`: default: `true` - `selectNodesOnDrag`: default: `true` @@ -145,13 +145,14 @@ const BasicFlow = () => ; ### project -Transforms pixel coordinates to the internal React Flow coordinate system +Transforms pixel coordinates to the internal ReactFlow coordinate system. +This can be used when you drag nodes (from a side bar for example) and need the position on the pane. `project = (position: XYPosition): XYPosition` ### fitView -Fits view port so that all nodes are visible +Fits view port so that all nodes are inside the view port. `fitView = ({ padding }): void` @@ -173,7 +174,7 @@ Fits view port so that all nodes are visible ### setTransform -Sets position and zoom of the pane +Sets position and zoom of the pane. `setTransform = (transform: FlowTransform): void` @@ -194,9 +195,9 @@ Node example: `{ id: '1', type: 'input', data: { label: 'Node 1' }, position: { - `targetPosition`: 'left' | 'right' | 'top' | 'bottom' handle position - default: 'top' - `sourcePosition`: 'left' | 'right' | 'top' | 'bottom' handle position - default: 'bottom' - `isHidden`: if `true`, the node will not be rendered -- `draggable`: boolean - if option is not set, the node is draggable (overwrites generel `nodesDraggable` option) -- `connectable`: boolean - if option is not set, the node is connectable (overwrites generel `nodesConnectable` option) -- `selectable`: boolean - if option is not set, the node is selectable (overwrites generel `elementsSelectable` option) +- `draggable`: boolean - if option is not set, the node is draggable (overwrites general `nodesDraggable` option) +- `connectable`: boolean - if option is not set, the node is connectable (overwrites general `nodesConnectable` option) +- `selectable`: boolean - if option is not set, the node is selectable (overwrites general `elementsSelectable` option) ## Node Types & Custom Nodes @@ -236,7 +237,7 @@ Your custom nodes are wrapped so that the basic functions like dragging or selec ### Prevent dragging -If you have controls inside your custom node that should not drag the node you can add the class name `nodrag`. +If you have controls or other elements inside your custom node that should not drag the node you can add the class name `nodrag`. ## Handle Component @@ -531,10 +532,12 @@ The React Flow wrapper has the className `react-flow`. If you want to change the You could achieve the same effect by passing a style prop to the `ReactFlow` component: ```javascript +const style = { background: 'red', width: '100%' height: '300px' }; + const FlowWithRedBg = ( ); ``` @@ -549,37 +552,37 @@ import ReactFlow, { isNode, isEdge, removeElements, addEdge } from 'react-flow-r ### isEdge -Returns true if element is an edge +Returns `true` if the passed element is an edge. `isEdge = (element: Node | Edge): element is Edge` ### isNode -Returns true if element is a node +Returns `true` if the passed element is a node. `isNode = (element: Node | Edge): element is Node` ### removeElements -Returns an array of elements without the ones from `elementsToRemove`. It also removes all incoming/outgoing edges if you just pass one or multiple nodes +Returns an array of elements without the ones from `elementsToRemove`. It also removes all incoming/outgoing edges if you just pass one or multiple nodes. `removeElements = (elementsToRemove: Elements, elements: Elements): Elements` ### addEdge -Returns elements array with added edge +Returns an array with elements with the added edge. `addEdge = (edgeParams: Edge, elements: Elements): Elements` ### getOutgoers -Returns all direct child nodes of the passed node +Returns all direct child nodes of the passed node. `getOutgoers = (node: Node, elements: Elements): Node[]` ### getConnectedEdges -Returns all edges that are connected to the passed nodes +Returns all edges that are connected to the passed nodes. `getConnectedEdges = (nodes: Node[], edges: Edge[]): Edge[]` @@ -657,7 +660,7 @@ This serves the content of the `example` folder and watches changes inside the ` # Testing -Testing is done with cypress. You can find all tests in the [`integration/flow`](/cypress/integration/flow) folder. In order to run the tests do: +Testing is done with cypress. You can find the tests in the [`integration/flow`](/cypress/integration/flow) folder. In order to run the tests do: ``` npm run test From 0cc95266303c68b67a43a27fb7dcd957c04e84c0 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 10 Sep 2020 17:56:36 +0200 Subject: [PATCH 6/8] refactor(wrapNode): clean up event handlers closes #482 --- src/components/Nodes/wrapNode.tsx | 312 ++++++++++-------------------- src/utils/index.ts | 2 - 2 files changed, 107 insertions(+), 207 deletions(-) diff --git a/src/components/Nodes/wrapNode.tsx b/src/components/Nodes/wrapNode.tsx index c43a3c6a..54be5214 100644 --- a/src/components/Nodes/wrapNode.tsx +++ b/src/components/Nodes/wrapNode.tsx @@ -16,151 +16,11 @@ import { ResizeObserver } from 'resize-observer'; import { useStoreActions } from '../../store/hooks'; import { Provider } from '../../contexts/NodeIdContext'; -import { - Node, - XYPosition, - Transform, - ElementId, - NodeComponentProps, - WrapNodeProps, - Elements, - Edge, - NodePosUpdate, -} from '../../types'; - -import { noop } from '../../utils'; +import { Node, NodeComponentProps, WrapNodeProps } from '../../types'; const getMouseEvent = (event: MouseEvent | TouchEvent) => typeof TouchEvent !== 'undefined' && event instanceof TouchEvent ? event.touches[0] : (event as MouseEvent); -interface OnDragStartParams { - event: MouseEvent | TouchEvent; - id: ElementId; - type: string; - data: any; - selectNodesOnDrag: boolean; - isSelectable: boolean; - setOffset: (pos: XYPosition) => void; - transform: Transform; - position: XYPosition; - setSelectedElements: (elms: Elements | Node | Edge) => void; - onNodeDragStart?: (event: MouseEvent, node: Node) => void; -} - -const onStart = ({ - event, - onNodeDragStart, - id, - type, - data, - selectNodesOnDrag, - setOffset, - transform, - position, - setSelectedElements, - isSelectable, -}: OnDragStartParams): false | void => { - const startEvent = getMouseEvent(event); - - const scaledClient: XYPosition = { - x: startEvent.clientX * (1 / transform[2]), - y: startEvent.clientY * (1 / transform[2]), - }; - - const offsetX = scaledClient.x - position.x - transform[0]; - const offsetY = scaledClient.y - position.y - transform[1]; - const node = { id, type, position, data }; - - setOffset({ x: offsetX, y: offsetY }); - - if (onNodeDragStart) { - onNodeDragStart(event as MouseEvent, node); - } - - if (selectNodesOnDrag && isSelectable) { - setSelectedElements({ id, type } as Node); - } -}; - -interface OnDragParams { - event: MouseEvent | TouchEvent; - setDragging: (isDragging: boolean) => void; - id: ElementId; - offset: XYPosition; - transform: Transform; - updateNodePos: (params: NodePosUpdate) => void; -} - -const onDrag = ({ event, setDragging, id, offset, transform, updateNodePos }: OnDragParams): void => { - const dragEvent = getMouseEvent(event); - - const scaledClient = { - x: dragEvent.clientX / transform[2], - y: dragEvent.clientY / transform[2], - }; - - setDragging(true); - updateNodePos({ - id, - pos: { - x: scaledClient.x - transform[0] - offset.x, - y: scaledClient.y - transform[1] - offset.y, - }, - }); -}; - -interface OnDragStopParams { - event: MouseEvent; - isDragging: boolean; - setDragging: (isDragging: boolean) => void; - id: ElementId; - type: string; - position: XYPosition; - data: any; - selectNodesOnDrag: boolean; - isSelectable: boolean; - setSelectedElements: (elms: Elements | Node | Edge) => void; - onNodeDragStop?: (event: MouseEvent, node: Node) => void; - onClick?: (event: MouseEvent, node: Node) => void; -} - -const onStop = ({ - event, - id, - type, - position, - data, - isDragging, - setDragging, - selectNodesOnDrag, - isSelectable, - onNodeDragStop, - onClick, - setSelectedElements, -}: OnDragStopParams): void => { - const node = { - id, - type, - position, - data, - } as Node; - if (!isDragging && isSelectable) { - if (!selectNodesOnDrag) { - setSelectedElements({ id, type } as Node); - } - - if (onClick) { - return onClick(event, node); - } - } - - setDragging(false); - - if (onNodeDragStop) { - onNodeDragStop(event, node); - } -}; - export default (NodeComponent: ComponentType) => { const NodeWrapper = ({ id, @@ -195,60 +55,129 @@ export default (NodeComponent: ComponentType) => { const nodeElement = useRef(null); const [offset, setOffset] = useState({ x: 0, y: 0 }); const [isDragging, setDragging] = useState(false); - const position = { x: xPos, y: yPos }; - const nodeClasses = cc([ - 'react-flow__node', - `react-flow__node-${type}`, - className, - { - selected, - selectable: isSelectable, - }, - ]); - const node = { id, type, position, data }; + + const position = useMemo(() => ({ x: xPos, y: yPos }), [xPos, yPos]); + const node = useMemo(() => ({ id, type, position, data }), [id, type, position, data]); + const nodeStyle: CSSProperties = useMemo( + () => ({ + zIndex: selected ? 10 : 3, + transform: `translate(${xPos}px,${yPos}px)`, + pointerEvents: isSelectable || isDraggable || onClick ? 'all' : 'none', + opacity: isInitialized ? 1 : 0, // prevents jumping of nodes on start + ...style, + }), + [selected, xPos, yPos, isSelectable, isDraggable, onClick, isInitialized, style] + ); const onMouseEnterHandler = useMemo(() => { if (!onMouseEnter || isDragging) { - return noop; + return; } return (event: MouseEvent) => onMouseEnter(event, node); - }, [onMouseEnter, isDragging]); + }, [onMouseEnter, isDragging, node]); const onMouseMoveHandler = useMemo(() => { if (!onMouseMove || isDragging) { - return noop; + return; } return (event: MouseEvent) => onMouseMove(event, node); - }, [onMouseMove, isDragging]); + }, [onMouseMove, isDragging, node]); const onMouseLeaveHandler = useMemo(() => { if (!onMouseLeave || isDragging) { - return noop; + return; } return (event: MouseEvent) => onMouseLeave(event, node); - }, [onMouseLeave, isDragging]); + }, [onMouseLeave, isDragging, node]); const onContextMenuHandler = useMemo(() => { if (!onContextMenu) { - return noop; + return; } return (event: MouseEvent) => onContextMenu(event, node); - }, [onContextMenu]); + }, [onContextMenu, node]); const onSelectNodeHandler = useCallback( (event: MouseEvent) => { - if (!isDraggable && isSelectable) { - setSelectedElements({ id: node.id, type: node.type } as Node); - } + if (!isDraggable) { + if (isSelectable) { + setSelectedElements({ id: node.id, type: node.type } as Node); + } - if (onClick) { - onClick(event, node); + if (onClick) { + onClick(event, node); + } } }, - [isSelectable, isDraggable, node] + [isSelectable, isDraggable, onClick, node] + ); + + const onDragStart = useCallback( + (event) => { + const startEvent = getMouseEvent(event); + + const scaledClientX = startEvent.clientX / transform[2]; + const scaledClientY = startEvent.clientY / transform[2]; + + const offsetX = scaledClientX - position.x - transform[0]; + const offsetY = scaledClientY - position.y - transform[1]; + + setOffset({ x: offsetX, y: offsetY }); + + if (onNodeDragStart) { + onNodeDragStart(event as MouseEvent, node); + } + + if (selectNodesOnDrag && isSelectable) { + setSelectedElements({ id: node.id, type: node.type } as Node); + } + }, + [node, transform, position, selectNodesOnDrag, isSelectable, onNodeDragStart] + ); + + const onDrag = useCallback( + (event) => { + const dragEvent = getMouseEvent(event); + + const scaledClientX = dragEvent.clientX / transform[2]; + const scaledClientY = dragEvent.clientY / transform[2]; + + setDragging(true); + updateNodePos({ + id, + pos: { + x: scaledClientX - transform[0] - offset.x, + y: scaledClientY - transform[1] - offset.y, + }, + }); + }, + [id, transform, offset] + ); + + const onDragStop = useCallback( + (event) => { + if (!isDragging) { + if (isSelectable && !selectNodesOnDrag) { + setSelectedElements({ id: node.id, type: node.type } as Node); + } + + if (onClick) { + onClick(event as MouseEvent, node); + } + + return; + } + + setDragging(false); + + if (onNodeDragStop) { + onNodeDragStop(event as MouseEvent, node); + } + }, + [node, isDragging, isSelectable, selectNodesOnDrag, onClick, onNodeDragStop] ); useEffect(() => { @@ -279,48 +208,21 @@ export default (NodeComponent: ComponentType) => { return null; } - const nodeStyle: CSSProperties = { - zIndex: selected ? 10 : 3, - transform: `translate(${xPos}px,${yPos}px)`, - pointerEvents: isSelectable || isDraggable || onClick ? 'all' : 'none', - opacity: isInitialized ? 1 : 0, // prevents jumping of nodes on start - ...style, - }; + const nodeClasses = cc([ + 'react-flow__node', + `react-flow__node-${type}`, + className, + { + selected, + selectable: isSelectable, + }, + ]); return ( - onStart({ - event: event as MouseEvent, - selectNodesOnDrag, - isSelectable, - onNodeDragStart, - id, - type, - data, - setOffset, - transform, - position, - setSelectedElements, - }) - } - onDrag={(event) => onDrag({ event: event as MouseEvent, setDragging, id, offset, transform, updateNodePos })} - onStop={(event) => - onStop({ - event: event as MouseEvent, - onNodeDragStop, - selectNodesOnDrag, - isSelectable, - onClick, - isDragging, - setDragging, - id, - type, - position, - data, - setSelectedElements, - }) - } + onStart={onDragStart} + onDrag={onDrag} + onStop={onDragStop} scale={transform[2]} disabled={!isDraggable} cancel=".nodrag" diff --git a/src/utils/index.ts b/src/utils/index.ts index 165d0e2f..95130e1e 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,8 +1,6 @@ import { DraggableEvent } from 'react-draggable'; import { MouseEvent as ReactMouseEvent } from 'react'; -export const noop = () => {}; - export const isInputDOMNode = (e: ReactMouseEvent | DraggableEvent | KeyboardEvent) => { const target = e.target as HTMLElement; return e && target && ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON'].includes(target.nodeName); From 29fa30c2215e93ac67f2366c92186f4ac7ee71e6 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 10 Sep 2020 18:03:36 +0200 Subject: [PATCH 7/8] chore(examples): add useStoreActions to provider example closes #492 closes #485 --- example/src/Provider/Sidebar.js | 11 ++++++++++- example/src/Provider/provider.css | 4 ++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/example/src/Provider/Sidebar.js b/example/src/Provider/Sidebar.js index ab8def0d..7006f086 100644 --- a/example/src/Provider/Sidebar.js +++ b/example/src/Provider/Sidebar.js @@ -1,9 +1,14 @@ import React from 'react'; -import { useStoreState } from 'react-flow-renderer'; +import { useStoreState, useStoreActions } from 'react-flow-renderer'; export default () => { const nodes = useStoreState((store) => store.nodes); const transform = useStoreState((store) => store.transform); + const setSelectedElements = useStoreActions((actions) => actions.setSelectedElements); + + const selectAll = () => { + setSelectedElements(nodes.map((node) => ({ id: node.id, type: node.type }))); + }; return ( ); }; diff --git a/example/src/Provider/provider.css b/example/src/Provider/provider.css index ac199bab..8bb8ebf2 100644 --- a/example/src/Provider/provider.css +++ b/example/src/Provider/provider.css @@ -30,3 +30,7 @@ flex-grow: 1; height: 100%; } + +.providerflow .selectall { + margin-top: 10px; +} \ No newline at end of file From 5c2c1eecad41401da932d5d5caab0d312b382da6 Mon Sep 17 00:00:00 2001 From: moklick Date: Thu, 10 Sep 2020 18:39:40 +0200 Subject: [PATCH 8/8] feat(paneview): add translateExtent option closes #479 --- README.md | 1 + src/container/GraphView/index.tsx | 10 ++++++++++ src/container/ReactFlow/index.tsx | 4 ++++ src/store/index.ts | 18 +++++++++++++++++- src/types/index.ts | 2 ++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index aa541672..802887c5 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,7 @@ const BasicFlow = () => ; - `snapToGrid`: default: `false` - `snapGrid`: [x, y] array - default: `[16, 16]` - `onlyRenderVisibleNodes`: default: `true` +- `translateExtent`: [default `[[-∞, -∞], [+∞, +∞]]`](https://github.com/d3/d3-zoom#zoom_translateExtent) #### Event Handlers - `onElementClick(event: MouseEvent, element: Node | Edge)`: called when user clicks node or edge diff --git a/src/container/GraphView/index.tsx b/src/container/GraphView/index.tsx index 0baef218..88e2013c 100644 --- a/src/container/GraphView/index.tsx +++ b/src/container/GraphView/index.tsx @@ -24,6 +24,7 @@ import { OnConnectStartFunc, OnConnectStopFunc, OnConnectEndFunc, + TranslateExtent, } from '../../types'; export interface GraphViewProps { @@ -67,6 +68,7 @@ export interface GraphViewProps { maxZoom: number; defaultZoom: number; defaultPosition: [number, number]; + translateExtent?: TranslateExtent; arrowHeadColor: string; markerEndId?: string; zoomOnScroll: boolean; @@ -112,6 +114,7 @@ const GraphView = ({ maxZoom, defaultZoom, defaultPosition, + translateExtent, arrowHeadColor, markerEndId, zoomOnScroll, @@ -137,6 +140,7 @@ const GraphView = ({ const setElementsSelectable = useStoreActions((actions) => actions.setElementsSelectable); const setInitTransform = useStoreActions((actions) => actions.setInitTransform); const setMinMaxZoom = useStoreActions((actions) => actions.setMinMaxZoom); + const setTranslateExtent = useStoreActions((actions) => actions.setTranslateExtent); const fitView = useStoreActions((actions) => actions.fitView); const zoom = useStoreActions((actions) => actions.zoom); const zoomTo = useStoreActions((actions) => actions.zoomTo); @@ -254,6 +258,12 @@ const GraphView = ({ setMinMaxZoom({ minZoom, maxZoom }); }, [minZoom, maxZoom]); + useEffect(() => { + if (typeof translateExtent !== 'undefined') { + setTranslateExtent(translateExtent); + } + }, [translateExtent]); + return (
, 'on maxZoom: number; defaultZoom: number; defaultPosition: [number, number]; + translateExtent?: TranslateExtent; arrowHeadColor: string; markerEndId?: string; zoomOnScroll: boolean; @@ -125,6 +127,7 @@ const ReactFlow = ({ maxZoom, defaultZoom, defaultPosition, + translateExtent, arrowHeadColor, markerEndId, zoomOnScroll, @@ -176,6 +179,7 @@ const ReactFlow = ({ maxZoom={maxZoom} defaultZoom={defaultZoom} defaultPosition={defaultPosition} + translateExtent={translateExtent} arrowHeadColor={arrowHeadColor} markerEndId={markerEndId} zoomOnScroll={zoomOnScroll} diff --git a/src/store/index.ts b/src/store/index.ts index 913ba56e..9827092c 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -26,6 +26,7 @@ import { SetConnectionId, NodePosUpdate, FitViewParams, + TranslateExtent, } from '../types'; type TransformXYK = { @@ -65,6 +66,7 @@ export interface StoreModel { d3Initialised: boolean; minZoom: number; maxZoom: number; + translateExtent: TranslateExtent; nodesSelectionActive: boolean; selectionActive: boolean; @@ -116,6 +118,8 @@ export interface StoreModel { setMinMaxZoom: Action; + setTranslateExtent: Action; + setSnapGrid: Action; setConnectionPosition: Action; @@ -154,6 +158,10 @@ export const storeModel: StoreModel = { d3Initialised: false, minZoom: 0.5, maxZoom: 2, + translateExtent: [ + [Number.NEGATIVE_INFINITY, Number.NEGATIVE_INFINITY], + [Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY], + ], nodesSelectionActive: false, selectionActive: false, @@ -351,7 +359,7 @@ export const storeModel: StoreModel = { }), initD3: action((state, zoomPaneNode) => { - const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]); + const d3ZoomInstance = zoom().scaleExtent([state.minZoom, state.maxZoom]).translateExtent(state.translateExtent); const selection = select(zoomPaneNode).call(d3ZoomInstance); @@ -369,6 +377,14 @@ export const storeModel: StoreModel = { } }), + setTranslateExtent: action((state, translateExtent) => { + state.translateExtent = translateExtent; + + if (state.d3Zoom) { + state.d3Zoom.translateExtent(translateExtent); + } + }), + setConnectionPosition: action((state, position) => { state.connectionPosition = position; }), diff --git a/src/types/index.ts b/src/types/index.ts index 8837c769..7d02712a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -272,3 +272,5 @@ export type FlowTransform = { y: number; zoom: number; }; + +export type TranslateExtent = [[number, number], [number, number]];