diff --git a/package-lock.json b/package-lock.json index c90006cd7..aeb472335 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4543,7 +4543,8 @@ "@juggle/resize-observer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.3.0.tgz", - "integrity": "sha512-P1v2nvK7z2gOLVM/bveIRLG9L99uEahTGgTltyF03zixZAjI9YmKLj5Z9MpS9wBIUt5WDoQORT2lXvLOIF89iA==" + "integrity": "sha512-P1v2nvK7z2gOLVM/bveIRLG9L99uEahTGgTltyF03zixZAjI9YmKLj5Z9MpS9wBIUt5WDoQORT2lXvLOIF89iA==", + "dev": true }, "@mdx-js/loader": { "version": "1.6.22", @@ -4857,6 +4858,53 @@ "react-lifecycles-compat": "^3.0.4" } }, + "@react-three/fiber": { + "version": "6.0.14", + "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-6.0.14.tgz", + "integrity": "sha512-wrHLFBGhruOitGCeT8sNtLO3qG4y0M1d0xAYpUNIXDD1/d/lrNlUvrTF9r7Q4sR0Reo1OGf2EMUg3CvFXpDYcg==", + "requires": { + "@babel/runtime": "^7.13.10", + "react-merge-refs": "^1.1.0", + "react-reconciler": "^0.26.2", + "react-three-fiber": "0.0.0-deprecated", + "react-use-measure": "^2.0.4", + "resize-observer-polyfill": "^1.5.1", + "scheduler": "^0.20.2", + "use-asset": "^1.0.4", + "utility-types": "^3.10.0", + "zustand": "^3.3.3" + }, + "dependencies": { + "@babel/runtime": { + "version": "7.13.10", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.13.10.tgz", + "integrity": "sha512-4QPkjJq6Ns3V/RgpEahRk+AGfL0eO6RHHtTWoNNr5mO49G6B5+X6d6THgWEAvTrznU5xYpbAlVKRYcsCgh/Akw==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, + "react-reconciler": { + "version": "0.26.2", + "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.26.2.tgz", + "integrity": "sha512-nK6kgY28HwrMNwDnMui3dvm3rCFjZrcGiuwLc5COUipBK5hWHLOxMJhSnSomirqWwjPBJKV1QcbkI0VJr7Gl1Q==", + "requires": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "scheduler": "^0.20.2" + } + }, + "react-three-fiber": { + "version": "0.0.0-deprecated", + "resolved": "https://registry.npmjs.org/react-three-fiber/-/react-three-fiber-0.0.0-deprecated.tgz", + "integrity": "sha512-EblIqTAsIpkYeM8bZtC4lcpTE0A2zCEGipFB52RgcQq/q+0oryrk7Sxt+sqhIjUu6xMNEVywV8dr74lz5yWO6A==" + }, + "regenerator-runtime": { + "version": "0.13.7", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", + "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" + } + } + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -8415,18 +8463,19 @@ } }, "@types/react": { - "version": "16.14.2", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.2.tgz", - "integrity": "sha512-BzzcAlyDxXl2nANlabtT4thtvbbnhee8hMmH/CcJrISDBVcJS1iOsP1f0OAgSdGE0MsY9tqcrb9YoZcOFv9dbQ==", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react/-/react-17.0.3.tgz", + "integrity": "sha512-wYOUxIgs2HZZ0ACNiIayItyluADNbONl7kt8lkLjVK8IitMH5QMyAh75Fwhmo37r1m7L2JaFj03sIfxBVDvRAg==", "requires": { "@types/prop-types": "*", + "@types/scheduler": "*", "csstype": "^3.0.2" }, "dependencies": { "csstype": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.5.tgz", - "integrity": "sha512-uVDi8LpBUKQj6sdxNaTetL6FpeCqTjOvAQuQUa/qAqq8oOd4ivkbhgnqayl0dnPal8Tb/yB1tF+gOvCBiicaiQ==" + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.7.tgz", + "integrity": "sha512-KxnUB0ZMlnUWCsx2Z8MUsr6qV6ja1w9ArPErJaJaF8a5SOWoHLIszeCTKGRGRgtLgYrs1E8CHkNSP1VZTTPc9g==" } } }, @@ -8440,11 +8489,11 @@ } }, "@types/react-dom": { - "version": "16.9.10", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-16.9.10.tgz", - "integrity": "sha512-ItatOrnXDMAYpv6G8UCk2VhbYVTjZT9aorLtA/OzDN9XJ2GKcfam68jutoAcILdRjsRUO8qb7AmyObF77Q8QFw==", + "version": "17.0.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-17.0.3.tgz", + "integrity": "sha512-4NnJbCeWE+8YBzupn/YrJxZ8VnjcJq5iR1laqQ1vkpQgBiA7bwk0Rp24fxsdNinzJY2U+HHS4dJJDPdoMjdJ7w==", "requires": { - "@types/react": "^16" + "@types/react": "*" } }, "@types/react-measure": { @@ -8513,6 +8562,11 @@ "@types/node": "*" } }, + "@types/scheduler": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.1.tgz", + "integrity": "sha512-EaCxbanVeyxDRTQBkdLb3Bvl/HK7PBK6UJjsSixB0iHKoWxE5uu2Q/DgtpOhPIojN0Zl1whvOd7PoHs2P0s5eA==" + }, "@types/sinonjs__fake-timers": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-6.0.2.tgz", @@ -17359,6 +17413,13 @@ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", "requires": { "react-is": "^16.7.0" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "hoopy": { @@ -24916,6 +24977,13 @@ "loose-envify": "^1.4.0", "object-assign": "^4.1.1", "react-is": "^16.8.1" + }, + "dependencies": { + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + } } }, "property-information": { @@ -25217,13 +25285,12 @@ } }, "react": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react/-/react-16.14.0.tgz", - "integrity": "sha512-0X2CImDkJGApiAlcf0ODKIneSwBPhqJawOa5wCtKbu7ZECrmS26NvtSILynQ66cgkT/RJ4LidJOc3bUESwmU8g==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react/-/react-17.0.2.tgz", + "integrity": "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==", "requires": { "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2" + "object-assign": "^4.1.1" } }, "react-app-polyfill": { @@ -25496,14 +25563,13 @@ } }, "react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz", + "integrity": "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" + "scheduler": "^0.20.2" } }, "react-draggable": { @@ -25616,9 +25682,10 @@ } }, "react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + "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 }, "react-lifecycles-compat": { "version": "3.0.4", @@ -25680,32 +25747,6 @@ } } }, - "react-promise-suspense": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/react-promise-suspense/-/react-promise-suspense-0.3.3.tgz", - "integrity": "sha512-OdehKsCEWYoV6pMcwxbvJH99UrbXylmXJ1QpEL9OfHaUBzcAihyfSJV8jFq325M/wW9iKc/BoiLROXxMul+MxA==", - "requires": { - "fast-deep-equal": "^2.0.1" - }, - "dependencies": { - "fast-deep-equal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", - "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" - } - } - }, - "react-reconciler": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.25.1.tgz", - "integrity": "sha512-R5UwsIvRcSs3w8n9k3tBoTtUHdVhu9u84EG7E5M0Jk9F5i6DA1pQzPfUZd6opYWGy56MJOtV3VADzy6DRwYDjw==", - "requires": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" - } - }, "react-reflex": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/react-reflex/-/react-reflex-4.0.0.tgz", @@ -25752,6 +25793,11 @@ "requires": { "isarray": "0.0.1" } + }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" } } }, @@ -26585,38 +26631,6 @@ } } }, - "react-three-fiber": { - "version": "4.2.21", - "resolved": "https://registry.npmjs.org/react-three-fiber/-/react-three-fiber-4.2.21.tgz", - "integrity": "sha512-lbopEkL36cbAaG/y+iEGT1EFbVaVZBrOe2XGt2+HxsCL8AeWWiQQERo1HYiiqFc4p6DuoNq1hhOSxr1TKQjXuQ==", - "requires": { - "@babel/runtime": "^7.9.2", - "@juggle/resize-observer": "^3.1.3", - "react-merge-refs": "^1.0.0", - "react-promise-suspense": "^0.3.2", - "react-reconciler": "0.25.1", - "react-use-measure": "^2.0.0", - "resize-observer-polyfill": "^1.5.1", - "scheduler": "0.19.1", - "tiny-emitter": "^2.1.0", - "utility-types": "^3.10.0" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "regenerator-runtime": { - "version": "0.13.7", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.7.tgz", - "integrity": "sha512-a54FxoJDIr27pgf7IgeQGxmqUNYrcV338lf/6gH456HZ/PhX+5BcwHXG9ajESmwe6WRO0tAzRUrRmNONWgkrew==" - } - } - }, "react-universal-interface": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", @@ -26661,9 +26675,9 @@ } }, "react-use-measure": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.0.1.tgz", - "integrity": "sha512-lFfHiqcXbJ2/6aUkZwt8g5YYM7EGqNVxJhMqMPqv1BVXRKp8D7jYLlmma0SvhRY4WYxxkZpCdbJvhDylb5gcEA==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.0.4.tgz", + "integrity": "sha512-7K2HIGaPMl3Q9ZQiEVjen3tRXl4UDda8LiTPy/QxP8dP2rl5gPBhf7mMH6MVjjRNv3loU7sNzey/ycPNnHVTxQ==", "requires": { "debounce": "^1.2.0" } @@ -27892,9 +27906,9 @@ } }, "scheduler": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.19.1.tgz", - "integrity": "sha512-n/zwRWRYSUj0/3g/otKDRPMh6qv2SYMWNq85IEa8iZyAv8od9zDYpGSnpBEjNgcMNq6Scbu5KfIPxNF72R/2EA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.20.2.tgz", + "integrity": "sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==", "requires": { "loose-envify": "^1.1.0", "object-assign": "^4.1.1" @@ -30190,7 +30204,9 @@ "tiny-emitter": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", - "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "dev": true, + "optional": true }, "tiny-invariant": { "version": "1.1.0", @@ -30859,6 +30875,21 @@ "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", "dev": true }, + "use-asset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/use-asset/-/use-asset-1.0.4.tgz", + "integrity": "sha512-7/hqDrWa0iMnCoET9W1T07EmD4Eg/Wmoj/X8TGBc++ECRK4m5yTsjP4O6s0yagbxfqIOuUkIxe2/sA+VR2GxZA==", + "requires": { + "fast-deep-equal": "^3.1.3" + }, + "dependencies": { + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==" + } + } + }, "use-composed-ref": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.1.0.tgz", diff --git a/package.json b/package.json index 577482415..798435376 100644 --- a/package.json +++ b/package.json @@ -29,6 +29,7 @@ "postversion": "git push && git push --tags" }, "dependencies": { + "@react-three/fiber": "^6.0.14", "@visx/axis": "^1.7.0", "@visx/grid": "^1.7.0", "@visx/scale": "^1.7.0", @@ -46,9 +47,9 @@ "ndarray-ops": "^1.2.2", "ndarray-unpack": "^1.0.0", "normalize.css": "^8.0.1", - "react": "^16.14.0", + "react": "^17.0.2", "react-aria-menubutton": "^7.0.1", - "react-dom": "^16.14.0", + "react-dom": "^17.0.2", "react-error-boundary": "^3.1.1", "react-icons": "^4.2.0", "react-measure": "^2.5.2", @@ -56,7 +57,6 @@ "react-router-dom": "^5.2.0", "react-slider": "^1.1.4", "react-suspense-fetch": "^0.3.0", - "react-three-fiber": "^4.2.21", "react-use": "^17.2.3", "react-window": "^1.8.6", "three": "^0.127.0", @@ -86,9 +86,9 @@ "@types/lodash-es": "^4.17.4", "@types/ndarray": "^1.0.8", "@types/node": "^12.19.7", - "@types/react": "^16.14.2", + "@types/react": "^17.0.3", "@types/react-aria-menubutton": "^6.2.7", - "@types/react-dom": "^16.9.10", + "@types/react-dom": "^17.0.3", "@types/react-measure": "^2.0.6", "@types/react-router-dom": "^5.1.7", "@types/react-slider": "^1.1.1", @@ -110,7 +110,7 @@ "npm-run-all": "^4.1.5", "prettier": "^2.2.1", "react-app-polyfill": "^2.0.0", - "react-is": "^16.13.1", + "react-is": "^17.0.2", "react-scripts": "^4.0.3", "typescript": "^4.2.4" }, diff --git a/src/h5web/vis-packs/core/heatmap/Mesh.tsx b/src/h5web/vis-packs/core/heatmap/Mesh.tsx index 782d15d44..755451959 100644 --- a/src/h5web/vis-packs/core/heatmap/Mesh.tsx +++ b/src/h5web/vis-packs/core/heatmap/Mesh.tsx @@ -1,6 +1,6 @@ import { rgb } from 'd3-color'; import { memo, useMemo } from 'react'; -import { useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; import { RedFormat, DataTexture, @@ -124,13 +124,12 @@ function Mesh(props: Props) { `, }; - const { size } = useThree(); - const { width, height } = size; + const { width, height } = useThree((state) => state.size); return ( - - + + ); } diff --git a/src/h5web/vis-packs/core/hooks.ts b/src/h5web/vis-packs/core/hooks.ts index 27228a844..9322cca99 100644 --- a/src/h5web/vis-packs/core/hooks.ts +++ b/src/h5web/vis-packs/core/hooks.ts @@ -2,7 +2,7 @@ import type ndarray from 'ndarray'; import { useContext, useEffect, useMemo, useRef, useState } from 'react'; import { isNumber } from 'lodash-es'; import { createMemo } from 'react-use'; -import { useFrame, useThree } from 'react-three-fiber'; +import { useFrame, useThree } from '@react-three/fiber'; import type { DimensionMapping } from '../../dimension-mapper/models'; import { applyMapping, @@ -72,8 +72,7 @@ export function useCanvasScales(): { ordinateScale: AxisScale; } { const { abscissaConfig, ordinateConfig } = useContext(AxisSystemContext); - const { size } = useThree(); - const { width, height } = size; + const { width, height } = useThree((state) => state.size); return { abscissaScale: getCanvasScale(abscissaConfig, width), diff --git a/src/h5web/vis-packs/core/line/DataCurve.tsx b/src/h5web/vis-packs/core/line/DataCurve.tsx index 0182aa7f5..39e392831 100644 --- a/src/h5web/vis-packs/core/line/DataCurve.tsx +++ b/src/h5web/vis-packs/core/line/DataCurve.tsx @@ -1,11 +1,23 @@ import { Suspense, useMemo } from 'react'; -import { Line } from 'react-three-fiber/components'; import { CurveType } from './models'; import GlyphMaterial from './GlyphMaterial'; -import { useThree } from 'react-three-fiber'; -import { BufferGeometry } from 'three'; +import { extend, useThree } from '@react-three/fiber'; +import { BufferGeometry, Line } from 'three'; import ErrorBars from './ErrorBars'; import { useCanvasPoints } from './hooks'; +import type { Object3DNode } from '@react-three/fiber'; + +extend({ Line_: Line }); + +// https://github.com/pmndrs/react-three-fiber/issues/1152 +declare global { + // eslint-disable-next-line @typescript-eslint/no-namespace + namespace JSX { + interface IntrinsicElements { + line_: Object3DNode; + } + } +} interface Props { abscissas: number[]; @@ -26,9 +38,9 @@ function DataCurve(props: Props) { curveType = CurveType.LineOnly, } = props; - const { gl } = useThree(); + const { domElement } = useThree((state) => state.gl); const curveColor = color.startsWith('--') - ? window.getComputedStyle(gl.domElement).getPropertyValue(color).trim() + ? window.getComputedStyle(domElement).getPropertyValue(color).trim() : color; const points = useCanvasPoints(abscissas, ordinates, errors); @@ -44,9 +56,9 @@ function DataCurve(props: Props) { return ( - - - + + + diff --git a/src/h5web/vis-packs/core/line/ErrorBars.tsx b/src/h5web/vis-packs/core/line/ErrorBars.tsx index dc77b8fa2..81891b103 100644 --- a/src/h5web/vis-packs/core/line/ErrorBars.tsx +++ b/src/h5web/vis-packs/core/line/ErrorBars.tsx @@ -1,4 +1,4 @@ -import { useUpdate } from 'react-three-fiber'; +import { useLayoutEffect, useRef } from 'react'; import type { BufferGeometry, Vector2, Vector3 } from 'three'; import GlyphMaterial from './GlyphMaterial'; import { GLYPH_URLS } from './models'; @@ -13,24 +13,25 @@ interface Props { function ErrorBars(props: Props) { const { barsSegments, capsPoints, color, visible } = props; - const barsGeometry = useUpdate( - (geometry: BufferGeometry) => geometry.setFromPoints(barsSegments), - [barsSegments] - ); - const capsGeometry = useUpdate( - (geometry) => geometry.setFromPoints(capsPoints), - [capsPoints] - ); + const barsGeometry = useRef(null); + useLayoutEffect(() => { + barsGeometry.current?.setFromPoints(barsSegments); + }, [barsGeometry, barsSegments]); + + const capsGeometry = useRef(null); + useLayoutEffect(() => { + capsGeometry.current?.setFromPoints(capsPoints); + }, [capsGeometry, capsPoints]); return ( <> - - + + - + ); diff --git a/src/h5web/vis-packs/core/line/GlyphMaterial.tsx b/src/h5web/vis-packs/core/line/GlyphMaterial.tsx index 2ffec8e58..02e8d41cc 100644 --- a/src/h5web/vis-packs/core/line/GlyphMaterial.tsx +++ b/src/h5web/vis-packs/core/line/GlyphMaterial.tsx @@ -1,4 +1,4 @@ -import { useLoader } from 'react-three-fiber'; +import { useLoader } from '@react-three/fiber'; import { NearestFilter, TextureLoader } from 'three'; import { GLYPH_URLS } from './models'; @@ -13,15 +13,7 @@ function GlyphMaterial(props: Props) { const sprite = useLoader(TextureLoader, glyphURL || GLYPH_URLS.Cross); sprite.magFilter = NearestFilter; - return ( - - ); + return ; } export default GlyphMaterial; diff --git a/src/h5web/vis-packs/core/line/hooks.ts b/src/h5web/vis-packs/core/line/hooks.ts index 4e39f6aa5..f4d51160d 100644 --- a/src/h5web/vis-packs/core/line/hooks.ts +++ b/src/h5web/vis-packs/core/line/hooks.ts @@ -1,5 +1,5 @@ import { useMemo } from 'react'; -import { useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; import { Vector3 } from 'three'; import { useCanvasScales } from '../hooks'; @@ -8,7 +8,7 @@ export function useCanvasPoints( ordinates: number[], errors?: number[] ) { - const { camera } = useThree(); + const camera = useThree((state) => state.camera); const { abscissaScale, ordinateScale } = useCanvasScales(); return useMemo(() => { diff --git a/src/h5web/vis-packs/core/shared/AxisSystem.tsx b/src/h5web/vis-packs/core/shared/AxisSystem.tsx index 70fc9c724..332c6ef8d 100644 --- a/src/h5web/vis-packs/core/shared/AxisSystem.tsx +++ b/src/h5web/vis-packs/core/shared/AxisSystem.tsx @@ -1,5 +1,5 @@ import { useContext } from 'react'; -import { useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; import Html from './Html'; import styles from './AxisSystem.module.css'; import type { AxisOffsets, Domain } from '../models'; @@ -17,8 +17,8 @@ function AxisSystem(props: Props) { const { abscissaConfig, ordinateConfig } = useContext(AxisSystemContext); - const { camera, size } = useThree(); - const { position, zoom } = camera; + const { position, zoom } = useThree((state) => state.camera); + const size = useThree((state) => state.size); const { width, height } = size; const { abscissaScale, ordinateScale } = useCanvasScales(); diff --git a/src/h5web/vis-packs/core/shared/Html.tsx b/src/h5web/vis-packs/core/shared/Html.tsx index 469853187..482a73b4b 100644 --- a/src/h5web/vis-packs/core/shared/Html.tsx +++ b/src/h5web/vis-packs/core/shared/Html.tsx @@ -6,7 +6,7 @@ import { useLayoutEffect, } from 'react'; import ReactDOM from 'react-dom'; -import { useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; // Simplified version of `drei`'s `` component // https://github.com/pmndrs/drei/blob/v2.2.3/src/Html.tsx @@ -14,15 +14,15 @@ const Html = forwardRef>( (props, ref) => { const { className, style, children, ...divProps } = props; - const { gl, size } = useThree(); - const { width, height } = size; + const { width, height } = useThree((state) => state.size); + const gl = useThree((state) => state.gl); const { parentElement } = gl.domElement; // Container `div` for ReactDOM to render into, appended next to R3F's `canvas` const [el] = useState(() => document.createElement('div')); useEffect(() => { - el.style.cssText = `position: absolute; top: 0; left: 0; z-index: 0;`; + el.style.cssText = `position: absolute; top: 0; left: 0;`; if (parentElement) { parentElement.append(el); @@ -48,6 +48,7 @@ const Html = forwardRef>( left: 0, width, height, + pointerEvents: 'none', // let pointer events pass through to canvas ...style, }} {...divProps} diff --git a/src/h5web/vis-packs/core/shared/PanZoomMesh.tsx b/src/h5web/vis-packs/core/shared/PanZoomMesh.tsx index 333e21297..5ce15cbc3 100644 --- a/src/h5web/vis-packs/core/shared/PanZoomMesh.tsx +++ b/src/h5web/vis-packs/core/shared/PanZoomMesh.tsx @@ -1,15 +1,17 @@ import { useRef, useCallback, useEffect } from 'react'; import type { Vector3 } from 'three'; -import { PointerEvent, WheelEvent, useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; import { clamp } from 'lodash-es'; import Html from './Html'; import { useWheelCapture } from '../hooks'; +import type { ThreeEvent } from '@react-three/fiber/dist/declarations/src/core/events'; const ZOOM_FACTOR = 0.95; function PanZoomMesh() { - const { camera, invalidate, size } = useThree(); - const { width, height } = size; + const camera = useThree((state) => state.camera); + const { width, height } = useThree((state) => state.size); + const invalidate = useThree((state) => state.invalidate); const startOffsetPosition = useRef(); // `useRef` to avoid re-renders @@ -33,9 +35,9 @@ function PanZoomMesh() { ); const onPointerDown = useCallback( - (evt: PointerEvent) => { - const { currentTarget, pointerId, unprojectedPoint } = evt; - currentTarget.setPointerCapture(pointerId); + (evt: ThreeEvent) => { + const { target, pointerId, unprojectedPoint } = evt; + (target as Element).setPointerCapture(pointerId); // https://stackoverflow.com/q/28900077/758806 const projectedPoint = camera.worldToLocal(unprojectedPoint.clone()); startOffsetPosition.current = camera.position.clone().add(projectedPoint); @@ -43,15 +45,15 @@ function PanZoomMesh() { [camera] ); - const onPointerUp = useCallback((evt: PointerEvent) => { - const { currentTarget, pointerId } = evt; - currentTarget.releasePointerCapture(pointerId); + const onPointerUp = useCallback((evt: ThreeEvent) => { + const { target, pointerId } = evt; + (target as Element).releasePointerCapture(pointerId); // https://stackoverflow.com/q/28900077/758806 startOffsetPosition.current = undefined; }, []); const onPointerMove = useCallback( - (evt: PointerEvent) => { + (evt: ThreeEvent) => { if (!startOffsetPosition.current) { return; } @@ -69,7 +71,7 @@ function PanZoomMesh() { ); const onWheel = useCallback( - (evt: WheelEvent) => { + (evt: ThreeEvent) => { const factor = evt.deltaY > 0 ? ZOOM_FACTOR : 1 / ZOOM_FACTOR; camera.zoom = Math.max(1, camera.zoom * factor); @@ -97,8 +99,8 @@ function PanZoomMesh() { return ( <> - - + + diff --git a/src/h5web/vis-packs/core/shared/TooltipMesh.tsx b/src/h5web/vis-packs/core/shared/TooltipMesh.tsx index 223435024..c2e11c0cb 100644 --- a/src/h5web/vis-packs/core/shared/TooltipMesh.tsx +++ b/src/h5web/vis-packs/core/shared/TooltipMesh.tsx @@ -1,10 +1,11 @@ import { useCallback } from 'react'; -import { PointerEvent, useThree } from 'react-three-fiber'; +import { useThree } from '@react-three/fiber'; import { TooltipWithBounds, useTooltip } from '@visx/tooltip'; import { Line } from '@visx/shape'; import Html from './Html'; import styles from './TooltipMesh.module.css'; import { useCanvasScales } from '../hooks'; +import type { ThreeEvent } from '@react-three/fiber/dist/declarations/src/core/events'; type Coords = [number, number]; type Guides = 'horizontal' | 'vertical' | 'both'; @@ -18,8 +19,8 @@ interface Props { function TooltipMesh(props: Props) { const { formatIndex, formatValue, guides } = props; - const { camera, size } = useThree(); - const { width, height } = size; + const camera = useThree((state) => state.camera); + const { width, height } = useThree((state) => state.size); // Scales to compute data coordinates from unprojected mesh coordinates const { abscissaScale, ordinateScale } = useCanvasScales(); @@ -36,7 +37,7 @@ function TooltipMesh(props: Props) { // Update tooltip when pointer moves // When panning, events are handled and stopped by texture mesh and do not reach this mesh (which is behind) const onPointerMove = useCallback( - (evt: PointerEvent) => { + (evt: ThreeEvent) => { const { zoom } = camera; const projectedPoint = camera.worldToLocal(evt.unprojectedPoint.clone()); @@ -58,8 +59,8 @@ function TooltipMesh(props: Props) { // Show tooltip after dragging unless pointer has left canvas const onPointerUp = useCallback( - (evt: PointerEvent) => { - const { offsetX: x, offsetY: y } = evt.nativeEvent; + (evt: ThreeEvent) => { + const { offsetX: x, offsetY: y } = evt; if (x >= 0 && x <= width && y >= 0 && y <= height) { onPointerMove(evt); } @@ -72,8 +73,8 @@ function TooltipMesh(props: Props) { return ( <> - - + + {tooltipOpen && tooltipData && value && ( diff --git a/src/h5web/vis-packs/core/shared/VisCanvas.tsx b/src/h5web/vis-packs/core/shared/VisCanvas.tsx index 38ff9527a..b4a6586e3 100644 --- a/src/h5web/vis-packs/core/shared/VisCanvas.tsx +++ b/src/h5web/vis-packs/core/shared/VisCanvas.tsx @@ -1,5 +1,5 @@ import type { ReactNode } from 'react'; -import { Canvas } from 'react-three-fiber'; +import { Canvas } from '@react-three/fiber'; import { useMeasure } from 'react-use'; import styles from './VisCanvas.module.css'; import type { AxisConfig } from '../models'; @@ -64,10 +64,10 @@ function VisCanvas(props: Props) {