diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 0000000..939b9a1 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,28 @@ +/* eslint-env node */ + +module.exports = { + root: true, + env: { browser: true, es2020: true }, + extends: [ + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:@typescript-eslint/recommended-requiring-type-checking', + 'plugin:react-hooks/recommended', + ], + ignorePatterns: ['src/ReShaperDocument.d.ts', 'src/ReShaperDocument.js'], + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + project: true, + tsconfigRootDir: __dirname, + }, + plugins: ['react-refresh'], + rules: { + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + '@typescript-eslint/no-non-null-assertion': 'off', + }, +}; diff --git a/package-lock.json b/package-lock.json index d5c5a3d..6b8db57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46,14 +46,20 @@ "@types/react": "^17.0.69", "@types/react-dom": "^18.2.14", "@types/three": "^0.130.1", - "@types/wicg-file-system-access": "^2020.9.1", + "@types/wicg-file-system-access": "^2023.10.2", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.4.1", + "eslint": "^8.44.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.1", "husky": "^6.0.0", "jsdom": "^22.1.0", "node-fetch": "^2.6.1", "npm-run-all": "^4.1.5", "prettier": "^3.0.3", "tsx": "^3.14.0", + "type-fest": "^4.8.3", "typescript": "^4.9.5", "vite": "^4.5.0", "vite-plugin-svgr": "^4.1.0", @@ -61,6 +67,15 @@ "vitest": "^0.34.6" } }, + "node_modules/@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/@allejo/prettier-config": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@allejo/prettier-config/-/prettier-config-1.0.3.tgz", @@ -530,7 +545,6 @@ "version": "7.16.5", "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz", "integrity": "sha1-fz40v4vbut8D+7ex6g2SlWnJSHo= sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", - "dev": true, "dependencies": { "regenerator-runtime": "^0.13.4" }, @@ -978,6 +992,89 @@ "node": ">=12" } }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/@fortawesome/fontawesome-common-types": { "version": "0.2.36", "resolved": "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", @@ -1035,6 +1132,39 @@ "react": ">=16.x" } }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, "node_modules/@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -1072,12 +1202,6 @@ "@types/istanbul-lib-report": "*" } }, - "node_modules/@jest/types/node_modules/@types/node": { - "version": "14.11.10", - "resolved": "https://registry.yarnpkg.com/@types/node/-/node-14.11.10.tgz", - "integrity": "sha1-jBAquhO/UlPzUUav+/iyYnUGm+8= sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA==", - "dev": true - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", @@ -1371,14 +1495,6 @@ } } }, - "node_modules/@react-three/drei/node_modules/@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha1-tBFqa2cR0BCy2tO3tuQ78bmVR0A= sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - } - }, "node_modules/@react-three/fiber": { "version": "7.0.6", "resolved": "https://registry.yarnpkg.com/@react-three/fiber/-/fiber-7.0.6.tgz", @@ -1406,17 +1522,6 @@ } } }, - "node_modules/@react-three/fiber/node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha1-LhwogMoRjlsvmYgyK9inZWoyUCs= sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@rollup/pluginutils": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.5.tgz", @@ -1928,18 +2033,6 @@ "node": ">=12" } }, - "node_modules/@testing-library/dom/node_modules/@babel/runtime": { - "version": "7.16.5", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz", - "integrity": "sha1-fz40v4vbut8D+7ex6g2SlWnJSHo= sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", - "dev": true, - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@testing-library/dom/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz", @@ -2129,6 +2222,12 @@ "integrity": "sha1-nzPNb78NXsV13IyPxpx/7BtOsgA= sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg==", "dev": true }, + "node_modules/@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, "node_modules/@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", @@ -2167,12 +2266,6 @@ "form-data": "^3.0.0" } }, - "node_modules/@types/node-fetch/node_modules/@types/node": { - "version": "14.11.10", - "resolved": "https://registry.yarnpkg.com/@types/node/-/node-14.11.10.tgz", - "integrity": "sha1-jBAquhO/UlPzUUav+/iyYnUGm+8= sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA==", - "dev": true - }, "node_modules/@types/prop-types": { "version": "15.7.4", "resolved": "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.4.tgz", @@ -2205,6 +2298,12 @@ "integrity": "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk= sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "dev": true }, + "node_modules/@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, "node_modules/@types/testing-library__jest-dom": { "version": "5.14.2", "resolved": "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz", @@ -2231,9 +2330,9 @@ "dev": true }, "node_modules/@types/wicg-file-system-access": { - "version": "2020.9.1", - "resolved": "https://registry.yarnpkg.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.1.tgz", - "integrity": "sha1-rh9CCwynD1RchiGptj7SknDvcko= sha512-hEN/YpLwvDjhRJrKoBiyiKtIh2zNkmJ/GY9VWIXNgjy7TBZNM9upfb/rnWDGpOoLomnEQtlTBjFBFCDra1oxOQ==", + "version": "2023.10.2", + "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.2.tgz", + "integrity": "sha512-nSiK8qt0O7sQmDcW3HYfvya7GDoD6ipgdcUFzk3QN+UBIqXeNg38Nh6VnKv7EIPfkVETRiquyMskCbpxUzgX1Q==", "dev": true }, "node_modules/@types/yargs": { @@ -2251,6 +2350,274 @@ "integrity": "sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", "dev": true }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true + }, "node_modules/@vitejs/plugin-react-swc": { "version": "3.4.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react-swc/-/plugin-react-swc-3.4.1.tgz", @@ -2447,9 +2814,18 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-walk": { - "version": "8.3.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", "integrity": "sha512-FS7hV565M5l1R08MXqo8odwMTB02C2UqzB17RVgu9EyuYFBqJZ3/ZY97sQD5FewVu1UyDFc1yztUDrAwT0EypA==", "dev": true, "engines": { @@ -2468,6 +2844,31 @@ "node": ">= 6.0.0" } }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2509,6 +2910,15 @@ "node": ">=6.0" } }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -2965,6 +3375,12 @@ "node": ">=6" } }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "node_modules/default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -3088,6 +3504,18 @@ "node": ">=8" } }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/dom-accessibility-api": { "version": "0.5.10", "resolved": "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz", @@ -3206,12 +3634,266 @@ "node": ">=6" } }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.4.tgz", + "integrity": "sha512-eD83+65e8YPVg6603Om2iCIwcQJf/y7++MWm4tACtEswFLYMwxwVWAfwN+e19f5Ad/FOyyNg9Dfi5lXhH3Y3rA==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint/node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esquery/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esrecurse/node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -3256,6 +3938,18 @@ "node": ">=8.6.0" } }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "node_modules/fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -3270,6 +3964,18 @@ "resolved": "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz", "integrity": "sha1-X0D5ZZIFk2otGKv4iy53gWYrbUM= sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, "node_modules/file-saver": { "version": "2.0.5", "resolved": "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz", @@ -3286,6 +3992,42 @@ "node": ">=8" } }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "node_modules/form-data": { "version": "3.0.1", "resolved": "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz", @@ -3300,6 +4042,12 @@ "node": ">= 6" } }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -3396,6 +4144,26 @@ "url": "https://github.com/fisker/git-hooks-list?sponsor=1" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz", @@ -3452,6 +4220,12 @@ "integrity": "sha1-5BK40z9eAGWTy9PO5t+fLOu+gCo= sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "node_modules/hamt_plus": { "version": "1.0.2", "resolved": "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz", @@ -3626,6 +4400,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz", @@ -3635,6 +4418,16 @@ "node": ">=8" } }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz", @@ -3815,6 +4608,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -4038,6 +4840,12 @@ "node": ">=4" } }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "node_modules/json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -4050,6 +4858,18 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -4068,11 +4888,33 @@ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/ktx-parse": { "version": "0.2.1", "resolved": "https://registry.yarnpkg.com/ktx-parse/-/ktx-parse-0.2.1.tgz", "integrity": "sha1-aAXAkp6uCh9XGrPOeJ6GDpE1tDI= sha512-I+2mYJ6nQdWGmOlE3m9d9idKfhn2MCw04zaVpgtzyuc19uQ8OwRmmYLf/TP5ueVFfYmHbdpM8mPmId2X5PBLEw==" }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -4136,12 +4978,33 @@ "url": "https://github.com/sponsors/antfu" } }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz", "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/lodash.omit": { "version": "4.5.0", "resolved": "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -4181,6 +5044,18 @@ "tslib": "^2.0.3" } }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/lz-string": { "version": "1.4.4", "resolved": "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz", @@ -4313,9 +5188,9 @@ } }, "node_modules/minimatch": { - "version": "3.0.4", - "resolved": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -4364,6 +5239,18 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "node_modules/nice-try": { "version": "1.0.5", "resolved": "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz", @@ -4689,39 +5576,98 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/open": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", - "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "node_modules/open": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-9.1.0.tgz", + "integrity": "sha512-OS+QTnw1/4vrf+9hh1jc1jnYjzSG4ttTBB8UxOwAnInG3Uo4ssetzC1ihqaIHjLJnA5GGlRl6QlZXOTQhRBUvg==", + "dev": true, + "dependencies": { + "default-browser": "^4.0.0", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opentype.js": { + "version": "1.3.3", + "resolved": "https://registry.yarnpkg.com/opentype.js/-/opentype.js-1.3.3.tgz", + "integrity": "sha1-ZbhkWwkKGtREBlt4TUQvoZ0QYfY= sha512-/qIY/+WnKGlPIIPhbeNjynfD2PO15G9lA/xqlX2bDH+4lc3Xz5GCQ68mqxj3DdUv6AJqCeaPvuAoH8mVL0zcuA==", + "dependencies": { + "string.prototype.codepointat": "^0.2.1", + "tiny-inflate": "^1.0.3" + }, + "bin": { + "ot": "bin/ot" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "dependencies": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-limit/node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "dependencies": { - "default-browser": "^4.0.0", - "define-lazy-prop": "^3.0.0", - "is-inside-container": "^1.0.0", - "is-wsl": "^2.2.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=14.16" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/opentype.js": { - "version": "1.3.3", - "resolved": "https://registry.yarnpkg.com/opentype.js/-/opentype.js-1.3.3.tgz", - "integrity": "sha1-ZbhkWwkKGtREBlt4TUQvoZ0QYfY= sha512-/qIY/+WnKGlPIIPhbeNjynfD2PO15G9lA/xqlX2bDH+4lc3Xz5GCQ68mqxj3DdUv6AJqCeaPvuAoH8mVL0zcuA==", - "dependencies": { - "string.prototype.codepointat": "^0.2.1", - "tiny-inflate": "^1.0.3" - }, - "bin": { - "ot": "bin/ot" - }, - "engines": { - "node": ">= 8.0.0" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4764,6 +5710,24 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4876,6 +5840,15 @@ "resolved": "https://registry.yarnpkg.com/potpack/-/potpack-1.0.1.tgz", "integrity": "sha1-0bGv2J5Mj3dihl7DC9ESq3Z+Lr8= sha512-15vItUAbViaYrmaB/Pbw7z6qX2xENbFSTA7Ii4tgbPtasxm5v6ryKhKtL91tpWovDJzTiZqdwzhcFBCwiMVdVw==" }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/prettier": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", @@ -4924,15 +5897,6 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ= sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/pretty-format/node_modules/ansi-styles": { "version": "5.2.0", "resolved": "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz", @@ -5161,15 +6125,6 @@ "react": "^16.8.0 || ^17.0.0" } }, - "node_modules/reakit/node_modules/@popperjs/core": { - "version": "2.9.3", - "resolved": "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.3.tgz", - "integrity": "sha1-i2jaHr1/xgOZnPbr7jSkiZoUuI4= sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, "node_modules/recoil": { "version": "0.4.0", "resolved": "https://registry.yarnpkg.com/recoil/-/recoil-0.4.0.tgz", @@ -5259,6 +6214,21 @@ "node": ">=0.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -5774,6 +6744,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz", @@ -5807,6 +6789,18 @@ "node": ">=8" } }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/strip-literal": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", @@ -5859,6 +6853,12 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "node_modules/three": { "version": "0.129.0", "resolved": "https://registry.yarnpkg.com/three/-/three-0.129.0.tgz", @@ -5892,17 +6892,6 @@ "three": ">=0.128.0" } }, - "node_modules/three-stdlib/node_modules/@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha1-LhwogMoRjlsvmYgyK9inZWoyUCs= sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "dependencies": { - "regenerator-runtime": "^0.13.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/tiny-inflate": { "version": "1.0.3", "resolved": "https://registry.yarnpkg.com/tiny-inflate/-/tiny-inflate-1.0.3.tgz", @@ -6023,6 +7012,27 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/tsx": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", @@ -6040,6 +7050,18 @@ "fsevents": "~2.3.3" } }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, "node_modules/type-detect": { "version": "4.0.8", "resolved": "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz", @@ -6049,6 +7071,18 @@ "node": ">=4" } }, + "node_modules/type-fest": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.3.tgz", + "integrity": "sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -6142,6 +7176,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -6550,6 +7593,12 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "node_modules/yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", @@ -6582,6 +7631,12 @@ } }, "dependencies": { + "@aashutoshrathi/word-wrap": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", + "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", + "dev": true + }, "@allejo/prettier-config": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/@allejo/prettier-config/-/prettier-config-1.0.3.tgz", @@ -6952,7 +8007,6 @@ "version": "7.16.5", "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz", "integrity": "sha1-fz40v4vbut8D+7ex6g2SlWnJSHo= sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", - "dev": true, "requires": { "regenerator-runtime": "^0.13.4" } @@ -7186,6 +8240,61 @@ "dev": true, "optional": true }, + "@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "requires": { + "eslint-visitor-keys": "^3.3.0" + } + }, + "@eslint-community/regexpp": { + "version": "4.10.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.10.0.tgz", + "integrity": "sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==", + "dev": true + }, + "@eslint/eslintrc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "dev": true, + "requires": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "@eslint/js": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.52.0.tgz", + "integrity": "sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA==", + "dev": true + }, "@fortawesome/fontawesome-common-types": { "version": "0.2.36", "resolved": "https://registry.yarnpkg.com/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", @@ -7223,6 +8332,29 @@ "prop-types": "^15.7.2" } }, + "@humanwhocodes/config-array": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", + "integrity": "sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ==", + "dev": true, + "requires": { + "@humanwhocodes/object-schema": "^2.0.1", + "debug": "^4.1.1", + "minimatch": "^3.0.5" + } + }, + "@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true + }, + "@humanwhocodes/object-schema": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz", + "integrity": "sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==", + "dev": true + }, "@jest/schemas": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", @@ -7253,12 +8385,6 @@ "requires": { "@types/istanbul-lib-report": "*" } - }, - "@types/node": { - "version": "14.11.10", - "resolved": "https://registry.yarnpkg.com/@types/node/-/node-14.11.10.tgz", - "integrity": "sha1-jBAquhO/UlPzUUav+/iyYnUGm+8= sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA==", - "dev": true } } }, @@ -7504,16 +8630,6 @@ "use-asset": "^1.0.4", "utility-types": "^3.10.0", "zustand": "^3.5.1" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.12.1", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.12.1.tgz", - "integrity": "sha1-tBFqa2cR0BCy2tO3tuQ78bmVR0A= sha512-J5AIf3vPj3UwXaAzb5j1xM4WAQDX3EMgemF8rjCP3SoW09LfRKAXQKt6CoVYl230P6iWdRcBbnLDDdnqWxZSCA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "@react-three/fiber": { @@ -7531,16 +8647,6 @@ "use-asset": "^1.0.4", "utility-types": "^3.10.0", "zustand": "^3.5.1" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha1-LhwogMoRjlsvmYgyK9inZWoyUCs= sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "@rollup/pluginutils": { @@ -7807,15 +8913,6 @@ "pretty-format": "^27.0.2" }, "dependencies": { - "@babel/runtime": { - "version": "7.16.5", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.16.5.tgz", - "integrity": "sha1-fz40v4vbut8D+7ex6g2SlWnJSHo= sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, "chalk": { "version": "4.1.2", "resolved": "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz", @@ -7968,6 +9065,12 @@ "integrity": "sha1-nzPNb78NXsV13IyPxpx/7BtOsgA= sha512-5t9BhoORasuF5uCPr+d5/hdB++zRFUTMIZOzbNkr+jZh3yQht4HYbRDyj9fY8n2TZT30iW9huzav73x4NikqWg==", "dev": true }, + "@types/json-schema": { + "version": "7.0.14", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.14.tgz", + "integrity": "sha512-U3PUjAudAdJBeC2pgN8uTIKgxrb4nlDF3SF0++EldXQvQBGkpFZMSnwQiIoDU77tv45VgNkl/L4ouD+rEomujw==", + "dev": true + }, "@types/linkify-it": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/@types/linkify-it/-/linkify-it-3.0.2.tgz", @@ -8004,14 +9107,6 @@ "requires": { "@types/node": "*", "form-data": "^3.0.0" - }, - "dependencies": { - "@types/node": { - "version": "14.11.10", - "resolved": "https://registry.yarnpkg.com/@types/node/-/node-14.11.10.tgz", - "integrity": "sha1-jBAquhO/UlPzUUav+/iyYnUGm+8= sha512-yV1nWZPlMFpoXyoknm4S56y2nlTAuFYaJuQtYRAOU7xA/FJ9RY0Xm7QOkaYMMmr8ESdHIuUb6oQgR/0+2NqlyA==", - "dev": true - } } }, "@types/prop-types": { @@ -8046,6 +9141,12 @@ "integrity": "sha1-GmL4lSVyPd4kuhsBsJK/XfitTTk= sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", "dev": true }, + "@types/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-MMzuxN3GdFwskAnb6fz0orFvhfqi752yjaXylr0Rp4oDg5H0Zn1IuyRhDVvYOwAXoJirx2xuS16I3WjxnAIHiQ==", + "dev": true + }, "@types/testing-library__jest-dom": { "version": "5.14.2", "resolved": "https://registry.yarnpkg.com/@types/testing-library__jest-dom/-/testing-library__jest-dom-5.14.2.tgz", @@ -8074,24 +9175,182 @@ "dev": true }, "@types/wicg-file-system-access": { - "version": "2020.9.1", - "resolved": "https://registry.yarnpkg.com/@types/wicg-file-system-access/-/wicg-file-system-access-2020.9.1.tgz", - "integrity": "sha1-rh9CCwynD1RchiGptj7SknDvcko= sha512-hEN/YpLwvDjhRJrKoBiyiKtIh2zNkmJ/GY9VWIXNgjy7TBZNM9upfb/rnWDGpOoLomnEQtlTBjFBFCDra1oxOQ==", + "version": "2023.10.2", + "resolved": "https://registry.npmjs.org/@types/wicg-file-system-access/-/wicg-file-system-access-2023.10.2.tgz", + "integrity": "sha512-nSiK8qt0O7sQmDcW3HYfvya7GDoD6ipgdcUFzk3QN+UBIqXeNg38Nh6VnKv7EIPfkVETRiquyMskCbpxUzgX1Q==", + "dev": true + }, + "@types/yargs": { + "version": "16.0.4", + "resolved": "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz", + "integrity": "sha1-JqrZjdLCo45CEIbqmtQrnlFkKXc= sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "dev": true, + "requires": { + "@types/yargs-parser": "*" + } + }, + "@types/yargs-parser": { + "version": "15.0.0", + "resolved": "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", + "integrity": "sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "dev": true + }, + "@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "requires": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + } + }, + "@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "requires": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + } + }, + "@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", "dev": true }, - "@types/yargs": { - "version": "16.0.4", - "resolved": "https://registry.yarnpkg.com/@types/yargs/-/yargs-16.0.4.tgz", - "integrity": "sha1-JqrZjdLCo45CEIbqmtQrnlFkKXc= sha512-T8Yc9wt/5LbJyCaLiHPReJa0kApcIgJ7Bn735GjItUfh08Z1pJvu8QZqb9s+mMvKV6WUQRV7K2R46YbjMXTTJw==", + "@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "requires": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "dependencies": { + "globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "requires": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true + } + } + }, + "@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "dependencies": { + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, + "@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", "dev": true, "requires": { - "@types/yargs-parser": "*" + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" } }, - "@types/yargs-parser": { - "version": "15.0.0", - "resolved": "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-15.0.0.tgz", - "integrity": "sha1-yz+fdBhp4gzOMw/765JxWQSDiC0= sha512-FA/BWv8t8ZWJ+gEOnLLd8ygxH/2UFbAvgEonyfN6yWGLKc7zVjbpl2Y4CTjid9h2RfgPP6SEt6uHwEOply00yw==", + "@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, "@vitejs/plugin-react-swc": { @@ -8245,6 +9504,13 @@ "integrity": "sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==", "dev": true }, + "acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "requires": {} + }, "acorn-walk": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.0.tgz", @@ -8260,6 +9526,24 @@ "debug": "4" } }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -8289,6 +9573,12 @@ "integrity": "sha1-IQwhqvRpYT7oyaYsf4ZSXgWNtSw= sha512-V+SM7AbUwJ+EBnB8+DXs0hPZHO0W6pqBcc0dW90OwtVG02PswOu/teuARoLQjdDOH+t9pJgGnW5/Qmouf3gPJg==", "dev": true }, + "array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true + }, "assertion-error": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", @@ -8621,6 +9911,12 @@ "type-detect": "^4.0.0" } }, + "deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, "default-browser": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-4.0.0.tgz", @@ -8705,6 +10001,15 @@ "path-type": "^4.0.0" } }, + "doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, "dom-accessibility-api": { "version": "0.5.10", "resolved": "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.5.10.tgz", @@ -8798,12 +10103,193 @@ "integrity": "sha1-2M/ccACWXFoBdLSoLqpcBVJ0LkA= sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", "dev": true }, + "escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true + }, + "eslint": { + "version": "8.52.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.52.0.tgz", + "integrity": "sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "8.52.0", + "@humanwhocodes/config-array": "^0.11.13", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "dependencies": { + "eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + } + }, + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + }, + "glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "requires": { + "is-glob": "^4.0.3" + } + }, + "globals": { + "version": "13.23.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.23.0.tgz", + "integrity": "sha512-XAmF0RjlrjY23MA51q3HltdlGxUpXPvg0GioKiD9X6HD28iMjo2dKC8Vqwm7lne4GNr78+RHTfliktR6ZH09wA==", + "dev": true, + "requires": { + "type-fest": "^0.20.2" + } + }, + "type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true + } + } + }, + "eslint-plugin-react-hooks": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz", + "integrity": "sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==", + "dev": true, + "requires": {} + }, + "eslint-plugin-react-refresh": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.4.tgz", + "integrity": "sha512-eD83+65e8YPVg6603Om2iCIwcQJf/y7++MWm4tACtEswFLYMwxwVWAfwN+e19f5Ad/FOyyNg9Dfi5lXhH3Y3rA==", + "dev": true, + "requires": {} + }, + "eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "requires": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true + }, + "espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "requires": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + } + }, + "esquery": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", + "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "dev": true, + "requires": { + "estraverse": "^5.1.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "requires": { + "estraverse": "^5.2.0" + }, + "dependencies": { + "estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true + } + } + }, + "estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true + }, "estree-walker": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true }, + "esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true + }, "execa": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", @@ -8839,6 +10325,18 @@ "micromatch": "^4.0.4" } }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, "fastq": { "version": "1.15.0", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", @@ -8853,6 +10351,15 @@ "resolved": "https://registry.yarnpkg.com/fflate/-/fflate-0.6.10.tgz", "integrity": "sha1-X0D5ZZIFk2otGKv4iy53gWYrbUM= sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg==" }, + "file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "requires": { + "flat-cache": "^3.0.4" + } + }, "file-saver": { "version": "2.0.5", "resolved": "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz", @@ -8866,6 +10373,33 @@ "to-regex-range": "^5.0.1" } }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "flat-cache": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.1.tgz", + "integrity": "sha512-/qM2b3LUIaIgviBQovTLvijfyOQXPtSRnRK26ksj2J7rzPIecePUIpJsZ4T02Qg+xiAEKIs5K8dsHEd+VaKa/Q==", + "dev": true, + "requires": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + } + }, + "flatted": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.9.tgz", + "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", + "dev": true + }, "form-data": { "version": "3.0.1", "resolved": "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz", @@ -8877,6 +10411,12 @@ "mime-types": "^2.1.12" } }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true + }, "fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -8939,6 +10479,20 @@ "integrity": "sha512-LF8VeHeR7v+wAbXqfgRlTSX/1BJR9Q1vEMR8JAz1cEg6GX07+zyj3sAdDvYjj/xnlIfVuGgj4qBei1K3hKH+PA==", "dev": true }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz", @@ -8983,6 +10537,12 @@ "integrity": "sha1-5BK40z9eAGWTy9PO5t+fLOu+gCo= sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "hamt_plus": { "version": "1.0.2", "resolved": "https://registry.yarnpkg.com/hamt_plus/-/hamt_plus-1.0.2.tgz", @@ -9102,12 +10662,28 @@ "resolve-from": "^4.0.0" } }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true + }, "indent-string": { "version": "4.0.0", "resolved": "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha1-Yk+PRJfWGbLZdoUx1Y9BIoVNclE= sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "inherits": { "version": "2.0.4", "resolved": "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz", @@ -9222,6 +10798,12 @@ "has-tostringtag": "^1.0.0" } }, + "is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true + }, "is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -9378,6 +10960,12 @@ "integrity": "sha1-gFZNLkg9rPbo7yCWUKZ98/DCg6Q= sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true }, + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -9390,6 +10978,18 @@ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, "json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -9402,11 +11002,30 @@ "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", "dev": true }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "ktx-parse": { "version": "0.2.1", "resolved": "https://registry.yarnpkg.com/ktx-parse/-/ktx-parse-0.2.1.tgz", "integrity": "sha1-aAXAkp6uCh9XGrPOeJ6GDpE1tDI= sha512-I+2mYJ6nQdWGmOlE3m9d9idKfhn2MCw04zaVpgtzyuc19uQ8OwRmmYLf/TP5ueVFfYmHbdpM8mPmId2X5PBLEw==" }, + "levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + } + }, "lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -9457,12 +11076,27 @@ "integrity": "sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g==", "dev": true }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, "lodash": { "version": "4.17.21", "resolved": "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz", "integrity": "sha1-Z5WRxWTDv/quhFTPCz3zcMPWkRw= sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", "dev": true }, + "lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "lodash.omit": { "version": "4.5.0", "resolved": "https://registry.yarnpkg.com/lodash.omit/-/lodash.omit-4.5.0.tgz", @@ -9499,6 +11133,15 @@ "tslib": "^2.0.3" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, "lz-string": { "version": "1.4.4", "resolved": "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz", @@ -9594,9 +11237,9 @@ "dev": true }, "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM= sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -9630,6 +11273,18 @@ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==" }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true + }, "nice-try": { "version": "1.0.5", "resolved": "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz", @@ -9899,6 +11554,46 @@ "tiny-inflate": "^1.0.3" } }, + "optionator": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", + "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "dev": true, + "requires": { + "@aashutoshrathi/word-wrap": "^1.2.3", + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0" + } + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + }, + "dependencies": { + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, "parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -9929,6 +11624,18 @@ "entities": "^4.4.0" } }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -10003,6 +11710,12 @@ "resolved": "https://registry.yarnpkg.com/potpack/-/potpack-1.0.1.tgz", "integrity": "sha1-0bGv2J5Mj3dihl7DC9ESq3Z+Lr8= sha512-15vItUAbViaYrmaB/Pbw7z6qX2xENbFSTA7Ii4tgbPtasxm5v6ryKhKtL91tpWovDJzTiZqdwzhcFBCwiMVdVw==" }, + "prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true + }, "prettier": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", @@ -10031,12 +11744,6 @@ "react-is": "^17.0.1" }, "dependencies": { - "ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha1-CCyyyJyf6GWaMRpTvWpNxTAdswQ= sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true - }, "ansi-styles": { "version": "5.2.0", "resolved": "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz", @@ -10177,13 +11884,6 @@ "reakit-system": "^0.15.1", "reakit-utils": "^0.15.1", "reakit-warning": "^0.6.1" - }, - "dependencies": { - "@popperjs/core": { - "version": "2.9.3", - "resolved": "https://registry.yarnpkg.com/@popperjs/core/-/core-2.9.3.tgz", - "integrity": "sha1-i2jaHr1/xgOZnPbr7jSkiZoUuI4= sha512-xDu17cEfh7Kid/d95kB6tZsLOmSWKCZKtprnhVepjsSaCij+lM3mItSJDuuHDMbCWTh8Ejmebwb+KONcCJ0eXQ==" - } } }, "reakit-system": { @@ -10270,6 +11970,15 @@ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true }, + "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" + } + }, "rollup": { "version": "3.29.4", "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.4.tgz", @@ -10665,6 +12374,15 @@ "define-properties": "^1.1.3" } }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, "strip-bom": { "version": "3.0.0", "resolved": "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz", @@ -10686,6 +12404,12 @@ "min-indent": "^1.0.0" } }, + "strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true + }, "strip-literal": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-1.3.0.tgz", @@ -10726,6 +12450,12 @@ "tslib": "^2.5.0" } }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, "three": { "version": "0.129.0", "resolved": "https://registry.yarnpkg.com/three/-/three-0.129.0.tgz", @@ -10752,16 +12482,6 @@ "opentype.js": "^1.3.3", "potpack": "^1.0.1", "zstddec": "^0.0.2" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.15.3", - "resolved": "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.15.3.tgz", - "integrity": "sha1-LhwogMoRjlsvmYgyK9inZWoyUCs= sha512-OvwMLqNXkCXSz1kSm58sEsNuhqOx/fKpnUnKnFB5v8uDda5bLNEHNgKPvhDN6IU0LDcnHQ90LlJ0Q6jnyBSIBA==", - "requires": { - "regenerator-runtime": "^0.13.4" - } - } } }, "tiny-inflate": { @@ -10855,6 +12575,23 @@ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==", "dev": true }, + "tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "requires": { + "tslib": "^1.8.1" + }, + "dependencies": { + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + } + } + }, "tsx": { "version": "3.14.0", "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.14.0.tgz", @@ -10867,12 +12604,27 @@ "source-map-support": "^0.5.21" } }, + "type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "requires": { + "prelude-ls": "^1.2.1" + } + }, "type-detect": { "version": "4.0.8", "resolved": "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz", "integrity": "sha1-dkb7XxiHHPu3dJ5pvTmmOI63RQw= sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", "dev": true }, + "type-fest": { + "version": "4.8.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.8.3.tgz", + "integrity": "sha512-//BaTm14Q/gHBn09xlnKNqfI8t6bmdzx2DXYfPBNofN0WUybCEUDcbCWcTa0oF09lzLjZgPphXAsvRiMK0V6Bw==", + "dev": true + }, "typescript": { "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", @@ -10930,6 +12682,15 @@ "picocolors": "^1.0.0" } }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, "url-parse": { "version": "1.5.10", "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", @@ -11162,6 +12923,12 @@ "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", "dev": true }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, "yocto-queue": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz", diff --git a/package.json b/package.json index ecc13b6..38808f5 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "fetch:bzdb-docs": "tsx scripts/fetch-bzdb-definitions.ts", "fetch:flag-docs": "tsx scripts/fetch-flags.ts", "husky-setup": "husky install", - "lint": "eslint src/", + "lint": "eslint src --ext ts,tsx --report-unused-disable-directives --max-warnings 0", "prepare": "npm-run-all husky-setup fetch:*", "prettify": "prettier --write .", "start": "vite", @@ -27,20 +27,6 @@ ] }, "prettier": "@allejo/prettier-config", - "eslintConfig": { - "extends": "react-app", - "rules": { - "prefer-const": "error" - }, - "overrides": [ - { - "files": [ - "**/*.ts?(x)" - ], - "rules": {} - } - ] - }, "dependencies": { "@fortawesome/fontawesome-svg-core": "^1.2.35", "@fortawesome/free-brands-svg-icons": "^5.15.4", @@ -80,14 +66,20 @@ "@types/react": "^17.0.69", "@types/react-dom": "^18.2.14", "@types/three": "^0.130.1", - "@types/wicg-file-system-access": "^2020.9.1", + "@types/wicg-file-system-access": "^2023.10.2", + "@typescript-eslint/eslint-plugin": "^5.61.0", + "@typescript-eslint/parser": "^5.61.0", "@vitejs/plugin-react-swc": "^3.4.1", + "eslint": "^8.44.0", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-refresh": "^0.4.1", "husky": "^6.0.0", "jsdom": "^22.1.0", "node-fetch": "^2.6.1", "npm-run-all": "^4.1.5", "prettier": "^3.0.3", "tsx": "^3.14.0", + "type-fest": "^4.8.3", "typescript": "^4.9.5", "vite": "^4.5.0", "vite-plugin-svgr": "^4.1.0", diff --git a/src/3DModels/Abstract/SkinnableBox.tsx b/src/3DModels/Abstract/SkinnableBox.tsx index 06d2395..484e1ba 100644 --- a/src/3DModels/Abstract/SkinnableBox.tsx +++ b/src/3DModels/Abstract/SkinnableBox.tsx @@ -3,12 +3,12 @@ import React from 'react'; import { MeshBasicMaterial, Texture } from 'three'; import { useHighlightableEdges } from '../../hooks/useHighlightableEdges'; +import { Vector3F } from '../../Utilities/contracts'; import { assertEveryIsNotNull, isDevEnv, } from '../../Utilities/developmentUtilities'; import { deg2rad } from '../../Utilities/math'; -import { Vector3F } from '../../Utilities/types'; export type MaterialParams = ConstructorParameters[0]; @@ -16,7 +16,7 @@ interface Props { position: Vector3F; size: Vector3F; rotation: number; - onClick: (e: MouseEvent) => void; + onClick?: (e: MouseEvent) => void; isSelected?: boolean; isSelectable?: boolean; renderOrder?: number; @@ -108,7 +108,7 @@ const SkinnableBox = ({ const handleOnClick = (e: ThreeEvent) => { e.stopPropagation(); - onClick(e); + onClick?.(e); }; // If any of our faces are not configured, then we must force our box to diff --git a/src/3DModels/Ground.tsx b/src/3DModels/Ground.tsx index b3f1810..cd6660b 100644 --- a/src/3DModels/Ground.tsx +++ b/src/3DModels/Ground.tsx @@ -11,7 +11,6 @@ interface Props { } const Ground = ({ worldSize }: Props) => { - const noop = () => {}; const [grassTexture] = useLoader(TextureLoader, [grass]); grassTexture.wrapS = grassTexture.wrapT = RepeatWrapping; @@ -23,7 +22,6 @@ const Ground = ({ worldSize }: Props) => { position={[0, 0, 0]} size={[worldSize, worldSize, 0.01]} rotation={0} - onClick={noop} topTexture={grassTexture} botTexture={grassTexture} xPosTexture={grassTexture} diff --git a/src/3DModels/Tank.tsx b/src/3DModels/Tank.tsx index bc9c471..2c65607 100644 --- a/src/3DModels/Tank.tsx +++ b/src/3DModels/Tank.tsx @@ -1,6 +1,6 @@ import { ThreeEvent, useLoader } from '@react-three/fiber'; import React, { useEffect, useRef, useState } from 'react'; -import { BoxGeometry, EdgesGeometry, LineSegments } from 'three'; +import { BoxGeometry, EdgesGeometry, LineSegments, Object3D } from 'three'; import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'; import { ITankModel } from '../Document/Obstacles/TankModel'; diff --git a/src/3DModels/Wall.tsx b/src/3DModels/Wall.tsx index 01efbf1..33ac436 100644 --- a/src/3DModels/Wall.tsx +++ b/src/3DModels/Wall.tsx @@ -2,39 +2,32 @@ import { useLoader } from '@react-three/fiber'; import React, { useMemo } from 'react'; import { RepeatWrapping, TextureLoader } from 'three'; +import { CardinalDirection } from '../Utilities/contracts'; import SkinnableBox from './Abstract/SkinnableBox'; import worldWall from '../assets/wall.png'; -export enum Direction { - North, - South, - East, - West, -} - interface Props { - direction: Direction; + direction: CardinalDirection; wallHeight: number; worldSize: number; } const Wall = ({ direction, wallHeight, worldSize }: Props) => { - const noop = () => {}; const [wallTexture] = useLoader(TextureLoader, [worldWall]); const position: [number, number, number] = useMemo(() => { switch (direction) { - case Direction.North: + case CardinalDirection.North: return [0, worldSize, 0]; - case Direction.South: + case CardinalDirection.South: return [0, -worldSize, 0]; - case Direction.East: + case CardinalDirection.East: return [worldSize, 0, 0]; - case Direction.West: + case CardinalDirection.West: return [-worldSize, 0, 0]; default: @@ -43,8 +36,8 @@ const Wall = ({ direction, wallHeight, worldSize }: Props) => { }, [direction, worldSize]); const rotation: number = useMemo(() => { switch (direction) { - case Direction.North: - case Direction.South: + case CardinalDirection.North: + case CardinalDirection.South: return 0; default: @@ -61,7 +54,6 @@ const Wall = ({ direction, wallHeight, worldSize }: Props) => { position={position} size={[worldSize, 0.01, wallHeight]} rotation={rotation} - onClick={noop} topTexture={wallTexture} botTexture={wallTexture} xPosTexture={wallTexture} diff --git a/src/3DModels/WorldBorder.tsx b/src/3DModels/WorldBorder.tsx index 0496d07..ddf7473 100644 --- a/src/3DModels/WorldBorder.tsx +++ b/src/3DModels/WorldBorder.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import Wall, { Direction } from './Wall'; +import { CardinalDirection } from '../Utilities/contracts'; +import Wall from './Wall'; interface Props { wallHeight: number; @@ -15,22 +16,22 @@ const WorldBorder = ({ wallHeight, worldSize }: Props) => { return ( <> diff --git a/src/Components/Alert.tsx b/src/Components/Alert.tsx index 69c4c74..a3b9627 100644 --- a/src/Components/Alert.tsx +++ b/src/Components/Alert.tsx @@ -9,17 +9,11 @@ import { import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import React, { HTMLAttributes, ReactNode, useState } from 'react'; +import { AlertType } from '../Utilities/contracts'; import { classList } from '../Utilities/cssClasses'; import styles from './Alert.module.scss'; -export enum AlertType { - Info, - Success, - Warning, - Danger, -} - interface Props extends HTMLAttributes { type: AlertType; header: ReactNode; diff --git a/src/Components/Form/BaseFormField.tsx b/src/Components/Form/BaseFormField.tsx index fe47b39..b359719 100644 --- a/src/Components/Form/BaseFormField.tsx +++ b/src/Components/Form/BaseFormField.tsx @@ -1,61 +1,22 @@ import { faCaretDown } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import React, { - HTMLAttributes, - HTMLProps, - ReactNode, - SyntheticEvent, -} from 'react'; - +import React, { HTMLProps, SyntheticEvent } from 'react'; + +import { + assumeType, + FieldLayout, + FieldProps, + InputProps, + SelectProps, + SupportedFormElement, + TextareaProps, +} from '../../Utilities/contracts'; import { classList } from '../../Utilities/cssClasses'; import { slugify } from '../../Utilities/slugify'; -import { assumeType } from '../../Utilities/types'; import a11yStyles from '../../sass/a11yUtilities.module.scss'; import styles from './BaseFormField.module.scss'; -type SupportedHTMLElements = - | HTMLInputElement - | HTMLSelectElement - | HTMLTextAreaElement; - -export type ValueValidator = (value: T) => boolean; - -type BaseFieldProps = HTMLAttributes; -type Blacklist = 'onChange'; - -export enum FieldLayout { - Stacked = 'default', - Horizontal = 'horizontal', -} - -export interface FieldProps extends Omit { - className?: string; - disabled?: boolean; - hideLabel?: boolean; - layout?: FieldLayout; - label: string; - labelProps?: HTMLProps; - description?: string; - allowChange?: ValueValidator; - onChange: (value: T) => void; - value: T; -} - -type InputProps = { - tag: 'input'; - type: string; -}; - -type SelectProps = { - tag: 'select'; - children: ReactNode; -}; - -type TextareaProps = { - tag: 'textarea'; -}; - type Props = { /** * This callback is used to cast a string value into `T` that is used for @@ -110,7 +71,7 @@ const BaseFormField = ({ const elementId = labelProps.id ?? slugify(label); const isCheckbox = tag === 'input' && type === 'checkbox'; - const handleOnChange = (e: SyntheticEvent) => { + const handleOnChange = (e: SyntheticEvent) => { let castedValue; if (isCheckbox) { @@ -128,14 +89,14 @@ const BaseFormField = ({ }; const helpDescRaw: string[] = []; - const helpDescId: string = `${elementId}__helpDesc`; + const helpDescId = `${elementId}__helpDesc`; if (description) { helpDescRaw.push(description); } const helpDesc = helpDescRaw.join(' '); - const standardProps: HTMLProps = { + const standardProps: HTMLProps = { id: elementId, disabled: disabled, onChange: handleOnChange, diff --git a/src/Components/Form/CheckboxField.tsx b/src/Components/Form/CheckboxField.tsx index 00b8b5e..40575d3 100644 --- a/src/Components/Form/CheckboxField.tsx +++ b/src/Components/Form/CheckboxField.tsx @@ -1,13 +1,14 @@ import React from 'react'; -import BaseFormField, { FieldProps } from './BaseFormField'; +import { FieldProps } from '../../Utilities/contracts'; +import BaseFormField from './BaseFormField'; const CheckboxField = (props: FieldProps) => ( false} - castTypeToStr={(_) => ''} + castStrToType={() => false} + castTypeToStr={() => ''} {...props} /> ); diff --git a/src/Components/Form/NumberField.tsx b/src/Components/Form/NumberField.tsx index 7ea955c..2ccbfd8 100644 --- a/src/Components/Form/NumberField.tsx +++ b/src/Components/Form/NumberField.tsx @@ -1,8 +1,9 @@ import React, { KeyboardEvent, useState } from 'react'; +import { FieldProps } from '../../Utilities/contracts'; import keyboard from '../../Utilities/keyboard'; import { safeValueInRange } from '../../Utilities/math'; -import BaseFormField, { FieldProps } from './BaseFormField'; +import BaseFormField from './BaseFormField'; interface Props extends FieldProps { minValue?: number; @@ -88,7 +89,7 @@ const NumberField = ({ tag="input" type="number" castStrToType={(s) => (s === null || s === '' ? NaN : +s)} - castTypeToStr={(v) => (isNaN(v) ? '' : v + '')} + castTypeToStr={(v) => (isNaN(v) ? '' : String(v))} onChange={handleOnChange} onKeyDown={handleKeyPress} onBlur={handleOnBlur} diff --git a/src/Components/Form/SelectField.tsx b/src/Components/Form/SelectField.tsx index 23a7742..f7765a0 100644 --- a/src/Components/Form/SelectField.tsx +++ b/src/Components/Form/SelectField.tsx @@ -1,6 +1,7 @@ import React, { useMemo } from 'react'; -import BaseFormField, { FieldProps } from './BaseFormField'; +import { FieldProps } from '../../Utilities/contracts'; +import BaseFormField from './BaseFormField'; type KVPair = { key: string; @@ -25,7 +26,7 @@ function createKeyValuePairs(options: Props['options']): KVPair[] { interface Props extends FieldProps { disabledItems?: (number | string)[]; - formatValue?: (value: any) => string; + formatValue?: (value: string) => string; options: | string[] | Record>; @@ -63,7 +64,7 @@ const SelectField = ({ {options.map((option, index) => { if (Array.isArray(option.val)) { return ( - + {option.val.map(kvPairToJsx)} ); diff --git a/src/Components/Form/TextField.tsx b/src/Components/Form/TextField.tsx index d372d98..6650fd9 100644 --- a/src/Components/Form/TextField.tsx +++ b/src/Components/Form/TextField.tsx @@ -1,6 +1,7 @@ import React from 'react'; -import BaseFormField, { FieldProps } from './BaseFormField'; +import { FieldProps } from '../../Utilities/contracts'; +import BaseFormField from './BaseFormField'; const TextField = (props: FieldProps) => ( { - it('should trigger `onChange` callback when user types', () => { + it('should trigger `onChange` callback when user types', async () => { let currentValue = ''; const { getByLabelText } = render( @@ -23,10 +23,10 @@ describe('TextField Component', () => { const content = 'I am not log4j'; userEvent.type(field, content); - waitFor(() => expect(currentValue).toEqual(content)); + await waitFor(() => expect(currentValue).toEqual(content)); }); - it('should not let further changes when `allowChange` returns false', () => { + it('should not let further changes when `allowChange` returns false', async () => { let currentValue = ''; const { getByLabelText } = render( @@ -45,6 +45,6 @@ describe('TextField Component', () => { const content = 'I heart BZFlag'; userEvent.type(field, content); - waitFor(() => expect(currentValue).toEqual(content.substr(0, 5))); + await waitFor(() => expect(currentValue).toEqual(content.substr(0, 5))); }); }); diff --git a/src/Components/HixDocumentLoader.tsx b/src/Components/HixDocumentLoader.tsx index 755956e..3cfc5d8 100644 --- a/src/Components/HixDocumentLoader.tsx +++ b/src/Components/HixDocumentLoader.tsx @@ -1,4 +1,3 @@ -// @ts-ignore import hix from '../assets/hix.bzw?url'; import React, { useEffect } from 'react'; @@ -13,7 +12,8 @@ const HixDocumentLoader = () => { useEffect(() => { fetch(hix) .then((res) => res.text()) - .then((body) => setDocument(loadBZWDocument(body))); + .then((body) => setDocument(loadBZWDocument(body))) + .catch(console.error); }, [setDocument]); return
; diff --git a/src/Components/ListenerModal.tsx b/src/Components/ListenerModal.tsx index 3e12c63..dd8e68b 100644 --- a/src/Components/ListenerModal.tsx +++ b/src/Components/ListenerModal.tsx @@ -19,7 +19,12 @@ interface Props extends Omit { * * @see Modal */ -const ListenerModal = ({ event, dialog, onOpen, ...props }: Props) => { +const ListenerModal = ({ + event, + dialog, + onOpen, + ...props +}: Props) => { const [eventData, setEventData] = useState(); const eventBusCallbackId = useRef(''); @@ -39,7 +44,7 @@ const ListenerModal = ({ event, dialog, onOpen, ...props }: Props) => { let body: ReactNode | [ReactNode, ReactNode]; let footer: ReactNode | undefined; - if (typeof props.children === 'function') { + if (props.children instanceof Function) { const result = props.children(eventData); if (Array.isArray(result)) { diff --git a/src/Components/Modals/FlagSettingsModal.tsx b/src/Components/Modals/FlagSettingsModal.tsx index 3ba439c..0916640 100644 --- a/src/Components/Modals/FlagSettingsModal.tsx +++ b/src/Components/Modals/FlagSettingsModal.tsx @@ -38,8 +38,8 @@ const FlagSettingsModal = () => { draftWorld._options['-set'] = {}; } - draftWorld._options['-set']._flagAltitude = flagAltitude + ''; - draftWorld._options['-set']._flagHeight = flagHeight + ''; + draftWorld._options['-set']._flagAltitude = String(flagAltitude); + draftWorld._options['-set']._flagHeight = String(flagHeight); }); setBZWDocument(nextWorld); diff --git a/src/Components/Modals/TeleporterLinkEditorModal.tsx b/src/Components/Modals/TeleporterLinkEditorModal.tsx index 8f20a7d..a8117f6 100644 --- a/src/Components/Modals/TeleporterLinkEditorModal.tsx +++ b/src/Components/Modals/TeleporterLinkEditorModal.tsx @@ -24,8 +24,9 @@ import { TeleLinkEditorOpenEvent, TeleLinkEditorOpenEventName, } from '../../Events/ITeleLinkEditorOpenEvent'; +import { AlertType } from '../../Utilities/contracts'; import { classList } from '../../Utilities/cssClasses'; -import Alert, { AlertType } from '../Alert'; +import Alert from '../Alert'; import Button from '../Button'; import SelectField from '../Form/SelectField'; import ListenerModal from '../ListenerModal'; @@ -88,7 +89,7 @@ const LinkListItemAdder = ({ const teleUUIDs = world?._teleporters ?? []; const [teleName, setTeleName] = useState( - world?.children[teleUUIDs[0]].name, + (world?.children[teleUUIDs[0]]?.name as string) ?? '', ); const [teleUUID, setTeleUUID] = useState(teleUUIDs[0]); const [teleSide, setTeleSide] = useState( @@ -96,7 +97,7 @@ const LinkListItemAdder = ({ ); const handleTeleNameChange = (teleUUID: string) => { - setTeleName((world?.children[teleUUID] as ITeleporter).name!); + setTeleName((world?.children[teleUUID] as ITeleporter).name); setTeleUUID(teleUUID); }; const handleTeleSideChange = (value: string) => { @@ -107,7 +108,7 @@ const LinkListItemAdder = ({ ...newITeleporterLink(), _uuid: nanoid(), from: { - name: teleporter.name!, + name: teleporter.name, side: side, }, to: { @@ -127,7 +128,7 @@ const LinkListItemAdder = ({ options={Object.fromEntries( teleUUIDs.map((uuid) => [ uuid, - (world?.children[uuid] as ITeleporter).name!, + (world?.children[uuid] as ITeleporter).name, ]), )} hideLabel={true} diff --git a/src/Components/Modals/ZoneFlagEditorModal.tsx b/src/Components/Modals/ZoneFlagEditorModal.tsx index 1eea92a..e385106 100644 --- a/src/Components/Modals/ZoneFlagEditorModal.tsx +++ b/src/Components/Modals/ZoneFlagEditorModal.tsx @@ -9,7 +9,8 @@ import { ZoneEditorOpenEvent, ZoneEditorOpenEventName, } from '../../Events/IZoneEditorOpenEvent'; -import Alert, { AlertType } from '../Alert'; +import { AlertType } from '../../Utilities/contracts'; +import Alert from '../Alert'; import Button from '../Button'; import FlagListEditor from '../FlagListEditor'; import ListenerModal from '../ListenerModal'; diff --git a/src/Components/Panels/Inventory/ObstacleSummary.tsx b/src/Components/Panels/Inventory/ObstacleSummary.tsx index b7cb2fb..a6d0a32 100644 --- a/src/Components/Panels/Inventory/ObstacleSummary.tsx +++ b/src/Components/Panels/Inventory/ObstacleSummary.tsx @@ -13,6 +13,7 @@ import React, { import { useRecoilState, useRecoilValue } from 'recoil'; import { documentState, selectionState } from '../../../atoms'; +import { INameable } from '../../../Document/Attributes/INameable'; import { WorldEditorHelper } from '../../../Document/Editor/WorldEditorHelper'; import { IBase } from '../../../Document/Obstacles/Base'; import { IBaseObject } from '../../../Document/Obstacles/BaseObject'; @@ -33,7 +34,7 @@ import thumbZone from '../../../assets/thumb_zone.png'; import styles from './ObstacleSummary.module.scss'; interface Props { - obstacle: IBaseObject; + obstacle: IBaseObject & INameable; onClick: (event: MouseEvent, obstacle: IBaseObject) => void; selected: boolean; } @@ -72,9 +73,10 @@ function getThumbnail(object: IBaseObject): JSX.Element { return ; } -function getSummary(obstacle: IBaseObject): JSX.Element { +function getSummary(obstacle: IBaseObject & INameable): JSX.Element { const displayName = - obstacle.name || `${obstacle._objectType} ${obstacle._uuid.substr(0, 8)}`; + obstacle.name ?? + `${obstacle._objectType} ${obstacle._uuid.substring(0, 8)}`; if (obstacle._objectType === 'teleporter') { // display teleporters and their links diff --git a/src/Components/Panels/Menubar/CameraMenu/ResetMenuItem.tsx b/src/Components/Panels/Menubar/CameraMenu/ResetMenuItem.tsx index 83e1f70..99b27a2 100644 --- a/src/Components/Panels/Menubar/CameraMenu/ResetMenuItem.tsx +++ b/src/Components/Panels/Menubar/CameraMenu/ResetMenuItem.tsx @@ -9,7 +9,7 @@ import { import eventBus from '../../../../Utilities/EventBus'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const ResetMenuItem = ({ ...menu }: Props) => { const handleOnTriggerMenuItem = () => { diff --git a/src/Components/Panels/Menubar/DebugMenu/ToggleBzwViewMenuItem.tsx b/src/Components/Panels/Menubar/DebugMenu/ToggleBzwViewMenuItem.tsx index 1d2b2fc..d1f0185 100644 --- a/src/Components/Panels/Menubar/DebugMenu/ToggleBzwViewMenuItem.tsx +++ b/src/Components/Panels/Menubar/DebugMenu/ToggleBzwViewMenuItem.tsx @@ -6,7 +6,7 @@ import { useRecoilState } from 'recoil'; import { bzwViewState } from '../../../../atoms'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const ToggleBzwViewMenuItem = ({ ...menu }: Props) => { const [isVisible, setIsVisible] = useRecoilState(bzwViewState); diff --git a/src/Components/Panels/Menubar/FileMenu/NewMapMenuItem.tsx b/src/Components/Panels/Menubar/FileMenu/NewMapMenuItem.tsx index d18868a..8051246 100644 --- a/src/Components/Panels/Menubar/FileMenu/NewMapMenuItem.tsx +++ b/src/Components/Panels/Menubar/FileMenu/NewMapMenuItem.tsx @@ -7,7 +7,7 @@ import { documentState } from '../../../../atoms'; import { loadBZWDocument } from '../../../../Document/loadBZWDocument'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const NewMapMenuItem = ({ ...menu }: Props) => { const setDocument = useSetRecoilState(documentState); diff --git a/src/Components/Panels/Menubar/FileMenu/OpenMapMenuItem.tsx b/src/Components/Panels/Menubar/FileMenu/OpenMapMenuItem.tsx index 069afc3..3683603 100644 --- a/src/Components/Panels/Menubar/FileMenu/OpenMapMenuItem.tsx +++ b/src/Components/Panels/Menubar/FileMenu/OpenMapMenuItem.tsx @@ -11,7 +11,7 @@ import { } from '../../../../Utilities/filesystem'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn; const OpenMapMenuItem = ({ ...menu }: Props) => { const setDocument = useSetRecoilState(documentState); @@ -22,16 +22,20 @@ const OpenMapMenuItem = ({ ...menu }: Props) => { setDocument(loadBZWDocument(contents)); }; - const handleMenuItemClick = async () => { + const handleMenuItemClick = () => { if (supportsFilesystemAPI()) { try { - const [fileHandle] = await window.showOpenFilePicker( - defaultFilePickerOptions(), - ); - const file = await fileHandle.getFile(); + (async () => { + const [fileHandle] = await window.showOpenFilePicker( + defaultFilePickerOptions(), + ); + const file = await fileHandle.getFile(); - loadWorldFileContents(await file.text()); - setFileHandle(fileHandle); + loadWorldFileContents(await file.text()); + setFileHandle(fileHandle); + })().catch((e) => { + throw e; + }); } catch (e) { if (e instanceof DOMException) { // User aborted the file open operation diff --git a/src/Components/Panels/Menubar/FileMenu/SaveMapMenuItem.tsx b/src/Components/Panels/Menubar/FileMenu/SaveMapMenuItem.tsx index 4127e70..0959204 100644 --- a/src/Components/Panels/Menubar/FileMenu/SaveMapMenuItem.tsx +++ b/src/Components/Panels/Menubar/FileMenu/SaveMapMenuItem.tsx @@ -16,7 +16,7 @@ import { } from '../../../../Utilities/filesystem'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn; const SaveMapMenuItem = ({ ...menu }: Props) => { const document = useRecoilValue(documentState); @@ -39,21 +39,33 @@ const SaveMapMenuItem = ({ ...menu }: Props) => { return fileHandle; }; - const handleMenuItemClick = async () => { + const handleMenuItemClick = () => { // @TODO: Can our document state be null in this situation? Should we // disable the Save button at that point? const bzwRaw = exportBZWDocument(document); if (supportsFilesystemAPI()) { try { - const fileHandle = await getFileHandle(); - const stream = await fileHandle.createWritable(); + (async () => { + const fileHandle = await getFileHandle(); + const stream = await fileHandle.createWritable(); - await stream.write(bzwRaw); - await stream.close(); + await stream.write(bzwRaw); + await stream.close(); + })().catch((e) => { + throw e; + }); } catch (e) { - // If the user aborted the selection, disregard + if (!(e instanceof DOMException)) { + console.error(e); + + throw new Error( + 'Unknown error occurred while trying to open a file handle', + ); + } + if (e.code === DOMException.ABORT_ERR) { + // no-op: if the user aborted the selection, disregard } // @TODO: Handle other potential exception codes? diff --git a/src/Components/Panels/Menubar/HelpMenu/AboutMenuItem.tsx b/src/Components/Panels/Menubar/HelpMenu/AboutMenuItem.tsx index 7b8499f..945ccd5 100644 --- a/src/Components/Panels/Menubar/HelpMenu/AboutMenuItem.tsx +++ b/src/Components/Panels/Menubar/HelpMenu/AboutMenuItem.tsx @@ -9,7 +9,7 @@ import { import eventBus from '../../../../Utilities/EventBus'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const AboutMenuItem = ({ ...menu }: Props) => { const handleOnTriggerMenuItem = () => { diff --git a/src/Components/Panels/Menubar/ObjectMenu/ClearSelectionMenuItem.tsx b/src/Components/Panels/Menubar/ObjectMenu/ClearSelectionMenuItem.tsx index 2a14359..7375ec0 100644 --- a/src/Components/Panels/Menubar/ObjectMenu/ClearSelectionMenuItem.tsx +++ b/src/Components/Panels/Menubar/ObjectMenu/ClearSelectionMenuItem.tsx @@ -6,7 +6,7 @@ import { useRecoilState } from 'recoil'; import { selectionState } from '../../../../atoms'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const ClearSelectionMenuItem = ({ ...menu }: Props) => { const [selection, setSelection] = useRecoilState(selectionState); diff --git a/src/Components/Panels/Menubar/ObjectMenu/DeleteSelectedMenuItem.tsx b/src/Components/Panels/Menubar/ObjectMenu/DeleteSelectedMenuItem.tsx index 6424a89..317a09a 100644 --- a/src/Components/Panels/Menubar/ObjectMenu/DeleteSelectedMenuItem.tsx +++ b/src/Components/Panels/Menubar/ObjectMenu/DeleteSelectedMenuItem.tsx @@ -9,7 +9,7 @@ import { WorldEditorHelper } from '../../../../Document/Editor/WorldEditorHelper import { IWorld } from '../../../../Document/Obstacles/World'; import MenuItem from '../MenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const DeleteSelectedMenuItem = ({ ...menu }: Props) => { const [document, setDocument] = useRecoilState(documentState); diff --git a/src/Components/Panels/Menubar/WorldMenu/FlagSettingsMenuItem.tsx b/src/Components/Panels/Menubar/WorldMenu/FlagSettingsMenuItem.tsx index 4d37bf6..90b274c 100644 --- a/src/Components/Panels/Menubar/WorldMenu/FlagSettingsMenuItem.tsx +++ b/src/Components/Panels/Menubar/WorldMenu/FlagSettingsMenuItem.tsx @@ -8,7 +8,7 @@ import { } from '../../../../Events/IFlagSettingsModalOpenEvent'; import TriggerModalMenuItem from '../shared/TriggerModalMenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const FlagSettingsMenuItem = ({ ...menu }: Props) => ( diff --git a/src/Components/Panels/Menubar/WorldMenu/GameplaySettingsMenuItem.tsx b/src/Components/Panels/Menubar/WorldMenu/GameplaySettingsMenuItem.tsx index 2f6f75d..6dd5d71 100644 --- a/src/Components/Panels/Menubar/WorldMenu/GameplaySettingsMenuItem.tsx +++ b/src/Components/Panels/Menubar/WorldMenu/GameplaySettingsMenuItem.tsx @@ -8,7 +8,7 @@ import { } from '../../../../Events/IGameplaySettingsModalOpenEvent'; import TriggerModalMenuItem from '../shared/TriggerModalMenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const GameplaySettingsMenuItem = ({ ...menu }: Props) => ( diff --git a/src/Components/Panels/Menubar/WorldMenu/WorldSettingsMenuItem.tsx b/src/Components/Panels/Menubar/WorldMenu/WorldSettingsMenuItem.tsx index c541164..b920932 100644 --- a/src/Components/Panels/Menubar/WorldMenu/WorldSettingsMenuItem.tsx +++ b/src/Components/Panels/Menubar/WorldMenu/WorldSettingsMenuItem.tsx @@ -8,7 +8,7 @@ import { } from '../../../../Events/IWorldSettingsModalOpenEvent'; import TriggerModalMenuItem from '../shared/TriggerModalMenuItem'; -interface Props extends MenuStateReturn {} +type Props = MenuStateReturn const WorldSettingsMenuItem = ({ ...menu }: Props) => ( diff --git a/src/Components/Panels/Menubar/shared/TriggerModalMenuItem.tsx b/src/Components/Panels/Menubar/shared/TriggerModalMenuItem.tsx index 2c6b704..3684b45 100644 --- a/src/Components/Panels/Menubar/shared/TriggerModalMenuItem.tsx +++ b/src/Components/Panels/Menubar/shared/TriggerModalMenuItem.tsx @@ -9,7 +9,7 @@ interface Props extends Omit { menuName: string; } -const TriggerModalMenuItem = ({ +const TriggerModalMenuItem = ({ eventData, eventName, menuName, diff --git a/src/Components/Panels/Renderer/BZWDocumentRenderer.tsx b/src/Components/Panels/Renderer/BZWDocumentRenderer.tsx index b3c52de..863e0bc 100644 --- a/src/Components/Panels/Renderer/BZWDocumentRenderer.tsx +++ b/src/Components/Panels/Renderer/BZWDocumentRenderer.tsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { useRecoilState, useRecoilValue } from 'recoil'; +import React, { useCallback } from 'react'; +import { SetterOrUpdater, useRecoilState, useRecoilValue } from 'recoil'; import Base from '../../../3DModels/Base'; import Box from '../../../3DModels/Box'; @@ -20,14 +20,17 @@ import { import { ITeleporter } from '../../../Document/Obstacles/Teleporter'; import { IZone } from '../../../Document/Obstacles/Zone'; -function handleOnClick(uuid: string | null, setter: any) { - return () => setter(uuid); -} - const BZWDocumentRenderer = () => { const [selection, setSelection] = useRecoilState(selectionState); const document = useRecoilValue(documentState); + const handleOnClick = useCallback( + (uuid: string | null, setter: SetterOrUpdater) => { + return () => setter(uuid); + }, + [], + ); + if (document === null) { return null; } diff --git a/src/Components/Panels/Renderer/CameraControls.tsx b/src/Components/Panels/Renderer/CameraControls.tsx index a329db7..f8c0c6c 100644 --- a/src/Components/Panels/Renderer/CameraControls.tsx +++ b/src/Components/Panels/Renderer/CameraControls.tsx @@ -20,7 +20,7 @@ declare global { extend({ OrbitControls }); -const CameraControls: React.FC = (props) => { +const CameraControls = (props: typeof OrbitControls) => { const pageStatus = usePageStatus(); const cameraResetListener = useRef(''); @@ -28,7 +28,7 @@ const CameraControls: React.FC = (props) => { const { camera, gl } = useThree(); useEffect(() => { - // @ts-ignore + // @ts-expect-error listenToKeyEvents can work on the `window` object, I think? orbitRef.current?.listenToKeyEvents(window); }, [orbitRef]); @@ -68,7 +68,4 @@ const CameraControls: React.FC = (props) => { ); }; -export const CAMERA_DEFAULT_POS: [number, number, number] = [-15, 15, 15]; export default CameraControls; - -Object.freeze(CAMERA_DEFAULT_POS); diff --git a/src/Components/Panels/RendererPanel.tsx b/src/Components/Panels/RendererPanel.tsx index d51b27e..42c8448 100644 --- a/src/Components/Panels/RendererPanel.tsx +++ b/src/Components/Panels/RendererPanel.tsx @@ -2,8 +2,9 @@ import { Canvas } from '@react-three/fiber'; import React, { Suspense } from 'react'; import { useRecoilBridgeAcrossReactRoots_UNSTABLE } from 'recoil'; +import { CAMERA_DEFAULT_POS } from '../../Utilities/contracts'; import BZWDocumentRenderer from './Renderer/BZWDocumentRenderer'; -import CameraControls, { CAMERA_DEFAULT_POS } from './Renderer/CameraControls'; +import CameraControls from './Renderer/CameraControls'; const RendererPanel = () => { const RecoilBridge = useRecoilBridgeAcrossReactRoots_UNSTABLE(); diff --git a/src/Components/Panels/Toolbox/AlterableControl.tsx b/src/Components/Panels/Toolbox/AlterableControl.tsx index 55df9fe..4f614c9 100644 --- a/src/Components/Panels/Toolbox/AlterableControl.tsx +++ b/src/Components/Panels/Toolbox/AlterableControl.tsx @@ -1,28 +1,16 @@ import React from 'react'; import { IAlterable } from '../../../Document/Attributes/IAlterable'; -import { - implementsIPositionable, - IPositionable, -} from '../../../Document/Attributes/IPositionable'; +import { IPositionable } from '../../../Document/Attributes/IPositionable'; import { implementsISizeable } from '../../../Document/Attributes/ISizeable'; import { IBaseObject } from '../../../Document/Obstacles/BaseObject'; import { ITankModelObjectType } from '../../../Document/Obstacles/TankModel'; -import { Vector3F } from '../../../Utilities/types'; +import { Vector3F } from '../../../Utilities/contracts'; import NumberField from '../../Form/NumberField'; import Vector3FControl from './Vector3FControl'; import styles from './AlterableControl.module.scss'; -export function canUseAlterableControlToolbox( - value: any, -): value is IPositionable | IAlterable { - const isPositionable = implementsIPositionable(value); - const isISizeable = implementsISizeable(value); - - return isPositionable || (isPositionable && isISizeable); -} - type DataType = IBaseObject & (IPositionable | IAlterable); interface Props { diff --git a/src/Components/Panels/Toolbox/Vector3FControl.tsx b/src/Components/Panels/Toolbox/Vector3FControl.tsx index 84539ac..42b3540 100644 --- a/src/Components/Panels/Toolbox/Vector3FControl.tsx +++ b/src/Components/Panels/Toolbox/Vector3FControl.tsx @@ -1,7 +1,6 @@ import React from 'react'; -import { Vector3F } from '../../../Utilities/types'; -import { FieldLayout } from '../../Form/BaseFormField'; +import { FieldLayout, Vector3F } from '../../../Utilities/contracts'; import NumberField from '../../Form/NumberField'; import styles from './Vector3FControl.module.scss'; diff --git a/src/Components/Panels/ToolboxPanel.tsx b/src/Components/Panels/ToolboxPanel.tsx index 61e37a0..13143ad 100644 --- a/src/Components/Panels/ToolboxPanel.tsx +++ b/src/Components/Panels/ToolboxPanel.tsx @@ -3,6 +3,7 @@ import React, { useEffect, useState } from 'react'; import { useRecoilState, useRecoilValue } from 'recoil'; import { documentState, selectionState } from '../../atoms'; +import { canUseAlterableControlToolbox } from '../../Document/Attributes/helpers'; import { implementsIPassableObject, IPassableObject, @@ -14,7 +15,6 @@ import { IPyramid } from '../../Document/Obstacles/Pyramid'; import { ITeleporter } from '../../Document/Obstacles/Teleporter'; import { IZone } from '../../Document/Obstacles/Zone'; import AlterableControl, { - canUseAlterableControlToolbox, IAlterableControlDataType, } from './Toolbox/AlterableControl'; import BaseControl from './Toolbox/BaseControl'; @@ -45,9 +45,9 @@ const ToolboxPanel = () => { } const nextWorld = produce(world, (draftWorld) => { - const obstacle: IAlterableControlDataType = draftWorld.children[ + const obstacle = draftWorld.children[ selectedUUID - ] as any; + ] as IAlterableControlDataType; obstacle.position = data.position; obstacle.rotation = data.rotation; @@ -66,9 +66,8 @@ const ToolboxPanel = () => { } const nextWorld = produce(world, (draftWorld) => { - const obstacle: IPassableObject = draftWorld.children[ - selectedUUID - ] as any; + type PassableObject = IBaseObject & IPassableObject; + const obstacle = draftWorld.children[selectedUUID] as PassableObject; obstacle.drivethrough = data.drivethrough; obstacle.shootthrough = data.shootthrough; @@ -83,7 +82,7 @@ const ToolboxPanel = () => { } const nextWorld = produce(world, (draftWorld) => { - const obstacle: IPyramid = draftWorld.children[selectedUUID] as any; + const obstacle = draftWorld.children[selectedUUID] as IPyramid; obstacle.flipz = data.flipz; }); @@ -97,7 +96,7 @@ const ToolboxPanel = () => { } const nextWorld = produce(world, (draftWorld) => { - const obstacle: IBase = draftWorld.children[selectedUUID] as any; + const obstacle: IBase = draftWorld.children[selectedUUID] as IBase; obstacle.color = data.color; }); @@ -111,7 +110,7 @@ const ToolboxPanel = () => { } const nextWorld = produce(world, (draftWorld) => { - const obstacle: IZone = draftWorld.children[selectedUUID] as any; + const obstacle: IZone = draftWorld.children[selectedUUID] as IZone; obstacle.team = data.team; obstacle.safety = data.safety; diff --git a/src/Components/Timestamp.tsx b/src/Components/Timestamp.tsx index 522ee84..d958443 100644 --- a/src/Components/Timestamp.tsx +++ b/src/Components/Timestamp.tsx @@ -64,7 +64,7 @@ const Timestamp = (props: Props) => { // Only output a warning if we're in a non-production environment if (isDevEnv()) { - console.warn(`"${date}" is not a valid date value`); + console.warn(`Not a valid date value`, date); } } diff --git a/src/Components/ToggleTip.tsx b/src/Components/ToggleTip.tsx index 21e79c6..468f550 100644 --- a/src/Components/ToggleTip.tsx +++ b/src/Components/ToggleTip.tsx @@ -92,7 +92,8 @@ const ToggleTip = ({ }; }, [location, handleDomClick]); - popperRef.current?.update(); + // @TODO when can this fail? and what should I do about it? + popperRef.current?.update().catch(console.error); const bubbleStyles: object = { ...popperRef.current?.state.styles['popper'], diff --git a/src/Components/__tests__/FlagListEditor.tsx b/src/Components/__tests__/FlagListEditor.tsx index bd4868e..52c91c4 100644 --- a/src/Components/__tests__/FlagListEditor.tsx +++ b/src/Components/__tests__/FlagListEditor.tsx @@ -4,7 +4,9 @@ import React from 'react'; import FlagListEditor, { IFlagListEditorProps } from '../FlagListEditor'; -function noop() {} +function noop() { + // no-op +} describe('FlagListEditor Component', () => { it('should render with a no flags warning', () => { @@ -47,7 +49,7 @@ describe('FlagListEditor Component', () => { expect(flagCounts[0]).toHaveValue(5); }); - it('should support removing flags with counts', async () => { + it('should support removing flags with counts', () => { const props: IFlagListEditorProps = { allowCount: true, flags: [ diff --git a/src/Document/Attributes/IAlterable.ts b/src/Document/Attributes/IAlterable.ts index 5737108..14e7186 100644 --- a/src/Document/Attributes/IAlterable.ts +++ b/src/Document/Attributes/IAlterable.ts @@ -3,6 +3,6 @@ import { implementsISizeable, ISizeable } from './ISizeable'; export type IAlterable = IPositionable & ISizeable; -export function implementsIAlterable(value: any): value is IAlterable { +export function implementsIAlterable(value: object): value is IAlterable { return implementsIPositionable(value) && implementsISizeable(value); } diff --git a/src/Document/Attributes/IMaterialFriendly.ts b/src/Document/Attributes/IMaterialFriendly.ts index 205ba8f..83bc7df 100644 --- a/src/Document/Attributes/IMaterialFriendly.ts +++ b/src/Document/Attributes/IMaterialFriendly.ts @@ -3,7 +3,7 @@ export interface IMaterialFriendly { } export function implementsIMaterialFriendly( - value: any, + value: object, ): value is IMaterialFriendly { - return value.hasOwnProperty('matref'); + return 'matref' in value; } diff --git a/src/Document/Attributes/INameable.ts b/src/Document/Attributes/INameable.ts index b2d7e98..b7fbeab 100644 --- a/src/Document/Attributes/INameable.ts +++ b/src/Document/Attributes/INameable.ts @@ -2,6 +2,6 @@ export interface INameable { name?: string; } -export function implementsINameable(value: any): value is INameable { - return value.hasOwnProperty('name'); +export function implementsINameable(value: object): value is INameable { + return 'name' in value; } diff --git a/src/Document/Attributes/IPassableObject.ts b/src/Document/Attributes/IPassableObject.ts index 7309ac4..53abbe5 100644 --- a/src/Document/Attributes/IPassableObject.ts +++ b/src/Document/Attributes/IPassableObject.ts @@ -5,12 +5,26 @@ export interface IPassableObject { } export function implementsIPassableObject( - value: any, + value: object, ): value is IPassableObject { return ( - value.hasOwnProperty('drivethrough') && - value.hasOwnProperty('shootthrough') && - value.hasOwnProperty('passable') && + 'drivethrough' in value && + 'shootthrough' in value && + 'passable' in value && true ); } + +export function newIPassableObject(): IPassableObject { + return { + drivethrough: false, + shootthrough: false, + get passable(): boolean { + return this.drivethrough && this.shootthrough; + }, + set passable(value: boolean) { + this.drivethrough = value; + this.shootthrough = value; + }, + }; +} diff --git a/src/Document/Attributes/IPhysicsDriverFriendly.ts b/src/Document/Attributes/IPhysicsDriverFriendly.ts index afaaefb..9e089c8 100644 --- a/src/Document/Attributes/IPhysicsDriverFriendly.ts +++ b/src/Document/Attributes/IPhysicsDriverFriendly.ts @@ -3,7 +3,7 @@ export interface IPhysicsDriverFriendly { } export function implementsIPhysicsDriverFriendly( - value: any, + value: object, ): value is IPhysicsDriverFriendly { - return value.hasOwnProperty('phydrv'); + return 'phydrv' in value; } diff --git a/src/Document/Attributes/IPositionable.ts b/src/Document/Attributes/IPositionable.ts index 001c4ac..2dbbddf 100644 --- a/src/Document/Attributes/IPositionable.ts +++ b/src/Document/Attributes/IPositionable.ts @@ -1,10 +1,10 @@ -import { Vector3F } from '../../Utilities/types'; +import { Vector3F } from '../../Utilities/contracts'; export interface IPositionable { position: Vector3F; rotation?: number; } -export function implementsIPositionable(value: any): value is IPositionable { - return value.hasOwnProperty('position') && value.hasOwnProperty('rotation'); +export function implementsIPositionable(value: object): value is IPositionable { + return 'position' in value && 'rotation' in value; } diff --git a/src/Document/Attributes/ISizeable.ts b/src/Document/Attributes/ISizeable.ts index 1396a5b..d60ac26 100644 --- a/src/Document/Attributes/ISizeable.ts +++ b/src/Document/Attributes/ISizeable.ts @@ -1,9 +1,9 @@ -import { Vector3F } from '../../Utilities/types'; +import { Vector3F } from '../../Utilities/contracts'; export interface ISizeable { size: Vector3F; } -export function implementsISizeable(value: any): value is ISizeable { - return value.hasOwnProperty('size'); +export function implementsISizeable(value: object): value is ISizeable { + return 'size' in value; } diff --git a/src/Document/Attributes/helpers.ts b/src/Document/Attributes/helpers.ts new file mode 100644 index 0000000..45a0e1e --- /dev/null +++ b/src/Document/Attributes/helpers.ts @@ -0,0 +1,12 @@ +import { IAlterable } from './IAlterable'; +import { implementsIPositionable, IPositionable } from './IPositionable'; +import { implementsISizeable } from './ISizeable'; + +export function canUseAlterableControlToolbox( + value: object, +): value is IPositionable | IAlterable { + const isPositionable = implementsIPositionable(value); + const isISizeable = implementsISizeable(value); + + return isPositionable || (isPositionable && isISizeable); +} diff --git a/src/Document/Editor/ObstacleEditor.ts b/src/Document/Editor/ObstacleEditor.ts index f381bb6..dda6d86 100644 --- a/src/Document/Editor/ObstacleEditor.ts +++ b/src/Document/Editor/ObstacleEditor.ts @@ -1,6 +1,6 @@ import { removeItem } from '../../Utilities/arrays'; +import { assumeType } from '../../Utilities/contracts'; import { slugify } from '../../Utilities/slugify'; -import { assumeType } from '../../Utilities/types'; import { INameable } from '../Attributes/INameable'; import { IBaseObject } from '../Obstacles/BaseObject'; import { ITeleporter } from '../Obstacles/Teleporter'; @@ -21,7 +21,7 @@ export function addObstacle( if (obstacle._objectType === 'teleporter') { assumeType(obstacle); - obstacle.name = 'tele' + this.world._teleporters.length; + obstacle.name = `tele${this.world._teleporters.length}`; this.world._teleporters.push(obstacle._uuid); } diff --git a/src/Document/Editor/TeleporterEditor.ts b/src/Document/Editor/TeleporterEditor.ts index 8221d59..999477c 100644 --- a/src/Document/Editor/TeleporterEditor.ts +++ b/src/Document/Editor/TeleporterEditor.ts @@ -4,7 +4,7 @@ import { ITeleporterLink } from '../Obstacles/TeleporterLink'; import { IWorld } from '../Obstacles/World'; import { WorldEditorHelper } from './WorldEditorHelper'; -let areLinksCached: boolean = false; +let areLinksCached = false; let teleCache: Record = {}; export function addLink(this: WorldEditorHelper, link: ITeleporterLink) { @@ -82,7 +82,7 @@ function cacheLinks(world: IWorld): void { return; } - teleCache[teleporter.name!] = teleUUID; + teleCache[teleporter.name] = teleUUID; }); areLinksCached = true; diff --git a/src/Document/Obstacles/Base.ts b/src/Document/Obstacles/Base.ts index cbd6a13..19aa93c 100644 --- a/src/Document/Obstacles/Base.ts +++ b/src/Document/Obstacles/Base.ts @@ -1,17 +1,15 @@ -import { bzwFloat, bzwInt, bzwString, bzwVector3F } from '../attributeParsers'; +import { + bzwFloat, + bzwInt, + BZWObjectProperties, + bzwString, + bzwVector3F, +} from '../attributeParsers'; import { INameable } from '../Attributes/INameable'; import { IPositionable } from '../Attributes/IPositionable'; import { ISizeable } from '../Attributes/ISizeable'; import { IBaseObject, newIBaseObject } from './BaseObject'; -export const BaseProperties = { - position: bzwVector3F, - size: bzwVector3F, - rotation: bzwFloat, - color: bzwInt, - oncap: bzwString, -}; - export interface IBase extends IBaseObject, INameable, @@ -21,6 +19,14 @@ export interface IBase oncap?: string; } +export const BaseProperties: BZWObjectProperties = { + position: bzwVector3F, + size: bzwVector3F, + rotation: bzwFloat, + color: bzwInt, + oncap: bzwString, +}; + export function newIBase(): IBase { return { ...newIBaseObject('base'), diff --git a/src/Document/Obstacles/BaseObject.ts b/src/Document/Obstacles/BaseObject.ts index cc56f54..e9b7f91 100644 --- a/src/Document/Obstacles/BaseObject.ts +++ b/src/Document/Obstacles/BaseObject.ts @@ -1,33 +1,16 @@ -import { IPassableObject } from '../Attributes/IPassableObject'; +import { MapObjectType } from '../contracts'; export interface IBaseObject { - [key: string]: any; + [key: string]: unknown; _uuid: string; _objectType: string; _infoString: string; _terminator: string; - children: Record; + children: Record; } -export function newIPassableObject(): IPassableObject { - return { - drivethrough: false, - shootthrough: false, - get passable(): boolean { - return this.drivethrough && this.shootthrough; - }, - set passable(value: boolean) { - this.drivethrough = value; - this.shootthrough = value; - }, - }; -} - -export function newIBaseObject( - objectType: string, - uuid: string = '', -): IBaseObject { +export function newIBaseObject(objectType: string, uuid = ''): IBaseObject { return { _uuid: uuid, _objectType: objectType, diff --git a/src/Document/Obstacles/Box.ts b/src/Document/Obstacles/Box.ts index 80d9a9a..a3dd6d0 100644 --- a/src/Document/Obstacles/Box.ts +++ b/src/Document/Obstacles/Box.ts @@ -1,13 +1,22 @@ -import { bzwBool, bzwFloat, bzwString, bzwVector3F } from '../attributeParsers'; +import { + bzwBool, + bzwFloat, + BZWObjectProperties, + bzwString, + bzwVector3F, +} from '../attributeParsers'; import { IMaterialFriendly } from '../Attributes/IMaterialFriendly'; import { INameable } from '../Attributes/INameable'; -import { IPassableObject } from '../Attributes/IPassableObject'; +import { + IPassableObject, + newIPassableObject, +} from '../Attributes/IPassableObject'; import { IPhysicsDriverFriendly } from '../Attributes/IPhysicsDriverFriendly'; import { IPositionable } from '../Attributes/IPositionable'; import { ISizeable } from '../Attributes/ISizeable'; -import { IBaseObject, newIBaseObject, newIPassableObject } from './BaseObject'; +import { IBaseObject, newIBaseObject } from './BaseObject'; -export const BoxProperties = { +export const BoxProperties: BZWObjectProperties = { name: bzwString, position: bzwVector3F, size: bzwVector3F, diff --git a/src/Document/Obstacles/Material.ts b/src/Document/Obstacles/Material.ts index c7884ab..4cb31f9 100644 --- a/src/Document/Obstacles/Material.ts +++ b/src/Document/Obstacles/Material.ts @@ -1,35 +1,14 @@ -import { Vector4F } from '../../Utilities/types'; -import { bzwBool, bzwFloat, bzwString, bzwVector4F } from '../attributeParsers'; +import { Vector4F } from '../../Utilities/contracts'; +import { + bzwBool, + bzwFloat, + BZWObjectProperties, + bzwString, + bzwVector4F, +} from '../attributeParsers'; import { INameable } from '../Attributes/INameable'; import { IBaseObject, newIBaseObject } from './BaseObject'; -export const MaterialProperties = { - name: bzwString, - texture: bzwString, - addtexture: bzwString, - notextures: bzwBool, - notexcolor: bzwBool, - notexalpha: bzwBool, - texmat: bzwString, - dyncol: bzwString, - ambient: bzwVector4F, - diffuse: bzwVector4F, - color: bzwVector4F, - specular: bzwVector4F, - emission: bzwVector4F, - shininess: bzwFloat, - resetmat: bzwBool, - spheremap: bzwBool, - noradar: bzwBool, - noshadow: bzwBool, - noculling: bzwBool, - nosorting: bzwBool, - nolighting: bzwBool, - alphathresh: bzwFloat, - groupalpha: bzwBool, - occluder: bzwBool, -}; - export interface IMaterial extends IBaseObject, INameable { texture?: string; addtexture?: string; @@ -56,6 +35,33 @@ export interface IMaterial extends IBaseObject, INameable { occluder?: boolean; } +export const MaterialProperties: BZWObjectProperties = { + name: bzwString, + texture: bzwString, + addtexture: bzwString, + notextures: bzwBool, + notexcolor: bzwBool, + notexalpha: bzwBool, + texmat: bzwString, + dyncol: bzwString, + ambient: bzwVector4F, + diffuse: bzwVector4F, + color: bzwVector4F, + specular: bzwVector4F, + emission: bzwVector4F, + shininess: bzwFloat, + resetmat: bzwBool, + spheremap: bzwBool, + noradar: bzwBool, + noshadow: bzwBool, + noculling: bzwBool, + nosorting: bzwBool, + nolighting: bzwBool, + alphathresh: bzwFloat, + groupalpha: bzwBool, + occluder: bzwBool, +}; + export function newIMaterial(): IMaterial { return { ...newIBaseObject('material'), diff --git a/src/Document/Obstacles/Mesh.ts b/src/Document/Obstacles/Mesh.ts index 1c8fecf..8964c3b 100644 --- a/src/Document/Obstacles/Mesh.ts +++ b/src/Document/Obstacles/Mesh.ts @@ -1,7 +1,8 @@ -import { Vector3F } from '../../Utilities/types'; +import { Vector3F } from '../../Utilities/contracts'; import { bzwBool, bzwFloatVector, + BZWObjectProperties, bzwRepeatable, bzwString, bzwVector3F, @@ -11,7 +12,21 @@ import { IPhysicsDriverFriendly } from '../Attributes/IPhysicsDriverFriendly'; import { IBaseObject, newIBaseObject } from './BaseObject'; import { IMeshFace } from './MeshFace'; -export const MeshProperties = { +export interface IMesh extends IBaseObject, INameable, IPhysicsDriverFriendly { + inside?: Vector3F[]; + outside?: Vector3F[]; + vertex?: Vector3F[]; + normal?: number[]; + texcoord?: number[]; + shift?: Vector3F[]; + scale?: Vector3F[]; + shear?: Vector3F[]; + spin?: number[]; + smoothbounce?: boolean; + noclusters?: boolean; +} + +export const MeshProperties: BZWObjectProperties = { name: bzwString, inside: bzwRepeatable(bzwVector3F), outside: bzwRepeatable(bzwVector3F), @@ -27,25 +42,11 @@ export const MeshProperties = { noclusters: bzwBool, }; -export interface IMesh extends IBaseObject, INameable, IPhysicsDriverFriendly { - inside?: Vector3F[]; - outside?: Vector3F[]; - vertex?: Vector3F[]; - normal?: number[]; - texcoord?: number[]; - shift?: Vector3F[]; - scale?: Vector3F[]; - shear?: Vector3F[]; - spin?: number[]; - smoothbounce?: boolean; - noclusters?: boolean; -} - export function newIMesh(): IMesh { return { ...newIBaseObject('mesh'), get faces(): IMeshFace[] { - return Object.values(this.children) as IMeshFace[]; + return Object.values(this.children as Record); }, }; } diff --git a/src/Document/Obstacles/MeshFace.ts b/src/Document/Obstacles/MeshFace.ts index e7bf98a..4f1184a 100644 --- a/src/Document/Obstacles/MeshFace.ts +++ b/src/Document/Obstacles/MeshFace.ts @@ -1,9 +1,28 @@ -import { bzwBool, bzwIntVector, bzwString } from '../attributeParsers'; +import { + bzwBool, + bzwIntVector, + BZWObjectProperties, + bzwString, +} from '../attributeParsers'; import { IMaterialFriendly } from '../Attributes/IMaterialFriendly'; -import { IPassableObject } from '../Attributes/IPassableObject'; -import { IBaseObject, newIBaseObject, newIPassableObject } from './BaseObject'; +import { + IPassableObject, + newIPassableObject, +} from '../Attributes/IPassableObject'; +import { IBaseObject, newIBaseObject } from './BaseObject'; -export const MeshFaceProperties = { +export interface IMeshFace + extends IBaseObject, + IMaterialFriendly, + IPassableObject { + vertices?: number[]; + normals?: number[]; + texcoords?: number[]; + smoothbounce?: boolean; + noclusters?: boolean; +} + +export const MeshFaceProperties: BZWObjectProperties = { vertices: bzwIntVector, normals: bzwIntVector, texcoords: bzwIntVector, @@ -16,17 +35,6 @@ export const MeshFaceProperties = { matref: bzwString, }; -export interface IMeshFace - extends IBaseObject, - IMaterialFriendly, - IPassableObject { - vertices?: number[]; - normals?: number[]; - texcoords?: number[]; - smoothbounce?: boolean; - noclusters?: boolean; -} - export function newIMeshFace(): IMeshFace { return { ...newIBaseObject('face'), diff --git a/src/Document/Obstacles/Option.ts b/src/Document/Obstacles/Option.ts index 0ffbb55..aaeb836 100644 --- a/src/Document/Obstacles/Option.ts +++ b/src/Document/Obstacles/Option.ts @@ -3,6 +3,8 @@ import { bzwBool, bzwHashable, bzwInt, + BZWObjectProperties, + BZWParseLine, bzwRepeatable, bzwString, } from '../attributeParsers'; @@ -44,7 +46,7 @@ export type MaxPlayersVerbose = { export type MaxPlayers = MaxPlayersSimple | MaxPlayersVerbose; -export function bzwAccelerations(input: string): Accelerations { +const bzwAccelerations: BZWParseLine = (input) => { const accArray = input.split(' '); const linear = accArray[0] ? parseInt(accArray[0]) : 50; const angular = accArray[1] ? parseInt(accArray[1]) : 38; @@ -53,13 +55,13 @@ export function bzwAccelerations(input: string): Accelerations { linear: linear, angular: angular, }; -} +}; -export function bzwBZDBSetting(input: string): [string, string] { +const bzwBZDBSetting: BZWParseLine<[string, string]> = (input) => { return input.split(' ') as [string, string]; -} +}; -export function bzwShotLimit(input: string): ShotLimit { +const bzwShotLimit: BZWParseLine = (input) => { const slArray = input.split(' '); const id = slArray[0]; const num = parseInt(slArray[1]); @@ -68,13 +70,13 @@ export function bzwShotLimit(input: string): ShotLimit { flag: id, num: num, }; -} +}; -export function bzwRabbitMode(value: string): RabbitMode { +const bzwRabbitMode: BZWParseLine = (value) => { return value as RabbitMode; -} +}; -export function bzwMaxPlayers(input: string): MaxPlayers { +const bzwMaxPlayers: BZWParseLine = (input) => { const maxMPArray = input.split(','); if (maxMPArray.length === 1) { @@ -91,9 +93,9 @@ export function bzwMaxPlayers(input: string): MaxPlayers { purple: parseInt(maxMPArray[4]) || 0, observer: parseInt(maxMPArray[5]) || 0, }; -} +}; -export function bzwFlag(input: string): FlagCount { +const bzwFlag: BZWParseLine = (input) => { const flagArray = input.split('{'); const id = flagArray[0]; @@ -103,9 +105,9 @@ export function bzwFlag(input: string): FlagCount { flag: id, count: count, }; -} +}; -export const OptionsProperties = { +export const OptionsProperties: BZWObjectProperties = { '-a': bzwAccelerations, '-admsg': bzwRepeatable(bzwString), '-autoteam': bzwBool, diff --git a/src/Document/Obstacles/Pyramid.ts b/src/Document/Obstacles/Pyramid.ts index 7746ba5..a3cd783 100644 --- a/src/Document/Obstacles/Pyramid.ts +++ b/src/Document/Obstacles/Pyramid.ts @@ -1,11 +1,14 @@ import { bzwBool, bzwFloat, bzwString, bzwVector3F } from '../attributeParsers'; import { IMaterialFriendly } from '../Attributes/IMaterialFriendly'; import { INameable } from '../Attributes/INameable'; -import { IPassableObject } from '../Attributes/IPassableObject'; +import { + IPassableObject, + newIPassableObject, +} from '../Attributes/IPassableObject'; import { IPhysicsDriverFriendly } from '../Attributes/IPhysicsDriverFriendly'; import { IPositionable } from '../Attributes/IPositionable'; import { ISizeable } from '../Attributes/ISizeable'; -import { IBaseObject, newIBaseObject, newIPassableObject } from './BaseObject'; +import { IBaseObject, newIBaseObject } from './BaseObject'; export const PyramidProperties = { name: bzwString, diff --git a/src/Document/Obstacles/Teleporter.ts b/src/Document/Obstacles/Teleporter.ts index b5a2869..70723d2 100644 --- a/src/Document/Obstacles/Teleporter.ts +++ b/src/Document/Obstacles/Teleporter.ts @@ -13,7 +13,7 @@ export const TeleporterProperties = { export interface ITeleporter extends IBaseObject, - INameable, + Required, IPositionable, ISizeable { border: number; diff --git a/src/Document/Obstacles/TextureMatrix.ts b/src/Document/Obstacles/TextureMatrix.ts index 2c3fc7a..d14ae13 100644 --- a/src/Document/Obstacles/TextureMatrix.ts +++ b/src/Document/Obstacles/TextureMatrix.ts @@ -1,4 +1,4 @@ -import { Vector4F } from '../../Utilities/types'; +import { Vector4F } from '../../Utilities/contracts'; import { bzwFloat, bzwFloatVector, diff --git a/src/Document/Obstacles/Zone.ts b/src/Document/Obstacles/Zone.ts index 83c270e..cc2fa0f 100644 --- a/src/Document/Obstacles/Zone.ts +++ b/src/Document/Obstacles/Zone.ts @@ -1,6 +1,7 @@ import { bzwFloat, bzwIntVector, + BZWObjectProperties, bzwRepeatable, bzwString, bzwStringVector, @@ -8,6 +9,7 @@ import { } from '../attributeParsers'; import { INameable } from '../Attributes/INameable'; import { IPositionable } from '../Attributes/IPositionable'; +import { ISizeable } from '../Attributes/ISizeable'; import { IBaseObject, newIBaseObject } from './BaseObject'; function bzwZoneFlag(value: string): IZoneFlag { @@ -16,7 +18,22 @@ function bzwZoneFlag(value: string): IZoneFlag { return [chunks[0], +(chunks[1] ?? 1)]; } -export const ZoneProperties = { +export interface IZone + extends IBaseObject, + INameable, + IPositionable, + ISizeable { + zoneflag: IZoneFlag[]; + flag: string[]; + team?: (0 | 1 | 2 | 3 | 4 | 5 | 6)[]; + safety?: (1 | 2 | 3 | 4)[]; +} + +export type IZoneFlag = [string, number]; +export type IZoneTeam = Exclude[0]; +export type IZoneSafety = Exclude[0]; + +export const ZoneProperties: BZWObjectProperties = { name: bzwString, position: bzwVector3F, size: bzwVector3F, @@ -27,16 +44,6 @@ export const ZoneProperties = { safety: bzwIntVector, }; -export interface IZone extends IBaseObject, INameable, IPositionable { - zoneflag: IZoneFlag[]; - flag: string[]; - team?: (0 | 1 | 2 | 3 | 4 | 5 | 6)[]; - safety?: (1 | 2 | 3 | 4)[]; -} -export type IZoneFlag = [string, number]; -export type IZoneTeam = Exclude[0]; -export type IZoneSafety = Exclude[0]; - export function newIZone(): IZone { return { ...newIBaseObject('zone'), diff --git a/src/Document/Writing/attributeWriters.ts b/src/Document/Writing/attributeWriters.ts index db188e3..80802d1 100644 --- a/src/Document/Writing/attributeWriters.ts +++ b/src/Document/Writing/attributeWriters.ts @@ -1,4 +1,4 @@ -export function writeArray(array: Array): string[] { +export function writeArray(array: Array): string[] { return array.map((value) => { if (typeof value === 'number') { return writeNumber(value); diff --git a/src/Document/Writing/obstacleWriters.ts b/src/Document/Writing/obstacleWriters.ts index 574bdf4..4502661 100644 --- a/src/Document/Writing/obstacleWriters.ts +++ b/src/Document/Writing/obstacleWriters.ts @@ -1,3 +1,4 @@ +import { MapObjectHeader } from '../contracts'; import { IBaseObject } from '../Obstacles/BaseObject'; import { Accelerations, @@ -22,7 +23,10 @@ export const AttributePriority: Record> = { }, }; -export const HeaderWriters: Record string> = { +export const HeaderWriters: Record< + MapObjectHeader, + (o: IBaseObject) => string +> = { teleporter: (tele: ITeleporter) => `${tele._objectType} ${tele.name}`, }; @@ -46,7 +50,7 @@ export const AttributeWriters: Record< let response = ''; if ('total' in m) { - response = m.total + ''; + response = String(m.total); } else { const { rogue, red, green, blue, purple, observer } = m; response = [rogue, red, green, blue, purple, observer].join(','); diff --git a/src/Document/attributeParsers.ts b/src/Document/attributeParsers.ts index 38ba766..40a9cfe 100644 --- a/src/Document/attributeParsers.ts +++ b/src/Document/attributeParsers.ts @@ -1,10 +1,17 @@ +import { OmitIndexSignature } from 'type-fest'; + +import { Vector3F, Vector4F } from '../Utilities/contracts'; +import { assertNotNull } from '../Utilities/developmentUtilities'; +import { IBaseObject } from './Obstacles/BaseObject'; import { TeleporterReference, TeleporterSide, } from './Obstacles/TeleporterLink'; import { IWorld } from './Obstacles/World'; -type KeyType = keyof any; +export type BZWParseLine = (line: string, world: IWorld) => R; + +type KeyType = number | string | symbol; export type HashableParserCallback = ( line: string, @@ -32,43 +39,43 @@ export interface Repeatable { callback: RepeatableParserCallback; } -export function bzwRepeatable(cb: Repeatable['callback']): Repeatable { - return { - type: 'repeatable', - callback: cb, - }; -} +export const bzwRepeatable = ( + cb: Repeatable['callback'], +): Repeatable => ({ + type: 'repeatable', + callback: cb, +}); -export function bzwBool(_: string): boolean { +export const bzwBool: BZWParseLine = () => { return true; -} +}; -export function bzwFloat(line: string): number { +export const bzwFloat: BZWParseLine = (line) => { return Number.parseFloat(line); -} +}; -export function bzwInt(line: string): number { +export const bzwInt: BZWParseLine = (line) => { return Number.parseInt(line); -} +}; -export function bzwString(line: string): string { +export const bzwString: BZWParseLine = (line) => { // Only use any string value before the `#`; i.e. the non-comment content return line.match(/([^#\n]+)(?!#)/)?.[0] ?? line; -} +}; -export function bzwStringVector(line: string): string[] { - return bzwString(line).split(/[ ]+/); -} +export const bzwStringVector: BZWParseLine = (line, world) => { + return bzwString(line, world).split(/[ ]+/); +}; -export function bzwIntVector(line: string): number[] { - return bzwStringVector(line).map((value) => Number.parseInt(value)); -} +export const bzwIntVector: BZWParseLine = (line, world) => { + return bzwStringVector(line, world).map((value) => Number.parseInt(value)); +}; -export function bzwFloatVector(line: string): number[] { - return bzwStringVector(line).map((value) => Number.parseFloat(value)); -} +export const bzwFloatVector: BZWParseLine = (line, world) => { + return bzwStringVector(line, world).map((value) => Number.parseFloat(value)); +}; -export function bzwVector3F(line: string): [number, number, number] { +export const bzwVector3F: BZWParseLine = (line) => { const tokens = line.split(/[ ]+/); return [ @@ -76,9 +83,9 @@ export function bzwVector3F(line: string): [number, number, number] { Number.parseFloat(tokens[1]), Number.parseFloat(tokens[2]), ]; -} +}; -export function bzwVector4F(line: string): [number, number, number, number] { +export const bzwVector4F: BZWParseLine = (line) => { const tokens = line.split(/[ ]+/); return [ @@ -87,9 +94,11 @@ export function bzwVector4F(line: string): [number, number, number, number] { Number.parseFloat(tokens[2]), Number.parseFloat(tokens[3]), ]; -} +}; + +export const bzwTeleRef: BZWParseLine = (line, world) => { + assertNotNull(world, 'This function requires "world" to be given.'); -export function bzwTeleRef(line: string, world: IWorld): TeleporterReference { let name = line; let side = TeleporterSide.Both; const i = line.lastIndexOf(':'); @@ -117,4 +126,15 @@ export function bzwTeleRef(line: string, world: IWorld): TeleporterReference { name: name, side: side, }; -} +}; + +export type BZWParserFunction = + | ReturnType> + | ReturnType> + | BZWParseLine; + +export type BZWObjectProperties = { + [key in keyof T]: NonNullable extends Array + ? Repeatable + : BZWParserFunction>; +}; diff --git a/src/Document/contracts.ts b/src/Document/contracts.ts new file mode 100644 index 0000000..bd670f6 --- /dev/null +++ b/src/Document/contracts.ts @@ -0,0 +1,149 @@ +import { BZWParserFunction } from './attributeParsers'; +import { BaseProperties, IBase, newIBase } from './Obstacles/Base'; +import { BoxProperties, IBox, newIBox } from './Obstacles/Box'; +import { + IMaterial, + MaterialProperties, + newIMaterial, +} from './Obstacles/Material'; +import { IMesh, MeshProperties, newIMesh } from './Obstacles/Mesh'; +import { + IMeshFace, + MeshFaceProperties, + newIMeshFace, +} from './Obstacles/MeshFace'; +import { IOptions, newIOptions, OptionsProperties } from './Obstacles/Option'; +import { IPyramid, newIPyramid, PyramidProperties } from './Obstacles/Pyramid'; +import { + ITeleporter, + newITeleporter, + TeleporterProperties, +} from './Obstacles/Teleporter'; +import { + ITeleporterLink, + newITeleporterLink, + TeleporterLinkProperties, +} from './Obstacles/TeleporterLink'; +import { + ITextureMatrix, + newITextureMatrix, + TextureMatrixProperties, +} from './Obstacles/TextureMatrix'; +import { IWorld, newIWorld, WorldProperties } from './Obstacles/World'; +import { IZone, newIZone, ZoneProperties } from './Obstacles/Zone'; + +type MapObjectTypeMappings = { + base: IBase; + box: IBox; + face: IMeshFace; + link: ITeleporterLink; + material: IMaterial; + mesh: IMesh; + options: IOptions; + pyramid: IPyramid; + teleporter: ITeleporter; + texturematrix: ITextureMatrix; + world: IWorld; + zone: IZone; +}; + +export type MapObjectHeader = keyof MapObjectTypeMappings; +export type MapObjectType = MapObjectTypeMappings[MapObjectHeader]; + +type ObjectBuilderMapping = { + [header in MapObjectHeader]: { + factory: () => MapObjectTypeMappings[header]; + parsers: Record; + onObstacleBegin?: ( + infoString: string, + obstacle: MapObjectTypeMappings[header], + world: IWorld, + ) => void; + onObstacleComplete?: ( + obstacle: MapObjectTypeMappings[header], + world: IWorld, + ) => void; + }; +}; + +export const ObjectBuilders: ObjectBuilderMapping = { + base: { + factory: newIBase, + parsers: BaseProperties, + }, + box: { + factory: newIBox, + parsers: BoxProperties, + }, + face: { + factory: newIMeshFace, + parsers: MeshFaceProperties, + }, + link: { + factory: newITeleporterLink, + parsers: TeleporterLinkProperties, + onObstacleComplete: (link, world) => { + // after parsing a Link object, associate it with relevant teleporters + for (const teleUUID of world._teleporters) { + const tele = world.children[teleUUID] as ITeleporter; + + if (tele.name === link.from.name || tele.name === link.to.name) { + tele._links.push(link._uuid); + } + } + }, + }, + material: { + factory: newIMaterial, + parsers: MaterialProperties, + }, + mesh: { + factory: newIMesh, + parsers: MeshProperties, + }, + options: { + factory: newIOptions, + parsers: OptionsProperties, + onObstacleComplete: (options, world) => { + world._options = options; + + // Don't save the `options` block as a child, treat it special as the + // `_options` property + delete world.children[options._uuid]; + }, + }, + pyramid: { + factory: newIPyramid, + parsers: PyramidProperties, + }, + teleporter: { + factory: newITeleporter, + parsers: TeleporterProperties, + onObstacleBegin: (infoString, obstacle, world) => { + obstacle.name = infoString; + + // teleporter didn't have a name; so give it one + if (obstacle.name === '') { + obstacle.name = `tele${world._teleporters.length}`; + } + + // keep track of teleporter objects so we can associate their links later + world._teleporters.push(obstacle._uuid); + }, + }, + texturematrix: { + factory: newITextureMatrix, + parsers: TextureMatrixProperties, + }, + world: { + factory: newIWorld, + parsers: WorldProperties, + }, + zone: { + factory: newIZone, + parsers: ZoneProperties, + onObstacleComplete: (zone: IZone) => { + zone.flag = zone.flag.flat(2); + }, + }, +}; diff --git a/src/Document/parseBZWDocument.ts b/src/Document/parseBZWDocument.ts index 78244ce..56b798b 100644 --- a/src/Document/parseBZWDocument.ts +++ b/src/Document/parseBZWDocument.ts @@ -1,158 +1,10 @@ import { nanoid } from 'nanoid'; import { Stack } from '../Utilities/Stack'; -import { - bzwString, - Hashable, - HashableParserCallback, - Repeatable, - RepeatableParserCallback, -} from './attributeParsers'; -import { BaseProperties, newIBase } from './Obstacles/Base'; +import { bzwString } from './attributeParsers'; +import { ObjectBuilders } from './contracts'; import { IBaseObject } from './Obstacles/BaseObject'; -import { BoxProperties, newIBox } from './Obstacles/Box'; -import { MaterialProperties, newIMaterial } from './Obstacles/Material'; -import { MeshProperties, newIMesh } from './Obstacles/Mesh'; -import { MeshFaceProperties, newIMeshFace } from './Obstacles/MeshFace'; -import { IOptions, newIOptions, OptionsProperties } from './Obstacles/Option'; -import { newIPyramid, PyramidProperties } from './Obstacles/Pyramid'; -import { - ITeleporter, - newITeleporter, - TeleporterProperties, -} from './Obstacles/Teleporter'; -import { - ITeleporterLink, - newITeleporterLink, - TeleporterLinkProperties, -} from './Obstacles/TeleporterLink'; -import { - newITextureMatrix, - TextureMatrixProperties, -} from './Obstacles/TextureMatrix'; -import { IWorld, newIWorld, WorldProperties } from './Obstacles/World'; -import { IZone, newIZone, ZoneProperties } from './Obstacles/Zone'; - -type ObjectBuilder = { - factory: () => IBaseObject & any; - parsers: Record< - string, - | HashableParserCallback - | Hashable - | RepeatableParserCallback - | Repeatable - >; - onObstacleBegin: ( - infoString: string, - obstacle: IBaseObject & any, - world: IWorld, - ) => void; - onObstacleComplete: (obstacle: IBaseObject & any, world: IWorld) => void; -}; - -const noop = () => {}; - -const ObjectBuilders: Record = { - base: { - factory: newIBase, - parsers: BaseProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - box: { - factory: newIBox, - parsers: BoxProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - face: { - factory: newIMeshFace, - parsers: MeshFaceProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - link: { - factory: newITeleporterLink, - parsers: TeleporterLinkProperties, - onObstacleBegin: noop, - onObstacleComplete: (link: ITeleporterLink, world) => { - // after parsing a Link object, associate it with relevant teleporters - for (const teleUUID of world._teleporters) { - const tele = world.children[teleUUID] as ITeleporter; - - if (tele.name === link.from.name || tele.name === link.to.name) { - tele._links.push(link._uuid); - } - } - }, - }, - material: { - factory: newIMaterial, - parsers: MaterialProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - mesh: { - factory: newIMesh, - parsers: MeshProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - options: { - factory: newIOptions, - parsers: OptionsProperties, - onObstacleBegin: noop, - onObstacleComplete: (options: IOptions, world) => { - world._options = options; - - // Don't save the `options` block as a child, treat it special as the - // `_options` property - delete world.children[options._uuid]; - }, - }, - pyramid: { - factory: newIPyramid, - parsers: PyramidProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - teleporter: { - factory: newITeleporter, - parsers: TeleporterProperties, - onObstacleBegin: (infoString, obstacle: ITeleporter, world) => { - obstacle.name = infoString; - - // teleporter didn't have a name; so give it one - if (obstacle.name === '') { - obstacle.name = `tele${world._teleporters.length}`; - } - - // keep track of teleporter objects so we can associate their links later - world._teleporters.push(obstacle._uuid); - }, - onObstacleComplete: noop, - }, - texturematrix: { - factory: newITextureMatrix, - parsers: TextureMatrixProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - world: { - factory: newIWorld, - parsers: WorldProperties, - onObstacleBegin: noop, - onObstacleComplete: noop, - }, - zone: { - factory: newIZone, - parsers: ZoneProperties, - onObstacleBegin: noop, - onObstacleComplete: (zone: IZone) => { - zone.flag = zone.flag.flat(2); - }, - }, -}; +import { IWorld, newIWorld } from './Obstacles/World'; function parseLine(line: string, object: IBaseObject, world: IWorld): void { const spacePos = line.search(/[ ]|$/); diff --git a/src/Utilities/EventBus.ts b/src/Utilities/EventBus.ts index e1b3938..c107062 100644 --- a/src/Utilities/EventBus.ts +++ b/src/Utilities/EventBus.ts @@ -1,12 +1,12 @@ import { nanoid } from 'nanoid'; -export type EventBusCallback = (data: T) => void; +export type EventBusCallback = (data: T) => void; type EventBusInternalCallback = (e: CustomEvent) => void; class EventBus { private callbacks: Record> = {}; - on(event: string, callback: EventBusCallback): string { + on(event: string, callback: EventBusCallback): string { const id = nanoid(7); this.callbacks[id] = (e: CustomEvent) => { diff --git a/src/Utilities/contracts.ts b/src/Utilities/contracts.ts new file mode 100644 index 0000000..4407e71 --- /dev/null +++ b/src/Utilities/contracts.ts @@ -0,0 +1,64 @@ +import { HTMLAttributes, HTMLProps, ReactNode } from 'react'; + +export enum AlertType { + Info, + Success, + Warning, + Danger, +} + +export enum CardinalDirection { + North, + South, + East, + West, +} + +export type SupportedFormElement = + | HTMLInputElement + | HTMLSelectElement + | HTMLTextAreaElement; +export type ValueValidator = (value: T) => boolean; +type BaseFieldProps = HTMLAttributes; +type Blacklist = 'onChange'; + +export enum FieldLayout { + Stacked = 'default', + Horizontal = 'horizontal', +} + +export interface FieldProps extends Omit { + className?: string; + disabled?: boolean; + hideLabel?: boolean; + layout?: FieldLayout; + label: string; + labelProps?: HTMLProps; + description?: string; + allowChange?: ValueValidator; + onChange: (value: T) => void; + value: T; +} + +export type InputProps = { + tag: 'input'; + type: string; +}; +export type SelectProps = { + tag: 'select'; + children: ReactNode; +}; +export type TextareaProps = { + tag: 'textarea'; +}; +export type Vector3F = [number, number, number]; +export type Vector4F = [number, number, number, number]; + +/** + * @link https://github.com/microsoft/TypeScript/issues/10421#issuecomment-518806979 + */ +export function assumeType(_: unknown): asserts _ is T { + // ¯\_(ツ)_/¯ +} + +export const CAMERA_DEFAULT_POS: [number, number, number] = [-15, 15, 15]; diff --git a/src/Utilities/developmentUtilities.ts b/src/Utilities/developmentUtilities.ts index 9bf11f5..b07affd 100644 --- a/src/Utilities/developmentUtilities.ts +++ b/src/Utilities/developmentUtilities.ts @@ -4,6 +4,15 @@ export function assertEveryIsNotNull(values: any[], message: string) { } } +export function assertNotNull( + value: T | null, + message: string, +): asserts value is NonNullable { + if (value == null) { + throw new Error(message); + } +} + export function isDevEnv() { return import.meta.env.DEV; } diff --git a/src/Utilities/types.ts b/src/Utilities/types.ts deleted file mode 100644 index 3dd34f2..0000000 --- a/src/Utilities/types.ts +++ /dev/null @@ -1,9 +0,0 @@ -export type Vector3F = [number, number, number]; -export type Vector4F = [number, number, number, number]; - -/** - * @link https://github.com/microsoft/TypeScript/issues/10421#issuecomment-518806979 - */ -export function assumeType(_: unknown): asserts _ is T { - // ¯\_(ツ)_/¯ -} diff --git a/src/atoms.ts b/src/atoms.ts index 0030e51..01dc479 100644 --- a/src/atoms.ts +++ b/src/atoms.ts @@ -33,7 +33,7 @@ export const documentTeles = selector>({ continue; } - entries[teleporter.name!] = teleUUID; + entries[teleporter.name] = teleUUID; } return entries;