diff --git a/.eslintrc.cjs b/.eslintrc.cjs index d6c9537..994d371 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -2,17 +2,43 @@ module.exports = { root: true, env: { browser: true, es2020: true }, extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", + "plugin:jsx-a11y/recommended", + "plugin:import/errors", + "plugin:import/warnings", + "plugin:import/typescript", ], - ignorePatterns: ['dist', '.eslintrc.cjs'], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], + ignorePatterns: ["dist", ".eslintrc.cjs"], + parser: "@typescript-eslint/parser", + plugins: ["react-refresh"], rules: { - 'react-refresh/only-export-components': [ - 'warn', + "react-refresh/only-export-components": [ + "warn", { allowConstantExport: true }, ], + "react/react-in-jsx-scope": "off", // Not needed with modern React + "import/order": ["error", { "newlines-between": "always" }], // Enforce a convention in module import order + "import/no-default-export": "error", // Prefer named exports + "jsx-a11y/anchor-is-valid": [ + "error", + { components: ["Link"], specialLink: ["to"] }, + ], // Enforce valid anchor elements + "react/prop-types": "off", }, -} + settings: { + react: { + version: "detect", + }, + "import/parsers": { + "@typescript-eslint/parser": [".ts", ".tsx"], + }, + "import/resolver": { + typescript: { + alwaysTryTypes: true, // always try to resolve types under `@types` directory even it doesn't contain any source code, like `@types/unist` + }, + }, + }, +}; diff --git a/package-lock.json b/package-lock.json index a868764..0a4fb72 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,10 @@ "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^1.0.4", "eslint": "^8.45.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "husky": "^8.0.3", @@ -2833,6 +2837,12 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true + }, "node_modules/@types/minimist": { "version": "1.2.5", "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", @@ -3527,6 +3537,25 @@ "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", "dev": true }, + "node_modules/array-includes": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.7.tgz", + "integrity": "sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", @@ -3536,6 +3565,95 @@ "node": ">=8" } }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", + "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz", + "integrity": "sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-shim-unscopables": "^1.0.0", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/arrify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", @@ -3556,6 +3674,21 @@ "node": "*" } }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true + }, + "node_modules/asynciterator.prototype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz", + "integrity": "sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg==", + "dev": true, + "dependencies": { + "has-symbols": "^1.0.3" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3574,6 +3707,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/axe-core": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.7.0.tgz", + "integrity": "sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-3.2.1.tgz", + "integrity": "sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, "node_modules/babel-plugin-macros": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz", @@ -4242,6 +4393,12 @@ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==" }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true + }, "node_modules/data-urls": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", @@ -4423,6 +4580,15 @@ "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true }, + "node_modules/dequal": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", + "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -4521,6 +4687,19 @@ "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", "dev": true }, + "node_modules/enhanced-resolve": { + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -4688,6 +4867,59 @@ "is-arrayish": "^0.2.1" } }, + "node_modules/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dev": true, + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -4708,6 +4940,68 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-iterator-helpers": { + "version": "1.0.15", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz", + "integrity": "sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g==", + "dev": true, + "dependencies": { + "asynciterator.prototype": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "es-set-tostringtag": "^2.0.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "iterator.prototype": "^1.1.2", + "safe-array-concat": "^1.0.1" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dev": true, + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", + "dev": true, + "dependencies": { + "hasown": "^2.0.0" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/esbuild": { "version": "0.19.11", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.11.tgz", @@ -4821,6 +5115,257 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz", + "integrity": "sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==", + "dev": true, + "dependencies": { + "debug": "^4.3.4", + "enhanced-resolve": "^5.12.0", + "eslint-module-utils": "^2.7.4", + "fast-glob": "^3.3.1", + "get-tsconfig": "^4.5.0", + "is-core-module": "^2.11.0", + "is-glob": "^4.0.3" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts/projects/eslint-import-resolver-ts" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*" + } + }, + "node_modules/eslint-module-utils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", + "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "dev": true, + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.8.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", + "semver": "^6.3.1", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + } + }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz", + "integrity": "sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.23.2", + "aria-query": "^5.3.0", + "array-includes": "^3.1.7", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "=4.7.0", + "axobject-query": "^3.2.1", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "es-iterator-helpers": "^1.0.15", + "hasown": "^2.0.0", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.entries": "^1.1.7", + "object.fromentries": "^2.0.7" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/aria-query": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz", + "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==", + "dev": true, + "dependencies": { + "dequal": "^2.0.3" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.33.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz", + "integrity": "sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flatmap": "^1.3.1", + "array.prototype.tosorted": "^1.1.1", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.0.12", + "estraverse": "^5.3.0", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.6", + "object.fromentries": "^2.0.6", + "object.hasown": "^1.1.2", + "object.values": "^1.1.6", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.4", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.8" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, "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", @@ -4842,6 +5387,66 @@ "eslint": ">=7" } }, + "node_modules/eslint-plugin-react/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/minimatch": { + "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" + }, + "engines": { + "node": "*" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/eslint-scope": { "version": "7.2.2", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", @@ -5273,6 +5878,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/functions-have-names": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", @@ -5348,6 +5971,34 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.2.tgz", + "integrity": "sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==", + "dev": true, + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, "node_modules/git-log-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/git-log-parser/-/git-log-parser-1.2.0.tgz", @@ -5434,6 +6085,21 @@ "node": ">=4" } }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dev": true, + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/globby": { "version": "11.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", @@ -5917,6 +6583,21 @@ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==" }, + "node_modules/is-async-function": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", + "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", @@ -6004,6 +6685,18 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz", + "integrity": "sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -6013,6 +6706,21 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", + "integrity": "sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A==", + "dev": true, + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -6034,6 +6742,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -6220,6 +6940,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakset": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", @@ -6320,6 +7052,19 @@ "node": ">=8" } }, + "node_modules/iterator.prototype": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.2.tgz", + "integrity": "sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "reflect.getprototypeof": "^1.0.4", + "set-function-name": "^2.0.1" + } + }, "node_modules/java-properties": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", @@ -6642,6 +7387,21 @@ "node": "*" } }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, "node_modules/jwt-decode": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", @@ -6670,6 +7430,24 @@ "node": ">=0.10.0" } }, + "node_modules/language-subtag-registry": { + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz", + "integrity": "sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w==", + "dev": true + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -10890,6 +11668,79 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/object.entries": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", + "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", + "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", + "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1" + } + }, + "node_modules/object.hasown": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/object.hasown/-/object.hasown-1.1.3.tgz", + "integrity": "sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA==", + "dev": true, + "dependencies": { + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", + "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -11677,6 +12528,26 @@ "esprima": "~4.0.0" } }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz", + "integrity": "sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "which-builtin-type": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/regenerator-runtime": { "version": "0.14.1", "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", @@ -11750,6 +12621,15 @@ "node": ">=4" } }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, "node_modules/response-iterator": { "version": "0.2.6", "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.6.tgz", @@ -11863,12 +12743,47 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/safe-array-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", + "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, + "node_modules/safe-regex-test": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", @@ -12628,6 +13543,71 @@ "node": ">=8" } }, + "node_modules/string.prototype.matchall": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", + "integrity": "sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "has-symbols": "^1.0.3", + "internal-slot": "^1.0.5", + "regexp.prototype.flags": "^1.5.0", + "set-function-name": "^2.0.0", + "side-channel": "^1.0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "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", @@ -12749,6 +13729,15 @@ "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", "dev": true }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, "node_modules/temp-dir": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz", @@ -13022,6 +14011,30 @@ } } }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tslib": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", @@ -13060,6 +14073,71 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/typescript": { "version": "5.3.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", @@ -13092,6 +14170,21 @@ "node": ">=0.8.0" } }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/undici-types": { "version": "5.26.5", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", @@ -13802,6 +14895,32 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/which-builtin-type": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.1.3.tgz", + "integrity": "sha512-YmjsSMDBYsM1CaFiayOVT06+KJeXf0o5M/CAd4o1lTadFAtacTUM49zoYxr/oroopFDfhvN6iEcBxUyc3gvKmw==", + "dev": true, + "dependencies": { + "function.prototype.name": "^1.1.5", + "has-tostringtag": "^1.0.0", + "is-async-function": "^2.0.0", + "is-date-object": "^1.0.5", + "is-finalizationregistry": "^1.0.2", + "is-generator-function": "^1.0.10", + "is-regex": "^1.1.4", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.0.2", + "which-collection": "^1.0.1", + "which-typed-array": "^1.1.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/which-collection": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", diff --git a/package.json b/package.json index ce66fb7..66f8f6a 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,10 @@ "@vitejs/plugin-react": "^4.2.1", "@vitest/coverage-v8": "^1.0.4", "eslint": "^8.45.0", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-jsx-a11y": "^6.8.0", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "husky": "^8.0.3", diff --git a/playwright.config.ts b/playwright.config.ts index 38b1c02..494053e 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -9,6 +9,7 @@ import { defineConfig, devices } from "@playwright/test"; /** * See https://playwright.dev/docs/test-configuration. */ +/* eslint-disable import/no-default-export */ export default defineConfig({ testDir: "./tests", /* Run tests in files in parallel */ @@ -40,7 +41,6 @@ export default defineConfig({ storageState: "playwright/.auth/user.json", }, testMatch: /.*\.auth\.spec\.ts/, - dependencies: ["setup"], }, { diff --git a/src/App.test.tsx b/src/App.test.tsx index 0690a8d..0385032 100644 --- a/src/App.test.tsx +++ b/src/App.test.tsx @@ -1,7 +1,8 @@ import { ReactNode } from "react"; import { describe, it, vi } from "vitest"; import { waitFor, render, screen } from "@testing-library/react"; -import App from "./App"; + +import { App } from "./App"; const mockLibraryPage = vi.fn(); diff --git a/src/App.tsx b/src/App.tsx index 1758793..ef6caf2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,13 +1,14 @@ import { ThemeProvider } from "@mui/material"; import { Auth0Provider } from "@auth0/auth0-react"; +import { ApolloProvider } from "@apollo/client"; + import { LibraryPage } from "./components/"; import { useTheme } from "./hooks"; import { AuthProvider } from "./contexts"; -import { ApolloProvider } from "@apollo/client"; import { client } from "./apolloClient"; import { getEnvironmentDependentUrl } from "./utils/"; -const App = () => { +export const App = () => { const theme = useTheme(); const redirectUri = getEnvironmentDependentUrl(); @@ -32,5 +33,3 @@ const App = () => { ); }; - -export default App; diff --git a/src/components/LibraryPage/LibraryPage.test.tsx b/src/components/LibraryPage/LibraryPage.test.tsx index e519fb7..6692aff 100644 --- a/src/components/LibraryPage/LibraryPage.test.tsx +++ b/src/components/LibraryPage/LibraryPage.test.tsx @@ -1,7 +1,8 @@ import { render, screen } from "@testing-library/react"; +import { vi } from "vitest"; + import { LibraryPage } from "./LibraryPage"; import { useLibraryPage } from "./hooks"; -import { vi } from "vitest"; vi.mock("./hooks", () => ({ useLibraryPage: vi.fn(), diff --git a/src/components/LibraryPage/LibraryPage.tsx b/src/components/LibraryPage/LibraryPage.tsx index 3aed0ba..1deb76f 100644 --- a/src/components/LibraryPage/LibraryPage.tsx +++ b/src/components/LibraryPage/LibraryPage.tsx @@ -1,8 +1,11 @@ -import { useLibraryPage } from "./hooks"; import { Box, Grid } from "@mui/material"; + +import { ErrorSnackbar } from "../shared"; + +import { useLibraryPage } from "./hooks"; import { Root } from "./LibraryPage.styles"; import { Books, Search, ThemeSwitch, UserAuthentication } from "./components"; -import { ErrorSnackbar } from "../shared"; + interface LibraryGridProps { search: string; diff --git a/src/components/LibraryPage/components/Books/Books.test.tsx b/src/components/LibraryPage/components/Books/Books.test.tsx index 195b992..1e84658 100644 --- a/src/components/LibraryPage/components/Books/Books.test.tsx +++ b/src/components/LibraryPage/components/Books/Books.test.tsx @@ -1,8 +1,9 @@ import { ApolloError } from "@apollo/client"; import { render, screen } from "@testing-library/react"; +import { vi } from "vitest"; + import { Books } from "./Books"; import { useBooks } from "./hooks"; -import { vi } from "vitest"; vi.mock("./hooks", () => ({ useBooks: vi.fn(), diff --git a/src/components/LibraryPage/components/Books/Books.tsx b/src/components/LibraryPage/components/Books/Books.tsx index 7b0fd6f..5ad0e17 100644 --- a/src/components/LibraryPage/components/Books/Books.tsx +++ b/src/components/LibraryPage/components/Books/Books.tsx @@ -1,4 +1,5 @@ import { Grid } from "@mui/material"; + import { ErrorView, LoadingView, BooksView } from "./components"; import { useBooks } from "./hooks"; diff --git a/src/components/LibraryPage/components/Books/components/BookCard/BookCard.test.tsx b/src/components/LibraryPage/components/Books/components/BookCard/BookCard.test.tsx index d981602..878276a 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/BookCard.test.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/BookCard.test.tsx @@ -1,8 +1,10 @@ import { render, screen } from "@testing-library/react"; import { MockedProvider } from "@apollo/client/testing"; -import { BookCard } from "./BookCard"; + import { Book } from "../../../../../../data/books"; +import { BookCard } from "./BookCard"; + test("renders book information correctly", async () => { const mockBook: Book = { id: "1", diff --git a/src/components/LibraryPage/components/Books/components/BookCard/BookCard.tsx b/src/components/LibraryPage/components/Books/components/BookCard/BookCard.tsx index fe9b392..0961f8d 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/BookCard.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/BookCard.tsx @@ -1,7 +1,9 @@ import { Box, Grid } from "@mui/material"; -import { FavoriteButton, CardContent } from "./components"; + import { Book } from "../../../../../../data/books"; +import { FavoriteButton, CardContent } from "./components"; + interface BookCardProps { book: Book; } diff --git a/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.test.tsx b/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.test.tsx index 47d5ed7..8cfe06e 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.test.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.test.tsx @@ -1,5 +1,7 @@ import { render, screen } from "@testing-library/react"; + import { CardContent } from "./CardContent"; + import { Book } from "@/data/books"; describe("CardContent", () => { diff --git a/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.tsx b/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.tsx index 3c994e6..9d8db54 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/components/CardContent.tsx @@ -1,4 +1,5 @@ import { faker } from "@faker-js/faker"; + import { Cover, CardWrapper, @@ -6,7 +7,9 @@ import { TextWrapper, CardActionAreaWrapper, } from "../BookCard.styles"; + import { CircularProgressWithLabel, BookDetails } from "./"; + import { Book } from "@/data/books"; interface CardContentProps { diff --git a/src/components/LibraryPage/components/Books/components/BookCard/components/CircularProgressWithlabel.test.tsx b/src/components/LibraryPage/components/Books/components/BookCard/components/CircularProgressWithlabel.test.tsx index 1487835..023e3ff 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/components/CircularProgressWithlabel.test.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/components/CircularProgressWithlabel.test.tsx @@ -1,5 +1,6 @@ import { render } from "@testing-library/react"; import { describe, expect, it } from "vitest"; + import { CircularProgressWithLabel } from "./CircularProgressWithLabel"; describe("CircularProgressWithLabel", () => { diff --git a/src/components/LibraryPage/components/Books/components/BookCard/components/FavoriteButton.tsx b/src/components/LibraryPage/components/Books/components/BookCard/components/FavoriteButton.tsx index 723e499..c7b8be0 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/components/FavoriteButton.tsx +++ b/src/components/LibraryPage/components/Books/components/BookCard/components/FavoriteButton.tsx @@ -1,8 +1,9 @@ -import { useFavoriteButton } from "./useFavoriteButton"; -import { StyledIconButton } from "./FavoriteButton.styles"; import Favorite from "@mui/icons-material/Favorite"; import FavoriteBorder from "@mui/icons-material/FavoriteBorder"; +import { useFavoriteButton } from "./useFavoriteButton"; +import { StyledIconButton } from "./FavoriteButton.styles"; + interface FavoriteButtonProps { bookId: string; isFavorited: boolean; diff --git a/src/components/LibraryPage/components/Books/components/BookCard/components/useFavoriteButton.ts b/src/components/LibraryPage/components/Books/components/BookCard/components/useFavoriteButton.ts index cfb8dbd..045e317 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/components/useFavoriteButton.ts +++ b/src/components/LibraryPage/components/Books/components/BookCard/components/useFavoriteButton.ts @@ -1,5 +1,6 @@ import { useEffect, useState, useCallback } from "react"; import { useAuth0 } from "@auth0/auth0-react"; + import { useFavorite } from "../useFavorite"; export const useFavoriteButton = ( diff --git a/src/components/LibraryPage/components/Books/components/BookCard/useFavorite.ts b/src/components/LibraryPage/components/Books/components/BookCard/useFavorite.ts index 7460b73..1ca67e9 100644 --- a/src/components/LibraryPage/components/Books/components/BookCard/useFavorite.ts +++ b/src/components/LibraryPage/components/Books/components/BookCard/useFavorite.ts @@ -1,4 +1,5 @@ import { useMutation } from "@apollo/client"; + import { ADD_FAVORITE_MUTATION, REMOVE_FAVORITE_MUTATION, diff --git a/src/components/LibraryPage/components/Books/components/BooksView/BooksView.test.tsx b/src/components/LibraryPage/components/Books/components/BooksView/BooksView.test.tsx index 69d430e..970eafd 100644 --- a/src/components/LibraryPage/components/Books/components/BooksView/BooksView.test.tsx +++ b/src/components/LibraryPage/components/Books/components/BooksView/BooksView.test.tsx @@ -1,5 +1,6 @@ import { MockedProvider } from "@apollo/client/testing"; import { render, screen } from "@testing-library/react"; + import { BooksView } from "./BooksView"; describe("BooksView", () => { diff --git a/src/components/LibraryPage/components/Books/components/BooksView/BooksView.tsx b/src/components/LibraryPage/components/Books/components/BooksView/BooksView.tsx index 36f3e32..d2733e5 100644 --- a/src/components/LibraryPage/components/Books/components/BooksView/BooksView.tsx +++ b/src/components/LibraryPage/components/Books/components/BooksView/BooksView.tsx @@ -1,4 +1,5 @@ import { BookCard, Message } from "../"; + import { Book } from "@/data/books"; export const BooksView = ({ books }: { books: Book[] }) => diff --git a/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.test.tsx b/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.test.tsx index 20bec95..baf1c98 100644 --- a/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.test.tsx +++ b/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.test.tsx @@ -1,9 +1,10 @@ import { render, screen } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; import { ApolloError } from "@apollo/client"; -import { ErrorView } from "./ErrorView"; import { vi } from "vitest"; +import { ErrorView } from "./ErrorView"; + describe("ErrorView", () => { it("renders an error message when provided", () => { const error = new ApolloError({ errorMessage: "Test error" }); diff --git a/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.tsx b/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.tsx index e99b6a0..46fe6ee 100644 --- a/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.tsx +++ b/src/components/LibraryPage/components/Books/components/ErrorView/ErrorView.tsx @@ -1,5 +1,6 @@ import { SnackbarCloseReason } from "@mui/material"; import { ApolloError } from "@apollo/client"; + import { Message } from "../Message"; import { ErrorSnackbar } from "../../../../../shared"; diff --git a/src/components/LibraryPage/components/Books/components/LoadingView/LoadingView.test.tsx b/src/components/LibraryPage/components/Books/components/LoadingView/LoadingView.test.tsx index dc3661a..14f680a 100644 --- a/src/components/LibraryPage/components/Books/components/LoadingView/LoadingView.test.tsx +++ b/src/components/LibraryPage/components/Books/components/LoadingView/LoadingView.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from "@testing-library/react"; + import { LoadingView } from "./LoadingView"; describe("LoadingView", () => { diff --git a/src/components/LibraryPage/components/Books/components/Message/Message.test.tsx b/src/components/LibraryPage/components/Books/components/Message/Message.test.tsx index a223272..a02ac35 100644 --- a/src/components/LibraryPage/components/Books/components/Message/Message.test.tsx +++ b/src/components/LibraryPage/components/Books/components/Message/Message.test.tsx @@ -1,4 +1,5 @@ import { render, screen } from "@testing-library/react"; + import { Message } from "./Message"; describe("Message", () => { diff --git a/src/components/LibraryPage/components/Books/hooks/useBooks.test.ts b/src/components/LibraryPage/components/Books/hooks/useBooks.test.ts index 8ad3b35..354e38b 100644 --- a/src/components/LibraryPage/components/Books/hooks/useBooks.test.ts +++ b/src/components/LibraryPage/components/Books/hooks/useBooks.test.ts @@ -1,8 +1,9 @@ import { renderHook, act } from "@testing-library/react"; import { useQuery } from "@apollo/client"; +import { vi } from "vitest"; + import { useBooks } from "./useBooks"; import { useIntersectionObserver } from "./useIntersectionObserver"; -import { vi } from "vitest"; vi.mock("@apollo/client", async () => { const actual = await vi.importActual("@apollo/client"); diff --git a/src/components/LibraryPage/components/Books/hooks/useBooks.ts b/src/components/LibraryPage/components/Books/hooks/useBooks.ts index a7dc470..9a638d8 100644 --- a/src/components/LibraryPage/components/Books/hooks/useBooks.ts +++ b/src/components/LibraryPage/components/Books/hooks/useBooks.ts @@ -1,12 +1,14 @@ import { useEffect, useRef, useState } from "react"; -import { useAuth } from "@/contexts"; import { useAuth0 } from "@auth0/auth0-react"; import { ApolloError, useQuery } from "@apollo/client"; -import { BOOKS_QUERY, BooksData, BooksVars } from "@/data/books"; + import { useIntersectionObserver } from "./useIntersectionObserver"; import { getCloseSnackbarHandler, getUpdateQuery } from "./utils"; import { useFetchMoreBooks } from "./useFetchMoreBooks"; +import { BOOKS_QUERY, BooksData, BooksVars } from "@/data/books"; +import { useAuth } from "@/contexts"; + const PAGE_SIZE = 50; interface UseBooksProps { diff --git a/src/components/LibraryPage/components/Books/hooks/useFetchMoreBooks.ts b/src/components/LibraryPage/components/Books/hooks/useFetchMoreBooks.ts index e58e2eb..3963c16 100644 --- a/src/components/LibraryPage/components/Books/hooks/useFetchMoreBooks.ts +++ b/src/components/LibraryPage/components/Books/hooks/useFetchMoreBooks.ts @@ -4,7 +4,9 @@ import { FetchMoreOptions, } from "@apollo/client"; import { useRef, useCallback } from "react"; + import { BooksData, BooksVars } from "../../../../../data/books"; + import { FetchMoreResult } from "./types"; type FetchMoreFunction = ( diff --git a/src/components/LibraryPage/components/Books/hooks/useIntersectionObserver.test.ts b/src/components/LibraryPage/components/Books/hooks/useIntersectionObserver.test.ts index 35442f0..54c7fed 100644 --- a/src/components/LibraryPage/components/Books/hooks/useIntersectionObserver.test.ts +++ b/src/components/LibraryPage/components/Books/hooks/useIntersectionObserver.test.ts @@ -1,8 +1,9 @@ import { renderHook } from "@testing-library/react"; -import { useIntersectionObserver } from "./useIntersectionObserver"; import { vi } from "vitest"; import { RefObject } from "react"; +import { useIntersectionObserver } from "./useIntersectionObserver"; + interface MockIntersectionObserver extends IntersectionObserver { triggerCallback(entries: IntersectionObserverEntry[]): void; } diff --git a/src/components/LibraryPage/components/Books/hooks/utils/utils.test.ts b/src/components/LibraryPage/components/Books/hooks/utils/utils.test.ts index f009c02..4c50e7f 100644 --- a/src/components/LibraryPage/components/Books/hooks/utils/utils.test.ts +++ b/src/components/LibraryPage/components/Books/hooks/utils/utils.test.ts @@ -1,7 +1,10 @@ +import { vi } from "vitest"; + +import { FetchMoreResult } from "../types"; + import { getCloseSnackbarHandler, getUpdateQuery } from "./utils"; + import { BooksData } from "@/data/books"; -import { FetchMoreResult } from "../types"; -import { vi } from "vitest"; describe("utils", () => { describe("getCloseSnackbarHandler", () => { diff --git a/src/components/LibraryPage/components/Books/hooks/utils/utils.ts b/src/components/LibraryPage/components/Books/hooks/utils/utils.ts index b2f175b..8ef8933 100644 --- a/src/components/LibraryPage/components/Books/hooks/utils/utils.ts +++ b/src/components/LibraryPage/components/Books/hooks/utils/utils.ts @@ -1,7 +1,9 @@ import { SnackbarCloseReason } from "@mui/material"; -import { BooksData } from "@/data/books"; + import { FetchMoreResult } from "../types"; +import { BooksData } from "@/data/books"; + const PAGE_SIZE = 50; export const getCloseSnackbarHandler = ( diff --git a/src/components/LibraryPage/components/LoginButton/LoginButton.test.tsx b/src/components/LibraryPage/components/LoginButton/LoginButton.test.tsx index c97c79d..a5f6e85 100644 --- a/src/components/LibraryPage/components/LoginButton/LoginButton.test.tsx +++ b/src/components/LibraryPage/components/LoginButton/LoginButton.test.tsx @@ -1,8 +1,9 @@ import { render, fireEvent, screen } from "@testing-library/react"; import { useAuth0 } from "@auth0/auth0-react"; -import { LoginButton } from "./LoginButton"; import { vi } from "vitest"; +import { LoginButton } from "./LoginButton"; + vi.mock("@auth0/auth0-react"); describe("LoginButton", () => { diff --git a/src/components/LibraryPage/components/Search/Search.test.tsx b/src/components/LibraryPage/components/Search/Search.test.tsx index f392208..bfc8a27 100644 --- a/src/components/LibraryPage/components/Search/Search.test.tsx +++ b/src/components/LibraryPage/components/Search/Search.test.tsx @@ -1,8 +1,9 @@ import { render, screen } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; -import { Search } from "./Search"; import { vi } from "vitest"; +import { Search } from "./Search"; + describe("Search", () => { it("updates the search value when typed into", async () => { const setSearch = vi.fn(); diff --git a/src/components/LibraryPage/components/Search/Search.tsx b/src/components/LibraryPage/components/Search/Search.tsx index 3687add..a5d8308 100644 --- a/src/components/LibraryPage/components/Search/Search.tsx +++ b/src/components/LibraryPage/components/Search/Search.tsx @@ -1,5 +1,6 @@ import { ChangeEvent, Dispatch, SetStateAction } from "react"; import { Box } from "@mui/material"; + import { StyledTextField } from "./SearchInput.styles"; interface SearchProps { diff --git a/src/components/LibraryPage/components/ThemeSwitch/ThemeSwitch.tsx b/src/components/LibraryPage/components/ThemeSwitch/ThemeSwitch.tsx index 0cf72d9..17192c3 100644 --- a/src/components/LibraryPage/components/ThemeSwitch/ThemeSwitch.tsx +++ b/src/components/LibraryPage/components/ThemeSwitch/ThemeSwitch.tsx @@ -1,10 +1,11 @@ import { useEffect } from "react"; import { Switch, FormControlLabel } from "@mui/material"; import { useReactiveVar } from "@apollo/client"; -import { darkModeVar } from "../../../../apolloClient"; import Brightness4 from "@mui/icons-material/Brightness4"; import Brightness7 from "@mui/icons-material/Brightness7"; +import { darkModeVar } from "../../../../apolloClient"; + export const ThemeSwitch = () => { const darkMode = useReactiveVar(darkModeVar); diff --git a/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.test.tsx b/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.test.tsx index 124fb4c..2518acb 100644 --- a/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.test.tsx +++ b/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.test.tsx @@ -1,8 +1,9 @@ import { render, fireEvent, waitFor, screen } from "@testing-library/react"; -import { UserAuthentication } from "./UserAuthentication"; import { useAuth0 } from "@auth0/auth0-react"; import { vi } from "vitest"; +import { UserAuthentication } from "./UserAuthentication"; + vi.mock("@auth0/auth0-react", () => ({ useAuth0: vi.fn().mockReturnValue({ getIdTokenClaims: vi.fn().mockResolvedValue({ diff --git a/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.tsx b/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.tsx index fb56f8d..60cb8d7 100644 --- a/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.tsx +++ b/src/components/LibraryPage/components/UserAuthentication/UserAuthentication.tsx @@ -1,7 +1,9 @@ import { useState, useCallback } from "react"; import { Avatar, CircularProgress, Menu, MenuItem } from "@mui/material"; import { User, useAuth0 } from "@auth0/auth0-react"; + import { LoginButton } from "../LoginButton"; + import { getEnvironmentDependentUrl } from "@/utils/"; const UserAvatar = ({ diff --git a/src/components/LibraryPage/hooks/useDebounce.test.ts b/src/components/LibraryPage/hooks/useDebounce.test.ts index bf14c3b..0d65b0c 100644 --- a/src/components/LibraryPage/hooks/useDebounce.test.ts +++ b/src/components/LibraryPage/hooks/useDebounce.test.ts @@ -1,7 +1,8 @@ import { renderHook, act } from "@testing-library/react"; -import { useDebounce } from "./useDebounce"; import { vi } from "vitest"; +import { useDebounce } from "./useDebounce"; + describe("useDebounce", () => { it("returns the same value after the delay", () => { vi.useFakeTimers(); diff --git a/src/components/LibraryPage/hooks/useLibraryPage.test.ts b/src/components/LibraryPage/hooks/useLibraryPage.test.ts index f659a63..9fe2f10 100644 --- a/src/components/LibraryPage/hooks/useLibraryPage.test.ts +++ b/src/components/LibraryPage/hooks/useLibraryPage.test.ts @@ -1,4 +1,5 @@ import { renderHook, act, waitFor } from "@testing-library/react"; + import { useLibraryPage } from "./useLibraryPage"; describe("useLibraryPage", () => { diff --git a/src/components/LibraryPage/hooks/useLibraryPage.ts b/src/components/LibraryPage/hooks/useLibraryPage.ts index 804fa8d..01d9705 100644 --- a/src/components/LibraryPage/hooks/useLibraryPage.ts +++ b/src/components/LibraryPage/hooks/useLibraryPage.ts @@ -1,4 +1,5 @@ import { useState } from "react"; + import { useDebounce } from "./useDebounce"; interface LibraryPageHook { diff --git a/src/components/shared/ErrorSnackbar/ErrorSnackbar.test.tsx b/src/components/shared/ErrorSnackbar/ErrorSnackbar.test.tsx index 0408103..ee2c2f3 100644 --- a/src/components/shared/ErrorSnackbar/ErrorSnackbar.test.tsx +++ b/src/components/shared/ErrorSnackbar/ErrorSnackbar.test.tsx @@ -1,8 +1,9 @@ import { render, screen } from "@testing-library/react"; import { userEvent } from "@testing-library/user-event"; -import { ErrorSnackbar } from "./ErrorSnackbar"; import { vi } from "vitest"; +import { ErrorSnackbar } from "./ErrorSnackbar"; + describe("ErrorSnackbar", () => { const user = userEvent.setup(); diff --git a/src/components/shared/ErrorSnackbar/ErrorSnackbar.tsx b/src/components/shared/ErrorSnackbar/ErrorSnackbar.tsx index 7c847e1..16861d0 100644 --- a/src/components/shared/ErrorSnackbar/ErrorSnackbar.tsx +++ b/src/components/shared/ErrorSnackbar/ErrorSnackbar.tsx @@ -1,6 +1,5 @@ import { Snackbar, Alert } from "@mui/material"; import { SnackbarCloseReason } from "@mui/material/Snackbar"; -import React from "react"; interface ErrorSnackbarProps { open: boolean; diff --git a/src/contexts/AuthProvider.test.tsx b/src/contexts/AuthProvider.test.tsx index 3e4554b..a510f3d 100644 --- a/src/contexts/AuthProvider.test.tsx +++ b/src/contexts/AuthProvider.test.tsx @@ -1,8 +1,9 @@ import { render, act, screen } from "@testing-library/react"; -import { AuthProvider } from "./AuthProvider"; import { useAuth0 } from "@auth0/auth0-react"; import { vi } from "vitest"; +import { AuthProvider } from "./AuthProvider"; + vi.mock("@auth0/auth0-react", () => ({ useAuth0: vi.fn().mockReturnValue({ user: { name: "Test User" }, diff --git a/src/contexts/AuthProvider.tsx b/src/contexts/AuthProvider.tsx index fbbbb60..10e924d 100644 --- a/src/contexts/AuthProvider.tsx +++ b/src/contexts/AuthProvider.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useMemo } from "react"; import { useAuth0, GetTokenSilentlyOptions } from "@auth0/auth0-react"; import { jwtDecode } from "jwt-decode"; + import { AuthContext } from "./AuthContext"; interface DecodedToken { diff --git a/src/contexts/useAuth.ts b/src/contexts/useAuth.ts index 8cc4eea..c355794 100644 --- a/src/contexts/useAuth.ts +++ b/src/contexts/useAuth.ts @@ -1,4 +1,5 @@ import { useContext } from "react"; + import { AuthContext } from "./AuthContext"; export const useAuth = () => useContext(AuthContext); diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts index d91c0c2..e97d8f1 100644 --- a/src/hooks/useTheme.ts +++ b/src/hooks/useTheme.ts @@ -1,6 +1,8 @@ import { createTheme } from "@mui/material"; import { useReactiveVar } from "@apollo/client"; + import { darkModeVar } from "../apolloClient"; + import { getThemeConfig } from "./themeConfig"; export const useTheme = () => { diff --git a/src/main.tsx b/src/main.tsx index 4924a70..17a4b80 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -2,13 +2,14 @@ import "@fontsource/roboto/300.css"; import "@fontsource/roboto/400.css"; import "@fontsource/roboto/500.css"; import "@fontsource/roboto/700.css"; -import React from "react"; -import ReactDOM from "react-dom/client"; -import App from "./App.tsx"; +import { StrictMode } from "react"; +import { createRoot } from "react-dom/client"; + +import { App } from "./App.tsx"; import "./index.css"; -ReactDOM.createRoot(document.getElementById("root")!).render( - +createRoot(document.getElementById("root")!).render( + - + ); diff --git a/tests/auth.setup.ts b/tests/auth.setup.ts index 70c4c77..a68fade 100644 --- a/tests/auth.setup.ts +++ b/tests/auth.setup.ts @@ -1,7 +1,7 @@ import { test as setup } from "@playwright/test"; -import dotenv from "dotenv"; +import { config } from "dotenv"; -dotenv.config(); +config(); const authFile = "playwright/.auth/user.json"; diff --git a/vite.config.ts b/vite.config.ts index 6c5abe4..2582180 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,13 +1,14 @@ +import path from "path"; + import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; -import checker from "vite-plugin-checker"; -import path from "path"; +import { checker } from "vite-plugin-checker"; +/* eslint-disable import/no-default-export */ export default defineConfig({ plugins: [ react(), checker({ - // e.g. use TypeScript check typescript: true, }), ], diff --git a/vitest.config.ts b/vitest.config.ts index 59df940..7bec1a9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -2,6 +2,7 @@ import react from "@vitejs/plugin-react"; import tsconfigPaths from "vite-tsconfig-paths"; import { configDefaults, defineConfig } from "vitest/config"; +/* eslint-disable import/no-default-export */ export default defineConfig({ plugins: [react(), tsconfigPaths()], test: {