refactor: bumped react18 to react19 along with associated deps and changes needed, long time coming, fixes #72, thanks @mmastrac for providing some of the groundwork - Stan

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Stan
2026-01-15 06:42:19 +00:00
parent 806cf08681
commit 2fa3a3c970
26 changed files with 171 additions and 228 deletions

284
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{
"name": "fossflow-monorepo",
"version": "1.9.0",
"version": "1.9.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "fossflow-monorepo",
"version": "1.9.0",
"version": "1.9.1",
"workspaces": [
"packages/*"
],
@@ -18,8 +18,8 @@
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@types/node": "^18.19.129",
"@types/react": "^18.3.26",
"@types/react-dom": "^18.3.7",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"semantic-release": "^25.0.2",
@@ -3308,69 +3308,30 @@
"license": "MIT"
},
"node_modules/@testing-library/react": {
"version": "14.3.1",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-14.3.1.tgz",
"integrity": "sha512-H99XjUhWQw0lTgyMN05W3xQG1Nh4lq574D8keFf1dDoNTJgp66VbJozRaczoF+wsiaPJNt/TcnfpLGufGxSrZQ==",
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.1.tgz",
"integrity": "sha512-gr4KtAWqIOQoucWYD/f6ki+j5chXfcPc74Col/6poTyqTmn7zRmodWahWRCp8tYd+GMqBonw6hstNzqjbs6gjw==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"@testing-library/dom": "^9.0.0",
"@types/react-dom": "^18.0.0"
"@babel/runtime": "^7.12.5"
},
"engines": {
"node": ">=14"
"node": ">=18"
},
"peerDependencies": {
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
},
"node_modules/@testing-library/react/node_modules/@testing-library/dom": {
"version": "9.3.4",
"resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-9.3.4.tgz",
"integrity": "sha512-FlS4ZWlp97iiNWig0Muq8p+3rVDjRiYE+YKGbAqXOu9nwJFFOdL00kFpz42M+4huzYi86vAK1sOOfyOG45muIQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.10.4",
"@babel/runtime": "^7.12.5",
"@types/aria-query": "^5.0.1",
"aria-query": "5.1.3",
"chalk": "^4.1.0",
"dom-accessibility-api": "^0.5.9",
"lz-string": "^1.5.0",
"pretty-format": "^27.0.2"
"@testing-library/dom": "^10.0.0",
"@types/react": "^18.0.0 || ^19.0.0",
"@types/react-dom": "^18.0.0 || ^19.0.0",
"react": "^18.0.0 || ^19.0.0",
"react-dom": "^18.0.0 || ^19.0.0"
},
"engines": {
"node": ">=14"
}
},
"node_modules/@testing-library/react/node_modules/aria-query": {
"version": "5.1.3",
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.1.3.tgz",
"integrity": "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==",
"dev": true,
"license": "Apache-2.0",
"dependencies": {
"deep-equal": "^2.0.5"
}
},
"node_modules/@testing-library/react/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
"peerDependenciesMeta": {
"@types/react": {
"optional": true
},
"@types/react-dom": {
"optional": true
}
}
},
"node_modules/@testing-library/user-event": {
@@ -3746,23 +3707,20 @@
}
},
"node_modules/@types/react": {
"version": "18.3.26",
"resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.26.tgz",
"integrity": "sha512-RFA/bURkcKzx/X9oumPG9Vp3D3JUgus/d0b67KB0t5S/raciymilkOa66olh78MUI92QLbEJevO7rvqU/kjwKA==",
"license": "MIT",
"version": "19.2.8",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.8.tgz",
"integrity": "sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==",
"dependencies": {
"@types/prop-types": "*",
"csstype": "^3.0.2"
"csstype": "^3.2.2"
}
},
"node_modules/@types/react-dom": {
"version": "18.3.7",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==",
"dev": true,
"license": "MIT",
"peerDependencies": {
"@types/react": "^18.0.0"
"@types/react": "^19.2.0"
}
},
"node_modules/@types/react-transition-group": {
@@ -5766,10 +5724,9 @@
}
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"license": "MIT"
"version": "3.2.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
"integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ=="
},
"node_modules/d3-array": {
"version": "3.2.4",
@@ -6025,46 +5982,6 @@
}
}
},
"node_modules/deep-equal": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz",
"integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==",
"dev": true,
"license": "MIT",
"dependencies": {
"array-buffer-byte-length": "^1.0.0",
"call-bind": "^1.0.5",
"es-get-iterator": "^1.1.3",
"get-intrinsic": "^1.2.2",
"is-arguments": "^1.1.1",
"is-array-buffer": "^3.0.2",
"is-date-object": "^1.0.5",
"is-regex": "^1.1.4",
"is-shared-array-buffer": "^1.0.2",
"isarray": "^2.0.5",
"object-is": "^1.1.5",
"object-keys": "^1.1.1",
"object.assign": "^4.1.4",
"regexp.prototype.flags": "^1.5.1",
"side-channel": "^1.0.4",
"which-boxed-primitive": "^1.0.2",
"which-collection": "^1.0.1",
"which-typed-array": "^1.1.13"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/deep-equal/node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true,
"license": "MIT"
},
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
@@ -6656,34 +6573,6 @@
"node": ">= 0.4"
}
},
"node_modules/es-get-iterator": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz",
"integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.2",
"get-intrinsic": "^1.1.3",
"has-symbols": "^1.0.3",
"is-arguments": "^1.1.1",
"is-map": "^2.0.2",
"is-set": "^2.0.2",
"is-string": "^1.0.7",
"isarray": "^2.0.5",
"stop-iteration-iterator": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/es-get-iterator/node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
"dev": true,
"license": "MIT"
},
"node_modules/es-iterator-helpers": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz",
@@ -8861,23 +8750,6 @@
"node": ">= 0.10"
}
},
"node_modules/is-arguments": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz",
"integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-array-buffer": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
@@ -14200,23 +14072,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-is": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
"integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"call-bind": "^1.0.7",
"define-properties": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object-keys": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
@@ -15276,6 +15131,7 @@
"resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
"integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
},
@@ -15288,6 +15144,7 @@
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
"integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0",
"scheduler": "^0.23.2"
@@ -15939,6 +15796,7 @@
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
"integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"loose-envify": "^1.1.0"
}
@@ -18977,15 +18835,15 @@
}
},
"packages/fossflow-app": {
"version": "1.9.0",
"version": "1.9.1",
"dependencies": {
"@isoflow/isopacks": "^0.0.10",
"fossflow": "^1.1.0",
"fossflow": "*",
"i18next": "^25.5.3",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-error-boundary": "^6.0.0",
"react-i18next": "^15.7.4",
"react-router-dom": "^7.9.6",
@@ -18996,12 +18854,36 @@
"@rsbuild/plugin-react": "^1.4.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^14.3.1",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.6.1"
}
},
"packages/fossflow-app/node_modules/react": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"engines": {
"node": ">=0.10.0"
}
},
"packages/fossflow-app/node_modules/react-dom": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"dependencies": {
"scheduler": "^0.27.0"
},
"peerDependencies": {
"react": "^19.2.3"
}
},
"packages/fossflow-app/node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="
},
"packages/fossflow-backend": {
"version": "1.9.0",
"version": "1.9.1",
"dependencies": {
"cors": "^2.8.5",
"dotenv": "^16.6.1",
@@ -19014,7 +18896,7 @@
},
"packages/fossflow-lib": {
"name": "fossflow",
"version": "1.9.0",
"version": "1.9.1",
"license": "MIT",
"dependencies": {
"@emotion/react": "^11.14.0",
@@ -19044,7 +18926,7 @@
"@rsbuild/plugin-react": "^1.4.1",
"@rslib/core": "^0.19.2",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^14.3.1",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.6.1",
"@types/chroma-js": "^2.4.5",
"@types/dom-to-image": "^2.6.7",
@@ -19067,8 +18949,8 @@
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^21.1.2",
"prettier": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"recharts": "^2.15.4",
"style-loader": "^3.3.4",
"ts-jest": "^29.4.4",
@@ -19076,8 +18958,8 @@
"typescript-eslint": "^8.46.0"
},
"peerDependencies": {
"react": ">=17",
"react-dom": ">=17"
"react": ">=18",
"react-dom": ">=18"
}
},
"packages/fossflow-lib/node_modules/@eslint/eslintrc": {
@@ -19628,6 +19510,25 @@
"node": ">=8"
}
},
"packages/fossflow-lib/node_modules/react": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react/-/react-19.2.3.tgz",
"integrity": "sha512-Ku/hhYbVjOQnXDZFv2+RibmLFGwFdeeKHFcOTlrt7xplBnya5OGn/hIRDsqDiSUcfORsDC7MPxwork8jBwsIWA==",
"engines": {
"node": ">=0.10.0"
}
},
"packages/fossflow-lib/node_modules/react-dom": {
"version": "19.2.3",
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.3.tgz",
"integrity": "sha512-yELu4WmLPw5Mr/lmeEpox5rw3RETacE++JgHqQzd2dg+YbJuat3jH4ingc+WPZhxaoFzdv9y33G+F7Nl5O0GBg==",
"dependencies": {
"scheduler": "^0.27.0"
},
"peerDependencies": {
"react": "^19.2.3"
}
},
"packages/fossflow-lib/node_modules/react-router-dom": {
"version": "6.30.3",
"resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
@@ -19658,6 +19559,11 @@
"react": ">=16.8"
}
},
"packages/fossflow-lib/node_modules/scheduler": {
"version": "0.27.0",
"resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz",
"integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q=="
},
"packages/fossflow-lib/node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",

