diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..b45236f1 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,32 @@ +--- +name: Publish to NPM + +on: + release: + types: [created] +jobs: + npm_publish: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Setup .npmrc file to publish to npm + - uses: actions/setup-node@v2 + with: + node-version: "14.x" + registry-url: "https://registry.npmjs.org" + - run: npm ci + - run: npm publish + env: + NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} + deploy_storybook: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + # Setup .npmrc file to publish to npm + - uses: actions/setup-node@v2 + with: + node-version: "14.x" + registry-url: "https://registry.npmjs.org" + - run: npm ci + - run: npm run build-storybook + - run: npm run deploy-storybook diff --git a/README.md b/README.md index f920cbc9..fd00d7ef 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,20 @@ It aims to provide high-level components that require minial configuration to pr `yarn add @chart-it/react-d3` +# Getting Started + +The best way to get started is to take a look at some of the examples in this Storybook https://ipwright83.github.io/chart-it/?path=/story/introduction--page. + +Here is an example of a very basic Scatter chart + +``` + + + + + +``` + ## Run Locally Clone the project diff --git a/config/jest/setupTests.js b/config/jest/setupTests.js index 75c1a621..2dde7968 100644 --- a/config/jest/setupTests.js +++ b/config/jest/setupTests.js @@ -11,3 +11,6 @@ window.crypto = { return nodeCrypto.randomFillSync(buffer); }, }; + +// Dump debug messages to the void +console.debug = () => {}; diff --git a/package-lock.json b/package-lock.json index 7da759d5..3edfad09 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@chart-it/react-d3", - "version": "0.1.4", + "version": "0.1.6", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2581,6 +2581,141 @@ } } }, + "@mapbox/node-pre-gyp": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.6.tgz", + "integrity": "sha512-qK1ECws8UxuPqOA8F5LFD90vyVU33W7N3hGfgsOVfrJaRVc8McC3JClTDHpeSbL9CBrOHly/4GsNPAvIgNZE+g==", + "dev": true, + "requires": { + "detect-libc": "^1.0.3", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.5", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dev": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + } + }, + "gauge": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.1.tgz", + "integrity": "sha512-6STz6KdQgxO4S/ko+AbjlFGGdGcknluoqU+79GOFCDqqyYj5OanQf9AjxwN0jCidtT+ziPMmPSt9E4hfQ0CwIQ==", + "dev": true, + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1 || ^2.0.0", + "strip-ansi": "^3.0.1 || ^4.0.0", + "wide-align": "^1.1.2" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dev": true, + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, "@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -4227,6 +4362,107 @@ } } }, + "@testing-library/dom": { + "version": "8.11.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-8.11.0.tgz", + "integrity": "sha512-8Ay4UDiMlB5YWy+ZvCeRyFFofs53ebxrWnOFvCoM1HpMAX4cHyuSrCuIM9l2lVuUWUt+Gr3loz/nCwdrnG6ShQ==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^4.2.0", + "aria-query": "^5.0.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.4.4", + "pretty-format": "^27.0.2" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } + } + }, + "@testing-library/react": { + "version": "12.1.2", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-12.1.2.tgz", + "integrity": "sha512-ihQiEOklNyHIpo2Y8FREkyD1QAea054U0MVbwH1m8N9TxeFz+KoJ9LkqoKqJlzx2JDm56DVwaJ1r36JYxZM05g==", + "dev": true, + "requires": { + "@babel/runtime": "^7.12.5", + "@testing-library/dom": "^8.0.0" + } + }, "@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -4239,6 +4475,12 @@ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true }, + "@types/aria-query": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-4.2.2.tgz", + "integrity": "sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==", + "dev": true + }, "@types/babel__core": { "version": "7.1.16", "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.1.16.tgz", @@ -5205,6 +5447,12 @@ "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -5426,6 +5674,12 @@ "sprintf-js": "~1.0.2" } }, + "aria-query": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.0.0.tgz", + "integrity": "sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", + "dev": true + }, "arr-diff": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", @@ -6671,6 +6925,17 @@ "integrity": "sha512-YzBnspggWV5hep1m9Z6sZVLOt7vrju8xWooFAgN6BA5qvy98qPAPb7vNUzypFaoh2pb3vlfzbDO8tB57UPGbtw==", "dev": true }, + "canvas": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/canvas/-/canvas-2.8.0.tgz", + "integrity": "sha512-gLTi17X8WY9Cf5GZ2Yns8T5lfBOcGgFehDFb+JQwDqdOoBOcECS9ZWMEAqMSVcMYwXD659J8NyzjRY/2aE+C2Q==", + "dev": true, + "requires": { + "@mapbox/node-pre-gyp": "^1.0.0", + "nan": "^2.14.0", + "simple-get": "^3.0.3" + } + }, "capture-exit": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/capture-exit/-/capture-exit-2.0.0.tgz", @@ -6955,6 +7220,12 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true + }, "colord": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/colord/-/colord-2.8.0.tgz", @@ -8194,6 +8465,15 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress-response": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-4.2.1.tgz", + "integrity": "sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==", + "dev": true, + "requires": { + "mimic-response": "^2.0.0" + } + }, "dedent": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", @@ -8322,6 +8602,12 @@ "repeat-string": "^1.5.4" } }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=", + "dev": true + }, "detect-newline": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", @@ -8398,6 +8684,12 @@ "esutils": "^2.0.2" } }, + "dom-accessibility-api": { + "version": "0.5.10", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz", + "integrity": "sha512-Xu9mD0UjrJisTmv7lmVSDMagQcU9R5hwAbxsaAE/35XPnPLJobbuREfV/rraiSaEj/UOvgrzQs66zyTWTlyd+g==", + "dev": true + }, "dom-converter": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz", @@ -8633,11 +8925,6 @@ "hoist-non-react-statics": "^3.3.0" } }, - "emptyfunction": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/emptyfunction/-/emptyfunction-1.0.0.tgz", - "integrity": "sha1-9aHmg3GBSMK5gdU+cAQ5OPO430o=" - }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -12029,6 +12316,12 @@ } } }, + "jest-canvas-snapshot-serializer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/jest-canvas-snapshot-serializer/-/jest-canvas-snapshot-serializer-1.0.1.tgz", + "integrity": "sha512-JOJkLhNninP1PltYJOuw8brUbobTQVUq9Lx0JYaTcUxGpz7OnO63EaUA7RHaEHASaglW/fizZ0dR8PEKt6Gnag==", + "dev": true + }, "jest-changed-files": { "version": "27.3.0", "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.3.0.tgz", @@ -12253,6 +12546,32 @@ "picomatch": "^2.2.3" } }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12357,6 +12676,32 @@ "picomatch": "^2.2.3" } }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12380,22 +12725,70 @@ "pretty-format": "^27.3.1" }, "dependencies": { - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - } - }, - "has-flag": { - "version": "4.0.0", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "has-flag": { + "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12487,6 +12880,32 @@ "picomatch": "^2.2.3" } }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12777,6 +13196,32 @@ "picomatch": "^2.2.3" } }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12796,6 +13241,90 @@ "requires": { "jest-get-type": "^27.3.1", "pretty-format": "^27.3.1" + }, + "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "dependencies": { + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + } + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + } } }, "jest-matcher-utils": { @@ -12810,6 +13339,28 @@ "pretty-format": "^27.3.1" }, "dependencies": { + "@jest/types": { + "version": "27.2.5", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", + "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", + "dev": true, + "requires": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -12826,6 +13377,32 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -12892,6 +13469,32 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -13831,6 +14434,32 @@ } } }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "semver": { "version": "7.3.5", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", @@ -13956,6 +14585,32 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "pretty-format": { + "version": "27.3.1", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", + "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "dev": true, + "requires": { + "@jest/types": "^27.2.5", + "ansi-regex": "^5.0.1", + "ansi-styles": "^5.0.0", + "react-is": "^17.0.1" + }, + "dependencies": { + "ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true + } + } + }, + "react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "dev": true + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14496,6 +15151,12 @@ "yallist": "^4.0.0" } }, + "lz-string": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.4.4.tgz", + "integrity": "sha1-wNjq82BZ9wV5bh40SBHPTEmNOiY=", + "dev": true + }, "magic-string": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", @@ -14747,6 +15408,12 @@ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true }, + "mimic-response": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-2.1.0.tgz", + "integrity": "sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==", + "dev": true + }, "min-document": { "version": "2.19.0", "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz", @@ -14903,6 +15570,12 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true }, + "nan": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz", + "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==", + "dev": true + }, "nanocolors": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/nanocolors/-/nanocolors-0.1.12.tgz", @@ -15050,6 +15723,15 @@ "integrity": "sha512-rB1DUFUNAN4Gn9keO2K1efO35IDK7yKHCdCaIMvFO7yUYmmZYeDjnGKle26G4rwj+LKRQpjyUUvMkPglwGCYNQ==", "dev": true }, + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dev": true, + "requires": { + "abbrev": "1" + } + }, "normalize-package-data": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", @@ -16287,86 +16969,44 @@ } }, "pretty-format": { - "version": "27.3.1", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.3.1.tgz", - "integrity": "sha512-DR/c+pvFc52nLimLROYjnXPtolawm+uWDxr4FjuLDLUn+ktWnSN851KoHwHzzqq6rfCOjkzN8FLgDrSub6UDuA==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-22.1.0.tgz", + "integrity": "sha512-0HHR5hCmjDGU4sez3w5zRDAAwn7V0vT4SgPiYPZ1XDm5sT3Icb+Bh+fsOP3+Y3UwPjMr7TbRj+L7eQyMkPAxAw==", "dev": true, "requires": { - "@jest/types": "^27.2.5", - "ansi-regex": "^5.0.1", - "ansi-styles": "^5.0.0", - "react-is": "^17.0.1" + "ansi-regex": "^3.0.0", + "ansi-styles": "^3.2.0" }, "dependencies": { - "@jest/types": { - "version": "27.2.5", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.2.5.tgz", - "integrity": "sha512-nmuM4VuDtCZcY+eTpw+0nvstwReMsjPoj7ZR80/BbixulhLaiX+fbv8oeLW8WZlJMcsGQsTmMKT/iTZu1Uy/lQ==", - "dev": true, - "requires": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - } + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "color-convert": "^1.9.0" } }, - "ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true - }, - "chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "requires": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - } + "color-name": "1.1.3" } }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "react-is": { - "version": "17.0.2", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", - "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } } } }, @@ -17038,6 +17678,15 @@ "use-latest": "^1.0.0" } }, + "react-use-compare-debugger": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/react-use-compare-debugger/-/react-use-compare-debugger-1.0.5.tgz", + "integrity": "sha512-jtpQi/s0PrnD30MAII/R5Fk2hPJ98PqJY45l5K8jhrQnHny1EqFfaHcazOiGfSxVj9PPCvEGEhHMZ/bhjxvUsQ==", + "dev": true, + "requires": { + "react": "^17.0.1" + } + }, "read-pkg": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", @@ -18143,6 +18792,23 @@ "integrity": "sha512-KWcOiKeQj6ZyXx7zq4YxSMgHRlod4czeBQZrPb8OKcohcqAXShm7E20kEMle9WBt26hFcAf0qLOcp5zmY7kOqQ==", "dev": true }, + "simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "dev": true + }, + "simple-get": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-3.1.0.tgz", + "integrity": "sha512-bCR6cP+aTdScaQCnQKbPKtJOKDp/hj9EDLJo3Nw4y1QksqaovlW/bnptB6/c1e+qmNIDHRK+oXFDdEqBT8WzUA==", + "dev": true, + "requires": { + "decompress-response": "^4.2.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, "sisteransi": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", @@ -19996,7 +20662,10 @@ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", "dev": true, - "optional": true + "optional": true, + "requires": { + "nan": "^2.12.1" + } }, "glob-parent": { "version": "3.1.0", diff --git a/package.json b/package.json index 8c5586fe..2d6dc899 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "@chart-it/react-d3", - "version": "0.1.4", + "version": "0.1.6", "description": "chart-it is a react-d3 charting library", "repository": "git@github.com:IPWright83/chart-it.git", "author": "\"Ian Wright\" <\"ipwright83+dev@gmail.com\">", "main": "lib/index.js", "module": "lib/index.esm.js", "types": "lib/index.d.ts", + "homepage": "http://localhost:6006/?path=/story/introduction--page", "scripts": { "test": "jest", "lint": "eslint -c .eslintrc.json .", @@ -28,7 +29,6 @@ "dependencies": { "d3": "^6.2.0", "d3-interpolate-path": "^2.2.3", - "emptyfunction": "^1.0.0", "lodash.debounce": "^4.0.8", "lodash.isequal": "^4.5.0" }, @@ -45,10 +45,12 @@ "@storybook/addon-links": "^6.1.9", "@storybook/react": "^6.1.9", "@storybook/storybook-deployer": "^2.8.10", + "@testing-library/react": "^12.1.2", "@types/d3": "^7.1.0", "@types/react": "^17.0.0", "babel-jest": "^27.3.1", "babel-loader": "^8.2.2", + "canvas": "^2.8.0", "chromatic": "^6.0.4", "crypto": "^1.0.1", "eslint": "^8.0.1", @@ -56,16 +58,19 @@ "eslint-plugin-jest": "^25.2.1", "eslint-plugin-react": "^7.26.1", "jest": "^27.3.1", + "jest-canvas-snapshot-serializer": "^1.0.1", "jest-circus": "^27.3.1", "jest-resolve": "^27.3.1", "jest-watch-typeahead": "^1.0.0", "postcss": "^8.2.1", + "pretty-format": "22.1.0", "prop-types": "^15.7.2", "react": "^17.0.2", "react-app-polyfill": "^2.0.0", "react-dom": "^17.0.2", "react-redux": "^7.2.2", "react-test-renderer": "^17.0.2", + "react-use-compare-debugger": "^1.0.5", "redux": "^4.0.5", "redux-devtools-extension": "^2.13.8", "redux-thunk": "^2.3.0", diff --git a/rollup.config.js b/rollup.config.js index 5ea9521c..1ebb2867 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -29,6 +29,7 @@ export default { babel({ exclude: "node_modules/**", presets: ["@babel/env", "@babel/preset-react"], + runtimeHelpers: true, }), commonjs(), //typescript({ useTsconfigDeclarationDir: true }), diff --git a/src/components/Chart/Chart.js b/src/components/Chart/Chart.js index 52643621..df4b9e5b 100644 --- a/src/components/Chart/Chart.js +++ b/src/components/Chart/Chart.js @@ -1,15 +1,11 @@ import React, { useEffect } from "react"; import PropTypes from "prop-types"; -import { useDispatch, useSelector } from "react-redux"; +import { useDispatch } from "react-redux"; -import { Background } from "../Background"; -import { Droplines } from "../Droplines"; -import { Legend } from "../Legend"; -import { Markers } from "../Markers"; import { VirtualCanvas } from "../VirtualCanvas"; -import { getColumnInfos } from "../../detection"; -import { chartActions, chartSelectors } from "../../store"; +// import { getColumnInfos } from "../../detection"; +import { chartActions } from "../../store"; import { getChildrenWithProps } from "./getChildrenWithProps"; import { getThemeName } from "./getThemeName"; @@ -26,7 +22,6 @@ const Chart = ({ onMouseOut, onClick, theme = "light", - ...props }) => { const dispatch = useDispatch(); const themeName = getThemeName(theme); @@ -66,7 +61,6 @@ const Chart = ({ return (
- {useCanvas ? ( {childrenWithProps} @@ -74,14 +68,18 @@ const Chart = ({ ) : ( childrenWithProps )} - -
); }; Chart.propTypes = { + /** + * The child components for the chart + * @type {Array || Node} + */ + children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]), + /** * The width of the chart * @default 500 diff --git a/src/components/Droplines/Droplines.unit.js b/src/components/Droplines/Droplines.unit.js new file mode 100644 index 00000000..c7522977 --- /dev/null +++ b/src/components/Droplines/Droplines.unit.js @@ -0,0 +1,75 @@ +import React from "react"; +import { Provider } from "react-redux"; +import TestRenderer from "react-test-renderer"; +import { render } from "@testing-library/react"; + +import { Droplines } from "./Droplines"; + +describe("Droplines", () => { + const store = { + getState: () => ({ + event: { + droplines: [ + { isHorizontal: true, color: "red", x1: 50, x2: 0, y1: 50, y2: 50 }, + { isVertical: true, color: "red", x1: 50, x2: 50, y1: 50, y2: 0 }, + ], + }, + }), + dispatch: () => {}, + subscribe: () => {}, + }; + + it("should render correctly", async () => { + const layer = { current: document.createElement("custom") }; + + render( + + + + ); + + expect(layer.current).toMatchSnapshot(); + }); + + it("should render just vertical lines correctly", () => { + const layer = { current: document.createElement("custom") }; + + TestRenderer.act(() => { + TestRenderer.create( + + + + ).toJSON(); + }); + + expect(layer.current).toMatchSnapshot(); + }); + + it("should render just horizontal lines correctly", () => { + const layer = { current: document.createElement("custom") }; + + TestRenderer.act(() => { + TestRenderer.create( + + + + ).toJSON(); + }); + + expect(layer.current).toMatchSnapshot(); + }); + + it("should skip if there is no layer avaliable", () => { + const layer = { current: null }; + TestRenderer.act(() => { + TestRenderer.create( + + + + ).toJSON(); + }); + + // Should be empty + expect(layer.current).toMatchSnapshot(); + }); +}); diff --git a/src/components/Droplines/__snapshots__/Droplines.unit.js.snap b/src/components/Droplines/__snapshots__/Droplines.unit.js.snap new file mode 100644 index 00000000..aa99feaa --- /dev/null +++ b/src/components/Droplines/__snapshots__/Droplines.unit.js.snap @@ -0,0 +1,50 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Droplines should render correctly 1`] = ` + + + + +`; + +exports[`Droplines should render just horizontal lines correctly 1`] = ` + + + +`; + +exports[`Droplines should render just vertical lines correctly 1`] = ` + + + +`; + +exports[`Droplines should skip if there is no layer avaliable 1`] = `null`; diff --git a/src/components/Markers/Markers.unit.js b/src/components/Markers/Markers.unit.js new file mode 100644 index 00000000..040f9134 --- /dev/null +++ b/src/components/Markers/Markers.unit.js @@ -0,0 +1,45 @@ +import React from "react"; +import { Provider } from "react-redux"; +import TestRenderer from "react-test-renderer"; + +import { Markers } from "./Markers"; + +describe("Markers", () => { + const store = { + getState: () => ({ + event: { + markers: [{ fill: "red", stroke: "blue", r1: 5, r2: 5, cx: 50, cy: 50 }], + }, + }), + dispatch: () => {}, + subscribe: () => {}, + }; + + it("should render correctly", () => { + const layer = { current: document.createElement("custom") }; + + TestRenderer.act(() => { + TestRenderer.create( + + + + ).toJSON(); + }); + + expect(layer.current).toMatchSnapshot(); + }); + + it("should skip if there is no layer avaliable", () => { + const layer = { current: null }; + TestRenderer.act(() => { + TestRenderer.create( + + + + ).toJSON(); + }); + + // Should be empty + expect(layer.current).toMatchSnapshot(); + }); +}); diff --git a/src/components/Markers/__snapshots__/Markers.unit.js.snap b/src/components/Markers/__snapshots__/Markers.unit.js.snap new file mode 100644 index 00000000..43dc1701 --- /dev/null +++ b/src/components/Markers/__snapshots__/Markers.unit.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Markers should render correctly 1`] = ` + + + +`; + +exports[`Markers should skip if there is no layer avaliable 1`] = `null`; diff --git a/src/components/Plots/Area/Area.stories.jsx b/src/components/Plots/Area/Area.stories.jsx index 304179bc..53891179 100644 --- a/src/components/Plots/Area/Area.stories.jsx +++ b/src/components/Plots/Area/Area.stories.jsx @@ -4,7 +4,7 @@ import { argTypes } from "../../../../stories/argTypes"; import { sales_records_dataset } from "../../../../data/sales_records_dataset"; import { Area } from "./Area"; import { Areas } from "./Areas"; -import { Chart } from "../../Chart"; +import { XYChart } from "../../XYChart"; import { XAxis, YAxis } from "../../Axis"; import mdx from "./Area.mdx"; @@ -17,6 +17,12 @@ export default { parameters: { docs: { page: mdx, + transformSource: (src) => { + src = src.replace(/data={\[.*?\]}/gs, "data={[ ...dataset ]}"); + src = src.replaceAll(/undefined,?/g, ""); + src = src.replace(/^\s*\n/gm, ""); + return src; + }, }, chromatic: { delay: 300 }, }, @@ -34,41 +40,48 @@ export default { }; const AreaTemplate = (args) => ( - - + - + ); const AreasTemplate = (args) => ( - - - + + ); const StackedAreasTemplate = (args) => ( - - - + + ); export const Basic = AreaTemplate.bind({}); @@ -123,7 +136,7 @@ MultipleAreas.args = { }; export const StackedAreas = StackedAreasTemplate.bind({}); -StackedAreas.storyName = "Staced Area Plots"; +StackedAreas.storyName = "Stacked Area Plots"; StackedAreas.args = { ...Basic.args, y: "Total Revenue", diff --git a/src/components/Plots/Area/Area/AreaBase.js b/src/components/Plots/Area/Area/AreaBase.js index 80f24ac0..e05e8146 100644 --- a/src/components/Plots/Area/Area/AreaBase.js +++ b/src/components/Plots/Area/Area/AreaBase.js @@ -81,7 +81,7 @@ const AreaBase = ({ x, y, y2, color, layer, canvas }) => { }, [x, y, sortedData, xScale, yScale, layer, canvas, width, height, theme.colors, animationDuration]); // If possible respond to global mouse events for tooltips etc - useDatumFocus(dispatch, layer, x, y, xScale, yScale, sortedData, eventMode, position, strokeColor); + useDatumFocus(dispatch, layer, x, y, xScale, yScale, sortedData, eventMode, position, strokeColor.toString()); return null; }; diff --git a/src/components/Plots/Bar/Bar.stories.jsx b/src/components/Plots/Bar/Bar.stories.jsx index c32a39b8..c803ea7d 100644 --- a/src/components/Plots/Bar/Bar.stories.jsx +++ b/src/components/Plots/Bar/Bar.stories.jsx @@ -4,7 +4,7 @@ import { argTypes } from "../../../../stories/argTypes"; import { sales_records_dataset } from "../../../../data/sales_records_dataset"; import { Bar } from "./Bar"; import { Bars } from "./Bars"; -import { Chart } from "../../Chart"; +import { XYChart } from "../../XYChart"; import { XAxis, YAxis } from "../../Axis"; import mdx from "./Bar.mdx"; @@ -17,6 +17,12 @@ export default { parameters: { docs: { page: mdx, + transformSource: (src) => { + src = src.replace(/data={\[.*?\]}/gs, "data={[ ...dataset ]}"); + src = src.replaceAll(/undefined,?/g, ""); + src = src.replace(/^\s*\n/gm, ""); + return src; + }, }, chromatic: { delay: 300 }, }, @@ -34,40 +40,34 @@ export default { }; const BarTemplate = (args) => ( - - - {args.x2 ? ( - - ) : undefined} - + + {args.x2 ? : undefined} + ); const BarsTemplate = (args) => ( - - - + + ); export const Basic = BarTemplate.bind({}); diff --git a/src/components/Plots/Column/Column.stories.jsx b/src/components/Plots/Column/Column.stories.jsx index 9bed664d..afada6f6 100644 --- a/src/components/Plots/Column/Column.stories.jsx +++ b/src/components/Plots/Column/Column.stories.jsx @@ -4,7 +4,7 @@ import { argTypes } from "../../../../stories/argTypes"; import { sales_records_dataset } from "../../../../data/sales_records_dataset"; import { Column } from "./Column"; import { Columns } from "./Columns"; -import { Chart } from "../../Chart"; +import { XYChart } from "../../XYChart"; import { XAxis, YAxis } from "../../Axis"; import mdx from "./Column.mdx"; @@ -17,6 +17,12 @@ export default { parameters: { docs: { page: mdx, + transformSource: (src) => { + src = src.replace(/data={\[.*?\]}/gs, "data={[ ...dataset ]}"); + src = src.replaceAll(/undefined,?/g, ""); + src = src.replace(/^\s*\n/gm, ""); + return src; + }, }, chromatic: { delay: 300 }, }, @@ -34,40 +40,34 @@ export default { }; const ColumnTemplate = (args) => ( - - - {args.y2 ? ( - - ) : undefined} - + + {args.y2 ? : undefined} + ); const ColumnsTemplate = (args) => ( - - - + + ); export const Basic = ColumnTemplate.bind({}); diff --git a/src/components/Plots/Line/Line.stories.jsx b/src/components/Plots/Line/Line.stories.jsx index eebce371..b42dc855 100644 --- a/src/components/Plots/Line/Line.stories.jsx +++ b/src/components/Plots/Line/Line.stories.jsx @@ -4,7 +4,7 @@ import { argTypes } from "../../../../stories/argTypes"; import { sales_records_dataset } from "../../../../data/sales_records_dataset"; import { Line } from "./Line"; import { Lines } from "./Lines"; -import { Chart } from "../../Chart"; +import { XYChart } from "../../XYChart"; import { XAxis, YAxis } from "../../Axis"; import mdx from "./Line.mdx"; @@ -17,6 +17,12 @@ export default { parameters: { docs: { page: mdx, + transformSource: (src) => { + src = src.replace(/data={\[.*?\]}/gs, "data={[ ...dataset ]}"); + src = src.replaceAll(/undefined,?/g, ""); + src = src.replace(/^\s*\n/gm, ""); + return src; + }, }, chromatic: { delay: 300 }, }, @@ -34,29 +40,33 @@ export default { }; const LineTemplate = (args) => ( - - + - + ); const LinesTemplate = (args) => ( - - - + + ); export const Basic = LineTemplate.bind({}); diff --git a/src/components/Plots/Scatter/Scatter.stories.jsx b/src/components/Plots/Scatter/Scatter.stories.jsx index da5e2b39..c7e6dbf8 100644 --- a/src/components/Plots/Scatter/Scatter.stories.jsx +++ b/src/components/Plots/Scatter/Scatter.stories.jsx @@ -5,7 +5,7 @@ import { sales_records_dataset } from "../../../../data/sales_records_dataset"; import { huge_data_set } from "../../../../data/huge_data_set"; import { Scatter } from "./Scatter"; import { Scatters } from "./Scatters"; -import { Chart } from "../../Chart"; +import { XYChart } from "../../XYChart"; import { XAxis, YAxis } from "../../Axis"; import mdx from "./Scatter.mdx"; @@ -18,6 +18,12 @@ export default { parameters: { docs: { page: mdx, + transformSource: (src) => { + src = src.replace(/data={\[.*?\]}/gs, "data={[ ...dataset ]}"); + src = src.replaceAll(/undefined,?/g, ""); + src = src.replace(/^\s*\n/gm, ""); + return src; + }, }, chromatic: { delay: 300 }, }, @@ -40,40 +46,33 @@ export default { }; const ScatterTemplate = (args) => ( - - + - + ); const ScattersTemplate = (args) => ( - - + - + ); export const Basic = ScatterTemplate.bind({}); diff --git a/src/components/Plots/Scatter/Scatter/Scatter.unit.js b/src/components/Plots/Scatter/Scatter/Scatter.unit.js new file mode 100644 index 00000000..615f7fce --- /dev/null +++ b/src/components/Plots/Scatter/Scatter/Scatter.unit.js @@ -0,0 +1,184 @@ +import * as d3 from "d3"; +import React from "react"; +import { Provider } from "react-redux"; +import { render, fireEvent } from "@testing-library/react"; +import { themes } from "../../../../themes"; +import canvasSerializer from "jest-canvas-snapshot-serializer"; + +import { Scatter } from "./Scatter"; + +expect.addSnapshotSerializer(canvasSerializer); + +describe("Scatter", () => { + let chartState; + + beforeEach(() => { + chartState = { + animationDuration: 0, + dimensions: { + height: 200, + width: 200, + }, + data: [ + { x: 5, y: 5 }, + { x: 10, y: 10 }, + ], + scales: { + x: d3.scaleLinear().domain([0, 20]).range([0, 100]), + y: d3.scaleLinear().domain([0, 20]).range([0, 100]), + }, + theme: themes.light, + }; + }); + + const store = { + getState: () => ({ + chart: chartState, + }), + dispatch: () => {}, + subscribe: () => {}, + }; + + describe("using SVG", () => { + it("should render correctly", () => { + const { asFragment } = render( + + + + + + ); + + expect(asFragment()).toMatchSnapshot(); + }); + + describe("should handle event", () => { + it("mouseover correctly", () => { + const onMouseOver = jest.fn(); + jest.spyOn(store, "dispatch"); + + const { container } = render( + + + + + + ); + + fireEvent.mouseOver(container.querySelector("circle")); + expect(onMouseOver).toHaveBeenCalledWith( + { + x: 5, + y: 5, + }, + expect.anything(), + expect.anything() + ); + + expect(store.dispatch.mock.calls[0]).toMatchSnapshot("ADD_MARKER action"); + expect(store.dispatch.mock.calls[1]).toMatchSnapshot("ADD_DROPLINE action"); + expect(store.dispatch.mock.calls[2]).toMatchSnapshot("ADD_DROPLINE action"); + }); + + it("mouseexit correctly", () => { + const onMouseOut = jest.fn(); + jest.spyOn(store, "dispatch"); + + const { container } = render( + + + + + + ); + + fireEvent.mouseOver(container.querySelector("circle")); + fireEvent.mouseLeave(container.querySelector("circle")); + expect(onMouseOut).toHaveBeenCalledWith( + { + x: 5, + y: 5, + }, + expect.anything(), + expect.anything() + ); + + expect(store.dispatch.mock.calls[3]).toMatchSnapshot("REMOVE_MARKER action"); + expect(store.dispatch.mock.calls[4]).toMatchSnapshot("REMOVE_DROPLINE action"); + expect(store.dispatch.mock.calls[5]).toMatchSnapshot("REMOVE_DROPLINE action"); + }); + + it("click correctly", () => { + const onClick = jest.fn(); + jest.spyOn(store, "dispatch"); + + const { container } = render( + + + + + + ); + + fireEvent.click(container.querySelector("circle")); + expect(onClick).toHaveBeenCalledWith( + { + x: 5, + y: 5, + }, + expect.anything(), + expect.anything() + ); + }); + }); + + describe("should skip rendering if", () => { + it("there is no x scale avaliable", () => { + delete chartState.scales.x; + + const { asFragment } = render( + + + + + + ); + + expect(asFragment()).toMatchSnapshot(); + }); + + it("there is no y scale avaliable", () => { + delete chartState.scales.y; + + const { asFragment } = render( + + + + + + ); + + expect(asFragment()).toMatchSnapshot(); + }); + }); + }); + + describe("using Canvas", () => { + it("should render correctly", async () => { + const { container } = render( + + + + + + ); + + await new Promise((resolve) => { + setTimeout(resolve, 250); + }); + + const canvas = container.querySelector("canvas"); + expect(canvas).toMatchSnapshot(); + }); + }); +}); diff --git a/src/components/Plots/Scatter/Scatter/ScatterBase.js b/src/components/Plots/Scatter/Scatter/ScatterBase.js index f24a88e3..2033fb3a 100644 --- a/src/components/Plots/Scatter/Scatter/ScatterBase.js +++ b/src/components/Plots/Scatter/Scatter/ScatterBase.js @@ -3,7 +3,6 @@ import PropTypes from "prop-types"; import { useEffect, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { useRender } from "../../../../hooks"; import { chartSelectors, eventActions } from "../../../../store"; import { eventDefaultProps, eventPropTypes, plotDefaultProps, plotPropTypes } from "../../../../types"; @@ -87,7 +86,7 @@ const ScatterBase = ({ }, [dispatch, xScale, yScale, focused]); // This is the main render function - useRender(() => { + useEffect(() => { // D3 data join const join = d3 .select(layer.current) @@ -113,15 +112,15 @@ const ScatterBase = ({ const update = enter .merge(join) .on("mouseover", function (event, datum) { - onMouseOver && onMouseOver(datum, this, event); + onMouseOver(datum, this, event); setFocused({ element: this, event, datum }); }) .on("mouseout", function (event, datum) { - onMouseOut && onMouseOut(datum, this, event); + onMouseOut(datum, this, event); setFocused(null); }) .on("click", function (event, datum) { - onClick && onClick(datum, this, event); + onClick(datum, this, event); }) .transition("scatter") .duration(animationDuration) diff --git a/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap b/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap new file mode 100644 index 00000000..7254d217 --- /dev/null +++ b/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap @@ -0,0 +1,150 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`Scatter using Canvas should render correctly 1`] = ` + +`; + +exports[`Scatter using SVG should handle event mouseexit correctly: REMOVE_DROPLINE action 1`] = ` +Array [ + Object { + "payload": Object { + "color": "rgba(153, 193, 220, 0.8)", + "isHorizontal": true, + "x1": 21, + "x2": 0, + "y1": 25, + "y2": 25, + }, + "type": "EVENT.REMOVE_DROPLINE", + }, +] +`; + +exports[`Scatter using SVG should handle event mouseexit correctly: REMOVE_DROPLINE action 2`] = ` +Array [ + Object { + "payload": Object { + "color": "rgba(153, 193, 220, 0.8)", + "isVertical": true, + "x1": 25, + "x2": 25, + "y1": 29, + "y2": 0, + }, + "type": "EVENT.REMOVE_DROPLINE", + }, +] +`; + +exports[`Scatter using SVG should handle event mouseexit correctly: REMOVE_MARKER action 1`] = ` +Array [ + Object { + "payload": Object { + "cx": 25, + "cy": 25, + "r1": 0, + "r2": 4, + "stroke": "rgba(153, 193, 220, 0.8)", + }, + "type": "EVENT.REMOVE_MARKER", + }, +] +`; + +exports[`Scatter using SVG should handle event mouseover correctly: ADD_DROPLINE action 1`] = ` +Array [ + Object { + "payload": Object { + "color": "rgba(153, 193, 220, 0.8)", + "isHorizontal": true, + "x1": 21, + "x2": 0, + "y1": 25, + "y2": 25, + }, + "type": "EVENT.ADD_DROPLINE", + }, +] +`; + +exports[`Scatter using SVG should handle event mouseover correctly: ADD_DROPLINE action 2`] = ` +Array [ + Object { + "payload": Object { + "color": "rgba(153, 193, 220, 0.8)", + "isVertical": true, + "x1": 25, + "x2": 25, + "y1": 29, + "y2": 0, + }, + "type": "EVENT.ADD_DROPLINE", + }, +] +`; + +exports[`Scatter using SVG should handle event mouseover correctly: ADD_MARKER action 1`] = ` +Array [ + Object { + "payload": Object { + "cx": 25, + "cy": 25, + "r1": 0, + "r2": 4, + "stroke": "rgba(153, 193, 220, 0.8)", + }, + "type": "EVENT.ADD_MARKER", + }, +] +`; + +exports[`Scatter using SVG should render correctly 1`] = ` + + + + + + + + +`; + +exports[`Scatter using SVG should skip rendering if there is no x scale avaliable 1`] = ` + + + + + +`; + +exports[`Scatter using SVG should skip rendering if there is no y scale avaliable 1`] = ` + + + + + +`; diff --git a/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap.Scatter-using-Canvas-should-render-correctly.canvas-image.png b/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap.Scatter-using-Canvas-should-render-correctly.canvas-image.png new file mode 100644 index 00000000..f0d91799 Binary files /dev/null and b/src/components/Plots/Scatter/Scatter/__snapshots__/Scatter.unit.js.snap.Scatter-using-Canvas-should-render-correctly.canvas-image.png differ diff --git a/src/components/VirtualCanvas/VirtualCanvas.js b/src/components/VirtualCanvas/VirtualCanvas.js index 54f26b3a..9d4c901d 100644 --- a/src/components/VirtualCanvas/VirtualCanvas.js +++ b/src/components/VirtualCanvas/VirtualCanvas.js @@ -1,6 +1,5 @@ import "./VirtualCanvas.css"; -import emptyFunction from "emptyfunction"; import debounce from "lodash.debounce"; import PropTypes from "prop-types"; import React, { useEffect, useRef } from "react"; @@ -80,7 +79,11 @@ const VirtualCanvas = (props) => { // Many layers don't require the virtual canvas. If // they are all of these types then disable the canvas - const childTypes = children.filter((c) => !!c).map((c) => c.props.mdxType); + const childTypes = children + // Fix for storybook + .filter((c) => !!c && !!c.props) + .map((c) => c.props.mdxType); + const typesNeedingCanvas = childTypes.filter((type) => !ignoreTypes.includes(type)); const includeVirtualCanvas = typesNeedingCanvas.length > 0; @@ -135,9 +138,9 @@ VirtualCanvas.propTypes = { }; VirtualCanvas.defaultProps = { - onMouseOver: emptyFunction, - onMouseOut: emptyFunction, - onClick: emptyFunction, + onMouseOver: () => {}, + onMouseOut: () => {}, + onClick: () => {}, }; export { VirtualCanvas }; diff --git a/src/components/XYChart/XYChart.js b/src/components/XYChart/XYChart.js index 926ff275..de89a931 100644 --- a/src/components/XYChart/XYChart.js +++ b/src/components/XYChart/XYChart.js @@ -5,15 +5,12 @@ import { Background } from "../Background"; import { Droplines } from "../Droplines"; import { Markers } from "../Markers"; import { Chart } from "../Chart"; -import { XAxis, YAxis } from "../Axis"; -const XYChart = ({ children, xs, ys, ...props }) => { +const XYChart = ({ children, ...props }) => { return ( {children} - - @@ -21,16 +18,6 @@ const XYChart = ({ children, xs, ys, ...props }) => { }; XYChart.propTypes = { - /** - * The set of x fields to use to access the data for each plot - * @type {Array} - */ - xs: PropTypes.arrayOf(PropTypes.string).isRequired, - /** - * The set of y fields to use to access the data for each plot - * @type {Array} - */ - ys: PropTypes.arrayOf(PropTypes.string).isRequired, /** * The child components (Plots) for the chart * @type {Array} diff --git a/src/hoc/canvas/canvasRenderLoop.js b/src/hoc/canvas/canvasRenderLoop.js index 2da527ec..4db6c2e3 100644 --- a/src/hoc/canvas/canvasRenderLoop.js +++ b/src/hoc/canvas/canvasRenderLoop.js @@ -19,12 +19,14 @@ const canvasRenderLoop = async (canvas, width, height, exit, update) => { // Ensure we've got the contexts to draw upon const context = canvas.getContext("2d"); - // Create a render loop that will run until the transitions complete - const renderLoop = d3.timer(() => { + const render = () => { context.clearRect(0, 0, width, height); renderElements(context, exit); renderElements(context, update); - }); + }; + + // Create a render loop that will run until the transitions complete + const renderLoop = d3.timer(render); try { await exit.end(); @@ -35,12 +37,9 @@ const canvasRenderLoop = async (canvas, width, height, exit, update) => { // eslint-disable-next-line no-empty } catch (e) {} - // Run 1 final render after animations have finished, but - // only of the update selection. As exit elements should - // now have been removed - setTimeout(() => { - renderLoop.stop(); - }, 0); + // Run 1 final render after animations have finished + renderLoop.stop(); + render(); }; export { canvasRenderLoop }; diff --git a/src/hoc/canvas/renderCircle.js b/src/hoc/canvas/renderCircle.js index a6e13c19..6bc0eb23 100644 --- a/src/hoc/canvas/renderCircle.js +++ b/src/hoc/canvas/renderCircle.js @@ -8,13 +8,13 @@ import * as d3 from "d3"; */ const renderCircle = (context, node, overrideColor) => { const selection = d3.select(node); - const cx = selection.attr("cx"); - const cy = selection.attr("cy"); - const r = selection.attr("r"); + const cx = Number(selection.attr("cx")); + const cy = Number(selection.attr("cy")); + const r = Number(selection.attr("r")); const fill = selection.style("fill"); const opacity = Number(selection.style("opacity")) || 1; const stroke = selection.style("stroke"); - const strokeWidth = selection.style("stroke-width") || 1; + const strokeWidth = Number(selection.style("stroke-width")) || 1; context.beginPath(); context.arc(cx, cy, r, 0, 2 * Math.PI); diff --git a/src/store/telemetry/telemetryActions.js b/src/store/telemetry/telemetryActions.js index 47467978..cf2a81cf 100644 --- a/src/store/telemetry/telemetryActions.js +++ b/src/store/telemetry/telemetryActions.js @@ -1,3 +1,5 @@ +/* eslint-disable */ + // import { getColumnInfos } from "lib/detection"; // import { telemetrySelectors } from "./telemetrySelectors"; @@ -27,18 +29,16 @@ const generateDataAnalytics = (data) => (dispatch, getState) => { * @param {Number} options.children The child components of the chart * @return {Object} A redux action object */ -const generateChartAnalytics = - ({ height, width, margin, useCanvas, animationDuration, children }) => - () => { - // console.log({ - // height, - // width, - // margin, - // useCanvas, - // animationDuration, - // children: children.map((c) => ({ name: c.type.name, props: c.props })), - // }); - }; +const generateChartAnalytics = ({ height, width, margin, useCanvas, animationDuration, children }) => () => { + // console.log({ + // height, + // width, + // margin, + // useCanvas, + // animationDuration, + // children: children.map((c) => ({ name: c.type.name, props: c.props })), + // }); +}; const telemetryActions = { generateDataAnalytics, diff --git a/src/types/plot/eventDefaultProps.js b/src/types/plot/eventDefaultProps.js index 080239ef..361a3500 100644 --- a/src/types/plot/eventDefaultProps.js +++ b/src/types/plot/eventDefaultProps.js @@ -1,13 +1,11 @@ -import emptyFunction from "emptyfunction"; - /** * Default set of props used for various plots that support their own events * @type {Object} */ const eventDefaultProps = { - onMouseOver: emptyFunction, - onMouseOut: emptyFunction, - onClick: emptyFunction, + onMouseOver: () => {}, + onMouseOut: () => {}, + onClick: () => {}, }; export { eventDefaultProps };