View File

@@ -28,8 +28,8 @@
"@semantic-release/exec": "^7.1.0",
"@semantic-release/git": "^10.0.1",
"@types/node": "^18.19.129",
"@types/react": "^18.3.26",
"@types/react-dom": "^18.3.7",
"@types/react": "^19.0.0",
"@types/react-dom": "^19.0.0",
"conventional-changelog-conventionalcommits": "^9.1.0",
"cross-env": "^10.1.0",
"semantic-release": "^25.0.2",

View File

@@ -5,12 +5,12 @@
"description": "Progressive Web App for creating isometric diagrams",
"dependencies": {
"@isoflow/isopacks": "^0.0.10",
"fossflow": "^1.1.0",
"fossflow": "*",
"i18next": "^25.5.3",
"i18next-browser-languagedetector": "^8.2.0",
"i18next-http-backend": "^3.0.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-error-boundary": "^6.0.0",
"react-i18next": "^15.7.4",
"react-router-dom": "^7.9.6",
@@ -45,7 +45,7 @@
"@rsbuild/plugin-react": "^1.4.1",
"@testing-library/dom": "^10.4.1",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^14.3.1",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.6.1"
}
}

View File

@@ -1,11 +1,22 @@
import { defineConfig } from '@rsbuild/core';
import { pluginReact } from '@rsbuild/plugin-react';
import path from 'path';
const publicUrl = process.env.PUBLIC_URL || '';
const assetPrefix = publicUrl ? (publicUrl.endsWith('/') ? publicUrl : publicUrl + '/') : '/';
// Resolve React from root node_modules to avoid duplicate instances
const rootNodeModules = path.resolve(__dirname, '../../node_modules');
export default defineConfig({
plugins: [pluginReact()],
resolve: {
alias: {
// Force React to resolve from root node_modules
'react': path.join(rootNodeModules, 'react'),
'react-dom': path.join(rootNodeModules, 'react-dom'),
},
},
html: {
template: './public/index.html',
templateParameters: {

View File

@@ -4,6 +4,14 @@ module.exports = {
testEnvironment: "jsdom",
modulePaths: ['node_modules', '<rootDir>'],
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
moduleNameMapper: {
// Force React to resolve from root node_modules to avoid duplicate React instances
"^react$": "<rootDir>/../../node_modules/react",
"^react-dom$": "<rootDir>/../../node_modules/react-dom",
"^react-dom/client$": "<rootDir>/../../node_modules/react-dom/client",
"^react/jsx-runtime$": "<rootDir>/../../node_modules/react/jsx-runtime",
"^react/jsx-dev-runtime$": "<rootDir>/../../node_modules/react/jsx-dev-runtime"
},
testPathIgnorePatterns: [
'/node_modules/',
'/dist/',

View File

@@ -46,8 +46,8 @@
"zustand": "^4.5.7"
},
"peerDependencies": {
"react": ">=17",
"react-dom": ">=17"
"react": ">=18",
"react-dom": ">=18"
},
"devDependencies": {
"@eslint/js": "^9.37.0",
@@ -56,7 +56,7 @@
"@rsbuild/plugin-react": "^1.4.1",
"@rslib/core": "^0.19.2",
"@testing-library/jest-dom": "^6.9.1",
"@testing-library/react": "^14.3.1",
"@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.6.1",
"@types/chroma-js": "^2.4.5",
"@types/dom-to-image": "^2.6.7",
@@ -79,8 +79,8 @@
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^21.1.2",
"prettier": "^3.6.2",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"recharts": "^2.15.4",
"style-loader": "^3.3.4",
"ts-jest": "^29.4.4",

View File

@@ -7,7 +7,7 @@ import { useTranslation } from 'src/stores/localeStore';
const STORAGE_KEY = 'fossflow_connector_hint_dismissed';
interface Props {
toolMenuRef?: React.RefObject<HTMLElement>;
toolMenuRef?: React.RefObject<HTMLElement | null>;
}
export const ConnectorHintTooltip = ({ toolMenuRef }: Props) => {

View File

@@ -1,16 +1,22 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@mui/material/styles';
import { theme } from 'src/styles/theme';
import { LineItem } from '../LineItem';
const renderWithTheme = (ui: React.ReactElement) => {
return render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>);
};
describe('LineItem', () => {
it('renders title and value', () => {
render(<LineItem title="Test Title" value="Test Value" />);
renderWithTheme(<LineItem title="Test Title" value="Test Value" />);
expect(screen.getByText('Test Title')).toBeInTheDocument();
expect(screen.getByText('Test Value')).toBeInTheDocument();
});
it('matches snapshot', () => {
const { asFragment } = render(
const { asFragment } = renderWithTheme(
<LineItem title="Snapshot Title" value="Snapshot Value" />
);
expect(asFragment()).toMatchSnapshot();

View File

@@ -1,15 +1,21 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@mui/material/styles';
import { theme } from 'src/styles/theme';
import { Value } from '../Value';
const renderWithTheme = (ui: React.ReactElement) => {
return render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>);
};
describe('Value', () => {
it('renders value', () => {
render(<Value value="Test Value" />);
renderWithTheme(<Value value="Test Value" />);
expect(screen.getByText('Test Value')).toBeInTheDocument();
});
it('matches snapshot', () => {
const { asFragment } = render(<Value value="Snapshot Value" />);
const { asFragment } = renderWithTheme(<Value value="Snapshot Value" />);
expect(asFragment()).toMatchSnapshot();
});
});

View File

@@ -9,7 +9,7 @@ exports[`LineItem matches snapshot 1`] = `
class="MuiBox-root css-v7v99c"
>
<p
class="MuiTypography-root MuiTypography-body1 css-ahj2mt-MuiTypography-root"
class="MuiTypography-root MuiTypography-body1 css-b9d4f8-MuiTypography-root"
>
Snapshot Title
</p>
@@ -21,7 +21,7 @@ exports[`LineItem matches snapshot 1`] = `
class="MuiBox-root css-1xrtkr"
>
<p
class="MuiTypography-root MuiTypography-body2 css-1xnd8mx-MuiTypography-root"
class="MuiTypography-root MuiTypography-body2 css-1788z1s-MuiTypography-root"
>
Snapshot Value
</p>

View File

@@ -6,7 +6,7 @@ exports[`Value matches snapshot 1`] = `
class="MuiBox-root css-1xrtkr"
>
<p
class="MuiTypography-root MuiTypography-body2 css-1xnd8mx-MuiTypography-root"
class="MuiTypography-root MuiTypography-body2 css-1788z1s-MuiTypography-root"
>
Snapshot Value
</p>

View File

@@ -50,7 +50,7 @@ interface CropArea {
}
export const ExportImageDialog = ({ onClose, quality = 1.5 }: Props) => {
const containerRef = useRef<HTMLDivElement>();
const containerRef = useRef<HTMLDivElement>(null);
const cropCanvasRef = useRef<HTMLCanvasElement>(null);
const isExporting = useRef<boolean>(false);
const [isDragging, setIsDragging] = useState(false);

View File

@@ -32,7 +32,7 @@ export const NodeSettings = ({
// Local state for smooth slider interaction
const currentIcon = icons.find(icon => icon.id === modelItem?.icon);
const [localScale, setLocalScale] = useState(currentIcon?.scale || 1);
const debounceRef = useRef<NodeJS.Timeout>();
const debounceRef = useRef<NodeJS.Timeout | undefined>(undefined);
// Update local scale when icon changes
useEffect(() => {

View File

@@ -21,7 +21,7 @@ export const ExpandableLabel = ({
const editorMode = useUiStateStore((state) => state.editorMode);
const labelSettings = useUiStateStore((state) => state.labelSettings);
const [isExpanded, setIsExpanded] = useState(false);
const contentRef = useRef<HTMLDivElement>();
const contentRef = useRef<HTMLDivElement>(null);
const { observe, size: contentSize } = useResizeObserver();
useEffect(() => {

View File

@@ -22,7 +22,7 @@ export const Label = ({
sx,
showLine = true
}: Props) => {
const contentRef = useRef<HTMLDivElement>();
const contentRef = useRef<HTMLDivElement>(null);
return (
<Box

View File

@@ -1,11 +1,17 @@
import React from 'react';
import { render, screen } from '@testing-library/react';
import { ThemeProvider } from '@mui/material/styles';
import { theme } from 'src/styles/theme';
import { Label } from '../Label';
const renderWithTheme = (ui: React.ReactElement) => {
return render(<ThemeProvider theme={theme}>{ui}</ThemeProvider>);
};
describe('Label', () => {
describe('dotted line', () => {
it('should render dotted line with pointerEvents none to not block clicks', () => {
const { container } = render(
const { container } = renderWithTheme(
<Label maxWidth={200} labelHeight={50}>
<span>Test Label</span>
</Label>
@@ -21,7 +27,7 @@ describe('Label', () => {
});
it('should not render dotted line when labelHeight is 0', () => {
const { container } = render(
const { container } = renderWithTheme(
<Label maxWidth={200} labelHeight={0}>
<span>Test Label</span>
</Label>
@@ -32,7 +38,7 @@ describe('Label', () => {
});
it('should not render dotted line when showLine is false', () => {
const { container } = render(
const { container } = renderWithTheme(
<Label maxWidth={200} labelHeight={50} showLine={false}>
<span>Test Label</span>
</Label>
@@ -43,7 +49,7 @@ describe('Label', () => {
});
it('should render children correctly', () => {
render(
renderWithTheme(
<Label maxWidth={200} labelHeight={50}>
<span data-testid="label-content">Test Label Content</span>
</Label>

View File

@@ -7,7 +7,7 @@ import { useTranslation } from 'src/stores/localeStore';
const STORAGE_KEY = 'fossflow_lasso_hint_dismissed';
interface Props {
toolMenuRef?: React.RefObject<HTMLElement>;
toolMenuRef?: React.RefObject<HTMLElement | null>;
}
export const LassoHintTooltip = ({ toolMenuRef }: Props) => {

View File

@@ -18,8 +18,8 @@ import { useScene } from 'src/hooks/useScene';
import { RendererProps } from 'src/types/rendererProps';
export const Renderer = ({ showGrid, backgroundColor }: RendererProps) => {
const containerRef = useRef<HTMLDivElement>();
const interactionsRef = useRef<HTMLDivElement>();
const containerRef = useRef<HTMLDivElement>(null);
const interactionsRef = useRef<HTMLDivElement>(null);
const enableDebugTools = useUiStateStore((state) => {
return state.enableDebugTools;
});

View File

@@ -10,7 +10,7 @@ interface Props {
}
export const IsometricIcon = ({ url, scale = 1, onImageLoaded }: Props) => {
const ref = useRef();
const ref = useRef<HTMLImageElement>(null);
const { size, observe, disconnect } = useResizeObserver();
useEffect(() => {

View File

@@ -58,7 +58,7 @@ const getEditorModeMapping = (editorMode: keyof typeof EditorModeEnum) => {
export const UiOverlay = () => {
const theme = useTheme();
const contextMenuAnchorRef = useRef();
const contextMenuAnchorRef = useRef<HTMLDivElement>(null);
const toolMenuRef = useRef<HTMLDivElement>(null);
const { appPadding } = theme.customVars;
const spacing = useCallback(

View File

@@ -16,7 +16,7 @@ import { modelSchema } from 'src/schemas/model';
export const useInitialDataManager = () => {
const [isReady, setIsReady] = useState(false);
const prevInitialData = useRef<InitialData>();
const prevInitialData = useRef<InitialData | undefined>(undefined);
const model = useModelStore((state) => {
return state;
});

View File

@@ -2,7 +2,7 @@ import { useCallback, useEffect, useRef, useState } from 'react';
import { Size } from 'src/types';
export const useResizeObserver = (el?: HTMLElement | null) => {
const resizeObserverRef = useRef<ResizeObserver>();
const resizeObserverRef = useRef<ResizeObserver | undefined>(undefined);
const [size, setSize] = useState<Size>({ width: 0, height: 0 });
const disconnect = useCallback(() => {

View File

@@ -48,8 +48,8 @@ const getModeFunction = (mode: ModeActions, e: SlimMouseEvent) => {
};
export const useInteractionManager = () => {
const rendererRef = useRef<HTMLElement>();
const reducerTypeRef = useRef<string>();
const rendererRef = useRef<HTMLElement | undefined>(undefined);
const reducerTypeRef = useRef<string | undefined>(undefined);
const uiState = useUiStateStore((state) => {
return state;
});

View File

@@ -169,7 +169,7 @@ interface ProviderProps {
}
export const ModelProvider = ({ children }: ProviderProps) => {
const storeRef = useRef<ReturnType<typeof initialState>>();
const storeRef = useRef<ReturnType<typeof initialState> | undefined>(undefined);
if (!storeRef.current) {
storeRef.current = initialState();

View File

@@ -166,7 +166,7 @@ interface ProviderProps {
}
export const SceneProvider = ({ children }: ProviderProps) => {
const storeRef = useRef<ReturnType<typeof initialState>>();
const storeRef = useRef<ReturnType<typeof initialState> | undefined>(undefined);
if (!storeRef.current) {
storeRef.current = initialState();

View File

@@ -141,7 +141,7 @@ interface ProviderProps {
// TODO: Typings below are pretty gnarly due to the way Zustand works.
// see https://github.com/pmndrs/zustand/discussions/1180#discussioncomment-3439061
export const UiStateProvider = ({ children }: ProviderProps) => {
const storeRef = useRef<ReturnType<typeof initialState>>();
const storeRef = useRef<ReturnType<typeof initialState> | undefined>(undefined);
if (!storeRef.current) {
storeRef.current = initialState();