diff --git a/package-lock.json b/package-lock.json index c783dec8f..8e92fea66 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1008,6 +1008,149 @@ "node": ">=14" } }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", + "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", + "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", + "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", + "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", + "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", + "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", + "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", + "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", + "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", + "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", + "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, "node_modules/@rollup/rollup-linux-x64-gnu": { "version": "4.27.4", "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", @@ -1020,6 +1163,58 @@ "linux" ] }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", + "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", + "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", + "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", + "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@sigstore/bundle": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-2.3.2.tgz", @@ -1173,6 +1368,42 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, + "node_modules/@types/react": { + "version": "19.0.2", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.2.tgz", + "integrity": "sha512-USU8ZI/xyKJwFTpjSVIrSeHBVAGagkHQKPNbxeWwql/vDmnTIBgx+TJnhFnj1NXgz8XfprU0egV2dROLGpsBEg==", + "dev": true, + "dependencies": { + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-helmet": { + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz", + "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-linkify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/react-linkify/-/react-linkify-1.0.4.tgz", + "integrity": "sha512-NOMw4X3kjvjY0lT5kXQdxZCXpPNi2hOuuqG+Kz+5EOQpi9rDUJJDitdE1j2JRNmrTnNIjrLnYG0HKyuOWN/uKA==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/react-window": { + "version": "1.8.8", + "resolved": "https://registry.npmjs.org/@types/react-window/-/react-window-1.8.8.tgz", + "integrity": "sha512-8Ls660bHR1AUA2kuRvVG9D/4XpRC6wjAaPT9dil7Ckc76eP9TKWZwwmgfq8Q1LANX3QNDnoU4Zp48A3w+zK69Q==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -2057,6 +2288,12 @@ "node": ">=4" } }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true + }, "node_modules/dargs": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", @@ -7264,6 +7501,19 @@ "darwin" ] }, + "packages/base-shell/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, "packages/base-shell/node_modules/@sideway/address": { "version": "4.1.5", "dev": true, @@ -7685,11 +7935,6 @@ "dev": true, "license": "MIT" }, - "packages/base-shell/node_modules/csstype": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, "packages/base-shell/node_modules/cypress": { "version": "13.16.0", "dev": true, @@ -9148,6 +9393,7 @@ "@fontsource/roboto": "^5.1.0", "@mui/icons-material": "^6.1.4", "@mui/material": "^6.1.4", + "@types/react-window": "^1.8.8", "@vitejs/plugin-react": "^4.3.2", "cypress": "^13.15.0", "glob": "^11.0.0", @@ -10047,6 +10293,19 @@ "darwin" ] }, + "packages/material-ui-shell/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, "packages/material-ui-shell/node_modules/@sideway/address": { "version": "4.1.5", "dev": true, @@ -10867,11 +11126,6 @@ "node": ">=10" } }, - "packages/material-ui-shell/node_modules/csstype": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, "packages/material-ui-shell/node_modules/cypress": { "version": "13.16.0", "dev": true, @@ -14047,6 +14301,9 @@ "@mui/material": "^6.1.4", "@mui/styles": "^6.1.4", "@mui/x-date-pickers": "^7.20.0", + "@types/react": "^18.3.12", + "@types/react-helmet": "^6.1.11", + "@types/react-linkify": "^1.0.4", "@vitejs/plugin-react": "^4.3.2", "chart.js": "^4.4.5", "cypress": "^13.15.0", @@ -15749,6 +16006,19 @@ "darwin" ] }, + "packages/rmw-shell/node_modules/@rollup/rollup-darwin-x64": { + "version": "4.27.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", + "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, "packages/rmw-shell/node_modules/@sideway/address": { "version": "4.1.5", "dev": true, @@ -16409,11 +16679,6 @@ "is-in-browser": "^1.0.2" } }, - "packages/rmw-shell/node_modules/csstype": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, "packages/rmw-shell/node_modules/cypress": { "version": "13.16.0", "dev": true, diff --git a/packages/base-shell/cypress.config.js b/packages/base-shell/cypress.config.ts similarity index 100% rename from packages/base-shell/cypress.config.js rename to packages/base-shell/cypress.config.ts diff --git a/packages/base-shell/package-lock.json b/packages/base-shell/package-lock.json deleted file mode 100644 index 8b4ac9b5d..000000000 --- a/packages/base-shell/package-lock.json +++ /dev/null @@ -1,4065 +0,0 @@ -{ - "name": "@ecronix/base-shell", - "version": "2.6.62", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@ecronix/base-shell", - "version": "2.6.62", - "license": "MIT", - "devDependencies": { - "@types/react": "^18.3.11", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^4.3.1", - "cypress": "^13.15.0", - "intl": "^1.2.5", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "react-intl": "^6.7.0", - "react-router-dom": "^6.26.2", - "rollup-plugin-visualizer": "^5.12.0", - "start-server-and-test": "^2.0.8", - "typescript": "^5.6.3", - "vite": "^5.4.8", - "vite-plugin-externalize-deps": "^0.8.0" - }, - "peerDependencies": { - "intl": "1.x", - "react": "17.x || 18.x", - "react-dom": "17.x || 18.x", - "react-intl": "6.x", - "react-router-dom": "6.x" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", - "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", - "dev": true, - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", - "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz", - "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz", - "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==", - "dev": true, - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz", - "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz", - "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==", - "dev": true, - "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", - "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", - "dev": true, - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", - "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", - "dev": true, - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz", - "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", - "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", - "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==", - "dev": true, - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz", - "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==", - "dev": true, - "dependencies": { - "@babel/types": "^7.26.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz", - "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz", - "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==", - "dev": true, - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", - "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", - "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", - "dev": true, - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "node_modules/@cypress/request": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.6.tgz", - "integrity": "sha512-fi0eVdCOtKu5Ed6+E8mYxUF6ZTFJDZvHogCBelM0xVXmrDEkyM22gRArQzq1YcHPm1V47Vf/iAD+WgVdUlJCGg==", - "dev": true, - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~4.0.0", - "http-signature": "~1.4.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.13.0", - "safe-buffer": "^5.1.2", - "tough-cookie": "^5.0.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", - "dev": true, - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "node_modules/@cypress/xvfb/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/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@formatjs/ecma402-abstract": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.4.tgz", - "integrity": "sha512-lFyiQDVvSbQOpU+WFd//ILolGj4UgA/qXrKeZxdV14uKiAUiPAtX6XAn7WBCRi7Mx6I7EybM9E5yYn4BIpZWYg==", - "dev": true, - "dependencies": { - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "node_modules/@formatjs/fast-memoize": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.3.tgz", - "integrity": "sha512-3jeJ+HyOfu8osl3GNSL4vVHUuWFXR03Iz9jjgI7RwjG6ysu/Ymdr0JRCPHfF5yGbTE6JCrd63EpvX1/WybYRbA==", - "dev": true, - "dependencies": { - "tslib": "2" - } - }, - "node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.9.4", - "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.4.tgz", - "integrity": "sha512-Tbvp5a9IWuxUcpWNIW6GlMQYEc4rwNHR259uUFoKWNN1jM9obf9Ul0e+7r7MvFOBNcN+13K7NuKCKqQiAn1QEg==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/icu-skeleton-parser": "1.8.8", - "tslib": "2" - } - }, - "node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.8", - "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.8.tgz", - "integrity": "sha512-vHwK3piXwamFcx5YQdCdJxUQ1WdTl6ANclt5xba5zLGDv5Bsur7qz8AD7BevaKxITwpgDeU0u8My3AIibW9ywA==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "tslib": "2" - } - }, - "node_modules/@formatjs/intl": { - "version": "2.10.15", - "resolved": "https://registry.npmjs.org/@formatjs/intl/-/intl-2.10.15.tgz", - "integrity": "sha512-i6+xVqT+6KCz7nBfk4ybMXmbKO36tKvbMKtgFz9KV+8idYFyFbfwKooYk8kGjyA5+T5f1kEPQM5IDLXucTAQ9g==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/icu-messageformat-parser": "2.9.4", - "@formatjs/intl-displaynames": "6.8.5", - "@formatjs/intl-listformat": "7.7.5", - "intl-messageformat": "10.7.7", - "tslib": "2" - }, - "peerDependencies": { - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@formatjs/intl-displaynames": { - "version": "6.8.5", - "resolved": "https://registry.npmjs.org/@formatjs/intl-displaynames/-/intl-displaynames-6.8.5.tgz", - "integrity": "sha512-85b+GdAKCsleS6cqVxf/Aw/uBd+20EM0wDpgaxzHo3RIR3bxF4xCJqH/Grbzx8CXurTgDDZHPdPdwJC+May41w==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "node_modules/@formatjs/intl-listformat": { - "version": "7.7.5", - "resolved": "https://registry.npmjs.org/@formatjs/intl-listformat/-/intl-listformat-7.7.5.tgz", - "integrity": "sha512-Wzes10SMNeYgnxYiKsda4rnHP3Q3II4XT2tZyOgnH5fWuHDtIkceuWlRQNsvrI3uiwP4hLqp2XdQTCsfkhXulg==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "node_modules/@formatjs/intl-localematcher": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.8.tgz", - "integrity": "sha512-I+WDNWWJFZie+jkfkiK5Mp4hEDyRSEvmyfYadflOno/mmKJKcB17fEpEH0oJu/OWhhCJ8kJBDz2YMd/6cDl7Mg==", - "dev": true, - "dependencies": { - "tslib": "2" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", - "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@remix-run/router": { - "version": "1.21.0", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz", - "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==", - "dev": true, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.27.4.tgz", - "integrity": "sha512-2Y3JT6f5MrQkICUyRVCw4oa0sutfAsgaSsb0Lmmy1Wi2y7X5vT9Euqw4gOsCyy0YfKURBg35nhUKZS4mDcfULw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.27.4.tgz", - "integrity": "sha512-wzKRQXISyi9UdCVRqEd0H4cMpzvHYt1f/C3CoIjES6cG++RHKhrBj2+29nPF0IB5kpy9MS71vs07fvrNGAl/iA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.27.4.tgz", - "integrity": "sha512-PlNiRQapift4LNS8DPUHuDX/IdXiLjf8mc5vdEmUR0fF/pyy2qWwzdLjB+iZquGr8LuN4LnUoSEvKRwjSVYz3Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.27.4.tgz", - "integrity": "sha512-o9bH2dbdgBDJaXWJCDTNDYa171ACUdzpxSZt+u/AAeQ20Nk5x+IhA+zsGmrQtpkLiumRJEYef68gcpn2ooXhSQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.27.4.tgz", - "integrity": "sha512-NBI2/i2hT9Q+HySSHTBh52da7isru4aAAo6qC3I7QFVsuhxi2gM8t/EI9EVcILiHLj1vfi+VGGPaLOUENn7pmw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.27.4.tgz", - "integrity": "sha512-wYcC5ycW2zvqtDYrE7deary2P2UFmSh85PUpAx+dwTCO9uw3sgzD6Gv9n5X4vLaQKsrfTSZZ7Z7uynQozPVvWA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.27.4.tgz", - "integrity": "sha512-9OwUnK/xKw6DyRlgx8UizeqRFOfi9mf5TYCw1uolDaJSbUmBxP85DE6T4ouCMoN6pXw8ZoTeZCSEfSaYo+/s1w==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.27.4.tgz", - "integrity": "sha512-Vgdo4fpuphS9V24WOV+KwkCVJ72u7idTgQaBoLRD0UxBAWTF9GWurJO9YD9yh00BzbkhpeXtm6na+MvJU7Z73A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.27.4.tgz", - "integrity": "sha512-pleyNgyd1kkBkw2kOqlBx+0atfIIkkExOTiifoODo6qKDSpnc6WzUY5RhHdmTdIJXBdSnh6JknnYTtmQyobrVg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.27.4.tgz", - "integrity": "sha512-caluiUXvUuVyCHr5DxL8ohaaFFzPGmgmMvwmqAITMpV/Q+tPoaHZ/PWa3t8B2WyoRcIIuu1hkaW5KkeTDNSnMA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.27.4.tgz", - "integrity": "sha512-FScrpHrO60hARyHh7s1zHE97u0KlT/RECzCKAdmI+LEoC1eDh/RDji9JgFqyO+wPDb86Oa/sXkily1+oi4FzJQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.27.4.tgz", - "integrity": "sha512-qyyprhyGb7+RBfMPeww9FlHwKkCXdKHeGgSqmIXw9VSUtvyFZ6WZRtnxgbuz76FK7LyoN8t/eINRbPUcvXB5fw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.27.4.tgz", - "integrity": "sha512-PFz+y2kb6tbh7m3A7nA9++eInGcDVZUACulf/KzDtovvdTizHpZaJty7Gp0lFwSQcrnebHOqxF1MaKZd7psVRg==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.27.4.tgz", - "integrity": "sha512-Ni8mMtfo+o/G7DVtweXXV/Ol2TFf63KYjTtoZ5f078AUgJTmaIJnj4JFU7TK/9SVWTaSJGxPi5zMDgK4w+Ez7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.27.4.tgz", - "integrity": "sha512-5AeeAF1PB9TUzD+3cROzFTnAJAcVUGLuR8ng0E0WXGkYhp6RD6L+6szYVX+64Rs0r72019KHZS1ka1q+zU/wUw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.27.4.tgz", - "integrity": "sha512-yOpVsA4K5qVwu2CaS3hHxluWIK5HQTjNV4tWjQXluMiiiu4pJj4BN98CvxohNCpcjMeTXk/ZMJBRbgRg8HBB6A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.27.4.tgz", - "integrity": "sha512-KtwEJOaHAVJlxV92rNYiG9JQwQAdhBlrjNRp7P9L8Cb4Rer3in+0A+IPhJC9y68WAi9H0sX4AiG2NTsVlmqJeQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.27.4.tgz", - "integrity": "sha512-3j4jx1TppORdTAoBJRd+/wJRGCPC0ETWkXOecJ6PPZLj6SptXkrXcNqdj0oclbKML6FkQltdz7bBA3rUSirZug==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", - "dev": true, - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz", - "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==", - "dev": true, - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "node_modules/@types/node": { - "version": "22.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz", - "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==", - "dev": true, - "optional": true, - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "node_modules/@types/prop-types": { - "version": "15.7.13", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", - "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", - "dev": true - }, - "node_modules/@types/react": { - "version": "18.3.12", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz", - "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==", - "dev": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==", - "dev": true, - "dependencies": { - "@types/react": "*" - } - }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true - }, - "node_modules/@types/sizzle": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", - "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", - "dev": true - }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.4.tgz", - "integrity": "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==", - "dev": true, - "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" - } - }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-escapes": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", - "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true - }, - "node_modules/asn1": { - "version": "0.2.6", - "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz", - "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==", - "dev": true, - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "node_modules/assert-plus": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", - "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", - "dev": true, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", - "dev": true, - "engines": { - "node": ">= 4.0.0" - } - }, - "node_modules/aws-sign2": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", - "integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", - "dev": true - }, - "node_modules/axios": { - "version": "1.7.8", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.8.tgz", - "integrity": "sha512-Uu0wb7KNqK2t5K+YQyVCLM76prD5sRFjKHbJYCP1J7JFGEQ6nN7HWn9+04LAeiJ3ji54lgS/gZCH1oxyrf1SPw==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/axios/node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", - "integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==", - "dev": true, - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", - "dev": true - }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", - "dev": true - }, - "node_modules/browserslist": { - "version": "4.24.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", - "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/call-bind": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", - "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001684", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001684.tgz", - "integrity": "sha512-G1LRwLIQjBQoyq0ZJGqGIJUXzJ8irpbjHLpVRXDvBEScFJ9b17sgK6vlx0GAJFE21okD7zXl08rRRUfq6HdoEQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ] - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/ci-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", - "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "engines": { - "node": ">=8" - } - }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", - "dev": true, - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", - "dev": true, - "engines": { - "node": ">= 6" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true - }, - "node_modules/core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true - }, - "node_modules/cypress": { - "version": "13.16.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.16.0.tgz", - "integrity": "sha512-g6XcwqnvzXrqiBQR/5gN+QsyRmKRhls1y5E42fyOvsmU7JuY+wM6uHJWj4ZPttjabzbnRvxcik2WemR8+xT6FA==", - "dev": true, - "hasInstallScript": true, - "dependencies": { - "@cypress/request": "^3.0.6", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.7.1", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "ci-info": "^4.0.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.3", - "tree-kill": "1.2.2", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" - } - }, - "node_modules/cypress/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", - "dev": true - }, - "node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/duplexer": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", - "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", - "dev": true - }, - "node_modules/ecc-jsbn": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", - "integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==", - "dev": true, - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.66", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.66.tgz", - "integrity": "sha512-pI2QF6+i+zjPbqRzJwkMvtvkdI7MjVbSh2g8dlMguDJIXEPw+kwasS1Jl+YGPEBfGVxsVgGUratAKymPdPo2vQ==", - "dev": true - }, - "node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, - "dependencies": { - "once": "^1.4.0" - } - }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", - "dev": true, - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/es-define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", - "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/event-stream": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-3.3.4.tgz", - "integrity": "sha512-QHpkERcGsR0T7Qm3HNJSyXKEEj8AHNxkY3PK8TS2KJvQ7NiSHe3DDpwVKKtoYprL/AreyzFBeIkBIWChAqn60g==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", - "dev": true - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", - "dev": true, - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "dev": true - }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extsprintf": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", - "integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==", - "dev": true, - "engines": [ - "node >=0.6.0" - ] - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, - "dependencies": { - "pend": "~1.2.0" - } - }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", - "dev": true, - "dependencies": { - "escape-string-regexp": "^1.0.5" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/forever-agent": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", - "integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==", - "dev": true, - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/from": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", - "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", - "dev": true - }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", - "dev": true, - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-intrinsic": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", - "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", - "dev": true, - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", - "dev": true, - "dependencies": { - "async": "^3.2.0" - } - }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", - "dev": true, - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-proto": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", - "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", - "dev": true, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", - "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==", - "dev": true, - "dependencies": { - "react-is": "^16.7.0" - } - }, - "node_modules/http-signature": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", - "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", - "dev": true, - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.18.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "engines": { - "node": ">=8.12.0" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/intl": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/intl/-/intl-1.2.5.tgz", - "integrity": "sha512-rK0KcPHeBFBcqsErKSpvZnrOmWOj+EmDkyJ57e90YWaQNqbcivcqmKDlHEeNprDWOsKzPsh1BfSpPQdDvclHVw==", - "dev": true - }, - "node_modules/intl-messageformat": { - "version": "10.7.7", - "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.7.tgz", - "integrity": "sha512-F134jIoeYMro/3I0h08D0Yt4N9o9pjddU/4IIxMMURqbAtI2wu70X8hvG1V48W49zXHXv3RKSF/po+0fDfsGjA==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/icu-messageformat-parser": "2.9.4", - "tslib": "2" - } - }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", - "dev": true, - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", - "dev": true, - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "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-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", - "dev": true, - "dependencies": { - "is-docker": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true - }, - "node_modules/joi": { - "version": "17.13.3", - "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", - "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", - "dev": true, - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true - }, - "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true - }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "dev": true, - "dependencies": { - "universalify": "^2.0.0" - }, - "optionalDependencies": { - "graceful-fs": "^4.1.6" - } - }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", - "dev": true, - "engines": { - "node": "> 0.8" - } - }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==", - "dev": true - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/map-stream": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.1.0.tgz", - "integrity": "sha512-CkYQrPYZfWnu/DAmVCpTSX/xHpKZ80eKh2lAkyA6AJTef6bW+6JpbQZN5rofum7da+SyN1bi5ctTm+lTfcCW3g==", - "dev": true - }, - "node_modules/merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", - "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", - "dev": true - }, - "node_modules/npm-run-path": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", - "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", - "dev": true, - "dependencies": { - "path-key": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", - "dev": true, - "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", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/open": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", - "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", - "dev": true, - "dependencies": { - "define-lazy-prop": "^2.0.0", - "is-docker": "^2.1.1", - "is-wsl": "^2.2.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true - }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "dev": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/pause-stream": { - "version": "0.0.11", - "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", - "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", - "dev": true, - "dependencies": { - "through": "~2.3" - } - }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true - }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", - "dev": true - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/process": { - "version": "0.11.10", - "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", - "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, - "engines": { - "node": ">= 0.6.0" - } - }, - "node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", - "dev": true - }, - "node_modules/ps-tree": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.2.0.tgz", - "integrity": "sha512-0VnamPPYHl4uaU/nSFeZZpR21QAWRz+sRv4iW9+v/GS/J5U5iZB5BNN6J0RMoOvdx2gWM2+ZFMIm58q24e4UYA==", - "dev": true, - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "node_modules/pump": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", - "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", - "dev": true, - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "dev": true, - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-intl": { - "version": "6.8.9", - "resolved": "https://registry.npmjs.org/react-intl/-/react-intl-6.8.9.tgz", - "integrity": "sha512-TUfj5E7lyUDvz/GtovC9OMh441kBr08rtIbgh3p0R8iF3hVY+V2W9Am7rb8BpJ/29BH1utJOqOOhmvEVh3GfZg==", - "dev": true, - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/icu-messageformat-parser": "2.9.4", - "@formatjs/intl": "2.10.15", - "@formatjs/intl-displaynames": "6.8.5", - "@formatjs/intl-listformat": "7.7.5", - "@types/hoist-non-react-statics": "3", - "@types/react": "16 || 17 || 18", - "hoist-non-react-statics": "3", - "intl-messageformat": "10.7.7", - "tslib": "2" - }, - "peerDependencies": { - "react": "^16.6.0 || 17 || 18", - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/react-is": { - "version": "16.13.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", - "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", - "dev": true - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", - "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz", - "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==", - "dev": true, - "dependencies": { - "@remix-run/router": "1.21.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.28.0", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz", - "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==", - "dev": true, - "dependencies": { - "@remix-run/router": "1.21.0", - "react-router": "6.28.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, - "dependencies": { - "throttleit": "^1.0.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "dev": true - }, - "node_modules/rollup": { - "version": "4.27.4", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.27.4.tgz", - "integrity": "sha512-RLKxqHEMjh/RGLsDxAEsaLO3mWgyoU6x9w6n1ikAzet4B3gI2/3yP6PWY2p9QzRTh6MfEIXB3MwsOY0Iv3vNrw==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.4", - "@rollup/rollup-android-arm64": "4.27.4", - "@rollup/rollup-darwin-arm64": "4.27.4", - "@rollup/rollup-darwin-x64": "4.27.4", - "@rollup/rollup-freebsd-arm64": "4.27.4", - "@rollup/rollup-freebsd-x64": "4.27.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", - "@rollup/rollup-linux-arm-musleabihf": "4.27.4", - "@rollup/rollup-linux-arm64-gnu": "4.27.4", - "@rollup/rollup-linux-arm64-musl": "4.27.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", - "@rollup/rollup-linux-riscv64-gnu": "4.27.4", - "@rollup/rollup-linux-s390x-gnu": "4.27.4", - "@rollup/rollup-linux-x64-gnu": "4.27.4", - "@rollup/rollup-linux-x64-musl": "4.27.4", - "@rollup/rollup-win32-arm64-msvc": "4.27.4", - "@rollup/rollup-win32-ia32-msvc": "4.27.4", - "@rollup/rollup-win32-x64-msvc": "4.27.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/rollup-plugin-visualizer": { - "version": "5.12.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-visualizer/-/rollup-plugin-visualizer-5.12.0.tgz", - "integrity": "sha512-8/NU9jXcHRs7Nnj07PF2o4gjxmm9lXIrZ8r175bT9dK8qoLlvKTwRMArRCMgpMGlq8CTLugRvEmyMeMXIU2pNQ==", - "dev": true, - "dependencies": { - "open": "^8.4.0", - "picomatch": "^2.3.1", - "source-map": "^0.7.4", - "yargs": "^17.5.1" - }, - "bin": { - "rollup-plugin-visualizer": "dist/bin/cli.js" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "rollup": "2.x || 3.x || 4.x" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/rxjs": { - "version": "7.8.1", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", - "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", - "dev": true, - "dependencies": { - "tslib": "^2.1.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "dev": true, - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "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/set-function-length": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", - "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", - "dev": true, - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/side-channel": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", - "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", - "dev": true, - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/split": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/split/-/split-0.3.3.tgz", - "integrity": "sha512-wD2AeVmxXRBoX44wAycgjVpMhvbwdI2aZjCkvfNcH1YqHQvJVa1duWc73OyVGJUc05fhFaTZeQ/PYsrmyH0JVA==", - "dev": true, - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "node_modules/sshpk": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz", - "integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==", - "dev": true, - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/start-server-and-test": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/start-server-and-test/-/start-server-and-test-2.0.8.tgz", - "integrity": "sha512-v2fV6NV2F7tL1ocwfI4Wpait+IKjRbT5l3ZZ+ZikXdMLmxYsS8ynGAsCQAUVXkVyGyS+UibsRnvgHkMvJIvCsw==", - "dev": true, - "dependencies": { - "arg": "^5.0.2", - "bluebird": "3.7.2", - "check-more-types": "2.24.0", - "debug": "4.3.7", - "execa": "5.1.1", - "lazy-ass": "1.6.0", - "ps-tree": "1.2.0", - "wait-on": "8.0.1" - }, - "bin": { - "server-test": "src/bin/start.js", - "start-server-and-test": "src/bin/start.js", - "start-test": "src/bin/start.js" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/start-server-and-test/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", - "dev": true, - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "node_modules/start-server-and-test/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/start-server-and-test/node_modules/human-signals": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", - "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", - "dev": true, - "engines": { - "node": ">=10.17.0" - } - }, - "node_modules/stream-combiner": { - "version": "0.0.4", - "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.0.4.tgz", - "integrity": "sha512-rT00SPnTVyRsaSz5zgSPma/aHSOic5U1prhYdRy5HS2kTZviFpmDgzilbtsJsxiroqACmayynDN/9VzIbX5DOw==", - "dev": true, - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "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-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true - }, - "node_modules/tldts": { - "version": "6.1.64", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.64.tgz", - "integrity": "sha512-ph4AE5BXWIOsSy9stpoeo7bYe/Cy7VfpciIH4RhVZUPItCJmhqWCN0EVzxd8BOHiyNb42vuJc6NWTjJkg91Tuw==", - "dev": true, - "dependencies": { - "tldts-core": "^6.1.64" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.64", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.64.tgz", - "integrity": "sha512-uqnl8vGV16KsyflHOzqrYjjArjfXaU6rMPXYy2/ZWoRKCkXtghgB4VwTDXUG+t0OTGeSewNAG31/x1gCTfLt+Q==", - "dev": true - }, - "node_modules/tmp": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", - "integrity": "sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==", - "dev": true, - "engines": { - "node": ">=14.14" - } - }, - "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", - "dev": true, - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/tree-kill": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", - "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", - "dev": true, - "bin": { - "tree-kill": "cli.js" - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "dev": true - }, - "node_modules/tunnel-agent": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", - "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "node_modules/tweetnacl": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", - "integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==", - "dev": true - }, - "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", - "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", - "dev": true, - "optional": true - }, - "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", - "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "dev": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/verror": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", - "integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "node_modules/vite": { - "version": "5.4.11", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz", - "integrity": "sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-plugin-externalize-deps": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/vite-plugin-externalize-deps/-/vite-plugin-externalize-deps-0.8.0.tgz", - "integrity": "sha512-MdC8kRNQ1ZjhUicU2HcqGVhL0UUFqv83Zp1JZdHjE82PoPR8wsSWZ3axpot7B6img3sW6g8shYJikE0CKA0chA==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/voracious" - }, - "peerDependencies": { - "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "node_modules/wait-on": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/wait-on/-/wait-on-8.0.1.tgz", - "integrity": "sha512-1wWQOyR2LVVtaqrcIL2+OM+x7bkpmzVROa0Nf6FryXkS+er5Sa1kzFGjzZRqLnHa3n1rACFLeTwUqE1ETL9Mig==", - "dev": true, - "dependencies": { - "axios": "^1.7.7", - "joi": "^17.13.3", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "rxjs": "^7.8.1" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "engines": { - "node": ">=12" - } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - } - } -} \ No newline at end of file diff --git a/packages/base-shell/src/components/AuthorizedRoute/index.tsx b/packages/base-shell/src/components/AuthorizedRoute/index.tsx index e5457a983..25b5644b6 100644 --- a/packages/base-shell/src/components/AuthorizedRoute/index.tsx +++ b/packages/base-shell/src/components/AuthorizedRoute/index.tsx @@ -1,11 +1,33 @@ import { Navigate, useLocation } from "react-router-dom"; -import { AppConfig, useAuth, useConfig } from "@ecronix/base-shell"; +import { useAuth, useConfig } from "@ecronix/base-shell"; -export function AuthorizedRoute({ children }: { children: React.ReactNode }) { - const { appConfig } = useConfig() +/** + * A route component that renders its children for authenticated users only. + * + * If the user is authenticated, the children components are rendered. + * If unauthenticated, the user is redirected to the sign-in page with the + * current path included as a query parameter for redirection after login. + * + * @param {object} props - The properties passed to the `AuthorizedRoute` component. + * @param {React.ReactNode} props.children - The components to render if the user is authenticated. + * + * @returns {JSX.Element} The rendered children for authorized users or a `` component for redirection. + * + * @example + * + * + * + */ + +export function AuthorizedRoute({ + children, +}: { + children: React.ReactNode; +}): React.ReactNode { + const { appConfig } = useConfig(); const { auth: authConfig } = appConfig || {}; const { signInURL = "/signin" } = authConfig || {}; - const { auth } = useAuth() + const { auth } = useAuth(); const location = useLocation(); if (auth.isAuthenticated) { diff --git a/packages/base-shell/src/components/UnauthorizedRoute/index.tsx b/packages/base-shell/src/components/UnauthorizedRoute/index.tsx index db076c4cf..8ad8c2e63 100644 --- a/packages/base-shell/src/components/UnauthorizedRoute/index.tsx +++ b/packages/base-shell/src/components/UnauthorizedRoute/index.tsx @@ -3,7 +3,29 @@ import { Navigate } from "react-router-dom"; import { useAuth, useConfig } from "@ecronix/base-shell"; import { useLocation } from "react-router-dom"; -export function UnauthorizedRoute({ children, redirectTo = "/", ...rest }: any) { +/** + * A route component that renders its children for unauthorized users only. + * + * If the user is authenticated, they are redirected to the specified path. + * If unauthenticated, the children components are rendered. + * + * @param {object} props - The properties passed to the `UnauthorizedRoute` component. + * @param {React.ReactNode} props.children - The components to render if the user is not authenticated. + * @param {string} [props.redirectTo="/"] - The default path to redirect to if the user is authenticated. + * @param rest - Additional props passed to the component. + * + * @returns {JSX.Element} The rendered children for unauthorized users or a `` component for redirection. + * + * @example + * + * + * + */ +export function UnauthorizedRoute({ + children, + redirectTo = "/", + ...rest +}: any): JSX.Element { const { appConfig } = useConfig(); let location = useLocation(); const { auth: authConfig } = appConfig || {}; diff --git a/packages/base-shell/src/containers/App/index.tsx b/packages/base-shell/src/containers/App/index.tsx index 4572478e3..1614d3ac7 100644 --- a/packages/base-shell/src/containers/App/index.tsx +++ b/packages/base-shell/src/containers/App/index.tsx @@ -11,15 +11,34 @@ export interface AppConfig { LandingPage?: React.ComponentType; }; components?: { + Menu?: React.ComponentType; Loading?: React.ComponentType; }; containers?: { AppContainer?: React.ComponentType; + LayoutContainer?: React.ComponentType; }; [key: string]: any; } -export const AppContainer: React.FC = ({ config: appConfig }) => { +/** + * React component that serves as the main container for the application. + * + * This component receives configuration data as props and manages the + * high-level layout or setup for the application. + * + * @param {AppContainerProps} props - The properties passed to the `AppContainer` component. + * @param {AppConfig} props.config - The application configuration object. + * + * @returns The rendered application container with embedded router and Loading component. + * + * @example + * + * + */ +export const AppContainer: React.FC = ({ + config: appConfig, +}) => { const config: AppConfig = { ...appConfig }; const { pages, components, containers } = config; const { LandingPage = false } = pages || {}; @@ -32,14 +51,12 @@ export const AppContainer: React.FC = ({ config: appConfig }) - {LandingPage && ( - } /> - )} + {LandingPage && } />} }> - + } /> diff --git a/packages/base-shell/src/containers/Layout/index.jsx b/packages/base-shell/src/containers/Layout/index.tsx similarity index 77% rename from packages/base-shell/src/containers/Layout/index.jsx rename to packages/base-shell/src/containers/Layout/index.tsx index 70712ceea..639c09637 100644 --- a/packages/base-shell/src/containers/Layout/index.jsx +++ b/packages/base-shell/src/containers/Layout/index.tsx @@ -1,7 +1,12 @@ import React, { Suspense, useEffect, useState } from "react"; import { useRoutes } from "react-router-dom"; import { IntlProvider } from "react-intl"; -import { useLocale, useConfig, getLocaleMessages } from "@ecronix/base-shell"; +import { + useLocale, + useConfig, + getLocaleMessages, + AppConfig, +} from "@ecronix/base-shell"; import { AddToHomeScreenProvider, AuthProvider, @@ -10,9 +15,10 @@ import { SimpleValuesProvider, LocaleProvider, } from "@ecronix/base-shell"; +import { LocaleContextType } from "@ecronix/base-shell/providers/Locale/Context"; export const LayoutContent = ({ appConfig = {} }) => { - const [messages, setMessages] = useState([]); + const [messages, setMessages] = useState>(); const { components, routes = [], @@ -21,36 +27,39 @@ export const LayoutContent = ({ appConfig = {} }) => { getDefaultRoutes, auth, update, - } = appConfig || {}; + }: AppConfig = appConfig || {}; const { persistKey } = auth || {}; const { checkInterval = 5000 } = update || {}; const { Menu, Loading = () =>
Loading...
} = components || {}; const { locales, onError } = confLocale || {}; const { LayoutContainer = React.Fragment } = containers || {}; const defaultRoutes = getDefaultRoutes ? getDefaultRoutes(appConfig) : []; - const { locale = {} } = useLocale(); + const { locale }: LocaleContextType = useLocale(); useEffect(() => { const loadPolyfills = async () => { //loadLocalePolyfill(locale) - if (locale.locales && locale.locales.length > 0) { - for (let i = 0; i < locales.length; i++) { - const l = locales[i]; - if (l.locale === locale) { - if (l.loadData) { - await l.loadData; - } + // if (locale.locales && locale.locales.length > 0) { + for (let i = 0; i < locales.length; i++) { + const l = locales[i]; + if (l.locale === locale) { + if (l.loadData) { + await l.loadData; } } } + // } }; loadPolyfills(); }, [locale, locales]); useEffect(() => { const loadMessages = async () => { - const messages = await getLocaleMessages(locale, locales); + const messages: Record = await getLocaleMessages( + locale, + locales + ); setMessages(messages); }; loadMessages(); diff --git a/packages/base-shell/src/index.ts b/packages/base-shell/src/index.ts index 4e4f9b730..2d6d30f2e 100644 --- a/packages/base-shell/src/index.ts +++ b/packages/base-shell/src/index.ts @@ -2,3 +2,9 @@ export * from "./components"; export * from "./containers"; export * from "./utils"; export * from "./providers"; + +declare global { + interface Window { + update?: () => void; + } +} diff --git a/packages/base-shell/src/providers/AddToHomeScreen/Context.jsx b/packages/base-shell/src/providers/AddToHomeScreen/Context.jsx deleted file mode 100644 index 017737531..000000000 --- a/packages/base-shell/src/providers/AddToHomeScreen/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -const Context = React.createContext(null); - -export default Context; diff --git a/packages/base-shell/src/providers/AddToHomeScreen/Context.tsx b/packages/base-shell/src/providers/AddToHomeScreen/Context.tsx new file mode 100644 index 000000000..ccabac87e --- /dev/null +++ b/packages/base-shell/src/providers/AddToHomeScreen/Context.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import { AddToHomeScreenStateProps } from "./Provider"; +export interface AddToHomeScreenContextType { + deferredPrompt?: Event | undefined; + isAppInstallable?: boolean; + isAppInstalled?: boolean; + + /** + * @description Updates addToHomeScreenContext with provided data + * @param {AddToHomeScreenStateProps} + */ + setA2HPState: React.Dispatch>; +} + +const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/base-shell/src/providers/AddToHomeScreen/Provider.jsx b/packages/base-shell/src/providers/AddToHomeScreen/Provider.tsx similarity index 63% rename from packages/base-shell/src/providers/AddToHomeScreen/Provider.jsx rename to packages/base-shell/src/providers/AddToHomeScreen/Provider.tsx index f6eb5df80..cba7fa4ed 100644 --- a/packages/base-shell/src/providers/AddToHomeScreen/Provider.jsx +++ b/packages/base-shell/src/providers/AddToHomeScreen/Provider.tsx @@ -1,14 +1,21 @@ import React, { useState } from "react"; import Context from "./Context"; -const initialState = { - deferredPrompt: () => {}, +const initialState: AddToHomeScreenStateProps = { + deferredPrompt: undefined, isAppInstallable: false, isAppInstalled: false, }; -const Provider = ({ children }) => { - const [state, setA2HPState] = useState(initialState); +export type AddToHomeScreenStateProps = { + deferredPrompt?: Event | undefined; + isAppInstallable?: boolean; + isAppInstalled?: boolean; +}; + +const Provider: React.FC<{ children: React.ReactNode }> = ({ children }) => { + const [state, setA2HPState] = + useState(initialState); window.addEventListener("beforeinstallprompt", (e) => { // Prevent Chrome 67 and earlier from automatically showing the prompt diff --git a/packages/base-shell/src/providers/AddToHomeScreen/index.jsx b/packages/base-shell/src/providers/AddToHomeScreen/index.jsx deleted file mode 100644 index 19977875d..000000000 --- a/packages/base-shell/src/providers/AddToHomeScreen/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useAddToHomeScreen() { - return useContext(Context); -} - -export { - useAddToHomeScreen, - Context as AddToHomeScreenContext, - Provider as AddToHomeScreenProvider, -}; diff --git a/packages/base-shell/src/providers/AddToHomeScreen/index.tsx b/packages/base-shell/src/providers/AddToHomeScreen/index.tsx new file mode 100644 index 000000000..c03e164ea --- /dev/null +++ b/packages/base-shell/src/providers/AddToHomeScreen/index.tsx @@ -0,0 +1,33 @@ +import { useContext } from "react"; +import Context, { AddToHomeScreenContextType } from "./Context"; +import Provider from "./Provider"; + +/** + * Custom hook for addToHomeScreenContext + * + * @function + * @returns {AddToHomeScreenContext} The locale context value. + * @throws {Error} If used outside of AddToHomeScreenProvider + * @example + * const a2HSContext = useAddToHomeScreen(); + * + * @description + * This hook provides access to AddToHomeScreenContext. + * + * @see {@link AddToHomeScreenContextType} for the shape of the returned context + */ +function useAddToHomeScreen(): AddToHomeScreenContextType { + const context = useContext(Context); + if (!context) { + throw new Error( + "useAddToHomeScreen must be used within a AddToHomeScreenProvider" + ); + } + return context; +} + +export { + useAddToHomeScreen, + Context as AddToHomeScreenContext, + Provider as AddToHomeScreenProvider, +}; diff --git a/packages/base-shell/src/providers/Auth/Context.tsx b/packages/base-shell/src/providers/Auth/Context.tsx index c26f7433f..ca92e647a 100644 --- a/packages/base-shell/src/providers/Auth/Context.tsx +++ b/packages/base-shell/src/providers/Auth/Context.tsx @@ -1,11 +1,40 @@ import React from "react"; -export interface AuthContextType { - auth: { - isAuthenticated: boolean; - }; +export type ProviderData = { providerId: string }; +export type AuthUser = { + isAuthenticated: boolean; + photoURL: string; + displayName: string; + email: string; + uid: string; + isAdmin?: boolean; + providerData?: ProviderData[]; + notificationsDisabled?: boolean; + grants?: string[]; +}; + +// TODO Fix isAuthGranted import everywhere +export interface IAuthContext { + /** + * @description Authorized user object + */ + auth: AuthUser; + + /** + * @description Set auth to provided auth parameter + * @param auth + */ + setAuth: (auth: any) => void; + + /** + * @description Update auth to provided auth parameter + * @param auth + */ + updateAuth: (auth: any) => void; + + isAuthGranted?: (auth: AuthUser, type: string) => boolean; } -const ConfigContext = React.createContext(undefined); +const ConfigContext = React.createContext(undefined); export default ConfigContext; diff --git a/packages/base-shell/src/providers/Auth/Provider.jsx b/packages/base-shell/src/providers/Auth/Provider.tsx similarity index 74% rename from packages/base-shell/src/providers/Auth/Provider.jsx rename to packages/base-shell/src/providers/Auth/Provider.tsx index 31118ea0b..da3f2ccb1 100644 --- a/packages/base-shell/src/providers/Auth/Provider.jsx +++ b/packages/base-shell/src/providers/Auth/Provider.tsx @@ -1,7 +1,12 @@ import React, { useEffect, useReducer } from "react"; import Context from "./Context"; -function reducer(state, action) { +type ReducerAction = { + type: string; + auth: any; +}; + +function reducer(state: any, action: ReducerAction) { const { type, auth } = action; switch (type) { case "SET_AUTH": @@ -13,7 +18,10 @@ function reducer(state, action) { } } -const Provider = ({ persistKey = "auth", children }) => { +const Provider: React.FC<{ + children: React.ReactNode; + persistKey: string; +}> = ({ persistKey = "auth", children }) => { const persistAuth = JSON.parse( localStorage.getItem(persistKey)?.replace("undefined", "{}") || "{}" ); @@ -28,11 +36,11 @@ const Provider = ({ persistKey = "auth", children }) => { } }, [auth, persistKey]); - const setAuth = (auth) => { + const setAuth = (auth: any) => { dispatch({ type: "SET_AUTH", auth }); }; - const updateAuth = (auth) => { + const updateAuth = (auth: any) => { dispatch({ type: "UPDATE_AUTH", auth }); }; diff --git a/packages/base-shell/src/providers/Auth/index.tsx b/packages/base-shell/src/providers/Auth/index.tsx index 6d67c17f1..0e24fcfe0 100644 --- a/packages/base-shell/src/providers/Auth/index.tsx +++ b/packages/base-shell/src/providers/Auth/index.tsx @@ -1,11 +1,11 @@ import React, { useContext } from "react"; -import Context, { AuthContextType } from "./Context"; +import Context, { IAuthContext } from "./Context"; import Provider from "./Provider"; /** * Custom hook to access the authentication context. * * @function - * @returns {AuthContextType} The authentication context value. + * @returns {IAuthContext} The authentication context value. * @throws {Error} If used outside of an AuthProvider. * @example * const auth = useAuth(); @@ -17,20 +17,19 @@ import Provider from "./Provider"; * functions. It must be used within a component that is wrapped by an * AuthProvider. * - * The AuthContextType typically includes properties such as: + * The IAuthContext typically includes properties such as: * - isAuthenticated: A boolean indicating if the user is authenticated * - user: The current user object (if authenticated) * - login: A function to log in the user * - logout: A function to log out the user * - * @see {@link AuthProvider} for providing the authentication context - * @see {@link AuthContextType} for the shape of the returned context + * @see {@link IAuthContext} for the shape of the returned context */ -function useAuth(): AuthContextType { +function useAuth(): IAuthContext { const context = useContext(Context); if (context === undefined) { - throw new Error('useAuth must be used within a AuthProvider'); + throw new Error("useAuth must be used within a AuthProvider"); } return context; diff --git a/packages/base-shell/src/providers/Config/Context.tsx b/packages/base-shell/src/providers/Config/Context.tsx index d07cd1fe7..b96ec74ff 100644 --- a/packages/base-shell/src/providers/Config/Context.tsx +++ b/packages/base-shell/src/providers/Config/Context.tsx @@ -2,9 +2,14 @@ import { AppConfig } from "@ecronix/base-shell"; import React from "react"; export interface ConfigContextType { + /** + * @description App configuration + */ appConfig: AppConfig; } -const ConfigContext = React.createContext(undefined); +const ConfigContext = React.createContext( + undefined +); export default ConfigContext; diff --git a/packages/base-shell/src/providers/Config/index.tsx b/packages/base-shell/src/providers/Config/index.tsx index be7200aec..05a07197b 100644 --- a/packages/base-shell/src/providers/Config/index.tsx +++ b/packages/base-shell/src/providers/Config/index.tsx @@ -2,11 +2,26 @@ import React, { useContext } from "react"; import Context, { ConfigContextType } from "./Context"; import Provider from "./Provider"; +/** + * Custom hook to access the config provider + * + * @function + * @returns {ConfigContextType} The configuration context. + * @throws {Error} If used outside of an ConfigProvider. + * @example + * const { appConfig } = useConfig(); + * + * @description + * This hook provides access to the configuration context. It provides json object containing all configuration data + * and must be used withing ConfigProvider + * + * @see {@link ConfigContextType} for the shape of the returned context + */ function useConfig(): ConfigContextType { const context = useContext(Context); if (context === undefined) { - throw new Error('useConfig must be used within a ConfigProvider'); + throw new Error("useConfig must be used within a ConfigProvider"); } return context; diff --git a/packages/base-shell/src/providers/Locale/Context.jsx b/packages/base-shell/src/providers/Locale/Context.jsx deleted file mode 100644 index 017737531..000000000 --- a/packages/base-shell/src/providers/Locale/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -const Context = React.createContext(null); - -export default Context; diff --git a/packages/base-shell/src/providers/Locale/Context.tsx b/packages/base-shell/src/providers/Locale/Context.tsx new file mode 100644 index 000000000..7a2cd04d3 --- /dev/null +++ b/packages/base-shell/src/providers/Locale/Context.tsx @@ -0,0 +1,19 @@ +import React from "react"; + +export interface LocaleContextType { + /** + * Current locale settings - defaults to 'en' + * @type {string} + */ + locale: string; + + /** + * Method to update locale settings + * @param {string} locale - New provided locale string + */ + setLocale: React.Dispatch>; +} + +const Context = React.createContext(undefined); + +export default Context; diff --git a/packages/base-shell/src/providers/Locale/Provider.jsx b/packages/base-shell/src/providers/Locale/Provider.tsx similarity index 77% rename from packages/base-shell/src/providers/Locale/Provider.jsx rename to packages/base-shell/src/providers/Locale/Provider.tsx index 6081107bf..eebf597bd 100644 --- a/packages/base-shell/src/providers/Locale/Provider.jsx +++ b/packages/base-shell/src/providers/Locale/Provider.tsx @@ -1,7 +1,13 @@ import React, { useState, useEffect } from "react"; import Context from "./Context"; -const Provider = ({ +export interface LocaleProviderProps { + children: React.ReactNode; + defaultLocale?: string; + persistKey?: string; +} + +const Provider: React.FC = ({ children, defaultLocale = "en", persistKey = "locale", diff --git a/packages/base-shell/src/providers/Locale/index.jsx b/packages/base-shell/src/providers/Locale/index.jsx deleted file mode 100644 index 3a17a99b1..000000000 --- a/packages/base-shell/src/providers/Locale/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useLocale() { - return useContext(Context); -} - -export { useLocale, Context as LocaleContext, Provider as LocaleProvider }; diff --git a/packages/base-shell/src/providers/Locale/index.tsx b/packages/base-shell/src/providers/Locale/index.tsx new file mode 100644 index 000000000..fa53456d4 --- /dev/null +++ b/packages/base-shell/src/providers/Locale/index.tsx @@ -0,0 +1,28 @@ +import { useContext } from "react"; +import Context, { LocaleContextType } from "./Context"; +import Provider from "./Provider"; + +/** + * Custom hook for accessing locale context + * + * @function + * @returns {LocaleContextType} The locale context value. + * @throws {Error} If used outside of LocaleContext + * @example + * const { setLocale, locale = "en" } = useLocale(); + * + * @description + * This hook provides access localization context. It provides locale value and method to update locale value. + * + * @see {@link LocaleProvider} for providing localization context + * @see {@link LocaleContextType} for the shape of the returned context + */ +function useLocale(): LocaleContextType { + const context = useContext(Context); + if (!context) { + throw new Error("useLocale must be used within a LocaleProvider"); + } + return context; +} + +export { useLocale, Context as LocaleContext, Provider as LocaleProvider }; diff --git a/packages/base-shell/src/providers/Online/Context.jsx b/packages/base-shell/src/providers/Online/Context.jsx deleted file mode 100644 index 017737531..000000000 --- a/packages/base-shell/src/providers/Online/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -const Context = React.createContext(null); - -export default Context; diff --git a/packages/base-shell/src/providers/Online/Context.tsx b/packages/base-shell/src/providers/Online/Context.tsx new file mode 100644 index 000000000..13bd85167 --- /dev/null +++ b/packages/base-shell/src/providers/Online/Context.tsx @@ -0,0 +1,5 @@ +import React from "react"; + +const Context = React.createContext(undefined); + +export default Context; diff --git a/packages/base-shell/src/providers/Online/Provider.jsx b/packages/base-shell/src/providers/Online/Provider.jsx deleted file mode 100644 index 6aef7e1e8..000000000 --- a/packages/base-shell/src/providers/Online/Provider.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import React, { useState } from 'react' -import Context from './Context' - -const Provider = ({ children }) => { - const [isOnline, setOnline] = useState(navigator.onLine) - - window.addEventListener('online', () => setOnline(true)) - window.addEventListener('offline', () => setOnline(false)) - - return {children} -} - -export default Provider diff --git a/packages/base-shell/src/providers/Online/Provider.tsx b/packages/base-shell/src/providers/Online/Provider.tsx new file mode 100644 index 000000000..94e05dfb7 --- /dev/null +++ b/packages/base-shell/src/providers/Online/Provider.tsx @@ -0,0 +1,17 @@ +import React, { useState } from "react"; +import Context from "./Context"; + +export interface OnlineProviderProps { + children: React.ReactNode; +} + +const Provider: React.FC = ({ children }) => { + const [isOnline, setOnline] = useState(navigator.onLine); + + window.addEventListener("online", () => setOnline(true)); + window.addEventListener("offline", () => setOnline(false)); + + return {children}; +}; + +export default Provider; diff --git a/packages/base-shell/src/providers/Online/index.jsx b/packages/base-shell/src/providers/Online/index.jsx deleted file mode 100644 index 60d773ff9..000000000 --- a/packages/base-shell/src/providers/Online/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useOnline() { - return useContext(Context); -} - -export { useOnline, Context as OnlineContext, Provider as OnlineProvider }; diff --git a/packages/base-shell/src/providers/Online/index.tsx b/packages/base-shell/src/providers/Online/index.tsx new file mode 100644 index 000000000..611af8e60 --- /dev/null +++ b/packages/base-shell/src/providers/Online/index.tsx @@ -0,0 +1,25 @@ +import { useContext } from "react"; +import Context from "./Context"; +import Provider from "./Provider"; + +/** + * Custom hook to access the online listener provider. + * + * @function + * @returns {boolean} Boolean value regarding if client is online or offline + * @throws {Error} If used outside of an OnlineProvider. + * @example + * const isOnline = useOnline(); + * + * @description + * This hook provides access to the online listener context. It returns true if client is online. + */ +function useOnline(): boolean { + const context = useContext(Context); + if (!context) { + throw new Error("useOnline must be used within a OnlineProvider"); + } + return context; +} + +export { useOnline, Context as OnlineContext, Provider as OnlineProvider }; diff --git a/packages/base-shell/src/providers/SimpleValues/Context.jsx b/packages/base-shell/src/providers/SimpleValues/Context.jsx deleted file mode 100644 index 017737531..000000000 --- a/packages/base-shell/src/providers/SimpleValues/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -const Context = React.createContext(null); - -export default Context; diff --git a/packages/base-shell/src/providers/SimpleValues/Context.tsx b/packages/base-shell/src/providers/SimpleValues/Context.tsx new file mode 100644 index 000000000..9f9fee514 --- /dev/null +++ b/packages/base-shell/src/providers/SimpleValues/Context.tsx @@ -0,0 +1,36 @@ +import React from "react"; + +export interface SimpleValuesContextType { + /** + * Sets a value in the context. + * @param params - The parameters to set a value. + * @param params.key - The key to identify the value. + * @param params.value - The value to set. + * @param boolean params.persist - Whether to persist the value (e.g., in local storage). Defaults to 'false'. + */ + setValue: (key: string, value: any, persist?: boolean) => void; + + /** + * Gets a value from the context by key. + * @param key - The key to retrieve the value for. + * @returns The value corresponding to the key. + */ + getValue: (key: string, defaultValue?: any) => string; + + /** + * Clears a value from the context by key. + * @param key - The key to clear the value for. + */ + clearValue: (key: string) => void; + + /** + * Clears all values from the context. + */ + clearAll: () => void; +} + +const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/base-shell/src/providers/SimpleValues/Provider.jsx b/packages/base-shell/src/providers/SimpleValues/Provider.tsx similarity index 68% rename from packages/base-shell/src/providers/SimpleValues/Provider.jsx rename to packages/base-shell/src/providers/SimpleValues/Provider.tsx index b9c33a425..ea7ac925a 100644 --- a/packages/base-shell/src/providers/SimpleValues/Provider.jsx +++ b/packages/base-shell/src/providers/SimpleValues/Provider.tsx @@ -1,12 +1,23 @@ import React, { useEffect, useReducer } from "react"; import Context from "./Context"; -function reducer(state, action) { +type ReducerAction = { + type: string; + key?: string; + value?: any; + persist?: boolean; +}; + +function reducer(state: any, action: ReducerAction) { const { type, key, value, persist } = action; switch (type) { case "add": + if (!key) + throw new Error("Reducer Error: Key must be present when adding"); return { ...state, [key]: { value, persist } }; case "clear": + if (!key) + throw new Error("Reducer Error: Key must be present when clearing"); const { [key]: clearedKey, ...rest } = state; return { ...rest }; case "clear_all": @@ -16,7 +27,7 @@ function reducer(state, action) { } } -function getInitState(persistKey) { +function getInitState(persistKey: string) { let persistedValues = {}; try { persistedValues = @@ -29,12 +40,15 @@ function getInitState(persistKey) { return persistedValues; } -const Provider = ({ children, persistKey = "simple_values" }) => { +const Provider: React.FC<{ + children: React.ReactNode; + persistKey?: string; +}> = ({ children, persistKey = "simple_values" }) => { const [state, dispatch] = useReducer(reducer, getInitState(persistKey)); useEffect(() => { try { - const persistValues = {}; + const persistValues: Record = {}; Object.keys(state).map((k) => { if (state[k].persist) { @@ -50,11 +64,11 @@ const Provider = ({ children, persistKey = "simple_values" }) => { } }, [state, persistKey]); - const setValue = (key, value, persist = false) => { + const setValue = (key: string, value: any, persist = false) => { dispatch({ type: "add", key, value, persist }); }; - const getValue = (key, defaultValue) => { + const getValue = (key: string, defaultValue: any) => { if (state[key] !== undefined) { return state[key].value; } else { @@ -62,7 +76,7 @@ const Provider = ({ children, persistKey = "simple_values" }) => { } }; - const clearValue = (key) => { + const clearValue = (key: string) => { dispatch({ type: "clear", key }); }; diff --git a/packages/base-shell/src/providers/SimpleValues/index.jsx b/packages/base-shell/src/providers/SimpleValues/index.jsx deleted file mode 100644 index 1efc4f654..000000000 --- a/packages/base-shell/src/providers/SimpleValues/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useSimpleValues() { - return useContext(Context); -} - -export { - useSimpleValues, - Context as SimpleValuesContext, - Provider as SimpleValuesProvider, -}; diff --git a/packages/base-shell/src/providers/SimpleValues/index.tsx b/packages/base-shell/src/providers/SimpleValues/index.tsx new file mode 100644 index 000000000..2905ced18 --- /dev/null +++ b/packages/base-shell/src/providers/SimpleValues/index.tsx @@ -0,0 +1,38 @@ +import { useContext } from "react"; +import Context, { SimpleValuesContextType } from "./Context"; +import Provider from "./Provider"; +/** + * Custom hook to access the simple values context. + * + * @function + * @returns {SimpleValuesContextType} The simple values context value. + * @throws {Error} If used outside of an SimpleValuesProvider. + * @example + * const { setValue, getValue, clearAll, clearValue } = useSimpleValues(); + * + * @description + * This hook provides access to the simple values context. It must be used inside SimpleValuesProvider. + * It provides set of methods for manipulating values. + * It provides following methods + * - setValue + * - getValue + * - clearAll + * - clearValue + * + * @see {@link SimpleValuesContextType} for the shape of the returned context + */ +function useSimpleValues(): SimpleValuesContextType { + const context = useContext(Context); + if (!context) { + throw new Error( + "useSimpleValues must be used within a SimpleValuesProvider" + ); + } + return context; +} + +export { + useSimpleValues, + Context as SimpleValuesContext, + Provider as SimpleValuesProvider, +}; diff --git a/packages/base-shell/src/providers/Update/Context.jsx b/packages/base-shell/src/providers/Update/Context.jsx deleted file mode 100644 index 017737531..000000000 --- a/packages/base-shell/src/providers/Update/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from "react"; - -const Context = React.createContext(null); - -export default Context; diff --git a/packages/base-shell/src/providers/Update/Context.tsx b/packages/base-shell/src/providers/Update/Context.tsx new file mode 100644 index 000000000..20b2dfaae --- /dev/null +++ b/packages/base-shell/src/providers/Update/Context.tsx @@ -0,0 +1,18 @@ +import React from "react"; + +export interface UpdateContextType { + /** + * @description Value indicating if update is available or not + */ + isUpdateAvailable: boolean; + + /** + * @description Method for updating window + * @param registration + */ + runUpdate: (registration: any) => void; +} + +const Context = React.createContext(undefined); + +export default Context; diff --git a/packages/base-shell/src/providers/Update/Provider.jsx b/packages/base-shell/src/providers/Update/Provider.jsx deleted file mode 100644 index af1f528e0..000000000 --- a/packages/base-shell/src/providers/Update/Provider.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import React, { useState, useEffect } from 'react' -import Context from './Context' - -const runUpdate = (registration) => { - try { - if (registration) { - registration.waiting.postMessage({ type: 'SKIP_WAITING' }) - } - if (window.update) { - window.update && window.update() - } - } catch (error) { - console.log(error) - } -} - -const Provider = ({ children, checkInterval }) => { - const [isUpdateAvailable, setUpdateAvailable] = useState(false) - - const checkUpdate = () => { - if (window.update) { - setUpdateAvailable(true) - } else { - setUpdateAvailable(false) - setTimeout(checkUpdate, checkInterval) - } - } - - useEffect(checkUpdate, [checkUpdate]) - - return ( - - {children} - - ) -} - -export default Provider diff --git a/packages/base-shell/src/providers/Update/Provider.tsx b/packages/base-shell/src/providers/Update/Provider.tsx new file mode 100644 index 000000000..d870dbc1c --- /dev/null +++ b/packages/base-shell/src/providers/Update/Provider.tsx @@ -0,0 +1,41 @@ +import React, { useState, useEffect } from "react"; +import Context from "./Context"; + +const runUpdate = (registration: any) => { + try { + if (registration) { + registration.waiting.postMessage({ type: "SKIP_WAITING" }); + } + if (window.update) { + window.update && window.update(); + } + } catch (error) { + console.log(error); + } +}; + +const Provider: React.FC<{ + children: React.ReactNode; + checkInterval: number; +}> = ({ children, checkInterval }) => { + const [isUpdateAvailable, setUpdateAvailable] = useState(false); + + const checkUpdate = () => { + if (window.update) { + setUpdateAvailable(true); + } else { + setUpdateAvailable(false); + setTimeout(checkUpdate, checkInterval); + } + }; + + useEffect(checkUpdate, [checkUpdate]); + + return ( + + {children} + + ); +}; + +export default Provider; diff --git a/packages/base-shell/src/providers/Update/index.jsx b/packages/base-shell/src/providers/Update/index.jsx deleted file mode 100644 index 3e9df510e..000000000 --- a/packages/base-shell/src/providers/Update/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useUpdate() { - return useContext(Context); -} - -export { useUpdate, Context as UpdateContext, Provider as UpdateProvider }; diff --git a/packages/base-shell/src/providers/Update/index.tsx b/packages/base-shell/src/providers/Update/index.tsx new file mode 100644 index 000000000..0651e21d1 --- /dev/null +++ b/packages/base-shell/src/providers/Update/index.tsx @@ -0,0 +1,26 @@ +import { useContext } from "react"; +import Context, { UpdateContextType } from "./Context"; +import Provider from "./Provider"; + +/** + * Custom hook to access the update context. + * + * @function + * @returns {UpdateContextType} The update context value. + * @throws {Error} If used outside of an UpdateProvider. + * + * @description + * This hook provides access to the update context. It must be used within UpdateProvider. + * + * + * @see {@link UpdateContextType} for the shape of the returned context + */ +function useUpdate(): UpdateContextType { + const context = useContext(Context); + if (!context) { + throw new Error("useUpdate must be used within a UpdateProvider"); + } + return context; +} + +export { useUpdate, Context as UpdateContext, Provider as UpdateProvider }; diff --git a/packages/base-shell/src/providers/index.js b/packages/base-shell/src/providers/index.ts similarity index 100% rename from packages/base-shell/src/providers/index.js rename to packages/base-shell/src/providers/index.ts diff --git a/packages/base-shell/src/utils/config.js b/packages/base-shell/src/utils/config.js deleted file mode 100644 index 19b597cba..000000000 --- a/packages/base-shell/src/utils/config.js +++ /dev/null @@ -1,11 +0,0 @@ -export const merge = (obj1, obj2) => { - let temp = { ...obj1, ...obj2 }; - - Object.keys(temp).forEach((key) => { - if (typeof temp[key] === "object" && !(temp[key] instanceof Array)) { - temp[key] = { ...obj1[key], ...obj2[key] }; - } - }); - - return temp; -}; diff --git a/packages/base-shell/src/utils/config.ts b/packages/base-shell/src/utils/config.ts new file mode 100644 index 000000000..15d9bc503 --- /dev/null +++ b/packages/base-shell/src/utils/config.ts @@ -0,0 +1,18 @@ +/** + * @function + * @description Method for merging two different objects. It accepts 2 objects and returns new object. + * @param {Record} obj1 First object + * @param {Record} obj2 Second object + * @returns New object created from merging provided objects + */ +export const merge = (obj1: Record, obj2: Record) => { + let temp = { ...obj1, ...obj2 }; + + Object.keys(temp).forEach((key) => { + if (typeof temp[key] === "object" && !(temp[key] instanceof Array)) { + temp[key] = { ...obj1[key], ...obj2[key] }; + } + }); + + return temp; +}; diff --git a/packages/base-shell/src/utils/index.js b/packages/base-shell/src/utils/index.ts similarity index 100% rename from packages/base-shell/src/utils/index.js rename to packages/base-shell/src/utils/index.ts diff --git a/packages/base-shell/src/utils/locale.js b/packages/base-shell/src/utils/locale.js deleted file mode 100644 index 8221cff65..000000000 --- a/packages/base-shell/src/utils/locale.js +++ /dev/null @@ -1,76 +0,0 @@ -//import areIntlLocalesSupported from 'intl-locales-supported' -//import intl from 'intl' -import { defineMessages } from 'react-intl' - -/* -const loadLocalePolyfill = (locale) => { - // START: Intl polyfill - // Required for working on Safari - // Code from here: https://formatjs.io/guides/runtime-environments/ - let localesMyAppSupports = [locale] - - if (global.Intl) { - // Determine if the built-in `Intl` has the locale data we need. - if (!areIntlLocalesSupported(localesMyAppSupports)) { - // `Intl` exists, but it doesn't have the data we need, so load the - // polyfill and replace the constructors with need with the polyfill's. - let IntlPolyfill = intl - Intl.NumberFormat = IntlPolyfill.NumberFormat - Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat - } - } else { - // No `Intl`, so use and load the polyfill. - global.Intl = intl - } - // END: Intl polyfill -} -*/ - -const getUsersPreferredLanguages = () => { - if (navigator.languages !== undefined) { - return navigator.languages - } else if (navigator.language !== undefined) { - return [navigator.language] - } else { - return undefined - } -} - -const parseLanguages = (acceptedLangs, defaultLang = false) => { - const userPref = getUsersPreferredLanguages() - - const match = userPref - ? userPref.find((lang) => acceptedLangs.includes(lang)) - : undefined - - if (match === undefined && defaultLang !== false) { - return defaultLang - } - - return match -} - -const getLocaleMessages = async (l, ls) => { - if (ls) { - for (let i = 0; i < ls.length; i++) { - if (ls[i]['locale'] === l) { - const { default: messages } = await defineMessages(ls[i].messages) - - return messages - } - } - } - - return {} -} - -const formatMessage = (messages = [], id) => { - return messages[id] || id -} - -export { - formatMessage, - getLocaleMessages, - //loadLocalePolyfill - parseLanguages -} \ No newline at end of file diff --git a/packages/base-shell/src/utils/locale.ts b/packages/base-shell/src/utils/locale.ts new file mode 100644 index 000000000..f2eda16de --- /dev/null +++ b/packages/base-shell/src/utils/locale.ts @@ -0,0 +1,125 @@ +//import areIntlLocalesSupported from 'intl-locales-supported' +//import intl from 'intl' +import { defineMessages } from "react-intl"; + +/* +const loadLocalePolyfill = (locale) => { + // START: Intl polyfill + // Required for working on Safari + // Code from here: https://formatjs.io/guides/runtime-environments/ + let localesMyAppSupports = [locale] + + if (global.Intl) { + // Determine if the built-in `Intl` has the locale data we need. + if (!areIntlLocalesSupported(localesMyAppSupports)) { + // `Intl` exists, but it doesn't have the data we need, so load the + // polyfill and replace the constructors with need with the polyfill's. + let IntlPolyfill = intl + Intl.NumberFormat = IntlPolyfill.NumberFormat + Intl.DateTimeFormat = IntlPolyfill.DateTimeFormat + } + } else { + // No `Intl`, so use and load the polyfill. + global.Intl = intl + } + // END: Intl polyfill +} +*/ + +const getUsersPreferredLanguages = () => { + if (navigator.languages !== undefined) { + return navigator.languages; + } else if (navigator.language !== undefined) { + return [navigator.language]; + } else { + return undefined; + } +}; + +/** + * Determines the best matching language based on user preferences and accepted languages. + * + * This function attempts to find a match between the user's preferred languages and a list + * of accepted languages. If no match is found and a default language is provided, it returns + * the default language. Otherwise, it returns `undefined`. + * + * @param acceptedLangs - An array of language codes (e.g., ['en', 'fr', 'de']) that are supported by the application. + * @param defaultLang - (Optional) A default language code to fall back to if no match is found. + * Defaults to an empty string. + * + * @returns A string representing the matched language or the default language if no match is found. + * If no match is found and no default language is provided, it returns `undefined`. + * + * @example + * const acceptedLangs = ['en', 'fr', 'de']; + * const defaultLang = 'en'; + * + * const preferredLang = parseLanguages(acceptedLangs, defaultLang); + */ +const parseLanguages = (acceptedLangs: string[], defaultLang: string = "") => { + const userPref = getUsersPreferredLanguages(); + + const match = userPref + ? userPref.find((lang) => acceptedLangs.includes(lang)) + : undefined; + + if (match === undefined && defaultLang !== "") { + return defaultLang; + } + + return match; +}; + +/** + * Asynchronously retrieves localized messages for a specified locale. + * + * This function searches through a list of locale objects to find a matching locale. + * If a match is found, it dynamically imports and resolves the corresponding + * messages using the `defineMessages` function from react-intl. If no match is found or the list + * of locales is not provided, it returns an empty object. + * + * @param {string} l - The locale string to search for (e.g., 'en', 'fr'). + * @param ls - An array of locale objects, where each object contains: + * - `locale`: The locale identifier as a string. + * - `messages`: The path or reference to the locale's message definitions. + * + * @returns A promise that resolves to the localized messages for the given locale. + * If the locale is not found, the promise resolves to an empty object. + * + * @example + * const { locale }: LocaleContextType = useLocale(); + * + * getLocaleMessages(locale, locales).then((messages) => { + * console.log(messages); + * }); + * + * @see {defineMessages} - Method from react-intl + */ +const getLocaleMessages = async ( + l: string, + ls: { locale: string; messages: any }[] +) => { + if (ls) { + for (let i = 0; i < ls.length; i++) { + if (ls[i]["locale"] === l) { + const { default: messages } = await defineMessages(ls[i].messages); + + return messages; + } + } + } + + return {}; +}; + +// TODO possibly unused - unused in base-shell +const formatMessage = (messages = [], id: any) => { + return messages[id] || id; +}; + +export { + // formatMessage, + getLocaleMessages, + //loadLocalePolyfill + parseLanguages, +}; diff --git a/packages/base-shell/vite.config.js b/packages/base-shell/vite.config.ts similarity index 100% rename from packages/base-shell/vite.config.js rename to packages/base-shell/vite.config.ts diff --git a/packages/material-ui-shell/create-material-ui-shell/template/package-lock.json b/packages/material-ui-shell/create-material-ui-shell/template/package-lock.json deleted file mode 100644 index 09c64cc21..000000000 --- a/packages/material-ui-shell/create-material-ui-shell/template/package-lock.json +++ /dev/null @@ -1,5180 +0,0 @@ -{ - "name": "material-ui-shell-template", - "version": "1.0.40", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "material-ui-shell-template", - "version": "1.0.40", - "license": "ISC", - "dependencies": { - "@ecronix/material-ui-shell": "^3.5.53" - }, - "devDependencies": { - "@vitejs/plugin-react": "^4", - "vite": "^5" - } - }, - "../..": { - "name": "@ecronix/material-ui-shell", - "version": "3.5.51", - "license": "MIT", - "devDependencies": { - "@ecronix/base-shell": "^2.6.60", - "@emotion/react": "^11.13.3", - "@emotion/styled": "^11.13.0", - "@fontsource/roboto": "^5.1.0", - "@mui/icons-material": "^6.1.4", - "@mui/material": "^6.1.4", - "@vitejs/plugin-react": "^4.3.2", - "cypress": "^13.15.0", - "glob": "^11.0.0", - "intl": "^1.2.5", - "jss-rtl": "^0.3.0", - "lp-react-virtualized-auto-sizer-react-18": "^1.0.7", - "notistack": "^3.0.1", - "prettier": "^3.3.3", - "raw-loader": "^4.0.2", - "react": "^18.3.1", - "react-custom-scrollbars-2": "^4.5.0", - "react-dom": "^18.3.1", - "react-easy-crop": "^5.1.0", - "react-intl": "^6.8.0", - "react-ios-pwa-prompt": "^2.0.6", - "react-markdown": "^9.0.1", - "react-router-dom": "^6.27.0", - "react-window": "^1.8.10", - "rollup-plugin-visualizer": "^5.12.0", - "start-server-and-test": "^2.0.8", - "vite": "^5.4.9", - "vite-plugin-externalize-deps": "^0.8.0" - }, - "peerDependencies": { - "@ecronix/base-shell": "2.x", - "@emotion/react": "11.x", - "@emotion/styled": "11.x", - "@fontsource/roboto": "5.x", - "@mui/icons-material": "6.x", - "@mui/material": "6.x", - "intl": "1.x", - "jss-rtl": "0.x", - "lp-react-virtualized-auto-sizer-react-18": "1.x", - "notistack": "3.x", - "react": "16.x || 17.x || 18.x", - "react-custom-scrollbars-2": "4.x", - "react-dom": "16.x || 17.x || 18.x", - "react-easy-crop": "5.x", - "react-intl": "6.x", - "react-ios-pwa-prompt": "2.x", - "react-markdown": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", - "react-router-dom": "6.x", - "react-window": "1.x" - } - }, - "../../node_modules/@ampproject/remapping": { - "version": "2.3.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "../../node_modules/@babel/compat-data": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/core": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "../../node_modules/@babel/core/node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@babel/generator": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "../../node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/helpers": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/parser": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "../../node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "../../node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "../../node_modules/@babel/runtime": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/template": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/traverse": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@babel/types": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/@colors/colors": { - "version": "1.5.0", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=0.1.90" - } - }, - "../../node_modules/@cypress/request": { - "version": "3.0.6", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "aws-sign2": "~0.7.0", - "aws4": "^1.8.0", - "caseless": "~0.12.0", - "combined-stream": "~1.0.6", - "extend": "~3.0.2", - "forever-agent": "~0.6.1", - "form-data": "~4.0.0", - "http-signature": "~1.4.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.13.0", - "safe-buffer": "^5.1.2", - "tough-cookie": "^5.0.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" - }, - "engines": { - "node": ">= 6" - } - }, - "../../node_modules/@cypress/xvfb": { - "version": "1.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" - } - }, - "../../node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.1" - } - }, - "../../node_modules/@emotion/babel-plugin": { - "version": "11.13.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.16.7", - "@babel/runtime": "^7.18.3", - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/serialize": "^1.3.3", - "babel-plugin-macros": "^3.1.0", - "convert-source-map": "^1.5.0", - "escape-string-regexp": "^4.0.0", - "find-root": "^1.1.0", - "source-map": "^0.5.7", - "stylis": "4.2.0" - } - }, - "../../node_modules/@emotion/cache": { - "version": "11.13.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.9.0", - "@emotion/sheet": "^1.4.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "stylis": "4.2.0" - } - }, - "../../node_modules/@emotion/hash": { - "version": "0.9.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@emotion/is-prop-valid": { - "version": "1.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@emotion/memoize": "^0.9.0" - } - }, - "../../node_modules/@emotion/memoize": { - "version": "0.9.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@emotion/react": { - "version": "11.13.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/cache": "^11.13.5", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", - "@emotion/utils": "^1.4.2", - "@emotion/weak-memoize": "^0.4.0", - "hoist-non-react-statics": "^3.3.1" - }, - "peerDependencies": { - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@emotion/serialize": { - "version": "1.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@emotion/hash": "^0.9.2", - "@emotion/memoize": "^0.9.0", - "@emotion/unitless": "^0.10.0", - "@emotion/utils": "^1.4.2", - "csstype": "^3.0.2" - } - }, - "../../node_modules/@emotion/sheet": { - "version": "1.4.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@emotion/styled": { - "version": "11.13.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.18.3", - "@emotion/babel-plugin": "^11.13.5", - "@emotion/is-prop-valid": "^1.3.0", - "@emotion/serialize": "^1.3.3", - "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0", - "@emotion/utils": "^1.4.2" - }, - "peerDependencies": { - "@emotion/react": "^11.0.0-rc.0", - "react": ">=16.8.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@emotion/unitless": { - "version": "0.10.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@emotion/use-insertion-effect-with-fallbacks": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "peerDependencies": { - "react": ">=16.8.0" - } - }, - "../../node_modules/@emotion/utils": { - "version": "1.4.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@emotion/weak-memoize": { - "version": "0.4.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "../../node_modules/@fontsource/roboto": { - "version": "5.1.0", - "dev": true, - "license": "Apache-2.0" - }, - "../../node_modules/@formatjs/ecma402-abstract": { - "version": "2.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "../../node_modules/@formatjs/fast-memoize": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "2" - } - }, - "../../node_modules/@formatjs/icu-messageformat-parser": { - "version": "2.9.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/icu-skeleton-parser": "1.8.8", - "tslib": "2" - } - }, - "../../node_modules/@formatjs/icu-skeleton-parser": { - "version": "1.8.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "tslib": "2" - } - }, - "../../node_modules/@formatjs/intl": { - "version": "2.10.15", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/icu-messageformat-parser": "2.9.4", - "@formatjs/intl-displaynames": "6.8.5", - "@formatjs/intl-listformat": "7.7.5", - "intl-messageformat": "10.7.7", - "tslib": "2" - }, - "peerDependencies": { - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "../../node_modules/@formatjs/intl-displaynames": { - "version": "6.8.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "../../node_modules/@formatjs/intl-listformat": { - "version": "7.7.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/intl-localematcher": "0.5.8", - "tslib": "2" - } - }, - "../../node_modules/@formatjs/intl-localematcher": { - "version": "0.5.8", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "2" - } - }, - "../../node_modules/@hapi/hoek": { - "version": "9.3.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "../../node_modules/@hapi/topo": { - "version": "5.1.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "../../node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "../../node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "../../node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "../../node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "../../node_modules/@mui/core-downloads-tracker": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - } - }, - "../../node_modules/@mui/icons-material": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@mui/material": "^6.1.8", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@mui/material": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/core-downloads-tracker": "^6.1.8", - "@mui/system": "^6.1.8", - "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.8", - "@popperjs/core": "^2.11.8", - "@types/react-transition-group": "^4.4.11", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1", - "react-is": "^18.3.1", - "react-transition-group": "^4.4.5" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@mui/material-pigment-css": "^6.1.8", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@mui/material-pigment-css": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@mui/private-theming": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/utils": "^6.1.8", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@mui/styled-engine": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@emotion/cache": "^11.13.1", - "@emotion/serialize": "^1.3.2", - "@emotion/sheet": "^1.4.0", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.4.1", - "@emotion/styled": "^11.3.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - } - } - }, - "../../node_modules/@mui/system": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/private-theming": "^6.1.8", - "@mui/styled-engine": "^6.1.8", - "@mui/types": "^7.2.19", - "@mui/utils": "^6.1.8", - "clsx": "^2.1.1", - "csstype": "^3.1.3", - "prop-types": "^15.8.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@emotion/react": "^11.5.0", - "@emotion/styled": "^11.3.0", - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/react": { - "optional": true - }, - "@emotion/styled": { - "optional": true - }, - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@mui/types": { - "version": "7.2.19", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@mui/utils": { - "version": "6.1.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.26.0", - "@mui/types": "^7.2.19", - "@types/prop-types": "^15.7.13", - "clsx": "^2.1.1", - "prop-types": "^15.8.1", - "react-is": "^18.3.1" - }, - "engines": { - "node": ">=14.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/mui-org" - }, - "peerDependencies": { - "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", - "react": "^17.0.0 || ^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@types/react": { - "optional": true - } - } - }, - "../../node_modules/@popperjs/core": { - "version": "2.11.8", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "../../node_modules/@remix-run/router": { - "version": "1.21.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "../../node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.4", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "../../node_modules/@sideway/address": { - "version": "4.1.5", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "../../node_modules/@sideway/formula": { - "version": "3.0.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "../../node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "dev": true, - "license": "BSD-3-Clause" - }, - "../../node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "../../node_modules/@types/babel__generator": { - "version": "7.6.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "../../node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "../../node_modules/@types/babel__traverse": { - "version": "7.20.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "../../node_modules/@types/debug": { - "version": "4.1.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "../../node_modules/@types/estree": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/estree-jsx": { - "version": "1.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "../../node_modules/@types/hast": { - "version": "3.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "../../node_modules/@types/hoist-non-react-statics": { - "version": "3.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*", - "hoist-non-react-statics": "^3.3.0" - } - }, - "../../node_modules/@types/json-schema": { - "version": "7.0.15", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/mdast": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "../../node_modules/@types/ms": { - "version": "0.7.34", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/node": { - "version": "22.10.0", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "undici-types": "~6.20.0" - } - }, - "../../node_modules/@types/parse-json": { - "version": "4.0.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/prop-types": { - "version": "15.7.13", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/react": { - "version": "18.3.12", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.0.2" - } - }, - "../../node_modules/@types/react-transition-group": { - "version": "4.4.11", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/react": "*" - } - }, - "../../node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/sizzle": { - "version": "2.3.9", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/unist": { - "version": "3.0.3", - "dev": true, - "license": "MIT" - }, - "../../node_modules/@types/yauzl": { - "version": "2.10.3", - "dev": true, - "license": "MIT", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, - "../../node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "dev": true, - "license": "ISC" - }, - "../../node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" - } - }, - "../../node_modules/add-px-to-style": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/ajv": { - "version": "6.12.6", - "dev": true, - "license": "MIT", - "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/ajv-keywords": { - "version": "3.5.2", - "dev": true, - "license": "MIT", - "peerDependencies": { - "ajv": "^6.9.1" - } - }, - "../../node_modules/arch": { - "version": "2.2.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "../../node_modules/arg": { - "version": "5.0.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/asn1": { - "version": "0.2.6", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": "~2.1.0" - } - }, - "../../node_modules/assert-plus": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "../../node_modules/astral-regex": { - "version": "2.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../../node_modules/at-least-node": { - "version": "1.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" - } - }, - "../../node_modules/aws-sign2": { - "version": "0.7.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "../../node_modules/aws4": { - "version": "1.13.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/babel-plugin-macros": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.12.5", - "cosmiconfig": "^7.0.0", - "resolve": "^1.19.0" - }, - "engines": { - "node": ">=10", - "npm": ">=6" - } - }, - "../../node_modules/bail": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/bcrypt-pbkdf": { - "version": "1.0.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tweetnacl": "^0.14.3" - } - }, - "../../node_modules/big.js": { - "version": "5.2.2", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "../../node_modules/blob-util": { - "version": "2.0.2", - "dev": true, - "license": "Apache-2.0" - }, - "../../node_modules/bluebird": { - "version": "3.7.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/brace-expansion": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "../../node_modules/browserslist": { - "version": "4.24.2", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "../../node_modules/buffer-crc32": { - "version": "0.2.13", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - } - }, - "../../node_modules/cachedir": { - "version": "2.4.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../../node_modules/call-bind": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/caniuse-lite": { - "version": "1.0.30001684", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "../../node_modules/caseless": { - "version": "0.12.0", - "dev": true, - "license": "Apache-2.0" - }, - "../../node_modules/ccount": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/chalk": { - "version": "4.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "../../node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "../../node_modules/character-entities": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/character-entities-html4": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/character-entities-legacy": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/character-reference-invalid": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/check-more-types": { - "version": "2.24.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "../../node_modules/ci-info": { - "version": "4.1.0", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../../node_modules/cli-table3": { - "version": "0.6.5", - "dev": true, - "license": "MIT", - "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" - } - }, - "../../node_modules/cli-truncate": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/clsx": { - "version": "2.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../../node_modules/colorette": { - "version": "2.0.20", - "dev": true, - "license": "MIT" - }, - "../../node_modules/comma-separated-tokens": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/commander": { - "version": "6.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "../../node_modules/common-tags": { - "version": "1.8.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "../../node_modules/convert-source-map": { - "version": "1.9.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/core-util-is": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/cosmiconfig": { - "version": "7.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/parse-json": "^4.0.0", - "import-fresh": "^3.2.1", - "parse-json": "^5.0.0", - "path-type": "^4.0.0", - "yaml": "^1.10.0" - }, - "engines": { - "node": ">=10" - } - }, - "../../node_modules/csstype": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "../../node_modules/cypress": { - "version": "13.16.0", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@cypress/request": "^3.0.6", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.7.1", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "ci-info": "^4.0.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.3", - "tree-kill": "1.2.2", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" - }, - "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" - } - }, - "../../node_modules/cypress/node_modules/semver": { - "version": "7.6.3", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "../../node_modules/dashdash": { - "version": "1.14.1", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "../../node_modules/dayjs": { - "version": "1.11.13", - "dev": true, - "license": "MIT" - }, - "../../node_modules/decode-named-character-reference": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/define-data-property": { - "version": "1.1.4", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/dequal": { - "version": "2.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../../node_modules/devlop": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/dom-css": { - "version": "2.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "add-px-to-style": "1.0.0", - "prefix-style": "2.0.1", - "to-camel-case": "1.0.0" - } - }, - "../../node_modules/dom-helpers": { - "version": "5.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, - "../../node_modules/ecc-jsbn": { - "version": "0.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" - } - }, - "../../node_modules/electron-to-chromium": { - "version": "1.5.65", - "dev": true, - "license": "ISC" - }, - "../../node_modules/emojis-list": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "../../node_modules/enquirer": { - "version": "2.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "../../node_modules/es-define-property": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.2.4" - }, - "engines": { - "node": ">= 0.4" - } - }, - "../../node_modules/es-errors": { - "version": "1.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "../../node_modules/esbuild": { - "version": "0.21.5", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "../../node_modules/escape-string-regexp": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/event-stream": { - "version": "3.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", - "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" - } - }, - "../../node_modules/eventemitter2": { - "version": "6.4.7", - "dev": true, - "license": "MIT" - }, - "../../node_modules/execa": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "../../node_modules/executable": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.2.0" - }, - "engines": { - "node": ">=4" - } - }, - "../../node_modules/extend": { - "version": "3.0.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/extract-zip": { - "version": "2.0.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "../../node_modules/extsprintf": { - "version": "1.3.0", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT" - }, - "../../node_modules/fast-deep-equal": { - "version": "3.1.3", - "dev": true, - "license": "MIT" - }, - "../../node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/fd-slicer": { - "version": "1.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pend": "~1.2.0" - } - }, - "../../node_modules/find-root": { - "version": "1.1.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/forever-agent": { - "version": "0.6.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "../../node_modules/from": { - "version": "0.1.7", - "dev": true, - "license": "MIT" - }, - "../../node_modules/fs-extra": { - "version": "9.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "../../node_modules/fsevents": { - "version": "2.3.3", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "../../node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "../../node_modules/get-intrinsic": { - "version": "1.2.4", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "hasown": "^2.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/get-stream": { - "version": "5.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/getos": { - "version": "3.2.1", - "dev": true, - "license": "MIT", - "dependencies": { - "async": "^3.2.0" - } - }, - "../../node_modules/getpass": { - "version": "0.1.7", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - } - }, - "../../node_modules/glob": { - "version": "11.0.0", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^4.0.1", - "minimatch": "^10.0.0", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^2.0.0" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../../node_modules/global-dirs": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "ini": "2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "../../node_modules/goober": { - "version": "2.1.16", - "dev": true, - "license": "MIT", - "peerDependencies": { - "csstype": "^3.0.10" - } - }, - "../../node_modules/gopd": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "get-intrinsic": "^1.1.3" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/has-property-descriptors": { - "version": "1.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/has-proto": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/has-symbols": { - "version": "1.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-object": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/hast-util-whitespace": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/hoist-non-react-statics": { - "version": "3.3.2", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "react-is": "^16.7.0" - } - }, - "../../node_modules/hoist-non-react-statics/node_modules/react-is": { - "version": "16.13.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/html-url-attributes": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/http-signature": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.18.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "../../node_modules/human-signals": { - "version": "1.1.1", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=8.12.0" - } - }, - "../../node_modules/ini": { - "version": "2.0.0", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "../../node_modules/inline-style-parser": { - "version": "0.2.4", - "dev": true, - "license": "MIT" - }, - "../../node_modules/intl": { - "version": "1.2.5", - "dev": true, - "license": "MIT" - }, - "../../node_modules/intl-messageformat": { - "version": "10.7.7", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/fast-memoize": "2.2.3", - "@formatjs/icu-messageformat-parser": "2.9.4", - "tslib": "2" - } - }, - "../../node_modules/is-alphabetical": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/is-alphanumerical": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/is-decimal": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/is-hexadecimal": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/is-installed-globally": { - "version": "0.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/is-path-inside": { - "version": "3.0.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../../node_modules/is-plain-obj": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/is-stream": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/is-typedarray": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/isstream": { - "version": "0.1.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/jackspeak": { - "version": "4.0.2", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../../node_modules/joi": { - "version": "17.13.3", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.3.0", - "@hapi/topo": "^5.1.0", - "@sideway/address": "^4.1.5", - "@sideway/formula": "^3.0.1", - "@sideway/pinpoint": "^2.0.0" - } - }, - "../../node_modules/jsbn": { - "version": "0.1.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/jsesc": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "../../node_modules/json-schema": { - "version": "0.4.0", - "dev": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, - "../../node_modules/json-schema-traverse": { - "version": "0.4.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/jsprim": { - "version": "2.0.2", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, - "../../node_modules/jss-rtl": { - "version": "0.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "rtl-css-js": "^1.13.1" - }, - "peerDependencies": { - "jss": "^10.0.0" - } - }, - "../../node_modules/lazy-ass": { - "version": "1.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": "> 0.8" - } - }, - "../../node_modules/listr2": { - "version": "3.14.0", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, - "../../node_modules/listr2/node_modules/wrap-ansi": { - "version": "7.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "../../node_modules/loader-utils": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "big.js": "^5.2.2", - "emojis-list": "^3.0.0", - "json5": "^2.1.2" - }, - "engines": { - "node": ">=8.9.0" - } - }, - "../../node_modules/lodash.once": { - "version": "4.1.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/log-update": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "../../node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "../../node_modules/longest-streak": { - "version": "3.1.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/loose-envify": { - "version": "1.4.0", - "dev": true, - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "../../node_modules/lp-react-virtualized-auto-sizer-react-18": { - "version": "1.0.7", - "dev": true, - "license": "MIT", - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0", - "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0|| ^18.0.0" - } - }, - "../../node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "../../node_modules/map-stream": { - "version": "0.1.0", - "dev": true - }, - "../../node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-mdx-jsx": { - "version": "3.1.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/mdast-util-to-string": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/memoize-one": { - "version": "5.2.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/micromark": { - "version": "4.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-core-commonmark": { - "version": "2.0.2", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-factory-destination": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-factory-label": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-factory-space": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-factory-title": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-character": { - "version": "2.1.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-chunked": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "../../node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "../../node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "../../node_modules/micromark-util-encode": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "../../node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "../../node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "../../node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "../../node_modules/micromark-util-subtokenize": { - "version": "2.0.3", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "../../node_modules/micromark-util-symbol": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "../../node_modules/micromark-util-types": { - "version": "2.0.1", - "dev": true, - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "../../node_modules/minimatch": { - "version": "10.0.1", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../../node_modules/nanoid": { - "version": "3.3.8", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "../../node_modules/node-releases": { - "version": "2.0.18", - "dev": true, - "license": "MIT" - }, - "../../node_modules/normalize-wheel": { - "version": "1.0.1", - "dev": true, - "license": "BSD-3-Clause" - }, - "../../node_modules/notistack": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "clsx": "^1.1.0", - "goober": "^2.0.33" - }, - "engines": { - "node": ">=12.0.0", - "npm": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/notistack" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0" - } - }, - "../../node_modules/notistack/node_modules/clsx": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../../node_modules/object-assign": { - "version": "4.1.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/object-inspect": { - "version": "1.13.3", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/ospath": { - "version": "1.2.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/parse-entities": { - "version": "4.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "dev": true, - "license": "MIT" - }, - "../../node_modules/path-scurry": { - "version": "2.0.0", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^11.0.0", - "minipass": "^7.1.2" - }, - "engines": { - "node": "20 || >=22" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "../../node_modules/path-scurry/node_modules/lru-cache": { - "version": "11.0.2", - "dev": true, - "license": "ISC", - "engines": { - "node": "20 || >=22" - } - }, - "../../node_modules/pause-stream": { - "version": "0.0.11", - "dev": true, - "license": [ - "MIT", - "Apache2" - ], - "dependencies": { - "through": "~2.3" - } - }, - "../../node_modules/pend": { - "version": "1.2.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/performance-now": { - "version": "2.1.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/pify": { - "version": "2.3.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/postcss": { - "version": "8.4.49", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "../../node_modules/prefix-style": { - "version": "2.0.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/prettier": { - "version": "3.4.1", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "../../node_modules/pretty-bytes": { - "version": "5.6.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/process": { - "version": "0.11.10", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6.0" - } - }, - "../../node_modules/prop-types": { - "version": "15.8.1", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - }, - "../../node_modules/prop-types/node_modules/react-is": { - "version": "16.13.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/property-information": { - "version": "6.5.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/proxy-from-env": { - "version": "1.0.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/ps-tree": { - "version": "1.2.0", - "dev": true, - "license": "MIT", - "dependencies": { - "event-stream": "=3.3.4" - }, - "bin": { - "ps-tree": "bin/ps-tree.js" - }, - "engines": { - "node": ">= 0.10" - } - }, - "../../node_modules/pump": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, - "../../node_modules/punycode": { - "version": "2.3.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "../../node_modules/qs": { - "version": "6.13.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/raf": { - "version": "3.4.1", - "dev": true, - "license": "MIT", - "dependencies": { - "performance-now": "^2.1.0" - } - }, - "../../node_modules/raw-loader": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "loader-utils": "^2.0.0", - "schema-utils": "^3.0.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" - } - }, - "../../node_modules/react": { - "version": "18.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/react-custom-scrollbars-2": { - "version": "4.5.0", - "dev": true, - "license": "MIT", - "dependencies": { - "dom-css": "^2.0.0", - "prop-types": "^15.5.10", - "raf": "^3.1.0" - }, - "peerDependencies": { - "react": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^0.14.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "../../node_modules/react-dom": { - "version": "18.3.1", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "../../node_modules/react-easy-crop": { - "version": "5.1.0", - "dev": true, - "license": "MIT", - "dependencies": { - "normalize-wheel": "^1.0.1", - "tslib": "^2.0.1" - }, - "peerDependencies": { - "react": ">=16.4.0", - "react-dom": ">=16.4.0" - } - }, - "../../node_modules/react-intl": { - "version": "6.8.9", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@formatjs/ecma402-abstract": "2.2.4", - "@formatjs/icu-messageformat-parser": "2.9.4", - "@formatjs/intl": "2.10.15", - "@formatjs/intl-displaynames": "6.8.5", - "@formatjs/intl-listformat": "7.7.5", - "@types/hoist-non-react-statics": "3", - "@types/react": "16 || 17 || 18", - "hoist-non-react-statics": "3", - "intl-messageformat": "10.7.7", - "tslib": "2" - }, - "peerDependencies": { - "react": "^16.6.0 || 17 || 18", - "typescript": "^4.7 || 5" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "../../node_modules/react-ios-pwa-prompt": { - "version": "2.0.6", - "dev": true, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" - } - }, - "../../node_modules/react-markdown": { - "version": "9.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "html-url-attributes": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "unified": "^11.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "@types/react": ">=18", - "react": ">=18" - } - }, - "../../node_modules/react-refresh": { - "version": "0.14.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/react-router": { - "version": "6.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.21.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "../../node_modules/react-router-dom": { - "version": "6.28.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.21.0", - "react-router": "6.28.0" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "../../node_modules/react-transition-group": { - "version": "4.4.5", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "peerDependencies": { - "react": ">=16.6.0", - "react-dom": ">=16.6.0" - } - }, - "../../node_modules/react-window": { - "version": "1.8.10", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.0.0", - "memoize-one": ">=3.1.1 <6" - }, - "engines": { - "node": ">8.0.0" - }, - "peerDependencies": { - "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0", - "react-dom": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0" - } - }, - "../../node_modules/regenerator-runtime": { - "version": "0.14.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/remark-parse": { - "version": "11.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/remark-rehype": { - "version": "11.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/request-progress": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "throttleit": "^1.0.0" - } - }, - "../../node_modules/rfdc": { - "version": "1.4.1", - "dev": true, - "license": "MIT" - }, - "../../node_modules/rollup": { - "version": "4.27.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.4", - "@rollup/rollup-android-arm64": "4.27.4", - "@rollup/rollup-darwin-arm64": "4.27.4", - "@rollup/rollup-darwin-x64": "4.27.4", - "@rollup/rollup-freebsd-arm64": "4.27.4", - "@rollup/rollup-freebsd-x64": "4.27.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", - "@rollup/rollup-linux-arm-musleabihf": "4.27.4", - "@rollup/rollup-linux-arm64-gnu": "4.27.4", - "@rollup/rollup-linux-arm64-musl": "4.27.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", - "@rollup/rollup-linux-riscv64-gnu": "4.27.4", - "@rollup/rollup-linux-s390x-gnu": "4.27.4", - "@rollup/rollup-linux-x64-gnu": "4.27.4", - "@rollup/rollup-linux-x64-musl": "4.27.4", - "@rollup/rollup-win32-arm64-msvc": "4.27.4", - "@rollup/rollup-win32-ia32-msvc": "4.27.4", - "@rollup/rollup-win32-x64-msvc": "4.27.4", - "fsevents": "~2.3.2" - } - }, - "../../node_modules/rollup-plugin-visualizer": { - "version": "5.12.0", - "dev": true, - "license": "MIT", - "dependencies": { - "open": "^8.4.0", - "picomatch": "^2.3.1", - "source-map": "^0.7.4", - "yargs": "^17.5.1" - }, - "bin": { - "rollup-plugin-visualizer": "dist/bin/cli.js" - }, - "engines": { - "node": ">=14" - }, - "peerDependencies": { - "rollup": "2.x || 3.x || 4.x" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "../../node_modules/rollup-plugin-visualizer/node_modules/source-map": { - "version": "0.7.4", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, - "../../node_modules/rtl-css-js": { - "version": "1.16.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.1.2" - } - }, - "../../node_modules/scheduler": { - "version": "0.23.2", - "dev": true, - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "../../node_modules/schema-utils": { - "version": "3.3.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.8", - "ajv": "^6.12.5", - "ajv-keywords": "^3.5.2" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, - "../../node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "../../node_modules/set-function-length": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "dependencies": { - "define-data-property": "^1.1.4", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "get-intrinsic": "^1.2.4", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "../../node_modules/side-channel": { - "version": "1.0.6", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.7", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.4", - "object-inspect": "^1.13.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "../../node_modules/slice-ansi": { - "version": "3.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "../../node_modules/source-map": { - "version": "0.5.7", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/source-map-js": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/space-separated-tokens": { - "version": "2.0.2", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/split": { - "version": "0.3.3", - "dev": true, - "license": "MIT", - "dependencies": { - "through": "2" - }, - "engines": { - "node": "*" - } - }, - "../../node_modules/sshpk": { - "version": "1.18.0", - "dev": true, - "license": "MIT", - "dependencies": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "safer-buffer": "^2.0.2", - "tweetnacl": "~0.14.0" - }, - "bin": { - "sshpk-conv": "bin/sshpk-conv", - "sshpk-sign": "bin/sshpk-sign", - "sshpk-verify": "bin/sshpk-verify" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "../../node_modules/start-server-and-test": { - "version": "2.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "arg": "^5.0.2", - "bluebird": "3.7.2", - "check-more-types": "2.24.0", - "debug": "4.3.7", - "execa": "5.1.1", - "lazy-ass": "1.6.0", - "ps-tree": "1.2.0", - "wait-on": "8.0.1" - }, - "bin": { - "server-test": "src/bin/start.js", - "start-server-and-test": "src/bin/start.js", - "start-test": "src/bin/start.js" - }, - "engines": { - "node": ">=16" - } - }, - "../../node_modules/start-server-and-test/node_modules/execa": { - "version": "5.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" - } - }, - "../../node_modules/start-server-and-test/node_modules/get-stream": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/start-server-and-test/node_modules/human-signals": { - "version": "2.1.0", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=10.17.0" - } - }, - "../../node_modules/stream-combiner": { - "version": "0.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "duplexer": "~0.1.1" - } - }, - "../../node_modules/stringify-entities": { - "version": "4.0.4", - "dev": true, - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/style-to-object": { - "version": "1.0.8", - "dev": true, - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.4" - } - }, - "../../node_modules/stylis": { - "version": "4.2.0", - "dev": true, - "license": "MIT" - }, - "../../node_modules/supports-color": { - "version": "8.1.1", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "../../node_modules/throttleit": { - "version": "1.0.1", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "../../node_modules/tldts": { - "version": "6.1.64", - "dev": true, - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.64" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "../../node_modules/tldts-core": { - "version": "6.1.64", - "dev": true, - "license": "MIT" - }, - "../../node_modules/to-camel-case": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "to-space-case": "^1.0.0" - } - }, - "../../node_modules/to-no-case": { - "version": "1.0.2", - "dev": true, - "license": "MIT" - }, - "../../node_modules/to-space-case": { - "version": "1.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "to-no-case": "^1.0.0" - } - }, - "../../node_modules/tough-cookie": { - "version": "5.0.0", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "tldts": "^6.1.32" - }, - "engines": { - "node": ">=16" - } - }, - "../../node_modules/tree-kill": { - "version": "1.2.2", - "dev": true, - "license": "MIT", - "bin": { - "tree-kill": "cli.js" - } - }, - "../../node_modules/trim-lines": { - "version": "3.0.1", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/trough": { - "version": "2.2.0", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "../../node_modules/tunnel-agent": { - "version": "0.6.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" - }, - "engines": { - "node": "*" - } - }, - "../../node_modules/tweetnacl": { - "version": "0.14.5", - "dev": true, - "license": "Unlicense" - }, - "../../node_modules/undici-types": { - "version": "6.20.0", - "dev": true, - "license": "MIT", - "optional": true - }, - "../../node_modules/unified": { - "version": "11.0.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/unist-util-is": { - "version": "6.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/unist-util-position": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/unist-util-visit": { - "version": "5.0.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/untildify": { - "version": "4.0.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "../../node_modules/update-browserslist-db": { - "version": "1.1.1", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "../../node_modules/uri-js": { - "version": "4.4.1", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, - "../../node_modules/uuid": { - "version": "8.3.2", - "dev": true, - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "../../node_modules/verror": { - "version": "1.10.0", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, - "../../node_modules/vfile": { - "version": "6.0.3", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/vfile-message": { - "version": "4.0.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "../../node_modules/vite": { - "version": "5.4.11", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "../../node_modules/vite-plugin-externalize-deps": { - "version": "0.8.0", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/voracious" - }, - "peerDependencies": { - "vite": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" - } - }, - "../../node_modules/wait-on": { - "version": "8.0.1", - "dev": true, - "license": "MIT", - "dependencies": { - "axios": "^1.7.7", - "joi": "^17.13.3", - "lodash": "^4.17.21", - "minimist": "^1.2.8", - "rxjs": "^7.8.1" - }, - "bin": { - "wait-on": "bin/wait-on" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "../../node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC" - }, - "../../node_modules/yaml": { - "version": "1.10.2", - "dev": true, - "license": "ISC", - "engines": { - "node": ">= 6" - } - }, - "../../node_modules/yauzl": { - "version": "2.10.0", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "../../node_modules/zwitch": { - "version": "2.0.4", - "dev": true, - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/@ampproject/remapping": { - "version": "2.3.0", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.25.9", - "js-tokens": "^4.0.0", - "picocolors": "^1.0.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.26.0", - "@babel/generator": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helpers": "^7.26.0", - "@babel/parser": "^7.26.0", - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.26.2", - "@babel/types": "^7.26.0", - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.2", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.0" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.25.9", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/generator": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/template": "^7.25.9", - "@babel/types": "^7.25.9", - "debug": "^4.3.1", - "globals": "^11.1.0" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.0", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@ecronix/material-ui-shell": { - "resolved": "../..", - "link": true - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.27.4", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" - } - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.3.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.26.0", - "@babel/plugin-transform-react-jsx-self": "^7.25.9", - "@babel/plugin-transform-react-jsx-source": "^7.25.9", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.14.2" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" - } - }, - "node_modules/browserslist": { - "version": "4.24.2", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "caniuse-lite": "^1.0.30001669", - "electron-to-chromium": "^1.5.41", - "node-releases": "^2.0.18", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001684", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.3.7", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.66", - "dev": true, - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/globals": { - "version": "11.12.0", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "dev": true, - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.0.2", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.8", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.18", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.4.49", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/react-refresh": { - "version": "0.14.2", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.27.4", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.27.4", - "@rollup/rollup-android-arm64": "4.27.4", - "@rollup/rollup-darwin-arm64": "4.27.4", - "@rollup/rollup-darwin-x64": "4.27.4", - "@rollup/rollup-freebsd-arm64": "4.27.4", - "@rollup/rollup-freebsd-x64": "4.27.4", - "@rollup/rollup-linux-arm-gnueabihf": "4.27.4", - "@rollup/rollup-linux-arm-musleabihf": "4.27.4", - "@rollup/rollup-linux-arm64-gnu": "4.27.4", - "@rollup/rollup-linux-arm64-musl": "4.27.4", - "@rollup/rollup-linux-powerpc64le-gnu": "4.27.4", - "@rollup/rollup-linux-riscv64-gnu": "4.27.4", - "@rollup/rollup-linux-s390x-gnu": "4.27.4", - "@rollup/rollup-linux-x64-gnu": "4.27.4", - "@rollup/rollup-linux-x64-musl": "4.27.4", - "@rollup/rollup-win32-arm64-msvc": "4.27.4", - "@rollup/rollup-win32-ia32-msvc": "4.27.4", - "@rollup/rollup-win32-x64-msvc": "4.27.4", - "fsevents": "~2.3.2" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.1.1", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.0" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/vite": { - "version": "5.4.11", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "dev": true, - "license": "ISC" - } - } -} \ No newline at end of file diff --git a/packages/material-ui-shell/create-material-ui-shell/template/src/config/config.jsx b/packages/material-ui-shell/create-material-ui-shell/template/src/config/config.jsx index 865fbc6e5..b610484ef 100644 --- a/packages/material-ui-shell/create-material-ui-shell/template/src/config/config.jsx +++ b/packages/material-ui-shell/create-material-ui-shell/template/src/config/config.jsx @@ -47,7 +47,7 @@ const config = { initialMiniSwitchVisibility: true, MenuHeader, MenuContent: Menu, - useWindowWatcher: false, + useWindowWatcher: true, }, theme: { themes, diff --git a/packages/material-ui-shell/create-material-ui-shell/template/src/config/menuItems.jsx b/packages/material-ui-shell/create-material-ui-shell/template/src/config/menuItems.jsx index eb02bb0b1..954d7063f 100644 --- a/packages/material-ui-shell/create-material-ui-shell/template/src/config/menuItems.jsx +++ b/packages/material-ui-shell/create-material-ui-shell/template/src/config/menuItems.jsx @@ -93,6 +93,7 @@ const getMenuItems = (props) => { }, ] } + return [ { value: '/home', diff --git a/packages/material-ui-shell/cypress.config.js b/packages/material-ui-shell/cypress.config.ts similarity index 100% rename from packages/material-ui-shell/cypress.config.js rename to packages/material-ui-shell/cypress.config.ts diff --git a/packages/material-ui-shell/package.json b/packages/material-ui-shell/package.json index 4a32450b8..5cd1b0b16 100644 --- a/packages/material-ui-shell/package.json +++ b/packages/material-ui-shell/package.json @@ -22,6 +22,7 @@ "types": "./dist/types/index.d.ts" } }, + "typings": "./dist/types/index.d.ts", "peerDependencies": { "@ecronix/base-shell": "2.x", "@emotion/react": "11.x", @@ -50,6 +51,7 @@ "@fontsource/roboto": "^5.1.0", "@mui/icons-material": "^6.1.4", "@mui/material": "^6.1.4", + "@types/react-window": "^1.8.8", "@vitejs/plugin-react": "^4.3.2", "cypress": "^13.15.0", "glob": "^11.0.0", diff --git a/packages/material-ui-shell/src/common.type.ts b/packages/material-ui-shell/src/common.type.ts new file mode 100644 index 000000000..203463aef --- /dev/null +++ b/packages/material-ui-shell/src/common.type.ts @@ -0,0 +1,59 @@ +import { AppConfig } from '@ecronix/base-shell' +import { TransitionProps } from '@mui/material/transitions' + +export type TransitionComponentProps = TransitionProps & { + children: React.ReactElement +} + +export type IProviderProps = { + children: React.ReactNode + persistKey?: string + appConfig?: AppConfig +} + +export type SortOrientationType = 1 | -1 +export type Operators = '=' | '>' | '<' | '!=' | '<=' | '>=' | 'like' | '!like' +export type OperatorType = { label: string; value: string } +export type FieldType = { + name: string + label?: string + type: 'text' | 'number' | 'bool' | 'time' | 'date' + sort?: any + filter?: any +} + +export type ThemeType = { + id: string + color: string + source: { + palette: { + primary: string + secondary: string + error: string + } + } +} + +export type MenuItemType = + | { + value: string + nestedItems?: never + visible?: boolean + primaryText: string + subheader?: string + leftIcon: React.ReactNode + onClick?: () => void + divider?: boolean + style?: React.CSSProperties + } + | { + value?: never + nestedItems: MenuItemType[] + visible?: boolean + primaryText: string + subheader?: string + leftIcon: React.ReactNode + onClick?: () => void + divider?: boolean + style?: React.CSSProperties + } diff --git a/packages/material-ui-shell/src/components/FilterDrawer/index.jsx b/packages/material-ui-shell/src/components/FilterDrawer/index.tsx similarity index 84% rename from packages/material-ui-shell/src/components/FilterDrawer/index.jsx rename to packages/material-ui-shell/src/components/FilterDrawer/index.tsx index 8e6f71c69..009bb8ab6 100644 --- a/packages/material-ui-shell/src/components/FilterDrawer/index.jsx +++ b/packages/material-ui-shell/src/components/FilterDrawer/index.tsx @@ -15,8 +15,35 @@ import { Add, ClearAll, SortByAlpha, Close, Delete } from '@mui/icons-material' import { useFilter } from '@ecronix/material-ui-shell' import { useIntl } from 'react-intl' import Scrollbar from '../Scrollbar' +import { FieldType, OperatorType } from '@ecronix/material-ui-shell/common.type' -export default function FilterDrawer({ name, width = 250, fields = [] }) { +type FilterDrawerProps = { + name: string + width?: number + fields: FieldType[] +} + +/** + * A functional React component for rendering a filter drawer. + * + * The `FilterDrawer` is a customizable drawer that displays filter fields + * based on the provided configuration. It supports optional width customization. + * + * @param {FilterDrawerProps} props - The properties passed to the `FilterDrawer` component. + * @param {string} props.name - The name of the filter drawer, used for identification purposes. + * @param {number} [props.width=250] - The width of the drawer in pixels. Defaults to 250px. + * @param {FieldType[]} props.fields - An array of field definitions to display within the drawer. + * + * @returns {JSX.Element} The rendered filter drawer component. + * + * @example + * + */ +export default function FilterDrawer({ + name, + width = 250, + fields = [], +}: FilterDrawerProps): JSX.Element { const intl = useIntl() const { isFilterOpen, @@ -124,7 +151,7 @@ export default function FilterDrawer({ name, width = 250, fields = [] }) {
- {queries.map((q, i) => { + {queries.map((q: any, i: number) => { const field = getField(q.field, fields) return ( @@ -180,7 +207,7 @@ export default function FilterDrawer({ name, width = 250, fields = [] }) { } displayEmpty > - {field.operators.map((o) => ( + {field.operators.map((o: OperatorType) => ( {o.label} @@ -194,7 +221,7 @@ export default function FilterDrawer({ name, width = 250, fields = [] }) {
{field && - field.render(q, (changes) => + field.render(q, (changes: any) => editFilterQuery(name, i, { ...q, ...changes }) )} diff --git a/packages/material-ui-shell/src/components/Loading/index.jsx b/packages/material-ui-shell/src/components/Loading/index.tsx similarity index 71% rename from packages/material-ui-shell/src/components/Loading/index.jsx rename to packages/material-ui-shell/src/components/Loading/index.tsx index c4dd7c8c3..24320017b 100644 --- a/packages/material-ui-shell/src/components/Loading/index.jsx +++ b/packages/material-ui-shell/src/components/Loading/index.tsx @@ -1,7 +1,11 @@ import React from 'react' import CircularProgress from '@mui/material/CircularProgress' -export default function Loading() { +/** + * @description Circular loading indicator. + * @returns CircularProgress component with size of 50 + */ +export default function Loading(): JSX.Element { return (
{ + const AvatarConstructor: React.FC = ({ + src, + alt, + avatar, + }) => { return ( - toggleThis('isAuthMenuOpen')}> - + toggleThis(togglerTypes.isAuthMenuOpen)}> + {/* {avatar} - + */} + {avatar ? {avatar} : } ) } @@ -119,8 +146,8 @@ export default function MenuHeader() { {isMiniSwitchVisibility && ( { - toggleThis('isMiniMode', true) - toggleThis('isMenuOpen', false) + toggleThis(togglerTypes.isMiniMode, true) + toggleThis(togglerTypes.isMenuOpen, false) }} > @@ -129,7 +156,7 @@ export default function MenuHeader() { { - toggleThis('isMenuOpen', false) + toggleThis(togglerTypes.isMenuOpen, false) }} > {isRTL ? ( @@ -147,7 +174,7 @@ export default function MenuHeader() { {isAuthenticated && ( { - toggleThis('isAuthMenuOpen') + toggleThis(togglerTypes.isAuthMenuOpen) }} > {!isMenuOpen && @@ -177,7 +204,7 @@ export default function MenuHeader() { textOverflow: 'ellipsis', }} secondaryTypographyProps={{ - color: (t) => theme.palette.grey.A100, + color: theme.palette.grey.A100, width: 80, textOverflow: 'ellipsis', }} @@ -188,7 +215,7 @@ export default function MenuHeader() { {isMenuOpen && ( { - toggleThis('isAuthMenuOpen') + toggleThis(togglerTypes.isAuthMenuOpen) }} > diff --git a/packages/material-ui-shell/src/components/QuestionDialog/index.jsx b/packages/material-ui-shell/src/components/QuestionDialog/index.jsx deleted file mode 100644 index afacdd75d..000000000 --- a/packages/material-ui-shell/src/components/QuestionDialog/index.jsx +++ /dev/null @@ -1,67 +0,0 @@ -import React from 'react' -import { useIntl } from 'react-intl' -import { useTheme } from '@mui/material/styles' - -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogContentText, - DialogTitle, - Slide, - useMediaQuery, -} from '@mui/material' - -const Transition = React.forwardRef((props, ref) => ( - -)) - -export default function QuestionDialog({ - isProcessing = false, - isOpen = false, - id = '', - message = '', - title = '', - action = '', - handleAction = () => {}, - handleClose = () => {}, - ...rest -}) { - const intl = useIntl() - const theme = useTheme() - const fullScreen = useMediaQuery(theme.breakpoints.down('sm')) - - return ( - - {title} - - - {message} - - - - - - - - ) -} diff --git a/packages/material-ui-shell/src/components/QuestionDialog/index.tsx b/packages/material-ui-shell/src/components/QuestionDialog/index.tsx new file mode 100644 index 000000000..289ad9f4a --- /dev/null +++ b/packages/material-ui-shell/src/components/QuestionDialog/index.tsx @@ -0,0 +1,100 @@ +import React from 'react' +import { useIntl } from 'react-intl' +import { useTheme } from '@mui/material/styles' + +import { + Button, + Dialog, + DialogActions, + DialogContent, + DialogContentText, + DialogTitle, + Slide, + useMediaQuery, +} from '@mui/material' +import { TransitionComponentProps } from '@ecronix/material-ui-shell/common.type' + +const Transition = React.forwardRef( + (props, ref) => +) + +type QuestionDialogProps = { + isProcessing?: boolean + isOpen?: boolean + id?: string + message?: string + title?: string + action?: string + handleAction?: (handleClose: () => void) => void + handleClose?: () => void + [key: string]: any +} + +/** + * @description Quection dialog react component. Uses Dialog from @mui/material as base component + * The `QuestionDialog` component displays a customizable dialog with a title, message, + * and action buttons. It supports asynchronous actions and allows for custom closing behavior. + * + * + * @param {QuestionDialogProps} props - The properties passed to the `QuestionDialog` component. + * @param {boolean} [props.isProcessing=false] - Indicates whether the dialog is in a loading or processing state. + * @param {boolean} [props.isOpen=false] - Determines whether the dialog is open or closed. + * @param {string} [props.id=''] - An optional identifier for the dialog instance. + * @param {string} [props.message=''] - The message displayed in the dialog body. + * @param {string} [props.title=''] - The title of the dialog. + * @param {string} [props.action=''] - The label for the action button. + * @param {(handleClose: () => void) => void} [props.handleAction] - Callback executed when the action button is clicked. + * Receives the `handleClose` function as an argument to allow closing the dialog. + * @param {() => void} [props.handleClose] - Callback executed when the dialog is closed. + * @param rest - Additional props passed to the dialog component. + * + * @returns React component Question dialog + */ +export default function QuestionDialog({ + isProcessing = false, + isOpen = false, + id = '', + message = '', + title = '', + action = '', + handleAction = (handleClose: () => void) => {}, + handleClose = () => {}, + ...rest +}: QuestionDialogProps) { + const intl = useIntl() + const theme = useTheme() + const fullScreen = useMediaQuery(theme.breakpoints.down('sm')) + + return ( + + {title} + + + {message} + + + + + + + + ) +} diff --git a/packages/material-ui-shell/src/components/Scrollbar/index.jsx b/packages/material-ui-shell/src/components/Scrollbar/index.tsx similarity index 55% rename from packages/material-ui-shell/src/components/Scrollbar/index.jsx rename to packages/material-ui-shell/src/components/Scrollbar/index.tsx index a2f3dc792..ffc9a21e8 100644 --- a/packages/material-ui-shell/src/components/Scrollbar/index.jsx +++ b/packages/material-ui-shell/src/components/Scrollbar/index.tsx @@ -2,12 +2,30 @@ import React, { useCallback } from 'react' import { Scrollbars } from 'react-custom-scrollbars-2' import { useTheme as useAppTheme } from '@ecronix/material-ui-shell' -export default function Scrollbar(props) { +/** + * A functional React component that wraps around a custom scrollbar implementation. + * + * The `Scrollbar` component provides a customizable scrollbar with support for RTL (right-to-left) + * layouts and dynamic reference forwarding. It uses react-custom-scrollbars-2 package as base. + * + * @param {ScrollbarProps} props - The properties passed to the `Scrollbar` component. + * @param {(ref: any) => void} [props.forwardedRef=() => {}] - A callback function for setting the forwarded reference + * to the scrollable view. + * @param rest - Additional props passed to the underlying `Scrollbars` component. + * + * @returns The rendered scrollbar component. + * + * @example + * + * + * + */ +export default function Scrollbar(props: any) { const { forwardedRef = () => {}, ...rest } = props const { isRTL } = useAppTheme() const refSetter = useCallback( - (scrollbarsRef) => { + (scrollbarsRef: any) => { if (scrollbarsRef) { forwardedRef(scrollbarsRef.view) } else { diff --git a/packages/material-ui-shell/src/components/SearchField/index.jsx b/packages/material-ui-shell/src/components/SearchField/index.tsx similarity index 56% rename from packages/material-ui-shell/src/components/SearchField/index.jsx rename to packages/material-ui-shell/src/components/SearchField/index.tsx index 7154c4593..c3c437dec 100644 --- a/packages/material-ui-shell/src/components/SearchField/index.jsx +++ b/packages/material-ui-shell/src/components/SearchField/index.tsx @@ -3,15 +3,13 @@ import { Search as SearchIcon } from '@mui/icons-material' import { styled, alpha } from '@mui/material/styles' import { InputBase } from '@mui/material' -let timeout = null +let timeout: NodeJS.Timeout | null = null -const Search = styled('div')(({ theme, isOpen }) => { +const Search = styled('div')<{ open: boolean }>(({ theme, open }) => { return { position: 'relative', borderRadius: theme.shape.borderRadius, - backgroundColor: isOpen - ? alpha(theme.palette.common.white, 0.15) - : undefined, + backgroundColor: open ? alpha(theme.palette.common.white, 0.15) : undefined, '&:hover': { backgroundColor: alpha(theme.palette.common.white, 0.25), }, @@ -34,7 +32,10 @@ const SearchIconWrapper = styled('div')(({ theme }) => ({ justifyContent: 'center', })) -const StyledInputBase = styled(InputBase)(({ theme, isOpen }) => { +const StyledInputBase = styled(InputBase)<{ open: boolean }>(({ + theme, + open, +}) => { return { color: 'inherit', '& .MuiInputBase-input': { @@ -44,7 +45,7 @@ const StyledInputBase = styled(InputBase)(({ theme, isOpen }) => { transition: theme.transitions.create('width'), width: '100%', [theme.breakpoints.up('sm')]: { - width: isOpen ? '20ch' : '0ch', + width: open ? '20ch' : '0ch', '&:focus': { width: '20ch', }, @@ -53,12 +54,40 @@ const StyledInputBase = styled(InputBase)(({ theme, isOpen }) => { } }) +type SearchFieldProps = { + onChange: (v: string) => void + initialValue: string + alwaysOpen?: boolean + deferTime?: number +} + +/** + * React component for a search input field with deferred updates. + * + * The `SearchField` component provides an input field for searching with customizable + * initial value, deferred execution of the `onChange` callback, and options to always keep the field open. + * + * @param {SearchFieldProps} props - The properties passed to the `SearchField` component. + * @param props.onChange - A callback function that is triggered when the input value changes. + * The callback is executed after a specified delay (`deferTime`). + * @param {string} props.initialValue - The initial value of the search input field. + * @param {boolean} [props.alwaysOpen=false] - If true, the search input is always displayed as open. + * @param {number} [props.deferTime=1000] - The delay (in milliseconds) before the `onChange` callback is executed. + * + * @returns The rendered search input field. + * + * @example + * console.log('Search input changed:', value)} + * /> + */ export default function SearchField({ onChange, initialValue = '', alwaysOpen, deferTime = 1000, -}) { +}: SearchFieldProps) { const [value, setValue] = useState('') useEffect(() => { setValue(initialValue) @@ -68,7 +97,7 @@ export default function SearchField({ const hasValue = value && value !== '' const isOpen = hasValue || alwaysOpen - const handleChange = (v) => { + const handleChange = (v: string) => { if (timeout) { clearTimeout(timeout) } @@ -83,16 +112,16 @@ export default function SearchField({ } return ( - + { + ref={(node: HTMLElement | null) => { if (node && initialValue && initialValue !== '') { node.focus() } diff --git a/packages/material-ui-shell/src/components/UpdateDialog/index.jsx b/packages/material-ui-shell/src/components/UpdateDialog/index.tsx similarity index 61% rename from packages/material-ui-shell/src/components/UpdateDialog/index.jsx rename to packages/material-ui-shell/src/components/UpdateDialog/index.tsx index afedb4ec8..9c2108028 100644 --- a/packages/material-ui-shell/src/components/UpdateDialog/index.jsx +++ b/packages/material-ui-shell/src/components/UpdateDialog/index.tsx @@ -1,4 +1,4 @@ -import React from 'react' +import React, { useState } from 'react' import { useIntl } from 'react-intl' import { useTheme } from '@mui/material/styles' import { @@ -11,16 +11,41 @@ import { useMediaQuery, } from '@mui/material' -export default function UpdateDialog({ isUpdateAvailable, runUpdate }) { - const [open, setOpen] = React.useState(undefined) +type UpdateDialogProps = { + isUpdateAvailable: boolean + runUpdate: () => void +} + +/** + * A functional React component that renders a dialog to notify the user about an available update. + * + * The `UpdateDialog` component provides options to proceed with an update or postpone it. + * It handles various UI states including responsiveness and localization. + * + * @param {UpdateDialogProps} props - The properties passed to the `UpdateDialog` component. + * @param {boolean} props.isUpdateAvailable - Indicates whether an update is available. If true, the dialog opens. + * @param props.runUpdate - Callback function to run the update when the "Update" button is clicked. + * + * @returns The rendered update dialog component. + * + * @example + * { + * console.log('Running update...'); + * }} + * /> + */ + +export default function UpdateDialog({ + isUpdateAvailable, + runUpdate, +}: UpdateDialogProps) { + const [open, setOpen] = useState(undefined) const intl = useIntl() const theme = useTheme() const fullScreen = useMediaQuery(theme.breakpoints.down('sm')) - const handleClickOpen = () => { - setOpen(true) - } - const handleClose = () => { setOpen(false) } diff --git a/packages/material-ui-shell/src/components/index.js b/packages/material-ui-shell/src/components/index.ts similarity index 100% rename from packages/material-ui-shell/src/components/index.js rename to packages/material-ui-shell/src/components/index.ts diff --git a/packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.jsx b/packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.jsx deleted file mode 100644 index d28626133..000000000 --- a/packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.jsx +++ /dev/null @@ -1,68 +0,0 @@ -const createImage = (url) => - new Promise((resolve, reject) => { - const image = new Image() - image.addEventListener('load', () => resolve(image)) - image.addEventListener('error', (error) => reject(error)) - image.setAttribute('crossOrigin', 'anonymous') // needed to avoid cross-origin issues on CodeSandbox - image.src = url - }) - -function getRadianAngle(degreeValue) { - return (degreeValue * Math.PI) / 180 -} - -/** - * This function was adapted from the one in the ReadMe of https://github.com/DominicTobias/react-image-crop - * @param {File} image - Image File url - * @param {Object} pixelCrop - pixelCrop Object provided by react-easy-crop - * @param {number} rotation - optional rotation parameter - */ -export default async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) { - const image = await createImage(imageSrc) - const canvas = document.createElement('canvas') - const ctx = canvas.getContext('2d') - - const maxSize = Math.max(image.width, image.height) - const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2)) - - // set each dimensions to double largest dimension to allow for a safe area for the - // image to rotate in without being clipped by canvas context - canvas.width = safeArea - canvas.height = safeArea - - // translate canvas context to a central location on image to allow rotating around the center. - ctx.translate(safeArea / 2, safeArea / 2) - ctx.rotate(getRadianAngle(rotation)) - ctx.translate(-safeArea / 2, -safeArea / 2) - - // draw rotated image and store data. - ctx.drawImage( - image, - safeArea / 2 - image.width * 0.5, - safeArea / 2 - image.height * 0.5 - ) - const data = ctx.getImageData(0, 0, safeArea, safeArea) - - // set canvas width to final desired crop size - this will clear existing context - canvas.width = pixelCrop.width - canvas.height = pixelCrop.height - - // paste generated rotate image with correct offsets for x,y crop values. - ctx.putImageData( - data, - 0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x, - 0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y - ) - - // As Base64 string - return canvas.toDataURL('image/jpeg') - - // As a blob - /* - return new Promise((resolve) => { - canvas.toBlob((file) => { - resolve(URL.createObjectURL(file)) - }, 'image/jpeg') - }) - */ -} diff --git a/packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.jsx b/packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.tsx similarity index 82% rename from packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.jsx rename to packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.tsx index d28626133..648a91507 100644 --- a/packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.jsx +++ b/packages/material-ui-shell/src/containers/ImageUploadDialog/getCropImage.tsx @@ -1,4 +1,4 @@ -const createImage = (url) => +const createImage = (url: string): Promise => new Promise((resolve, reject) => { const image = new Image() image.addEventListener('load', () => resolve(image)) @@ -7,17 +7,28 @@ const createImage = (url) => image.src = url }) -function getRadianAngle(degreeValue) { +function getRadianAngle(degreeValue: number): number { return (degreeValue * Math.PI) / 180 } +export interface IPixelCrop { + width: number + height: number + x: number + y: number +} + /** * This function was adapted from the one in the ReadMe of https://github.com/DominicTobias/react-image-crop - * @param {File} image - Image File url + * @param {string} imageSrc - Image File url * @param {Object} pixelCrop - pixelCrop Object provided by react-easy-crop * @param {number} rotation - optional rotation parameter */ -export default async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) { +export default async function getCroppedImg( + imageSrc: string, + pixelCrop: IPixelCrop, + rotation: number = 0 +): Promise { const image = await createImage(imageSrc) const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') @@ -30,6 +41,10 @@ export default async function getCroppedImg(imageSrc, pixelCrop, rotation = 0) { canvas.width = safeArea canvas.height = safeArea + if (!ctx) { + throw new Error('Canvas context is null') + } + // translate canvas context to a central location on image to allow rotating around the center. ctx.translate(safeArea / 2, safeArea / 2) ctx.rotate(getRadianAngle(rotation)) diff --git a/packages/material-ui-shell/src/containers/ImageUploadDialog/index.jsx b/packages/material-ui-shell/src/containers/ImageUploadDialog/index.tsx similarity index 76% rename from packages/material-ui-shell/src/containers/ImageUploadDialog/index.jsx rename to packages/material-ui-shell/src/containers/ImageUploadDialog/index.tsx index 60c629cca..a40c0d550 100644 --- a/packages/material-ui-shell/src/containers/ImageUploadDialog/index.jsx +++ b/packages/material-ui-shell/src/containers/ImageUploadDialog/index.tsx @@ -1,6 +1,6 @@ import Cropper from 'react-easy-crop' import React, { useState, useCallback, useEffect } from 'react' -import getCroppedImg from './getCropImage' +import getCroppedImg, { IPixelCrop } from './getCropImage' import { useIntl } from 'react-intl' import { useTheme } from '@emotion/react' import { @@ -16,12 +16,13 @@ import { } from '@mui/material' import { CloudUpload } from '@mui/icons-material' +import { TransitionComponentProps } from '@ecronix/material-ui-shell/common.type' -const Transition = React.forwardRef((props, ref) => ( - -)) +const Transition = React.forwardRef( + (props, ref) => +) -const getFiles = (ev) => { +const getFiles = (ev: React.DragEvent) => { const files = [] if (ev.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) @@ -41,30 +42,62 @@ const getFiles = (ev) => { return files } +type ImageUploadDialogContainerProps = { + isOpen: boolean + handleClose: () => void + handleCropSubmit: (image: string) => void + path: string + cropperProps: any +} + +/** + * + * @description Dialog for uploading image + * @example + * setImageDialogOpen(false)} + * handleCropSubmit={handleImageChange} + * /> + * + * @param {ImageUploadDialogContainerProps} props + * @param {boolean} props.isOpen - Boolean flag indicating if Dialog is open + * @param props.handleClose - Method for closing Dialog + * @param props.handleCropSubmit - Method for submitting Dialog + * @param {string} props.path - Path of image - on change clear all states on Dialog + */ export function ImageUploadDialogContainer({ isOpen = false, handleClose, handleCropSubmit, path, cropperProps, -}) { +}: ImageUploadDialogContainerProps) { const intl = useIntl() const theme = useTheme() const [isOver, setIsOver] = useState(false) - const [file, setFile] = useState(false) + const [file, setFile] = useState(null) const fullScreen = useMediaQuery((theme) => theme.breakpoints.down('sm')) - const [croppedImage, setCroppedImage] = useState(false) - const [crop, setCrop] = useState({ x: 0, y: 0 }) + const [croppedImage, setCroppedImage] = useState(null) + const [crop, setCrop] = useState>({ + x: 0, + y: 0, + }) const [zoom, setZoom] = useState(1) - const [croppedAreaPixels, setCroppedAreaPixels] = useState(null) + const [croppedAreaPixels, setCroppedAreaPixels] = useState( + null + ) - const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => { - setCroppedAreaPixels(croppedAreaPixels) - }, []) + const onCropComplete = useCallback( + (_croppedArea: never, croppedAreaPixels: IPixelCrop) => { + setCroppedAreaPixels(croppedAreaPixels) + }, + [] + ) const clear = () => { - setCroppedImage(false) - setFile(false) + setCroppedImage(null) + setFile(null) setCroppedAreaPixels(null) setIsOver(false) } @@ -76,6 +109,10 @@ export function ImageUploadDialogContainer({ const showCroppedImage = useCallback(async () => { try { + if (!file || !croppedAreaPixels) { + throw new Error('Invalid parameters when showing cropped image') + } + const croppedImage = await getCroppedImg(file, croppedAreaPixels, 0) setCroppedImage(croppedImage) @@ -120,10 +157,10 @@ export function ImageUploadDialogContainer({ var reader = new FileReader() reader.onload = (e) => { - setFile(e.target.result) + setFile(e.target?.result as string) } - reader.readAsDataURL(files[0]) + reader.readAsDataURL(files[0]!) } }} onDragOver={(e) => { @@ -163,7 +200,7 @@ export function ImageUploadDialogContainer({ var reader = new FileReader() reader.onload = (e) => { - setFile(e.target.result) + setFile(e.target?.result as string) } reader.readAsDataURL(e.target.files[0]) diff --git a/packages/material-ui-shell/src/containers/LayoutContainer/index.jsx b/packages/material-ui-shell/src/containers/LayoutContainer/index.tsx similarity index 74% rename from packages/material-ui-shell/src/containers/LayoutContainer/index.jsx rename to packages/material-ui-shell/src/containers/LayoutContainer/index.tsx index d8ee6d7ff..8f1f49c77 100644 --- a/packages/material-ui-shell/src/containers/LayoutContainer/index.jsx +++ b/packages/material-ui-shell/src/containers/LayoutContainer/index.tsx @@ -22,7 +22,9 @@ import '@fontsource/roboto/400.css' import '@fontsource/roboto/500.css' import '@fontsource/roboto/700.css' -const LayoutContent = ({ children }) => { +const LayoutContent: React.FC<{ children: React.ReactNode }> = ({ + children, +}) => { const intl = useIntl() const { appConfig } = useConfig() const { themeID, isDarkMode, isRTL } = useTheme() @@ -30,6 +32,8 @@ const LayoutContent = ({ children }) => { const { useiOSPWAPrompt, iOSPWAPromptProps } = pwa || {} const { themes = [] } = themeConfig || {} const theme = getThemeSource(themeID, themes, isDarkMode, isRTL) + console.log('theme') + console.log(theme) return ( @@ -77,7 +81,29 @@ const LayoutContent = ({ children }) => { ) } -export function LayoutContainer({ children }) { +type LCProps = { + children: React.ReactNode +} + +/** + * A functional React component that provides a layout container for the application. + * LayoutContainer is provided in app configuration under container section + * + * The `LayoutContainer` component is responsible for wrapping the children with necessary providers + * such as the `MenuProvider` and `AppThemeProvider`. It also integrates the `LayoutContent` component + * for setting up the theme and other configurations. + * + * @param {LCProps} props - The properties passed to the `LayoutContainer` component. + * @param {React.ReactNode} props.children - The child elements to be rendered inside the container. + * + * @returns The rendered layout container with applied theme and menu context. + * + * @example + * + * + * + */ +export function LayoutContainer({ children }: LCProps): JSX.Element { const { appConfig } = useConfig() return ( diff --git a/packages/material-ui-shell/src/containers/Menu/index.jsx b/packages/material-ui-shell/src/containers/Menu/index.jsx deleted file mode 100644 index 0b4623f03..000000000 --- a/packages/material-ui-shell/src/containers/Menu/index.jsx +++ /dev/null @@ -1,18 +0,0 @@ -import React from 'react' -import { ResponsiveMenuContainer } from '@ecronix/material-ui-shell' -import { useConfig } from '@ecronix/base-shell' - -export function MenuContainer() { - const { appConfig } = useConfig() - const { menu } = appConfig || {} - const { MenuHeader, MenuContent, BaseMenu } = menu || {} - - const Menu = BaseMenu || ResponsiveMenuContainer - - return ( - - {MenuHeader && } - {MenuContent && } - - ) -} diff --git a/packages/material-ui-shell/src/containers/Menu/index.tsx b/packages/material-ui-shell/src/containers/Menu/index.tsx new file mode 100644 index 000000000..251495d0d --- /dev/null +++ b/packages/material-ui-shell/src/containers/Menu/index.tsx @@ -0,0 +1,33 @@ +import React from 'react' +import { ResponsiveMenuContainer } from '@ecronix/material-ui-shell' +import { useConfig } from '@ecronix/base-shell' + +/** + * React component rendering MenuHeader and MenuContent. It loads data from config using useConfig hook. + * It renders MenuHeader and MenuContent component if they are provided in application configuration under + * menu scetion. As main wrapper it sets BaseMenu component defined in app config under menu section + * + * If MenuContainer is not provided it uses ResponsiveMenuContainer from material-ui-shell + * + * @example + * appConfig: { + * components: { + * Menu: MenuContainer + * } + * } + * @see {ResponsiveMenuContainer} - for fallback component + */ +export function MenuContainer() { + const { appConfig } = useConfig() + const { menu } = appConfig || {} + const { MenuHeader, MenuContent, BaseMenu } = menu || {} + + const Menu = BaseMenu || ResponsiveMenuContainer + + return ( + + {MenuHeader && } + {MenuContent && } + + ) +} diff --git a/packages/material-ui-shell/src/containers/ResponsiveMenu/index.jsx b/packages/material-ui-shell/src/containers/ResponsiveMenu/index.tsx similarity index 78% rename from packages/material-ui-shell/src/containers/ResponsiveMenu/index.jsx rename to packages/material-ui-shell/src/containers/ResponsiveMenu/index.tsx index fefe5d7c1..b82163ab2 100644 --- a/packages/material-ui-shell/src/containers/ResponsiveMenu/index.jsx +++ b/packages/material-ui-shell/src/containers/ResponsiveMenu/index.tsx @@ -2,10 +2,22 @@ import React from 'react' import { SwipeableDrawer, styled } from '@mui/material' import { useMenu, useTheme as useAppTheme } from '@ecronix/material-ui-shell' import { useConfig } from '@ecronix/base-shell' +import { + MenuContextType, + togglerTypes, +} from '@ecronix/material-ui-shell/providers/Menu/Context' //const iOS = process.browser && /iPad|iPhone|iPod/.test(navigator.userAgent) -const CustomSwipeableDrawer = styled(SwipeableDrawer)(({ +interface CustomSwipeableDrawerProps { + theme?: any + width: number | string + menucontext: MenuContextType +} + +const CustomSwipeableDrawer = styled( + SwipeableDrawer +)(({ theme, width, menucontext: { isDesktop, isMenuOpen, isMiniMode }, @@ -46,7 +58,15 @@ const CustomSwipeableDrawer = styled(SwipeableDrawer)(({ } }) -export function ResponsiveMenuContainer({ children }) { +/** + * @description Wraps provided component in swipable drawer from @mui/material + * @param props.children - Children passed in compontent + */ +export function ResponsiveMenuContainer({ + children, +}: { + children: React.ReactNode +}) { const { isRTL } = useAppTheme() const config = useConfig() const width = config?.appConfig?.menu?.width || 240 @@ -55,7 +75,7 @@ export function ResponsiveMenuContainer({ children }) { menuContext || {} const handleDrawerToggle = () => { - toggleThis('isMobileMenuOpen') + toggleThis(togglerTypes.isMobileMenuOpen) } return ( diff --git a/packages/material-ui-shell/src/containers/SelectableMenuList/index.jsx b/packages/material-ui-shell/src/containers/SelectableMenuList/index.tsx similarity index 61% rename from packages/material-ui-shell/src/containers/SelectableMenuList/index.jsx rename to packages/material-ui-shell/src/containers/SelectableMenuList/index.tsx index d765f5736..25dd7ecff 100644 --- a/packages/material-ui-shell/src/containers/SelectableMenuList/index.jsx +++ b/packages/material-ui-shell/src/containers/SelectableMenuList/index.tsx @@ -18,52 +18,101 @@ import { Typography, } from '@mui/material' import { useLocation } from 'react-router-dom' +import { MenuItemType } from '@ecronix/material-ui-shell/common.type' +type PropTypes = { + onIndexChange: ( + e: React.FormEvent, + v: string + ) => React.FormEventHandler + useMinified: boolean + items: any[] + index: number +} +type StateType = { + previousItems?: MenuItemType[][] + items?: MenuItemType[] + previousTitles?: string[] + title?: string + index?: number | string +} + +/** + * @description Menu list container component takeing in account RTL properties from theme and + * isMiniMode property from menu context + * @param {PropTypes} props - properties passed in component + * @param props.onIndexChange - method triggered on index change on List component from @mui/material + * @param {boolean} props.useMinfied - defines if minified menu should be displayed + * @param props.items - Menu items to be renderd + * @param props.index - optional parameter + * + * @example + * + * @returns + * + * @see {useMenu} - for referencing isMiniMode + * @see {useAppTheme} - for referencing isRTL + */ export function SelectableMenuListContainer({ onIndexChange, useMinified, items, index, -}) { - const [state, setState] = useState({}) +}: PropTypes) { + const [state, setState] = useState({}) const { isRTL } = useAppTheme() const { isMiniMode } = useMenu() const { pathname = '' } = useLocation() - const loopItems = useCallback((items, previousItems = [], title) => { - items.map((i) => { - const { value = 'none', nestedItems = [], primaryText = '' } = i - if (pathname === value) { - if (previousItems.length) { - setState({ - index: value, - previousItems: [previousItems], - items, - title, - }) - } else { - setState({ - index: value, - }) + const loopItems = useCallback( + ( + items: MenuItemType[], + previousItems: MenuItemType[] = [], + title: string + ) => { + items.map((i) => { + const { value = 'none', nestedItems = [], primaryText = '' } = i + if (pathname === value) { + if (previousItems.length) { + setState({ + index: value, + previousItems: [previousItems], + items, + title, + }) + } else { + setState({ + index: value, + }) + } + + return i } + if (nestedItems.length) { + loopItems(nestedItems, [...previousItems, ...items], primaryText) + } + //console.log('i', i) return i - } - - if (nestedItems.length) { - loopItems(nestedItems, [...previousItems, items], primaryText) - } - //console.log('i', i) - return i - }) - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []) + }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, + [] + ) - const list = - state.previousItems && state.previousItems.length > 0 ? state.items : items + const list: MenuItemType[] = + state.previousItems && state.items && state.previousItems.length > 0 + ? state.items + : items useEffect(() => { - loopItems(items) + loopItems(items, [], '') // eslint-disable-next-line react-hooks/exhaustive-deps }, []) @@ -74,7 +123,7 @@ export function SelectableMenuListContainer({ //setState({}) }, [items.length]) - const handleNestedItemsClick = (item) => { + const handleNestedItemsClick = (item: MenuItemType) => { if (item.nestedItems) { let previousItems = state.previousItems || [] let previousTitles = state.previousTitles || [] @@ -111,20 +160,21 @@ export function SelectableMenuListContainer({ setState({ ...state, items, previousItems, previousTitles, title }) } - const getItem = (item, i) => { + const getItem = (item: MenuItemType, i: number) => { const { index } = state delete item.visible if (item !== undefined) { if (item.subheader !== undefined) { + // Removed inset={item.inset} doesn't exist return ( -
+
{item.subheader}
) } else if (item.divider !== undefined) { - return + return // Removed inset={item.inset} doesn't exist } else { return ( { - onIndexChange(e, item.value) + onClick={(e: React.FormEvent) => { + onIndexChange(e, item.value!) handleNestedItemsClick(item) if (item.onClick) { item.onClick() } }} - onMouseDown={(e) => { + onMouseDown={( + e: React.MouseEvent + ) => { if (e.button === 1) { var win = window.open(`${item.value}`, '_blank') - win.focus() + win?.focus() } }} > @@ -191,7 +243,12 @@ export function SelectableMenuListContainer({ } return ( - + ) => + onIndexChange(e, index.toString()) + } + > {state.items && state.previousItems && state.previousItems.length > 0 && (
{ window.update && window.update() } -export function UpdateContainer({ children }) { +/** + * @description React component that manages the update process. + * The `UpdateContainer` component checks for updates periodically and shows a notification + * if an update is available. It provides buttons to either update immediately or defer the update. + * The update process is handled by a global `window.update` function, if available. + * + * @param {UpdateContainerProps} props - The properties passed to the `UpdateContainer` component. + * @param {React.ReactNode} props.children - The child elements to be rendered inside the container. + * + * @returns The rendered update container which wraps its children. + * + * @example + * + * + * + */ +export function UpdateContainer({ children }: { children: React.ReactNode }) { const intl = useIntl() const { appConfig } = useConfig() const { enqueueSnackbar, closeSnackbar } = useSnackbar() const { update } = appConfig || {} const { checkInterval = 3000, repeatInterval = 300000 } = update || {} - const action = (key) => ( + const action = (key: SnackbarKey) => ( } + * tabs={
My Custom Tabs
} + * > + *
This is the content of the page.
+ * + * ) + * + * @param {Object} props - Component props. + * @param {React.ReactNode} props.children - The content to render within the page. + * @param {string | String} [props.pageTitle] - The title to display in the app bar. + * @param [props.onBackClick] - A callback function to handle the back button click event. + * @param {boolean} [props.isLoading] - A flag to indicate whether the page is in a loading state. + * @param {React.ReactNode} [props.appBarContent=null] - Content to be placed within the app bar (e.g., buttons, icons). + * @param {React.CSSProperties} [props.contentStyle] - Additional styles to apply to the content area of the page. + * @param {React.ReactNode} [props.tabs=null] - Tabs content to be rendered below the app bar (optional). + * + * @returns The rendered `Page` component. + */ export function Page({ children, pageTitle, @@ -24,7 +61,7 @@ export function Page({ appBarContent = null, contentStyle, tabs = null, -}) { +}: PageProps) { const { isRTL } = useAppTheme() const isOnline = useOnline() const theme = useTheme() @@ -32,23 +69,24 @@ export function Page({ const { menu } = appConfig || {} const { width = 240, appBarLeadingContent = null } = menu || {} - const { toggleThis, isDesktop, isMenuOpen } = useContext(MenuContext) + // const { toggleThis, isDesktop, isMenuOpen } = useContext(MenuContext) + const { toggleThis, isDesktop, isMenuOpen } = useMenu() const intl = useIntl() let headerTitle = '' if (typeof pageTitle === 'string' || pageTitle instanceof String) { - headerTitle = pageTitle + headerTitle = pageTitle as string } const handleDrawerMenuClick = () => { if (!isMenuOpen) { - toggleThis('isMiniMode', false) - toggleThis('isMenuOpen', true) + toggleThis(togglerTypes.isMiniMode, false) + toggleThis(togglerTypes.isMenuOpen, true) if (!isDesktop) { - toggleThis('isMobileMenuOpen') + toggleThis(togglerTypes.isMobileMenuOpen) } } else { - toggleThis('isMobileMenuOpen') + toggleThis(togglerTypes.isMobileMenuOpen) } } @@ -78,17 +116,18 @@ export function Page({ }} > - {(isMenuOpen && isDesktop) || - (!onBackClick && ( - - - - ))} + {isMenuOpen && isDesktop + ? null + : !onBackClick && ( + + + + )} {/* james- check if this is dead code? */} {onBackClick && ( { +/** + * @description Renders not found page + */ +export const NotFoundPage: React.FC = () => { const intl = useIntl() return ( diff --git a/packages/material-ui-shell/src/providers/Dialogs/Question/Context.jsx b/packages/material-ui-shell/src/providers/Dialogs/Question/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/material-ui-shell/src/providers/Dialogs/Question/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/material-ui-shell/src/providers/Dialogs/Question/Context.tsx b/packages/material-ui-shell/src/providers/Dialogs/Question/Context.tsx new file mode 100644 index 000000000..05f20c233 --- /dev/null +++ b/packages/material-ui-shell/src/providers/Dialogs/Question/Context.tsx @@ -0,0 +1,27 @@ +import React from 'react' + +export interface DialogsContextType { + /** + * @description Open dialog - sets isOpen to true, and pass additional props + * @param props + */ + openDialog: (props: any) => void + + /** + * @description Closes dialog - sets isOpen to false + * @param name + * @param offset + */ + closeDialog: () => void + /** + * @description Set processing to true or false + * @param isProcessing + */ + setProcessing: (isProcessing: boolean) => void +} + +export const Context = React.createContext( + undefined +) + +export default Context diff --git a/packages/material-ui-shell/src/providers/Dialogs/Question/Provider.jsx b/packages/material-ui-shell/src/providers/Dialogs/Question/Provider.tsx similarity index 76% rename from packages/material-ui-shell/src/providers/Dialogs/Question/Provider.jsx rename to packages/material-ui-shell/src/providers/Dialogs/Question/Provider.tsx index c41be72cc..856c9d440 100644 --- a/packages/material-ui-shell/src/providers/Dialogs/Question/Provider.jsx +++ b/packages/material-ui-shell/src/providers/Dialogs/Question/Provider.tsx @@ -1,12 +1,13 @@ import React, { useState, Fragment } from 'react' import Context from './Context' import QuestionDialog from '../../../components/QuestionDialog' +import { IProviderProps } from '@ecronix/material-ui-shell/common.type' -const Provider = ({ children }) => { +const Provider: React.FC = ({ children }) => { const [state, setState] = useState({ isOpen: false }) const [isProcessing, setIsProcessing] = useState(false) - const openDialog = (props) => { + const openDialog = (props: any) => { setState({ isOpen: true, ...props }) } @@ -14,7 +15,7 @@ const Provider = ({ children }) => { setState({ isOpen: false }) } - const setProcessing = (isProcessing) => { + const setProcessing = (isProcessing: boolean) => { setIsProcessing(isProcessing) } diff --git a/packages/material-ui-shell/src/providers/Dialogs/Question/index.jsx b/packages/material-ui-shell/src/providers/Dialogs/Question/index.jsx deleted file mode 100644 index 85e2eeca0..000000000 --- a/packages/material-ui-shell/src/providers/Dialogs/Question/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from 'react' -import Context from './Context' -import Provider from './Provider' - -function useQuestionsDialog() { - return useContext(Context) -} - -export { - useQuestionsDialog, - Context as QuestionsDialogContext, - Provider as QuestionsDialogProvider, -} diff --git a/packages/material-ui-shell/src/providers/Dialogs/Question/index.tsx b/packages/material-ui-shell/src/providers/Dialogs/Question/index.tsx new file mode 100644 index 000000000..dd630544b --- /dev/null +++ b/packages/material-ui-shell/src/providers/Dialogs/Question/index.tsx @@ -0,0 +1,32 @@ +import { useContext } from 'react' +import Context, { DialogsContextType } from './Context' +import Provider from './Provider' + +/** + * Custom hook to access the question dialog context. + * + * @function + * @returns {DialogsContextType} The theme context value. + * @throws {Error} If used outside of an QuestionsDialogProvider. + * @example + * const { openDialog, closeDialog, setProcessing } = useQuestionsDialog(); + * + * @description Gives you access to questions dialog. It must be used within QuestionsDialogProvider and it provides you + * with methods for opening and closing dialog, as well as handling processing + * + */ +function useQuestionsDialog(): DialogsContextType { + const context = useContext(Context) + if (context === undefined) { + throw new Error( + 'useQuestionsDialog must be used within a QuestionsDialogProvider' + ) + } + return context +} + +export { + useQuestionsDialog, + Context as QuestionsDialogContext, + Provider as QuestionsDialogProvider, +} diff --git a/packages/material-ui-shell/src/providers/Filter/Context.jsx b/packages/material-ui-shell/src/providers/Filter/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/material-ui-shell/src/providers/Filter/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/material-ui-shell/src/providers/Filter/Context.tsx b/packages/material-ui-shell/src/providers/Filter/Context.tsx new file mode 100644 index 000000000..7b1af19e3 --- /dev/null +++ b/packages/material-ui-shell/src/providers/Filter/Context.tsx @@ -0,0 +1,128 @@ +import React from 'react' +import { + FieldType, + SortOrientationType, +} from '@ecronix/material-ui-shell/common.type' + +export interface FilterContextType { + /** + * Opens the filter panel for the specified list. + * + * @param {string} name - The name of the list for which the filter panel should be opened. + */ + openFilter: (name: string) => void + + /** + * Closes the filter panel for the specified list. + * + * @param {string} name - The name of the list for which the filter panel should be closed. + */ + closeFilter: (name: string) => void + + /** + * Clears the filter queries for the specified list. + * + * @param {string} name - The name of the list whose filters should be cleared. + */ + clearFilter: (name: string) => void + + /** + * Sets the search query for the specified list. + * + * @param {string} name - The name of the list for which the search query should be set. + * @param {string} search - The search query string. + */ + setSearch: (name: string, search: string) => void + + /** + * Sets the field by which the list should be sorted. + * + * @param {string} name - The name of the list for which the sort field should be set. + * @param {string} sortField - The field to sort by. + */ + setFilterSortField: (name: string, sortField: string) => void + + /** + * Sets the sort orientation (ascending or descending) for the specified list. + * + * @param {string} name - The name of the list for which the sort orientation should be set. + * @param {SortOrientationType} sortOrientation - The sort orientation (e.g., 'asc' or 'desc'). + */ + setFilterSortOrientation: ( + name: string, + sortOrientation: SortOrientationType + ) => void + + /** + * Adds a new filter query to the specified list. + * + * @param {string} name - The name of the list to which the filter query should be added. + * @param {any} query - The filter query to be added. + */ + addFilterQuery: (name: string, query: any) => void + + /** + * Removes a filter query from the specified list by index. + * + * @param {string} name - The name of the list from which the filter query should be removed. + * @param {number} index - The index of the filter query to be removed. + */ + removeFilterQuery: (name: string, index: number) => void + + /** + * Edits an existing filter query for the specified list. + * + * @param {string} name - The name of the list for which the filter query should be edited. + * @param {number} index - The index of the filter query to be edited. + * @param {any} query - The new filter query. + */ + editFilterQuery: (name: string, index: number, query: any) => void + + /** + * Retrieves the filtered and sorted list for the specified list. + * + * @param {string} name - The name of the list to retrieve the filtered and sorted data. + * @param {any} list - The original list to apply filters and sorting to. + * @param {FieldType[]} fields - The fields that should be considered for filtering and sorting. + * @returns {any} The filtered and sorted list. + */ + getList: (name: string, list: any, fields: FieldType[]) => any + + /** + * Checks whether the filter panel is open for the specified list. + * + * @param {string} name - The name of the list to check the filter panel state. + * @returns {boolean} `true` if the filter panel is open, `false` otherwise. + */ + isFilterOpen: (name: string) => boolean + + /** + * Retrieves the filter queries for the specified list. + * + * @param {string} name - The name of the list to retrieve the filter queries for. + * @returns {any[]} An array of filter queries for the specified list. + */ + getFilterQueries: (name: string) => any[] + + /** + * Retrieves the current filter state for the specified list. + * + * @param {string} name - The name of the list to retrieve the filter state for. + * @returns {any} The current filter state for the specified list. + */ + getFilter: (name: string) => any + + /** + * Retrieves the field object by its name from the list of fields. + * + * @param {string} fieldName - The name of the field to retrieve. + * @param {FieldType[]} fields - The list of fields to search from. + * @returns {any} The field object corresponding to the provided field name. + */ + getField: (fieldName: string, fields: FieldType[]) => any +} +export const Context = React.createContext( + undefined +) + +export default Context diff --git a/packages/material-ui-shell/src/providers/Filter/Provider.jsx b/packages/material-ui-shell/src/providers/Filter/Provider.jsx deleted file mode 100644 index 679a9aa5f..000000000 --- a/packages/material-ui-shell/src/providers/Filter/Provider.jsx +++ /dev/null @@ -1,72 +0,0 @@ -import React, { useEffect, useReducer } from 'react' -import Context from './Context' -import reducer from './store/reducer' -import { - addFilterQuery, - clearFilter, - closeFilter, - editFilterQuery, - openFilter, - removeFilterQuery, - setFilterSortField, - setFilterSortOrientation, - setSearch, -} from './store/actions' -import { getList, getField } from './store/selectors' - -function getInitState(persistKey) { - let persistedValues = {} - try { - persistedValues = JSON.parse(localStorage.getItem(persistKey)) || {} - } catch (error) { - console.warn(error) - } - return persistedValues -} - -const Provider = ({ children, persistKey = 'mui_filter' }) => { - const [state, dispatch] = useReducer(reducer, getInitState(persistKey)) - - useEffect(() => { - try { - localStorage.setItem(persistKey, JSON.stringify(state)) - } catch (error) { - console.warn(error) - } - }, [state, persistKey]) - - const props = { - openFilter: (name) => dispatch(openFilter(name)), - closeFilter: (name) => dispatch(closeFilter(name)), - clearFilter: (name) => dispatch(clearFilter(name)), - setSearch: (name, search) => dispatch(setSearch(name, search)), - - setFilterSortField: (name, sortField) => - dispatch(setFilterSortField(name, sortField)), - setFilterSortOrientation: (name, sortOrientation) => - dispatch(setFilterSortOrientation(name, sortOrientation)), - addFilterQuery: (name, query) => dispatch(addFilterQuery(name, query)), - removeFilterQuery: (name, index) => - dispatch(removeFilterQuery(name, index)), - editFilterQuery: (name, index, query) => - dispatch(editFilterQuery(name, index, query)), - getList: (name, list, fields) => getList(state[name], list, fields), - isFilterOpen: (name) => (state[name] ? !!state[name].isOpen : false), - getFilterQueries: (name) => - state[name] && state[name].queries ? state[name].queries : [], - getFilter: (name) => (state[name] ? state[name] : {}), - getField: (fieldName, fields) => getField(fieldName, fields), - } - - return ( - - {children} - - ) -} - -export default Provider diff --git a/packages/material-ui-shell/src/providers/Filter/Provider.tsx b/packages/material-ui-shell/src/providers/Filter/Provider.tsx new file mode 100644 index 000000000..995d44819 --- /dev/null +++ b/packages/material-ui-shell/src/providers/Filter/Provider.tsx @@ -0,0 +1,88 @@ +import React, { useEffect, useReducer } from 'react' +import Context from './Context' +import reducer from './store/reducer' +import { + addFilterQuery, + clearFilter, + closeFilter, + editFilterQuery, + openFilter, + removeFilterQuery, + setFilterSortField, + setFilterSortOrientation, + setSearch, +} from './store/actions' +import { getList, getField } from './store/selectors' +import { + FieldType, + IProviderProps, + SortOrientationType, +} from '@ecronix/material-ui-shell/common.type' + +function getInitState(persistKey: string) { + const pkString = localStorage.getItem(persistKey) + let persistedValues = {} + try { + persistedValues = pkString ? JSON.parse(pkString) : {} + } catch (error) { + console.warn(error) + } + return persistedValues +} + +const Provider: React.FC = ({ + children, + persistKey = 'mui_filter', +}) => { + const [state, dispatch] = useReducer(reducer, getInitState(persistKey)) + + useEffect(() => { + try { + localStorage.setItem(persistKey, JSON.stringify(state)) + } catch (error) { + console.warn(error) + } + }, [state, persistKey]) + + const props = { + openFilter: (name: string) => dispatch(openFilter(name)), + closeFilter: (name: string) => dispatch(closeFilter(name)), + clearFilter: (name: string) => dispatch(clearFilter(name)), + setSearch: (name: string, search: string) => + dispatch(setSearch(name, search)), + + setFilterSortField: (name: string, sortField: string) => + dispatch(setFilterSortField(name, sortField)), + setFilterSortOrientation: ( + name: string, + sortOrientation: SortOrientationType + ) => dispatch(setFilterSortOrientation(name, sortOrientation)), + addFilterQuery: (name: string, query: any) => + dispatch(addFilterQuery(name, query)), + removeFilterQuery: (name: string, index: number) => + dispatch(removeFilterQuery(name, index)), + editFilterQuery: (name: string, index: number, query: any) => + dispatch(editFilterQuery(name, index, query)), + getList: (name: string, list: any, fields: FieldType[]) => + getList(state[name], list, fields), + isFilterOpen: (name: string) => + state[name] ? !!state[name].isOpen : false, + getFilterQueries: (name: string) => + state[name] && state[name].queries ? state[name].queries : [], + getFilter: (name: string) => (state[name] ? state[name] : {}), + getField: (fieldName: string, fields: FieldType[]) => + getField(fieldName, fields), + } + + return ( + + {children} + + ) +} + +export default Provider diff --git a/packages/material-ui-shell/src/providers/Filter/fields/boolean.jsx b/packages/material-ui-shell/src/providers/Filter/fields/boolean.tsx similarity index 70% rename from packages/material-ui-shell/src/providers/Filter/fields/boolean.jsx rename to packages/material-ui-shell/src/providers/Filter/fields/boolean.tsx index 1f774b2cb..8dc89450a 100644 --- a/packages/material-ui-shell/src/providers/Filter/fields/boolean.jsx +++ b/packages/material-ui-shell/src/providers/Filter/fields/boolean.tsx @@ -1,13 +1,21 @@ import React from 'react' import { Switch } from '@mui/material' +import { + Operators, + OperatorType, + SortOrientationType, +} from '@ecronix/material-ui-shell/common.type' const field = { operators: [ { value: '=', label: '=' }, { value: '!=', label: '!=' }, - ], + ] as OperatorType[], defaultOperator: '=', - filter: (value, q) => { + filter: ( + value: boolean, + q: { operator: Operators; value: boolean | string } + ) => { const { operator, value: qv } = q if (qv !== '') { const queryValue = !!qv @@ -23,10 +31,13 @@ const field = { return true } }, - sort: (orientation, a, b) => { + sort: (orientation: SortOrientationType, a: number, b: number) => { return (a - b) * orientation }, - render: ({ value = '' }, onChange) => { + render: ( + { value = '' }, + onChange: ({ value }: { value: boolean }) => void + ) => { return (
=', label: '>=' }, - ], + ] as OperatorType[], defaultOperator: '=', - filter: (rawValue, q) => { + + filter: ( + rawValue: any, + q: { operator: Operators; value: number | string } + ) => { const { operator, value: qv } = q + if (qv !== '') { const queryValue = new Date(qv).getTime() const value = new Date(rawValue).getTime() @@ -36,13 +46,16 @@ const field = { return true } }, - sort: (orientation, aRaw, bRaw) => { + sort: (orientation: SortOrientationType, aRaw: string, bRaw: string) => { const a = new Date(aRaw).getTime() const b = new Date(bRaw).getTime() var result = a < b ? -1 : a > b ? 1 : 0 return result * orientation }, - render: ({ value = '', isCaseSensitive = false }, onChange) => { + render: ( + { value = '', _isCaseSensitive = false }, + onChange: (data: any) => void + ) => { return ( =', label: '>=' }, { value: 'like', label: 'like' }, { value: '!like', label: '!like' }, - ], + ] as OperatorType[], defaultOperator: '=', - filter: (value, q) => { + filter: ( + value: number, + q: { operator: Operators; value: number | string } + ) => { const { operator, value: qv } = q if (qv !== '') { - const queryValue = parseFloat(qv) + const queryValue = typeof qv === 'string' ? parseFloat(qv) : qv switch (operator) { case '=': return value === queryValue @@ -41,10 +49,10 @@ const field = { return true } }, - sort: (orientation, a, b) => { + sort: (orientation: SortOrientationType, a: number, b: number) => { return (a - b) * orientation }, - render: ({ value = '' }, onChange) => { + render: ({ value = '' }, onChange: (data: any) => void) => { return ( =', label: '>=' }, { value: 'like', label: 'like' }, { value: '!like', label: '!like' }, - ], + ] as OperatorType[], defaultOperator: 'like', - filter: (rawValue = '', q) => { + filter: ( + rawValue = '', + q: { operator: string; value: string; isCaseSensitive: boolean } + ) => { const { operator, value: qv, isCaseSensitive = false } = q if (qv !== '') { @@ -49,11 +56,14 @@ const field = { return true } }, - sort: (orientation, a, b) => { + sort: (orientation: SortOrientationType, a: number, b: number) => { var result = a < b ? -1 : a > b ? 1 : 0 return result * orientation }, - render: ({ value = '', isCaseSensitive = false }, onChange) => { + render: ( + { value = '', isCaseSensitive = false }, + onChange: (data: any) => void + ) => { return ( =', label: '>=' }, - ], + ] as OperatorType[], defaultOperator: '=', - filter: (rawValue, q) => { + filter: (rawValue: any, q: { operator: string; value: string }) => { const { operator, value: qv } = q if (qv !== '') { const queryValue = qv ? parseInt(qv.split(':').join('')) : 0 @@ -37,13 +41,13 @@ const field = { return true } }, - sort: (orientation, aRaw, bRaw) => { + sort: (orientation: SortOrientationType, aRaw: string, bRaw: string) => { const a = new Date(aRaw).getTime() const b = new Date(bRaw).getTime() var result = a < b ? -1 : a > b ? 1 : 0 return result * orientation }, - render: ({ value = '', isCaseSensitive = false }, onChange) => { + render: ({ value = '', _isCaseSensitive = false }, onChange: any) => { return ( { +export function getField(name: string, fields: FieldType[] = []) { + let field: FieldType | undefined = fields.find((f) => f.name === name) + if (!field) return undefined + + fields.map((f: FieldType) => { const { type = 'text' } = f if (f.name === name) { let defaultProps = {} @@ -25,7 +37,17 @@ export function getField(name, fields = []) { return field } -export function getList(filter = {}, list = [], fields = []) { +type FilterType = { + queries?: any + sortField?: string + sortOrientation?: SortOrientationType + search?: any +} +export function getList( + filter: FilterType = {}, + list = [], + fields: FieldType[] = [] +) { let result = [...list] const { queries = [], @@ -72,9 +94,9 @@ export function getList(filter = {}, list = [], fields = []) { } if (sortFieldName && sortFieldName !== '') { - const sortField = getField(sortFieldName, fields) + const sortField: FieldType | undefined = getField(sortFieldName, fields) - if (result !== undefined && sortField.sort !== undefined) { + if (sortField && result !== undefined && sortField.sort !== undefined) { result.sort((a, b) => sortField.sort(sortOrientation, a[sortFieldName], b[sortFieldName]) ) diff --git a/packages/material-ui-shell/src/providers/Filter/store/types.jsx b/packages/material-ui-shell/src/providers/Filter/store/types.tsx similarity index 100% rename from packages/material-ui-shell/src/providers/Filter/store/types.jsx rename to packages/material-ui-shell/src/providers/Filter/store/types.tsx diff --git a/packages/material-ui-shell/src/providers/Menu/Context.jsx b/packages/material-ui-shell/src/providers/Menu/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/material-ui-shell/src/providers/Menu/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/material-ui-shell/src/providers/Menu/Context.tsx b/packages/material-ui-shell/src/providers/Menu/Context.tsx new file mode 100644 index 000000000..79e9e0426 --- /dev/null +++ b/packages/material-ui-shell/src/providers/Menu/Context.tsx @@ -0,0 +1,26 @@ +import React from 'react' + +export enum togglerTypes { + isAuthMenuOpen = 'isAuthMenuOpen', + isMiniMode = 'isMiniMode', + isMenuOpen = 'isMenuOpen', + isMobileMenuOpen = 'isMobileMenuOpen', + isMiniSwitchVisibility = 'isMiniSwitchVisibility', +} + +export type MenuContextType = { + /** Method for updating context values. Use `togglerTypes` enum to access properties. Provide new value to set to specified property */ + toggleThis: (value: togglerTypes, newValue?: boolean | null) => void + isDesktop: boolean + isAuthMenuOpen?: boolean + isMiniMode?: boolean + isMenuOpen?: boolean + isMobileMenuOpen?: boolean + isMiniSwitchVisibility?: boolean +} + +export const Context = React.createContext( + undefined +) + +export default Context diff --git a/packages/material-ui-shell/src/providers/Menu/Provider.jsx b/packages/material-ui-shell/src/providers/Menu/Provider.tsx similarity index 71% rename from packages/material-ui-shell/src/providers/Menu/Provider.jsx rename to packages/material-ui-shell/src/providers/Menu/Provider.tsx index 23bccd39a..9f2b70ecc 100644 --- a/packages/material-ui-shell/src/providers/Menu/Provider.jsx +++ b/packages/material-ui-shell/src/providers/Menu/Provider.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useReducer } from 'react' -import Context from './Context' +import Context, { togglerTypes } from './Context' import { useMediaQuery } from '@mui/material' import { setIsAuthMenuOpen, @@ -9,8 +9,13 @@ import { setIsMiniSwitchVisibility, } from './store/actions' import reducer from './store/reducer' +import { IProviderProps } from '@ecronix/material-ui-shell/common.type' -const Provider = ({ appConfig, children, persistKey = 'menu' }) => { +const Provider: React.FC = ({ + appConfig, + children, + persistKey = 'menu', +}) => { const { menu } = appConfig || {} const { initialAuthMenuOpen, @@ -21,7 +26,9 @@ const Provider = ({ appConfig, children, persistKey = 'menu' }) => { useWindowWatcher, } = menu - const savedState = JSON.parse(localStorage.getItem(persistKey)) + const pkString = localStorage.getItem(persistKey) + + const savedState = pkString !== null ? JSON.parse(pkString) : null const [menuStore, dispatch] = useReducer(reducer, { isAuthMenuOpen: initialAuthMenuOpen, @@ -34,28 +41,28 @@ const Provider = ({ appConfig, children, persistKey = 'menu' }) => { const props = { //setter - toggleThis(value, newValue = null) { - if (value === 'isAuthMenuOpen') { + toggleThis(value: togglerTypes, newValue: boolean | null = null) { + if (value === togglerTypes.isAuthMenuOpen) { dispatch( setIsAuthMenuOpen( newValue !== null ? newValue : !menuStore.isAuthMenuOpen ) ) - } else if (value === 'isMiniMode') { + } else if (value === togglerTypes.isMiniMode) { dispatch( setIsMiniMode(newValue !== null ? newValue : !menuStore.isMiniMode) ) - } else if (value === 'isMenuOpen') { + } else if (value === togglerTypes.isMenuOpen) { dispatch( setIsMenuOpen(newValue !== null ? newValue : !menuStore.isMenuOpen) ) - } else if (value === 'isMobileMenuOpen') { + } else if (value === togglerTypes.isMobileMenuOpen) { dispatch( setIsMobileMenuOpen( newValue !== null ? newValue : !menuStore.isMobileMenuOpen ) ) - } else if (value === 'isMiniSwitchVisibility') { + } else if (value === togglerTypes.isMiniSwitchVisibility) { dispatch( setIsMiniSwitchVisibility( newValue !== null ? newValue : !menuStore.isMiniSwitchVisibility @@ -82,12 +89,10 @@ const Provider = ({ appConfig, children, persistKey = 'menu' }) => { useEffect(() => { if (useWindowWatcher) { - if (!isDesktop) { - props.setMenuOpen(false) - props.setMiniMode(false) - } + props.toggleThis(togglerTypes.isMiniMode, false) + props.toggleThis(togglerTypes.isMenuOpen, isDesktop) } - }, [isDesktop, props, useWindowWatcher]) + }, [isDesktop, useWindowWatcher]) return ( = {}, + action: ReducerAction +) { const { type, payload } = action switch (type) { case types.SET_IS_AUTH_MENU_OPEN: - return { ...state, isAuthMenuOpen: payload} + return { ...state, isAuthMenuOpen: payload } case types.SET_IS_MINI_MODE: return { ...state, isMiniMode: payload } case types.SET_IS_MENU_OPEN: @@ -16,4 +25,4 @@ export default function reducer(state = {}, action) { default: return state } -} \ No newline at end of file +} diff --git a/packages/material-ui-shell/src/providers/Menu/store/types.jsx b/packages/material-ui-shell/src/providers/Menu/store/types.tsx similarity index 100% rename from packages/material-ui-shell/src/providers/Menu/store/types.jsx rename to packages/material-ui-shell/src/providers/Menu/store/types.tsx diff --git a/packages/material-ui-shell/src/providers/Theme/Context.jsx b/packages/material-ui-shell/src/providers/Theme/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/material-ui-shell/src/providers/Theme/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/material-ui-shell/src/providers/Theme/Context.tsx b/packages/material-ui-shell/src/providers/Theme/Context.tsx new file mode 100644 index 000000000..193c72b1d --- /dev/null +++ b/packages/material-ui-shell/src/providers/Theme/Context.tsx @@ -0,0 +1,35 @@ +import React from 'react' + +export interface ThemeContextType { + /** + * @description Changing theme id + * @param auth + */ + setThemeID: (val: string) => void + /** + * @description Toggle dark mode ro RTL in this theme + * @param mode - Parameter mode can be 'isRTL' or 'isDarkMode' and accordingly theme parameters will switch for that param + */ + toggleThisTheme: (mode: 'isRTL' | 'isDarkMode') => void + + /** + * @description Boolean value definig if dark mode is enabled + */ + isDarkMode: boolean + + /** + * @description Boolean value definig if RTL is enabled + */ + isRTL: boolean + + /** + * @description Id of theme + */ + themeID: string +} + +export const Context = React.createContext( + undefined +) + +export default Context diff --git a/packages/material-ui-shell/src/providers/Theme/Provider.jsx b/packages/material-ui-shell/src/providers/Theme/Provider.tsx similarity index 81% rename from packages/material-ui-shell/src/providers/Theme/Provider.jsx rename to packages/material-ui-shell/src/providers/Theme/Provider.tsx index 9eaceee53..6376c441c 100644 --- a/packages/material-ui-shell/src/providers/Theme/Provider.jsx +++ b/packages/material-ui-shell/src/providers/Theme/Provider.tsx @@ -1,7 +1,12 @@ import React, { useState, useEffect } from 'react' import Context from './Context' +import { IProviderProps } from '@ecronix/material-ui-shell/common.type' -const Provider = ({ children, persistKey = 'theme', appConfig }) => { +const Provider: React.FC = ({ + children, + persistKey = 'theme', + appConfig, +}) => { const { theme: themeConfig } = appConfig || {} const { defaultThemeID, defaultIsDarkMode, defaultIsRTL } = themeConfig || {} @@ -13,16 +18,16 @@ const Provider = ({ children, persistKey = 'theme', appConfig }) => { const isDarkModeKey = `${persistKey}:isDarkMode` const isRTLKey = `${persistKey}:isRTL` - const toggleThisTheme = (mode) => { + const persistThemeID = localStorage.getItem(themeIDKey) + const persistIsDarkMode = localStorage.getItem(isDarkModeKey) + const persistIsRTL = localStorage.getItem(isRTLKey) + + const toggleThisTheme = (mode: 'isRTL' | 'isDarkMode') => { if (mode === 'isRTL') setIsRTL(!isRTL) if (mode === 'isDarkMode') setIsDarkMode(!isDarkMode) } useEffect(() => { - const persistThemeID = localStorage.getItem(themeIDKey) - const persistIsDarkMode = localStorage.getItem(isDarkModeKey) - const persistIsRTL = localStorage.getItem(isRTLKey) - if (persistThemeID) { setThemeID(persistThemeID) } diff --git a/packages/material-ui-shell/src/providers/Theme/index.jsx b/packages/material-ui-shell/src/providers/Theme/index.jsx deleted file mode 100644 index 1ae6333bd..000000000 --- a/packages/material-ui-shell/src/providers/Theme/index.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { useContext } from 'react' -import Context from './Context' -import Provider from './Provider' - -function useTheme() { - return useContext(Context) -} - -export { useTheme, Context as ThemeContext, Provider as ThemeProvider } diff --git a/packages/material-ui-shell/src/providers/Theme/index.tsx b/packages/material-ui-shell/src/providers/Theme/index.tsx new file mode 100644 index 000000000..326bf0129 --- /dev/null +++ b/packages/material-ui-shell/src/providers/Theme/index.tsx @@ -0,0 +1,27 @@ +import { useContext } from 'react' +import Context, { ThemeContextType } from './Context' +import Provider from './Provider' + +/** + * Custom hook to access the theme context. + * + * @function + * @returns {ThemeContextType} The theme context value. + * @throws {Error} If used outside of an ThemeProvider. + * @example + * const theme = useTheme() + * + * @description Gives you access to theme context. Theme context provides you with set of methods and properties that define + * look of the App. + * Default values are provided in application configuration file. + */ +function useTheme(): ThemeContextType { + const context = useContext(Context) + + if (context === undefined) { + throw new Error('useTheme must be used within a ThemeProvider') + } + return context +} + +export { useTheme, Context as ThemeContext, Provider as ThemeProvider } diff --git a/packages/material-ui-shell/src/providers/VirtualLists/Context.jsx b/packages/material-ui-shell/src/providers/VirtualLists/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/material-ui-shell/src/providers/VirtualLists/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/material-ui-shell/src/providers/VirtualLists/Context.tsx b/packages/material-ui-shell/src/providers/VirtualLists/Context.tsx new file mode 100644 index 000000000..2c334d8a2 --- /dev/null +++ b/packages/material-ui-shell/src/providers/VirtualLists/Context.tsx @@ -0,0 +1,21 @@ +import React from 'react' + +export interface VirtualListsContextType { + /** + * @description Set offset for provided name to provided value + * @param name + * @param offset + */ + setOffset: (name: string, offset: any) => void + /** + * @description Toggle dark mode ro RTL in this theme + * @param name - Get offset by name + */ + getOffset: (name: string) => void +} + +export const Context = React.createContext( + undefined +) + +export default Context diff --git a/packages/material-ui-shell/src/providers/VirtualLists/Provider.jsx b/packages/material-ui-shell/src/providers/VirtualLists/Provider.tsx similarity index 59% rename from packages/material-ui-shell/src/providers/VirtualLists/Provider.jsx rename to packages/material-ui-shell/src/providers/VirtualLists/Provider.tsx index ae3d85d1d..dcebbaa25 100644 --- a/packages/material-ui-shell/src/providers/VirtualLists/Provider.jsx +++ b/packages/material-ui-shell/src/providers/VirtualLists/Provider.tsx @@ -1,7 +1,14 @@ import React, { useReducer } from 'react' import Context from './Context' +import { IProviderProps } from '@ecronix/material-ui-shell/common.type' -function reducer(state, action) { +type ReducerAction = { + type: string + name: string + offset: any +} + +function reducer(state: any, action: ReducerAction) { const { type, name, offset } = action switch (type) { case 'SET_OFFSET': @@ -11,14 +18,14 @@ function reducer(state, action) { } } -const Provider = ({ children }) => { +const Provider: React.FC = ({ children }) => { const [state, dispatch] = useReducer(reducer, {}) - const setOffset = (name, offset) => { + const setOffset = (name: string, offset: any) => { dispatch({ type: 'SET_OFFSET', name, offset }) } - const getOffset = (name) => { + const getOffset = (name: string) => { return state[name] || 0 } diff --git a/packages/material-ui-shell/src/providers/VirtualLists/index.jsx b/packages/material-ui-shell/src/providers/VirtualLists/index.jsx deleted file mode 100644 index f7e41f050..000000000 --- a/packages/material-ui-shell/src/providers/VirtualLists/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from 'react' -import Context from './Context' -import Provider from './Provider' - -function useVirtualLists() { - return useContext(Context) -} - -export { - useVirtualLists, - Context as VirtualListsContext, - Provider as VirtualListsProvider, -} diff --git a/packages/material-ui-shell/src/providers/VirtualLists/index.tsx b/packages/material-ui-shell/src/providers/VirtualLists/index.tsx new file mode 100644 index 000000000..a362aa2b9 --- /dev/null +++ b/packages/material-ui-shell/src/providers/VirtualLists/index.tsx @@ -0,0 +1,37 @@ +import { useContext } from 'react' +import Context, { VirtualListsContextType } from './Context' +import Provider from './Provider' + +/** + * Custom hook to access virtual lists. + * + * @function + * @returns {VirtualListsContextType} Virtual list context value. + * @throws {Error} If used outside of an VirtualListsProvider. + * @example + * const { getOffset, setOffset } = useVirtualLists() + * + * @description + * This hook provides access to the virtual lists context. It must be used withgin VirutalListsProvider. + * It provides methods for setting and getting offset by name: + * - setOffset + * - getOffset + * + * @see {VirtualListsContextType} for methods reference + */ +function useVirtualLists(): VirtualListsContextType { + const context = useContext(Context) + + if (context === undefined) { + throw new Error( + 'useVirtualLists must be used within a VirtualListsProvider' + ) + } + return context +} + +export { + useVirtualLists, + Context as VirtualListsContext, + Provider as VirtualListsProvider, +} diff --git a/packages/material-ui-shell/src/providers/index.js b/packages/material-ui-shell/src/providers/index.ts similarity index 75% rename from packages/material-ui-shell/src/providers/index.js rename to packages/material-ui-shell/src/providers/index.ts index 945bfa707..3d5eb364a 100644 --- a/packages/material-ui-shell/src/providers/index.js +++ b/packages/material-ui-shell/src/providers/index.ts @@ -3,3 +3,4 @@ export * from './Theme' export * from './Menu' export * from './Dialogs/Question' export * from './Filter' +export { togglerTypes } from './Menu/Context' diff --git a/packages/material-ui-shell/src/utils/index.js b/packages/material-ui-shell/src/utils/index.ts similarity index 78% rename from packages/material-ui-shell/src/utils/index.js rename to packages/material-ui-shell/src/utils/index.ts index 584cf694a..9a76ee176 100644 --- a/packages/material-ui-shell/src/utils/index.js +++ b/packages/material-ui-shell/src/utils/index.ts @@ -1,6 +1,12 @@ import { createTheme } from '@mui/material/styles' +import { ThemeType } from '../common.type' -export const getThemeSource = (id, ts, isDarkMode, isRTL) => { +export const getThemeSource = ( + id: string, + ts: ThemeType[], + isDarkMode: boolean, + isRTL: boolean +) => { if (ts) { for (let i = 0; i < ts.length; i++) { if (ts[i]['id'] === id) { diff --git a/packages/material-ui-shell/vite.config.js b/packages/material-ui-shell/vite.config.ts similarity index 100% rename from packages/material-ui-shell/vite.config.js rename to packages/material-ui-shell/vite.config.ts diff --git a/packages/rmw-shell/create-rmw-shell/template/src/config/menuItems.jsx b/packages/rmw-shell/create-rmw-shell/template/src/config/menuItems.jsx index e0fd73bdb..af6c39c99 100644 --- a/packages/rmw-shell/create-rmw-shell/template/src/config/menuItems.jsx +++ b/packages/rmw-shell/create-rmw-shell/template/src/config/menuItems.jsx @@ -44,8 +44,8 @@ const getMenuItems = (props) => { const { isAppInstallable, isAppInstalled, deferredPrompt } = a2HSContext || {}; - const { auth } = authData || {}; - const { isAuthGranted = () => false, isAdmin = false } = auth || {}; + const { auth, isAuthGranted = () => false } = authData || {}; + const { isAdmin = false } = auth || {}; const localeItems = allLocales.map((l) => { return { @@ -332,7 +332,7 @@ const getMenuItems = (props) => { visible: true, onClick: () => { toggleThisTheme("isRTL"); - window.location.reload(false); + // window.location.reload(false); }, primaryText: `${isRTL ? "LTR" : "RTL"} mode`, leftIcon: isRTL ? : , diff --git a/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Companies/Company.jsx b/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Companies/Company.jsx index 59035edaa..c7ac12bd4 100644 --- a/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Companies/Company.jsx +++ b/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Companies/Company.jsx @@ -16,7 +16,7 @@ export default function CompanyPage() { { + getPageProps={(_values) => { return { pageTitle: intl.formatMessage({ id: path, diff --git a/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Tasks/Task.jsx b/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Tasks/Task.jsx index 5a1931b6e..bc4bc58db 100644 --- a/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Tasks/Task.jsx +++ b/packages/rmw-shell/create-rmw-shell/template/src/pages/Demo/Tasks/Task.jsx @@ -36,7 +36,7 @@ export default function TaskPage() { console.log("parse values", values); return { ...values, due_to: moment(due_to).format() }; }} - getPageProps={(values) => { + getPageProps={(_values) => { return { pageTitle: intl.formatMessage({ id: path, diff --git a/packages/rmw-shell/package.json b/packages/rmw-shell/package.json index c89198143..84da81d83 100644 --- a/packages/rmw-shell/package.json +++ b/packages/rmw-shell/package.json @@ -72,6 +72,9 @@ "@mui/material": "^6.1.4", "@mui/styles": "^6.1.4", "@mui/x-date-pickers": "^7.20.0", + "@types/react": "^18.3.12", + "@types/react-helmet": "^6.1.11", + "@types/react-linkify": "^1.0.4", "@vitejs/plugin-react": "^4.3.2", "chart.js": "^4.4.5", "cypress": "^13.15.0", diff --git a/packages/rmw-shell/src/components/ChatMessage/index.jsx b/packages/rmw-shell/src/components/ChatMessage/index.tsx similarity index 91% rename from packages/rmw-shell/src/components/ChatMessage/index.jsx rename to packages/rmw-shell/src/components/ChatMessage/index.tsx index dd43128e6..ec7d34144 100644 --- a/packages/rmw-shell/src/components/ChatMessage/index.jsx +++ b/packages/rmw-shell/src/components/ChatMessage/index.tsx @@ -17,9 +17,9 @@ import { ImageViewerContainer } from "@ecronix/rmw-shell"; import Linkify from "react-linkify"; import { getDatabase, ref, update, set } from "firebase/database"; -const getMapLoc = (loc) => { - let lat = 0; - let lng = 0; +const getMapLoc = (loc: string) => { + let lat: string | null = null; + let lng: string | null = null; if (loc) { const data = loc.split("@") ? loc.split("@")[1] : false; @@ -32,13 +32,21 @@ const getMapLoc = (loc) => { return { lat, lng }; }; +type ChatMessageProps = { + message: any; + path: string; + uid: string; + userChanged: boolean; + dateChanged: boolean; + scrollToBottom: any; // TODO Check it is passed in container/chat but it is not used - probably should remove +}; export function ChatMessage({ message: data, path, uid, userChanged = false, dateChanged = false, -}) { +}: ChatMessageProps) { const navigate = useNavigate(); const theme = useTheme(); const { auth } = useAuth(); @@ -64,7 +72,7 @@ export function ChatMessage({ const open = Boolean(anchorEl); const db = getDatabase(); - const handleClick = (event) => { + const handleClick = (event: any) => { setAnchorEl(event.currentTarget); }; @@ -77,7 +85,7 @@ export function ChatMessage({ useEffect(() => { if (authorUid && auth.uid !== authorUid && !isRead) { const db = getDatabase(); - const updates = {}; + const updates: { [key: string]: boolean | null } = {}; updates[`${path}/${uid}`] = true; updates[`user_chats/${auth.uid}/${authorUid}/unread`] = null; @@ -175,7 +183,7 @@ export function ChatMessage({ key={"delete"} onClick={async () => { handleClose(); - await set(ref(db), `${path}/${uid}`, null); + await set(ref(db), `${path}/${uid}`); }} > {intl.formatMessage({ @@ -221,7 +229,12 @@ export function ChatMessage({ )}
{type === "text" && ( + // Even properties exist in documentation examples + // http://tasti.github.io/react-linkify/ + // It does not exist in Class and it doesn't work + // @ts-ignore - React.createElement( - AutocompleteWrapper, - Object.assign({}, fieldRenderProps, rest) - ), - }, - fieldProps - ) - ) -} -function AutocompleteWrapper(props) { - const { - input: { name, onChange, value }, - meta, - options, - label, - required, - multiple, - textFieldProps, - getOptionValue, - getOptionSelected, - showError = showErrorOnChange, - placeholder, - onChange: onChangeCallback, - ...rest - } = props - - function getValue(values) { - if (!getOptionValue) { - return values - } - // ternary hell... - return multiple - ? values - ? values.map(getOptionValue) - : null - : values - ? getOptionValue(values) - : null - } - const { helperText, ...lessrest } = rest - const { variant, ...restTextFieldProps } = textFieldProps || {} - - // yuck... - let defaultValue = null - if (!getOptionValue) { - defaultValue = value - } else if (value) { - options.forEach((option) => { - const optionValue = getOptionValue(option) - if (multiple) { - if (!defaultValue) { - defaultValue = [] - } - value.forEach((v) => { - if (getOptionSelected(optionValue, v)) { - defaultValue.push(option) - } - }) - } else { - if (getOptionSelected(optionValue, value)) { - defaultValue = option - } - } - }) - } - - //defaultValue = getValue(value) - - const onChangeFunc = (event, value, reason, details) => { - const gotValue = getValue(value) - onChange(gotValue) - if (onChangeCallback) { - onChangeCallback(event, value, reason, details) - } - } - const { error, submitError } = meta - const isError = showError({ meta }) - - return React.createElement( - MuiAutocomplete, - Object.assign( - { - multiple: multiple, - onChange: onChangeFunc, - options: options, - value: defaultValue, - renderInput: (params) => - React.createElement( - TextField, - Object.assign( - { - label: label, - required: required, - helperText: isError ? error || submitError : helperText, - error: isError, - name: name, - placeholder: placeholder, - variant: variant, - }, - params, - restTextFieldProps, - { fullWidth: true, value } - ) - ), - }, - lessrest - ) - ) -} diff --git a/packages/rmw-shell/src/components/FormFields/Autocomplete.tsx b/packages/rmw-shell/src/components/FormFields/Autocomplete.tsx new file mode 100644 index 000000000..dfc2f5751 --- /dev/null +++ b/packages/rmw-shell/src/components/FormFields/Autocomplete.tsx @@ -0,0 +1,161 @@ +/* +*SOURCE: https://github.com/lookfirst/mui-rff/blob/master/src/Autocomplete.tsx +This should be removed and the native one used ASAP this issues is fixed: https://github.com/lookfirst/mui-rff/issues/308 +*/ + +import TextField, { TextFieldProps } from "@mui/material/TextField"; +import { + AutocompleteChangeDetails, + Autocomplete as MuiAutocomplete, +} from "@mui/material"; +import React from "react"; +import { Field, FieldInputProps, FieldMetaState } from "react-final-form"; +import { showErrorOnChange } from "./Util"; + +type AutocompleteProps = { + name: string; + fieldProps: any; + input: FieldInputProps; + meta: FieldMetaState; + options: string[]; + label: string; + // [key: string]: any; +}; +export function Autocomplete(props: AutocompleteProps) { + const { name, fieldProps, ...rest } = props; + return React.createElement( + Field, + Object.assign( + { + name: name, + render: (fieldRenderProps: AutocompleteProps) => + React.createElement( + AutocompleteWrapper, + Object.assign({}, fieldRenderProps, rest) + ), + }, + fieldProps + ) + ); +} +type AutocompleteWrapperProps = { + input: FieldInputProps; + meta: FieldMetaState; + options: string[]; + label: string; + required?: boolean; + multiple?: boolean; + textFieldProps?: TextFieldProps; + getOptionValue?: (option: string) => string; + getOptionSelected?: (option: string, value: string) => boolean; + showError?: (meta: FieldMetaState) => boolean; + placeholder?: string; + onChangeCallback?: (value: any) => void; + [key: string]: any; +}; +function AutocompleteWrapper(props: AutocompleteWrapperProps) { + const { + input: { name, onChange, value }, + meta, + options, + label, + required, + multiple, + textFieldProps, + getOptionValue, + getOptionSelected, + showError = showErrorOnChange, + placeholder, + onChange: onChangeCallback, + ...rest + } = props; + + function getValue(values: any) { + if (!getOptionValue) { + return values; + } + // ternary hell... + return multiple + ? values + ? values.map(getOptionValue) + : null + : values + ? getOptionValue(values) + : null; + } + const { helperText, ...lessrest } = rest; + const { variant, ...restTextFieldProps } = textFieldProps || {}; + + // yuck... + // Value is any by docs https://mui.com/material-ui/api/autocomplete/ + let defaultValue: null | any[] | any = null; + if (!getOptionValue) { + defaultValue = value; + } else if (value) { + options.forEach((option) => { + const optionValue = getOptionValue(option); + if (multiple) { + if (!defaultValue) { + defaultValue = []; + } + value.forEach((v: any) => { + if (getOptionSelected?.(optionValue, v)) { + defaultValue?.push(option); + } + }); + } else { + if (getOptionSelected?.(optionValue, value)) { + defaultValue = option; + } + } + }); + } + + //defaultValue = getValue(value) + + const onChangeFunc = ( + event: React.SyntheticEvent, + value: any, + details?: string, + reason?: AutocompleteChangeDetails + ) => { + const gotValue = getValue(value); + onChange(gotValue); + if (onChangeCallback) { + onChangeCallback(event, value, reason, details); + } + }; + const { error, submitError } = meta; + const isError = showError({ meta }); + + return React.createElement( + MuiAutocomplete, + Object.assign( + { + multiple: multiple, + onChange: onChangeFunc, + options: options, + value: defaultValue, + renderInput: (params: TextFieldProps) => + React.createElement( + TextField, + Object.assign( + { + label: label, + required: required, + helperText: isError ? error || submitError : helperText, + error: isError, + name: name, + placeholder: placeholder, + variant: variant, + }, + params, + restTextFieldProps, + { fullWidth: true, value } + ) + ), + }, + lessrest + ) + ); +} diff --git a/packages/rmw-shell/src/components/FormFields/AvatarImage.jsx b/packages/rmw-shell/src/components/FormFields/AvatarImage.tsx similarity index 86% rename from packages/rmw-shell/src/components/FormFields/AvatarImage.jsx rename to packages/rmw-shell/src/components/FormFields/AvatarImage.tsx index 86d21bdd1..66444ba14 100644 --- a/packages/rmw-shell/src/components/FormFields/AvatarImage.jsx +++ b/packages/rmw-shell/src/components/FormFields/AvatarImage.tsx @@ -1,12 +1,18 @@ import React, { useState } from "react"; -import { Box, TextField as MuiTextField } from "@mui/material"; +import { Box } from "@mui/material"; import Fab from "@mui/material/Fab"; import Camera from "@mui/icons-material/CameraAlt"; import { Field } from "react-final-form"; import Avatar from "@mui/material/Avatar"; import { ImageUploadDialogContainer } from "@ecronix/rmw-shell"; -export function AvatarImage(props) { +type AvatarImageProps = { + name: string; + type: string; + fieldProps: any; + path: string; +}; +export function AvatarImage(props: AvatarImageProps) { const [isImageDialogOpen, setImageDialogOpen] = useState(false); const { name, type, fieldProps, path, ...rest } = props; @@ -16,7 +22,7 @@ export function AvatarImage(props) { type={type} render={({ input, meta }) => { const { value, onChange } = input; - const handleImageChange = (image) => { + const handleImageChange = (image: string) => { onChange(image); }; return ( diff --git a/packages/rmw-shell/src/components/FormFields/DatePicker.jsx b/packages/rmw-shell/src/components/FormFields/DatePicker.jsx deleted file mode 100644 index 59355ee8a..000000000 --- a/packages/rmw-shell/src/components/FormFields/DatePicker.jsx +++ /dev/null @@ -1,68 +0,0 @@ -import React from "react"; -import { DesktopDatePicker } from "@mui/x-date-pickers"; -import { TextField } from "@mui/material"; -import { showErrorOnChange } from "./Util"; -import { Field } from "react-final-form"; - -export function DatePicker(props) { - const { name, type, fieldProps, ...rest } = props; - - return ( - ( - - )} - {...fieldProps} - /> - ); -} - -export function DatePickerWrapper(props) { - const { - input: { name, value, type, onChange, onBlur, onFocus, ...restInput }, - formatValue = (v) => { - if (v && v.isValid()) { - return v.format(); - } else { - return null; //v?._i - } - }, - meta, - required, - fullWidth = true, - helperText, - showError = showErrorOnChange, - ...rest - } = props; - - const { error, submitError } = meta; - const isError = showError({ meta }); - - return ( - { - onChange(formatValue(v)); - }} - onBlur={onBlur} - onFocus={onFocus} - name={name} - value={value} - type={type} - required={required} - inputProps={{ required, ...restInput }} - renderInput={(params) => } - {...rest} - /> - ); -} diff --git a/packages/rmw-shell/src/components/FormFields/DatePicker.tsx b/packages/rmw-shell/src/components/FormFields/DatePicker.tsx new file mode 100644 index 000000000..005a5b02b --- /dev/null +++ b/packages/rmw-shell/src/components/FormFields/DatePicker.tsx @@ -0,0 +1,91 @@ +import React from "react"; +import { DesktopDatePicker, DesktopDatePickerProps } from "@mui/x-date-pickers"; +import { showErrorOnChange } from "./Util"; +import { Field, FieldInputProps, FieldMetaState } from "react-final-form"; +import { Moment } from "moment"; + +type DatePickerProps = { + input: FieldInputProps; + meta: FieldMetaState; + formatValue?: (value: Moment | null) => string | null; + fullWidth: boolean; + helperText?: React.ReactNode; + showError?: (meta: any) => boolean; + required?: boolean; + [key: string]: any; +}; + +export function DatePicker(props: DatePickerProps) { + const { name, type, fieldProps, ...rest } = props; + + return ( + ( + + )} + {...fieldProps} + /> + ); +} + +type DatePickerWrapperProps = DesktopDatePickerProps & { + input: FieldInputProps; + meta: FieldMetaState; + formatValue?: (value: Moment | null) => string | null; + fullWidth?: boolean; + helperText?: React.ReactNode; + showError?: (meta: any) => boolean; + required?: boolean; + name?: string; + type?: string; +}; + +export function DatePickerWrapper(props: DatePickerWrapperProps) { + const { + input: { name, value, type, onChange, onBlur, onFocus, ...restInput }, + formatValue = (v) => { + if (v && v.isValid()) { + return v.format(); + } else { + return null; //v?._i + } + }, + meta, + required, + fullWidth = true, + helperText, + showError = showErrorOnChange, + ...rest + } = props; + + const { error, submitError } = meta; + const isError = showError({ meta }); + + return ( + { + onChange(formatValue(v)); + }} + // onBlur={onBlur} + // onFocus={onFocus} + name={name} + value={value} + type={type} + // required={required} + // inputProps={{ required, ...restInput }} + // renderInput={(params: TextFieldProps) => } + {...rest} + /> + ); +} diff --git a/packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.jsx b/packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.tsx similarity index 52% rename from packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.jsx rename to packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.tsx index d1e439214..8dd8548f8 100644 --- a/packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.jsx +++ b/packages/rmw-shell/src/components/FormFields/KeyboardDatePicker.tsx @@ -1,17 +1,23 @@ import React from "react"; -import { DatePicker } from "@mui/x-date-pickers"; -import { Field } from "react-final-form"; -import { showErrorOnChange } from "./Util"; -import TextField from "@mui/material/TextField"; +import { DatePicker, DatePickerProps } from "@mui/x-date-pickers"; +import { Field, FieldRenderProps } from "react-final-form"; +import { ErrorMetaType, showErrorOnChange } from "./Util"; +import TextField, { TextFieldProps } from "@mui/material/TextField"; +import { Moment } from "moment"; -export function KeyboardDatePicker(props) { +type KeyboardDatePickerProps = { + name: string; + fieldProps?: any; +} & React.ComponentProps; + +export function KeyboardDatePicker(props: KeyboardDatePickerProps) { const { name, fieldProps, ...rest } = props; return React.createElement( Field, Object.assign( { name: name, - render: (fieldRenderProps) => + render: (fieldRenderProps: FieldRenderProps) => React.createElement( KeyboardDatePickerWrapper, Object.assign({}, fieldRenderProps, rest) @@ -21,10 +27,21 @@ export function KeyboardDatePicker(props) { ) ); } -function KeyboardDatePickerWrapper(props) { + +type KeyboardDatePickerWrapperProps = FieldRenderProps & { + formatValue?: (value: Moment | null) => string | null; + dateFunsUtils?: any; + locale?: string; + showError?: (meta: ErrorMetaType) => boolean; +} & Omit< + DatePickerProps, + "onChange" | "value" | "renderInput" + >; + +function KeyboardDatePickerWrapper(props: KeyboardDatePickerWrapperProps) { const { input: { name, onChange, value, ...restInput }, - formatValue = (v) => { + formatValue = (v: Moment | null) => { if (v && v.isValid()) { return v.format(); } else { @@ -51,13 +68,13 @@ function KeyboardDatePickerWrapper(props) { autoOk: true, helperText: isError ? error || submitError : helperText, error: isError, - onChange: (v) => { + onChange: (v: Moment | null) => { onChange(formatValue(v)); }, name: name, value: value === "" ? null : value, inputProps: restInput, - renderInput: (params) => , + renderInput: (params: TextFieldProps) => , }, lessrest ) diff --git a/packages/rmw-shell/src/components/FormFields/TextField.jsx b/packages/rmw-shell/src/components/FormFields/TextField.jsx deleted file mode 100644 index be9c79607..000000000 --- a/packages/rmw-shell/src/components/FormFields/TextField.jsx +++ /dev/null @@ -1,75 +0,0 @@ -import React from 'react' -//import { TextField as SourceField } from 'mui-rff' -import { TextField as MuiTextField } from '@mui/material' -import { showErrorOnChange } from './Util' -import { Field } from 'react-final-form' - -/* -const identity = (value) => value - -const TextField = ({ fieldProps, ...rest }) => { - return ( - - ) -} - -export { TextField } -export default TextField -*/ - -export function TextField(props) { - const { name, type, fieldProps, ...rest } = props - - return ( - ( - - )} - {...fieldProps} - /> - ) -} - -export function TextFieldWrapper(props) { - const { - input: { name, value, type, onChange, onBlur, onFocus, ...restInput }, - meta, - required, - fullWidth = true, - helperText, - showError = showErrorOnChange, - ...rest - } = props - - const { error, submitError } = meta - const isError = showError({ meta }) - - return ( - - ) -} diff --git a/packages/rmw-shell/src/components/FormFields/TextField.tsx b/packages/rmw-shell/src/components/FormFields/TextField.tsx new file mode 100644 index 000000000..e829a2b57 --- /dev/null +++ b/packages/rmw-shell/src/components/FormFields/TextField.tsx @@ -0,0 +1,98 @@ +import React from "react"; +import { TextField as MuiTextField } from "@mui/material"; +import { ErrorMetaType, showErrorOnChange } from "./Util"; +import { + Field, + FieldInputProps, + FieldMetaState, + FieldProps, + FieldRenderProps, +} from "react-final-form"; +import { TextFieldProps } from "mui-rff"; +import { TEXT_FIELD_TYPE } from "mui-rff/dist/TextField"; + +/* +const identity = (value) => value + +const TextField = ({ fieldProps, ...rest }) => { + return ( + + ) +} + +export { TextField } +export default TextField +*/ + +type TextFieldType = { + name: string; + type?: TEXT_FIELD_TYPE; + fieldProps?: FieldProps; +} & Omit; + +export function TextField(props: TextFieldType) { + const { name, type, fieldProps, ...rest } = props; + + return ( + ( + + )} + {...fieldProps} + /> + ); +} + +type TextFieldWrapperType = FieldRenderProps & { + input: FieldInputProps; + meta: FieldMetaState; + required?: boolean; + fullWidth?: boolean; + helperText?: React.ReactNode; + showError?: (meta: ErrorMetaType) => boolean; +} & Omit; + +export function TextFieldWrapper(props: TextFieldWrapperType) { + const { + input: { name, value, type, onChange, onBlur, onFocus, ...restInput }, + meta, + required, + fullWidth = true, + helperText, + showError = showErrorOnChange, + ...rest + } = props; + + const { error, submitError } = meta; + const isError = showError({ meta }); + + return ( + + ); +} diff --git a/packages/rmw-shell/src/components/FormFields/Util.jsx b/packages/rmw-shell/src/components/FormFields/Util.tsx similarity index 50% rename from packages/rmw-shell/src/components/FormFields/Util.jsx rename to packages/rmw-shell/src/components/FormFields/Util.tsx index 1c5b80495..c2fe81288 100644 --- a/packages/rmw-shell/src/components/FormFields/Util.jsx +++ b/packages/rmw-shell/src/components/FormFields/Util.tsx @@ -1,26 +1,37 @@ -import React from 'react' -import { FormHelperText } from '@mui/material' -import { useField } from 'react-final-form' +import React, { Attributes } from "react"; +import { FormHelperText } from "@mui/material"; +import { FieldMetaState, useField } from "react-final-form"; + +type ErrorMessageProps = { + showError: boolean; + meta: { error: string; submitError: string }; + formHelperTextProps: Attributes; + helperText: string; +}; + +export type ErrorMetaType = { + meta: FieldMetaState; +}; export function ErrorMessage({ showError, meta, formHelperTextProps, helperText, -}) { +}: ErrorMessageProps) { if (showError) { return React.createElement( FormHelperText, Object.assign({}, formHelperTextProps), meta.error || meta.submitError - ) + ); } else if (!!helperText) { return React.createElement( FormHelperText, Object.assign({}, formHelperTextProps), helperText - ) + ); } else { - return React.createElement(React.Fragment, null) + return React.createElement(React.Fragment, null); } } const config = { @@ -31,13 +42,17 @@ const config = { touched: true, modified: true, }, -} -export const useFieldForErrors = (name) => useField(name, config) +}; +export const useFieldForErrors = (name: string) => useField(name, config); export const showErrorOnChange = ({ meta: { submitError, dirtySinceLastSubmit, error, touched, modified }, -}) => - !!(((submitError && !dirtySinceLastSubmit) || error) && (touched || modified)) +}: ErrorMetaType) => + !!( + ((submitError && !dirtySinceLastSubmit) || error) && + (touched || modified) + ); export const showErrorOnBlur = ({ meta: { submitError, dirtySinceLastSubmit, error, touched }, -}) => !!(((submitError && !dirtySinceLastSubmit) || error) && touched) +}: ErrorMetaType) => + !!(((submitError && !dirtySinceLastSubmit) || error) && touched); diff --git a/packages/rmw-shell/src/components/FormFields/index.jsx b/packages/rmw-shell/src/components/FormFields/index.tsx similarity index 100% rename from packages/rmw-shell/src/components/FormFields/index.jsx rename to packages/rmw-shell/src/components/FormFields/index.tsx diff --git a/packages/rmw-shell/src/components/Forms/Role.jsx b/packages/rmw-shell/src/components/Forms/Role.tsx similarity index 90% rename from packages/rmw-shell/src/components/Forms/Role.jsx rename to packages/rmw-shell/src/components/Forms/Role.tsx index 8bb1ed065..30e32f49d 100644 --- a/packages/rmw-shell/src/components/Forms/Role.jsx +++ b/packages/rmw-shell/src/components/Forms/Role.tsx @@ -1,7 +1,7 @@ import React from "react"; import { TextField } from "mui-rff"; -export function FormsRole({ handleSubmit }) { +export function FormsRole({ handleSubmit }: { handleSubmit: () => void }) { return (
{ +const FacebookIcon = (props: any) => { return ( { v99.803H182.409z" /> - ) -} + ); +}; -export default FacebookIcon +export default FacebookIcon; diff --git a/packages/rmw-shell/src/components/Icons/GitHubIcon.jsx b/packages/rmw-shell/src/components/Icons/GitHubIcon.tsx similarity index 77% rename from packages/rmw-shell/src/components/Icons/GitHubIcon.jsx rename to packages/rmw-shell/src/components/Icons/GitHubIcon.tsx index cca40dc89..75f6029dd 100644 --- a/packages/rmw-shell/src/components/Icons/GitHubIcon.jsx +++ b/packages/rmw-shell/src/components/Icons/GitHubIcon.tsx @@ -1,16 +1,16 @@ -import React from 'react' -import SvgIcon from '@mui/material/SvgIcon' +import React from "react"; +import SvgIcon from "@mui/material/SvgIcon"; -const GitHubIcon = (props) => { +const GitHubIcon = (props: any) => { return ( - ) -} + ); +}; -export default GitHubIcon +export default GitHubIcon; diff --git a/packages/rmw-shell/src/components/Icons/GoogleIcon.jsx b/packages/rmw-shell/src/components/Icons/GoogleIcon.tsx similarity index 68% rename from packages/rmw-shell/src/components/Icons/GoogleIcon.jsx rename to packages/rmw-shell/src/components/Icons/GoogleIcon.tsx index 818f1daaa..a5551b0d4 100644 --- a/packages/rmw-shell/src/components/Icons/GoogleIcon.jsx +++ b/packages/rmw-shell/src/components/Icons/GoogleIcon.tsx @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@mui/material/SvgIcon' +import React from "react"; +import SvgIcon from "@mui/material/SvgIcon"; -const GoogleIcon = (props) => { +const GoogleIcon = (props: any) => { return ( - ) -} + ); +}; -export default GoogleIcon +export default GoogleIcon; diff --git a/packages/rmw-shell/src/components/Icons/RMWIcon.jsx b/packages/rmw-shell/src/components/Icons/RMWIcon.tsx similarity index 97% rename from packages/rmw-shell/src/components/Icons/RMWIcon.jsx rename to packages/rmw-shell/src/components/Icons/RMWIcon.tsx index f46fa99fc..063e81f63 100644 --- a/packages/rmw-shell/src/components/Icons/RMWIcon.jsx +++ b/packages/rmw-shell/src/components/Icons/RMWIcon.tsx @@ -1,7 +1,7 @@ -import React from 'react' -import SvgIcon from '@mui/material/SvgIcon' +import React from "react"; +import SvgIcon from "@mui/material/SvgIcon"; -const RMWIcon = (props) => { +const RMWIcon = (props: any) => { return ( { /> - ) -} + ); +}; -export default RMWIcon +export default RMWIcon; diff --git a/packages/rmw-shell/src/components/Icons/ReduxIcon.jsx b/packages/rmw-shell/src/components/Icons/ReduxIcon.tsx similarity index 70% rename from packages/rmw-shell/src/components/Icons/ReduxIcon.jsx rename to packages/rmw-shell/src/components/Icons/ReduxIcon.tsx index 2c318e9eb..27156abdb 100644 --- a/packages/rmw-shell/src/components/Icons/ReduxIcon.jsx +++ b/packages/rmw-shell/src/components/Icons/ReduxIcon.tsx @@ -1,26 +1,26 @@ -import React from 'react' -import SvgIcon from '@mui/material/SvgIcon' +import React from "react"; +import SvgIcon from "@mui/material/SvgIcon"; -const GitHubIcon = (props) => { +const GitHubIcon = (props: any) => { return ( - ) -} + ); +}; -export default GitHubIcon +export default GitHubIcon; diff --git a/packages/rmw-shell/src/components/Icons/TwitterIcon.jsx b/packages/rmw-shell/src/components/Icons/TwitterIcon.tsx similarity index 86% rename from packages/rmw-shell/src/components/Icons/TwitterIcon.jsx rename to packages/rmw-shell/src/components/Icons/TwitterIcon.tsx index 1cb7c7d59..dd8297fc9 100644 --- a/packages/rmw-shell/src/components/Icons/TwitterIcon.jsx +++ b/packages/rmw-shell/src/components/Icons/TwitterIcon.tsx @@ -1,12 +1,12 @@ -import React from 'react' -import SvgIcon from '@mui/material/SvgIcon' +import React from "react"; +import SvgIcon from "@mui/material/SvgIcon"; -const TwitterIcon = (props) => { +const TwitterIcon = (props: any) => { return ( - ) -} + ); +}; -export default TwitterIcon +export default TwitterIcon; diff --git a/packages/rmw-shell/src/components/Icons/index.jsx b/packages/rmw-shell/src/components/Icons/index.tsx similarity index 100% rename from packages/rmw-shell/src/components/Icons/index.jsx rename to packages/rmw-shell/src/components/Icons/index.tsx diff --git a/packages/rmw-shell/src/components/SnackMessage/index.jsx b/packages/rmw-shell/src/components/SnackMessage/index.jsx deleted file mode 100644 index 35ae8d054..000000000 --- a/packages/rmw-shell/src/components/SnackMessage/index.jsx +++ /dev/null @@ -1,89 +0,0 @@ -import React from "react"; -import { makeStyles } from "@mui/styles"; -import { useSnackbar, SnackbarContent } from "notistack"; -import CloseIcon from "@mui/icons-material/Close"; - -import { Avatar, CardMedia, IconButton, Card, CardHeader } from "@mui/material"; - -import Notifications from "@mui/icons-material/Notifications"; -import { useNavigate } from "react-router-dom"; -import { ThemeProvider } from "@mui/styles"; -import { createTheme } from "@mui/material/styles"; -import { useTheme as useAppTheme } from "@ecronix/material-ui-shell"; - -const useStyles = makeStyles((theme) => ({ - root: { - [theme.breakpoints.up("sm")]: { - minWidth: "344px !important", - }, - maxWidth: 400, - cursor: "pointer", - }, - card: { - width: "100%", - }, -})); - -export const SnackMessage = React.forwardRef((props, ref) => { - const classes = useStyles(); - const navigate = useNavigate(); - const { closeSnackbar } = useSnackbar(); - const { payload, id } = props; - const { notification } = payload; - const { title, body, icon, image, click_action } = notification || {}; - - // const theme = useTheme() - // const type = theme.palette.type === 'light' ? 'dark' : 'light' - const { isDarkMode } = useAppTheme(); - - const innerTheme = createTheme({ - palette: { - type: isDarkMode ? "light" : "dark", - }, - }); - - const handleDismiss = () => { - closeSnackbar(id); - }; - - const handleClick = () => { - const url = new URL(click_action); - navigate(url.pathname); - handleDismiss(); - }; - - return ( - - - - {image && ( - - )} - - - - } - action={ - - - - } - title={
{title}
} - subheader={
{body}
} - /> -
-
-
- ); -}); diff --git a/packages/rmw-shell/src/components/SnackMessage/index.tsx b/packages/rmw-shell/src/components/SnackMessage/index.tsx new file mode 100644 index 000000000..f8a4065d6 --- /dev/null +++ b/packages/rmw-shell/src/components/SnackMessage/index.tsx @@ -0,0 +1,97 @@ +import React from "react"; +import { makeStyles } from "@mui/styles"; +import { useSnackbar, SnackbarContent, SnackbarKey } from "notistack"; +import CloseIcon from "@mui/icons-material/Close"; + +import { Avatar, CardMedia, IconButton, Card, CardHeader } from "@mui/material"; + +import Notifications from "@mui/icons-material/Notifications"; +import { useNavigate } from "react-router-dom"; +import { ThemeProvider } from "@mui/styles"; +import { createTheme } from "@mui/material/styles"; +import { useTheme as useAppTheme } from "@ecronix/material-ui-shell"; + +const useStyles = makeStyles((theme) => ({ + root: { + [theme.breakpoints.up("sm")]: { + minWidth: "344px !important", + }, + maxWidth: 400, + cursor: "pointer", + }, + + card: { + width: "100%", + }, + expand: {}, +})); + +export const SnackMessage = React.forwardRef( + ( + props: { payload: any; id: SnackbarKey }, + ref: React.LegacyRef | undefined + ) => { + const classes = useStyles(); + const navigate = useNavigate(); + const { closeSnackbar } = useSnackbar(); + const { payload, id } = props; + const { notification } = payload; + const { title, body, icon, image, click_action } = notification || {}; + + // const theme = useTheme() + // const type = theme.palette.type === 'light' ? 'dark' : 'light' + const { isDarkMode } = useAppTheme(); + + const innerTheme = createTheme({ + palette: { + // type: isDarkMode ? "light" : "dark", + mode: isDarkMode ? "light" : "dark", + }, + }); + + const handleDismiss = () => { + closeSnackbar(id); + }; + + const handleClick = () => { + const url = new URL(click_action); + navigate(url.pathname); + handleDismiss(); + }; + + return ( + + + + {image && ( + + )} + + + + } + action={ + + + + } + title={
{title}
} + subheader={
{body}
} + /> +
+
+
+ ); + } +); diff --git a/packages/rmw-shell/src/components/UserRow/index.jsx b/packages/rmw-shell/src/components/UserRow/index.tsx similarity index 84% rename from packages/rmw-shell/src/components/UserRow/index.jsx rename to packages/rmw-shell/src/components/UserRow/index.tsx index 2ce46349b..fd5890711 100644 --- a/packages/rmw-shell/src/components/UserRow/index.jsx +++ b/packages/rmw-shell/src/components/UserRow/index.tsx @@ -15,9 +15,11 @@ import { import Badge from "@mui/material/Badge"; import ListItemSecondaryAction from "@mui/material/ListItemSecondaryAction"; import Checkbox from "@mui/material/Checkbox"; +import { SvgIconProps } from "@mui/material"; +import { AuthUser } from "@ecronix/base-shell/dist/types/providers/Auth/Context"; -const getProviderIcon = (id) => { - const iconProps = { +const getProviderIcon = (id: string) => { + const iconProps: SvgIconProps = { color: "primary", style: { height: 20, @@ -41,6 +43,21 @@ const getProviderIcon = (id) => { return ; }; +export type UserRowData = AuthUser & { + key: string; + icon: string; + secondaryText: string; +}; + +type UserRowProps = { + data: UserRowData; + index?: number; + style?: Object; + admins: any[]; + isChecked?: boolean; + handleRowClick: (data: UserRowData) => void; + hasCheckbox?: boolean; +}; export const UserRow = ({ data, index, @@ -49,7 +66,7 @@ export const UserRow = ({ isChecked = false, handleRowClick = () => {}, hasCheckbox = false, -}) => { +}: UserRowProps) => { const { displayName = "", key, @@ -71,7 +88,7 @@ export const UserRow = ({ return (
handleRowClick(data)} diff --git a/packages/rmw-shell/src/components/index.js b/packages/rmw-shell/src/components/index.ts similarity index 100% rename from packages/rmw-shell/src/components/index.js rename to packages/rmw-shell/src/components/index.ts diff --git a/packages/rmw-shell/src/containers/AuthUI/index.jsx b/packages/rmw-shell/src/containers/AuthUI/index.tsx similarity index 84% rename from packages/rmw-shell/src/containers/AuthUI/index.jsx rename to packages/rmw-shell/src/containers/AuthUI/index.tsx index b1abd1041..5dd221cad 100644 --- a/packages/rmw-shell/src/containers/AuthUI/index.jsx +++ b/packages/rmw-shell/src/containers/AuthUI/index.tsx @@ -3,10 +3,14 @@ import { useIntl } from "react-intl"; import * as firebaseui from "firebaseui"; import { getAuth } from "firebase/auth"; -let authUi = null; +let authUi: firebaseui.auth.AuthUI | null = null; /*eslint-disable */ -export function AuthUIContainer({ uiConfig }) { +export function AuthUIContainer({ + uiConfig, +}: { + uiConfig: firebaseui.auth.Config | null; +}) { if (!uiConfig) { return null; } @@ -28,7 +32,7 @@ export function AuthUIContainer({ uiConfig }) { } try { - authUi.start("#firebaseui-auth", uiConfig); + authUi?.start("#firebaseui-auth", uiConfig); } catch (error) { console.warn(error); } diff --git a/packages/rmw-shell/src/containers/Chat/Input.jsx b/packages/rmw-shell/src/containers/Chat/Input.tsx similarity index 92% rename from packages/rmw-shell/src/containers/Chat/Input.jsx rename to packages/rmw-shell/src/containers/Chat/Input.tsx index 41334ca4b..57d60c15e 100644 --- a/packages/rmw-shell/src/containers/Chat/Input.jsx +++ b/packages/rmw-shell/src/containers/Chat/Input.tsx @@ -26,7 +26,7 @@ import { } from "firebase/storage"; import { getApp } from "firebase/app"; -export function InputContainer({ path }) { +export function InputContainer({ path }: { path: string }) { const theme = useTheme(); const intl = useIntl(); const { auth } = useAuth(); @@ -34,12 +34,12 @@ export function InputContainer({ path }) { const [isUploading, setUploading] = useState(false); const db = getDatabase(); - const uploadSelectedFile = (file) => { + const uploadSelectedFile = (file: File) => { if (file === null) { return; } - if ((file.size / 1024 / 1024).toFixed(4) > 20) { + if (+(file.size / 1024 / 1024).toFixed(4) > 20) { //file larger than 10mb alert(intl.formatMessage({ id: "max_file_size" })); return; @@ -55,10 +55,10 @@ export function InputContainer({ path }) { const snap = await uploadString( storageRef( getStorage(getApp()), - `/user_chats/${auth.uid}/${r.key}.jpg`, + `/user_chats/${auth.uid}/${r.key}.jpg` ), - fileData.target.result, - "data_url", + fileData.target!.result!.toString(), + "data_url" ); const downloadURL = await getDownloadURL(snap.ref); @@ -74,7 +74,7 @@ export function InputContainer({ path }) { reader.readAsDataURL(file); }; - const sendMessage = async (props) => { + const sendMessage = async (props: Record) => { let newMessage = { created: serverTimestamp(), authorName: auth.displayName, @@ -123,7 +123,7 @@ export function InputContainer({ path }) { color: "black", }} multiline - rowsMax="2" + // rowsMax="2" disableUnderline={true} fullWidth={true} autoFocus @@ -149,7 +149,7 @@ export function InputContainer({ path }) { id="icon-button-file" type="file" onChange={(e) => { - uploadSelectedFile(e.target.files[0]); + uploadSelectedFile(e.target.files![0]); }} />
(null); const alias = `${path}_${size}`; const messages = getList(alias); @@ -42,7 +42,7 @@ export function ChatContainer({ path }) { let messagesRef = query( ref(getDatabase(), path), orderByKey(), - limitToLast(size), + limitToLast(size) ); watchList(messagesRef, alias); @@ -94,7 +94,7 @@ export function ChatContainer({ path }) { //backgroundColor: theme.palette.background.default, width: "100%", }} - renderView={(props) => ( + renderView={(props: any) => (
)} > @@ -157,7 +157,7 @@ export function ChatContainer({ path }) { path={path} userChanged={userChanged} dateChanged={dateChanged} - scrollToBottom={scrollToBottom} + scrollToBottom={scrollToBottom} // TODO Check it is passed to ChatMessage but it is not used - probably should remove /> ); })} @@ -174,7 +174,7 @@ export function ChatContainer({ path }) {
- +
); diff --git a/packages/rmw-shell/src/containers/Firebase/From.jsx b/packages/rmw-shell/src/containers/Firebase/From.tsx similarity index 69% rename from packages/rmw-shell/src/containers/Firebase/From.jsx rename to packages/rmw-shell/src/containers/Firebase/From.tsx index 00ec9fdea..31a306193 100644 --- a/packages/rmw-shell/src/containers/Firebase/From.jsx +++ b/packages/rmw-shell/src/containers/Firebase/From.tsx @@ -3,8 +3,20 @@ import { Form as FinalForm } from "react-final-form"; import { useFirebasePaths } from "@ecronix/rmw-shell"; import { useAuth } from "@ecronix/base-shell"; import arrayMutators from "final-form-arrays"; -import { getDatabase, ref, push, set, update } from "firebase/database"; +import { getDatabase, ref, push, set } from "firebase/database"; +type FirebaseFromContainerProps = { + uid: string; + path: string; + handleSubmit?: (values: any, id: string) => void; + Form?: any; + grants?: any; + formProps?: any; + initialValues?: any; + parseValues?: (v: string) => string; + setSubmit: (v: (e: any) => void) => void; + submit?: ((e: any) => void) | null; +}; export function FirebaseFromContainer({ uid, path = "none", @@ -16,10 +28,9 @@ export function FirebaseFromContainer({ parseValues = (v) => v, setSubmit, ...rest -}) { +}: FirebaseFromContainerProps) { const { watchPath, clearPath, getPath } = useFirebasePaths(); - const { auth } = useAuth(); - const { isAuthGranted = () => false } = auth || {}; + const { auth, isAuthGranted = () => false } = useAuth(); const databasePath = `${path}/${uid}`; const data = getPath(databasePath) || initialValues; @@ -36,7 +47,7 @@ export function FirebaseFromContainer({ mutators={{ ...arrayMutators }} keepDirtyOnReinitialize onSubmit={async (rawValues) => { - let newUid = false; + let newUid: string | null = null; let values = rawValues; if (parseValues) { values = parseValues(values); @@ -55,11 +66,12 @@ export function FirebaseFromContainer({ } } - handleSubmit(values, newUid); + handleSubmit(values, newUid!); }} initialValues={data} - render={({ handleSubmit, submit, ...r }) => { - if (!submit && setSubmit) { + // TODO submit -> submitting check if its working + render={({ handleSubmit, submitting, ...r }) => { + if (!submitting && setSubmit) { setSubmit(() => handleSubmit); } diff --git a/packages/rmw-shell/src/containers/Firebase/index.jsx b/packages/rmw-shell/src/containers/Firebase/index.tsx similarity index 88% rename from packages/rmw-shell/src/containers/Firebase/index.jsx rename to packages/rmw-shell/src/containers/Firebase/index.tsx index 22ecc0e0f..b57c546ac 100644 --- a/packages/rmw-shell/src/containers/Firebase/index.jsx +++ b/packages/rmw-shell/src/containers/Firebase/index.tsx @@ -1,5 +1,5 @@ import React, { useEffect } from "react"; -import { useConfig, useAuth } from "@ecronix/base-shell"; +import { useConfig, useAuth, AppConfig } from "@ecronix/base-shell"; import { FirebasePathsProvider as PathsProvider, FirebaseListsProvider as ListsProvider, @@ -14,7 +14,7 @@ import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import { AdapterMoment as DateAdapter } from "@mui/x-date-pickers/AdapterMoment"; import { useLocale } from "@ecronix/base-shell"; -export function FirebaseContainer({ children }) { +export function FirebaseContainer({ children }: { children: React.ReactNode }) { const { appConfig } = useConfig(); const auth = useAuth(); const { firebase: firebaseConfig, auth: authConfig = {} } = appConfig || {}; @@ -24,13 +24,14 @@ export function FirebaseContainer({ children }) { if (getApps().length === 0) { initializeApp( - process.env.NODE_ENV !== "production" ? dev.initConfig : prod.initConfig, + process.env.NODE_ENV !== "production" ? dev.initConfig : prod.initConfig ); } useEffect(() => { const unsubscribe = onAuthStateChanged(getAuth(getApp()), (user) => { - if (onAuthStateChanged) { + if (onAuthStateChanged !== null) { + // TODO Check if works -> added !== null internalOnAuthStateChanged(user, auth); } }); diff --git a/packages/rmw-shell/src/containers/GrantsList/index.jsx b/packages/rmw-shell/src/containers/GrantsList/index.tsx similarity index 85% rename from packages/rmw-shell/src/containers/GrantsList/index.jsx rename to packages/rmw-shell/src/containers/GrantsList/index.tsx index e80e21fd8..4abffa19e 100644 --- a/packages/rmw-shell/src/containers/GrantsList/index.jsx +++ b/packages/rmw-shell/src/containers/GrantsList/index.tsx @@ -9,7 +9,7 @@ import { useConfig } from "@ecronix/base-shell"; import { useFirebaseLists } from "@ecronix/rmw-shell"; import { getDatabase, ref, set } from "firebase/database"; -export function GrantsListContainer({ grantsPath }) { +export function GrantsListContainer({ grantsPath }: { grantsPath: string }) { const { appConfig } = useConfig(); const { auth: authConfig } = appConfig || {}; const { grants = [] } = authConfig || {}; @@ -21,17 +21,25 @@ export function GrantsListContainer({ grantsPath }) { const list = getList( "grants", - grants.map((g) => { + grants.map((g: string) => { return { name: g }; }), - [{ name: "name" }], + [{ name: "name" }] ); useEffect(() => { watchList(grantsPath); }, [grantsPath, watchList]); - const Row = ({ index, style, data }) => { + const Row = ({ + index, + style, + data, + }: { + index: number; + style: Object; + data: any; + }) => { const { name } = data; let isSelected = false; @@ -47,12 +55,12 @@ export function GrantsListContainer({ grantsPath }) { return (
{ await set( ref(db, `${grantsPath}/${name}`), - isSelected ? null : true, + isSelected ? null : true ); }} > diff --git a/packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.tsx b/packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.tsx new file mode 100644 index 000000000..a1daceae8 --- /dev/null +++ b/packages/rmw-shell/src/containers/ImageUploadDialog/getCropImage.tsx @@ -0,0 +1,78 @@ +import { IPixelCrop } from "@ecronix/material-ui-shell"; + +const createImage = (url: string): Promise => + new Promise((resolve, reject) => { + const image = new Image(); + image.addEventListener("load", () => resolve(image)); + image.addEventListener("error", (error) => reject(error)); + image.setAttribute("crossOrigin", "anonymous"); // needed to avoid cross-origin issues on CodeSandbox + image.src = url; + }); + +function getRadianAngle(degreeValue: number) { + return (degreeValue * Math.PI) / 180; +} + +/** + * This function was adapted from the one in the ReadMe of https://github.com/DominicTobias/react-image-crop + * @param {File} image - Image File url + * @param {Object} pixelCrop - pixelCrop Object provided by react-easy-crop + * @param {number} rotation - optional rotation parameter + */ +export default async function getCroppedImg( + imageSrc: string, + pixelCrop: IPixelCrop, + rotation = 0 +) { + const image = await createImage(imageSrc); + const canvas = document.createElement("canvas"); + const ctx = canvas.getContext("2d"); + + const maxSize = Math.max(image.width, image.height); + const safeArea = 2 * ((maxSize / 2) * Math.sqrt(2)); + + // set each dimensions to double largest dimension to allow for a safe area for the + // image to rotate in without being clipped by canvas context + canvas.width = safeArea; + canvas.height = safeArea; + + if (!ctx) { + throw new Error("Canvas context is null"); + } + + // translate canvas context to a central location on image to allow rotating around the center. + ctx.translate(safeArea / 2, safeArea / 2); + ctx.rotate(getRadianAngle(rotation)); + ctx.translate(-safeArea / 2, -safeArea / 2); + + // draw rotated image and store data. + ctx.drawImage( + image, + safeArea / 2 - image.width * 0.5, + safeArea / 2 - image.height * 0.5 + ); + const data = ctx.getImageData(0, 0, safeArea, safeArea); + + // set canvas width to final desired crop size - this will clear existing context + canvas.width = pixelCrop.width; + canvas.height = pixelCrop.height; + + // paste generated rotate image with correct offsets for x,y crop values. + ctx.putImageData( + data, + 0 - safeArea / 2 + image.width * 0.5 - pixelCrop.x, + 0 - safeArea / 2 + image.height * 0.5 - pixelCrop.y + ); + + // As Base64 string + return canvas.toDataURL("image/jpeg"); + + // As a blob + /* + return new Promise((resolve) => { + canvas.toBlob((file) => { + resolve(URL.createObjectURL(file)) + }, 'image/jpeg') + }) + */ +} diff --git a/packages/rmw-shell/src/containers/ImageUploadDialog/index.jsx b/packages/rmw-shell/src/containers/ImageUploadDialog/index.tsx similarity index 84% rename from packages/rmw-shell/src/containers/ImageUploadDialog/index.jsx rename to packages/rmw-shell/src/containers/ImageUploadDialog/index.tsx index fa9548671..524163781 100644 --- a/packages/rmw-shell/src/containers/ImageUploadDialog/index.jsx +++ b/packages/rmw-shell/src/containers/ImageUploadDialog/index.tsx @@ -14,12 +14,16 @@ import useMediaQuery from "@mui/material/useMediaQuery"; import { useIntl } from "react-intl"; import { useFirebaseStorage } from "@ecronix/rmw-shell"; import { useTheme } from "@mui/material/styles"; +import { + IPixelCrop, + TransitionComponentProps, +} from "@ecronix/material-ui-shell"; -const Transition = React.forwardRef((props, ref) => ( - -)); +const Transition = React.forwardRef( + (props, ref) => +); -const getFiles = (ev) => { +const getFiles = (ev: React.DragEvent) => { const files = []; if (ev.dataTransfer.items) { // Use DataTransferItemList interface to access the file(s) @@ -39,39 +43,55 @@ const getFiles = (ev) => { return files; }; +type ImageUploadDialogContainerProps = { + isOpen: boolean; + handleClose: () => void; + handleCropSubmit: (image: string) => void; + path: string; + cropperProps?: any; +}; + export function ImageUploadDialogContainer({ isOpen = false, handleClose, handleCropSubmit, path, cropperProps, -}) { +}: ImageUploadDialogContainerProps) { const intl = useIntl(); const theme = useTheme(); const [isOver, setIsOver] = useState(false); - const [file, setFile] = useState(false); + const [file, setFile] = useState(null); const fullScreen = useMediaQuery(theme.breakpoints.down("sm")); - const [croppedImage, setCroppedImage] = useState(false); + const [croppedImage, setCroppedImage] = useState(null); const [crop, setCrop] = useState({ x: 0, y: 0 }); const [zoom, setZoom] = useState(1); - const [croppedAreaPixels, setCroppedAreaPixels] = useState(null); + const [croppedAreaPixels, setCroppedAreaPixels] = useState( + null + ); const { getUploadError, isUploading, hasUploadError, uploadString, clearUpload, + clearAllUploads, getUploadProgress, } = useFirebaseStorage(); - const onCropComplete = useCallback((croppedArea, croppedAreaPixels) => { - setCroppedAreaPixels(croppedAreaPixels); - }, []); + const onCropComplete = useCallback( + (_croppedArea: never, croppedAreaPixels: IPixelCrop) => { + setCroppedAreaPixels(croppedAreaPixels); + }, + [] + ); const clear = () => { - clearUpload(); - setCroppedImage(false); - setFile(false); + //TODO check - possibly call clearAllUploads + // clearUpload(); + clearAllUploads(); + setCroppedImage(null); + setFile(null); setCroppedAreaPixels(null); setIsOver(false); }; @@ -83,6 +103,9 @@ export function ImageUploadDialogContainer({ const showCroppedImage = useCallback(async () => { try { + if (!file || !croppedAreaPixels) { + throw new Error("Invalid parameters when showing cropped image"); + } const croppedImage = await getCroppedImg(file, croppedAreaPixels, 0); setCroppedImage(croppedImage); @@ -94,12 +117,12 @@ export function ImageUploadDialogContainer({ { contentType: "image/jpeg", }, - (downloadURL) => { + (downloadURL: string) => { if (handleCropSubmit) { handleClose(); handleCropSubmit(downloadURL); } - }, + } ); } catch (e) { console.error(e); @@ -137,10 +160,10 @@ export function ImageUploadDialogContainer({ var reader = new FileReader(); reader.onload = (e) => { - setFile(e.target.result); + setFile(e.target?.result as string); }; - reader.readAsDataURL(files[0]); + reader.readAsDataURL(files[0]!); } }} onDragOver={(e) => { @@ -180,7 +203,7 @@ export function ImageUploadDialogContainer({ var reader = new FileReader(); reader.onload = (e) => { - setFile(e.target.result); + setFile(e.target?.result as string); }; reader.readAsDataURL(e.target.files[0]); diff --git a/packages/rmw-shell/src/containers/ImageViewer/index.jsx b/packages/rmw-shell/src/containers/ImageViewer/index.tsx similarity index 78% rename from packages/rmw-shell/src/containers/ImageViewer/index.jsx rename to packages/rmw-shell/src/containers/ImageViewer/index.tsx index 239475444..6119996e1 100644 --- a/packages/rmw-shell/src/containers/ImageViewer/index.jsx +++ b/packages/rmw-shell/src/containers/ImageViewer/index.tsx @@ -6,7 +6,7 @@ import Fab from "@mui/material/Fab"; import CloseIcon from "@mui/icons-material/Close"; import Slide from "@mui/material/Slide"; -export function ImageViewerContainer({ src, ...rest }) { +export function ImageViewerContainer({ src, ...rest }: any) { const [open, setOpen] = useState(false); const handleOpen = () => { @@ -26,7 +26,7 @@ export function ImageViewerContainer({ src, ...rest }) { aria-describedby="transition-modal-description" open={open} onClose={handleClose} - onEscapeKeyDown={handleClose} + // onEscapeKeyDown={handleClose} closeAfterTransition BackdropComponent={Backdrop} BackdropProps={{ @@ -75,15 +75,26 @@ export function ImageViewerContainer({ src, ...rest }) { > {children} diff --git a/packages/rmw-shell/src/containers/Page/FormPage.jsx b/packages/rmw-shell/src/containers/Page/FormPage.tsx similarity index 68% rename from packages/rmw-shell/src/containers/Page/FormPage.jsx rename to packages/rmw-shell/src/containers/Page/FormPage.tsx index 58f412b19..388cb89a1 100644 --- a/packages/rmw-shell/src/containers/Page/FormPage.jsx +++ b/packages/rmw-shell/src/containers/Page/FormPage.tsx @@ -10,7 +10,23 @@ import { useAuth } from "@ecronix/base-shell"; import { FirebaseFromContainer } from "@ecronix/rmw-shell"; import { getDatabase, ref, set } from "firebase/database"; -export function FormPageContainer(props) { +type FormPageContainerProps = { + uid: string; + path: string; + getPageProps: (data: Object) => Record; + handleDelete: () => {}; + deleteDialogProps: Object; + grants: { + create?: string; + delete?: string; + }; // TODO Check because in config grants are string[] + initialValues: Object; + useSave: boolean; + useDelete: boolean; + alwaysAllowSave: boolean; + alwaysAllowDelete: boolean; +}; +export function FormPageContainer(props: FormPageContainerProps) { const { uid, path = "none", @@ -27,17 +43,16 @@ export function FormPageContainer(props) { const navigate = useNavigate(); const { openDialog } = useQuestionsDialog(); const { getPath } = useFirebasePaths(); - const { auth } = useAuth(); - const [submit, setSubmit] = useState(false); + const { auth, isAuthGranted = () => false } = useAuth(); + const [submit, setSubmit] = useState<((e: any) => void) | null>(null); const db = getDatabase(); - const { isAuthGranted = () => false } = auth || {}; const databasePath = `${path}/${uid}`; - const data = getPath(databasePath, {}) || initialValues; + const data = getPath(databasePath) || initialValues; const openDeleteDialog = () => { openDialog({ - handleAction: async (handleClose) => { + handleAction: async (handleClose: () => void) => { await set(ref(db, `${path}/${uid}`), null); handleClose(); handleDelete(); @@ -55,10 +70,12 @@ export function FormPageContainer(props) {
{useSave && ( { - submit(e); + submit?.(e); }} > @@ -69,7 +86,7 @@ export function FormPageContainer(props) { { diff --git a/packages/rmw-shell/src/containers/Page/ListPage.jsx b/packages/rmw-shell/src/containers/Page/ListPage.tsx similarity index 77% rename from packages/rmw-shell/src/containers/Page/ListPage.jsx rename to packages/rmw-shell/src/containers/Page/ListPage.tsx index 7b1ffd1b1..845d2e0d4 100644 --- a/packages/rmw-shell/src/containers/Page/ListPage.jsx +++ b/packages/rmw-shell/src/containers/Page/ListPage.tsx @@ -1,15 +1,29 @@ import Add from "@mui/icons-material/Add"; import Fab from "@mui/material/Fab"; -import { ListPage } from "@ecronix/material-ui-shell"; +import { ListPage, RowProps } from "@ecronix/material-ui-shell"; import React, { useEffect } from "react"; import { useAuth } from "@ecronix/base-shell"; import { useFirebaseLists } from "@ecronix/rmw-shell"; import useMediaQuery from "@mui/material/useMediaQuery"; +type ListPageContainerProps = { + fields: any[]; + path: string; + getRef: (() => React.Ref) | any; + Row: React.FC; + listProps?: Object; + getPageProps: (list: any[]) => any; + onCreateClick: () => void; + createGrant: string; + listPageProps: any[]; + reverse: boolean; + disableCreate: boolean; + fabLabel: boolean | null; +}; export function ListPageContainer({ fields = [], path = "none", - getRef = false, + getRef = null, Row, listProps = {}, getPageProps = () => {}, @@ -19,10 +33,9 @@ export function ListPageContainer({ reverse = false, disableCreate = false, fabLabel = null, -}) { +}: ListPageContainerProps) { const { watchList, getList, isListLoading, unwatchList } = useFirebaseLists(); - const { auth } = useAuth(); - const { isAuthGranted = () => false } = auth || {}; + const { auth, isAuthGranted = () => false } = useAuth(); const matches = useMediaQuery("(min-width:400px)"); useEffect(() => { diff --git a/packages/rmw-shell/src/containers/Page/MarkdownPage.jsx b/packages/rmw-shell/src/containers/Page/MarkdownPage.tsx similarity index 71% rename from packages/rmw-shell/src/containers/Page/MarkdownPage.jsx rename to packages/rmw-shell/src/containers/Page/MarkdownPage.tsx index 9eb016cc9..713b43606 100644 --- a/packages/rmw-shell/src/containers/Page/MarkdownPage.jsx +++ b/packages/rmw-shell/src/containers/Page/MarkdownPage.tsx @@ -2,15 +2,19 @@ import React, { useEffect, useState } from "react"; import ReactMarkdown from "react-markdown"; import { Scrollbar, Page } from "@ecronix/material-ui-shell"; -const loadData = async (path) => { +const loadData = async (path: string): Promise => { const data = await fetch(path); const text = await data.text(); return text; }; +type MarkdownProps = { + path: string; + pageProps: any; +}; // eslint-disable-next-lin -export function MarkdownPageContainer({ path, pageProps }) { - const [source, setSource] = useState(null); +export function MarkdownPageContainer({ path, pageProps }: MarkdownProps) { + const [source, setSource] = useState(null); useEffect(() => { loadData(path).then((text) => { diff --git a/packages/rmw-shell/src/containers/Page/index.jsx b/packages/rmw-shell/src/containers/Page/index.tsx similarity index 100% rename from packages/rmw-shell/src/containers/Page/index.jsx rename to packages/rmw-shell/src/containers/Page/index.tsx diff --git a/packages/rmw-shell/src/containers/ResponsiveMenu/index.jsx b/packages/rmw-shell/src/containers/ResponsiveMenu/index.tsx similarity index 86% rename from packages/rmw-shell/src/containers/ResponsiveMenu/index.jsx rename to packages/rmw-shell/src/containers/ResponsiveMenu/index.tsx index f737fcad2..2d7c36c50 100644 --- a/packages/rmw-shell/src/containers/ResponsiveMenu/index.jsx +++ b/packages/rmw-shell/src/containers/ResponsiveMenu/index.tsx @@ -11,7 +11,6 @@ import List from "@mui/material/List"; import ListItem from "@mui/material/ListItem"; import ListItemIcon from "@mui/material/ListItemIcon"; import ListItemText from "@mui/material/ListItemText"; -import { useTheme } from "@emotion/react"; import { styled } from "@mui/material/styles"; const DesktopDiv = styled("div")(({ theme }) => ({ @@ -28,18 +27,26 @@ const MobileDiv = styled("div")(({ theme }) => ({ }, })); +type ResponsiveMenuContainerProps = { + _scroll?: never; + sections: any[]; + _handleMenuClose?: never; + _statemobileMoreAnchorEl?: never; + transparent: boolean; + contrastColor: string; +}; export function ResponsiveMenuContainer({ - scroll, + _scroll, sections = [], - handleMenuClose, - statemobileMoreAnchorEl, + _handleMenuClose, + _statemobileMoreAnchorEl, transparent, contrastColor = "white", -}) { +}: ResponsiveMenuContainerProps) { const [isOpen, setOpen] = useState(false); - const theme = useTheme(); + // const theme = useTheme(); - const handleOpen = (e) => { + const handleOpen = () => { setOpen(true); }; @@ -59,7 +66,7 @@ export function ResponsiveMenuContainer({ flexItem style={{ margin: 5, - backgroundColor: transparent ? contrastColor : null, + backgroundColor: transparent ? contrastColor : undefined, }} /> ); @@ -92,7 +99,11 @@ export function ResponsiveMenuContainer({ - + @@ -105,7 +116,7 @@ export function ResponsiveMenuContainer({ } return ( { handleClose(); @@ -116,7 +127,7 @@ export function ResponsiveMenuContainer({ ); - }, + } )} diff --git a/packages/rmw-shell/src/containers/RolesList/index.jsx b/packages/rmw-shell/src/containers/RolesList/index.tsx similarity index 86% rename from packages/rmw-shell/src/containers/RolesList/index.jsx rename to packages/rmw-shell/src/containers/RolesList/index.tsx index 81e76e877..d1c235052 100644 --- a/packages/rmw-shell/src/containers/RolesList/index.jsx +++ b/packages/rmw-shell/src/containers/RolesList/index.tsx @@ -7,12 +7,16 @@ import { } from "@mui/material"; import React, { useEffect } from "react"; -import { VirtualListContainer, useFilter } from "@ecronix/material-ui-shell"; +import { + RowProps, + VirtualListContainer, + useFilter, +} from "@ecronix/material-ui-shell"; import { useFirebaseLists } from "@ecronix/rmw-shell"; import { getDatabase, ref, set } from "firebase/database"; // eslint-disable-next-line import/no-anonymous-default-export -export function RolesListContainer({ path }) { +export function RolesListContainer({ path }: { path: string }) { const { watchList, getList: getFirebaseList } = useFirebaseLists(); const { getList } = useFilter(); const db = getDatabase(); @@ -25,7 +29,7 @@ export function RolesListContainer({ path }) { roles.map((r) => { return { key: r.key, ...r.val }; }), - [{ name: "name" }], + [{ name: "name" }] ); useEffect(() => { @@ -34,7 +38,7 @@ export function RolesListContainer({ path }) { // eslint-disable-next-line react-hooks/exhaustive-deps }, [path, watchList]); - const Row = ({ index, style, data }) => { + const Row: React.FC = ({ index, style, data }: RowProps) => { const { key, name = "" } = data; let isSelected = false; @@ -50,7 +54,7 @@ export function RolesListContainer({ path }) { return (
{ await set(ref(db, `${path}/${key}`), isSelected ? null : true); diff --git a/packages/rmw-shell/src/containers/index.js b/packages/rmw-shell/src/containers/index.ts similarity index 100% rename from packages/rmw-shell/src/containers/index.js rename to packages/rmw-shell/src/containers/index.ts diff --git a/packages/rmw-shell/src/index.ts b/packages/rmw-shell/src/index.ts index f4be2e1d4..f5a9ac4ee 100644 --- a/packages/rmw-shell/src/index.ts +++ b/packages/rmw-shell/src/index.ts @@ -1,5 +1,11 @@ +import { Theme } from "@mui/material/styles"; + export * from "./providers"; export * from "./pages"; export * from "./utils"; export * from "./containers"; export * from "./components"; + +declare module "@mui/styles/defaultTheme" { + interface DefaultTheme extends Theme {} +} diff --git a/packages/rmw-shell/src/pages/Chats/index.jsx b/packages/rmw-shell/src/pages/Chats/index.tsx similarity index 97% rename from packages/rmw-shell/src/pages/Chats/index.jsx rename to packages/rmw-shell/src/pages/Chats/index.tsx index bf122619e..921565b26 100644 --- a/packages/rmw-shell/src/pages/Chats/index.jsx +++ b/packages/rmw-shell/src/pages/Chats/index.tsx @@ -15,6 +15,7 @@ import { VirtualListContainer, Page, useTheme as useAppTheme, + RowProps, } from "@ecronix/material-ui-shell"; import React, { useEffect } from "react"; import useMediaQuery from "@mui/material/useMediaQuery"; @@ -37,7 +38,7 @@ import ListItemIcon from "@mui/material/ListItemIcon"; import moment from "moment"; import { getDatabase, ref, set } from "firebase/database"; -const Row = ({ data, index, style }) => { +const Row: React.FC = ({ data, index, style }: RowProps) => { const navigate = useNavigate(); const intl = useIntl(); const { auth } = useAuth(); @@ -52,9 +53,8 @@ const Row = ({ data, index, style }) => { lastCreated = "", } = data; const [anchorEl, setAnchorEl] = React.useState(null); - const { uid = "" } = useParams(); - const handleClick = (event) => { + const handleClick = (event: any) => { setAnchorEl(event.currentTarget); }; @@ -76,8 +76,10 @@ const Row = ({ data, index, style }) => {
{/* james- revisit this code */} { @@ -93,7 +95,7 @@ const Row = ({ data, index, style }) => { { }} > {lastMessage} -
+ } /> @@ -258,7 +260,6 @@ export function ChatsPage() { ) */ } - return ( []>([]); const { getFilter } = useFilter(); const { search = {} } = getFilter("users"); const searchValue = search.value; @@ -32,7 +32,7 @@ export function CreateChatPage() { const ref = collection(db, "users"); const q = query( ref, - where("search", "array-contains", searchValue.toLowerCase() || ""), + where("search", "array-contains", searchValue.toLowerCase() || "") ); const snap = await getDocs(q); @@ -58,7 +58,7 @@ export function CreateChatPage() { setList(tempLlist); }, - [searchValue, intl], + [searchValue, intl] ); useEffect(() => { @@ -89,7 +89,7 @@ export function CreateChatPage() { const admins = getList("admins"); - const handleRowClick = async (user) => { + const handleRowClick = async (user: UserRowData & { isGroup?: boolean }) => { const { key, displayName, photoURL = "", isGroup } = user; if (isGroup) { diff --git a/packages/rmw-shell/src/pages/EditAdmins/index.jsx b/packages/rmw-shell/src/pages/EditAdmins/index.tsx similarity index 93% rename from packages/rmw-shell/src/pages/EditAdmins/index.jsx rename to packages/rmw-shell/src/pages/EditAdmins/index.tsx index f990c7da2..5273f7919 100644 --- a/packages/rmw-shell/src/pages/EditAdmins/index.jsx +++ b/packages/rmw-shell/src/pages/EditAdmins/index.tsx @@ -34,14 +34,15 @@ export function EditAdminsPage() { }) .filter((u) => u.key !== auth.uid); - const isChecked = (key) => { + const isChecked = (key: string) => { return members.find((m) => m.key === key); }; - const handleRowClick = async (user) => { + const handleRowClick = async (user: any) => { await set( + //@ts-ignore ref(db, groupAdminsPath).child(user.key), - isChecked(user.key) ? null : true, + isChecked(user.key) ? null : true ); }; diff --git a/packages/rmw-shell/src/pages/EditMembers/index.jsx b/packages/rmw-shell/src/pages/EditMembers/index.tsx similarity index 88% rename from packages/rmw-shell/src/pages/EditMembers/index.jsx rename to packages/rmw-shell/src/pages/EditMembers/index.tsx index f9297a7ad..f0bd32cdc 100644 --- a/packages/rmw-shell/src/pages/EditMembers/index.jsx +++ b/packages/rmw-shell/src/pages/EditMembers/index.tsx @@ -1,5 +1,5 @@ import React, { useEffect } from "react"; -import { useFirebaseLists } from "@ecronix/rmw-shell"; +import { useFirebaseLists, UserRowData } from "@ecronix/rmw-shell"; import { ListPage } from "@ecronix/material-ui-shell"; import { useIntl } from "react-intl"; import { useNavigate, useParams } from "react-router-dom"; @@ -34,14 +34,16 @@ export function EditMembersPage() { }) .filter((u) => u.key !== auth.uid); - const isChecked = (key) => { + const isChecked = (key: string) => { return members.find((m) => m.key === key); }; - const handleRowClick = async (user) => { + const handleRowClick = async (user: UserRowData) => { await set( + // TODO .child does not exist on ref() + // @ts-ignore ref(db, groupMembersPath).child(user.key), - isChecked(user.key) ? null : true, + isChecked(user.key) ? null : true ); }; diff --git a/packages/rmw-shell/src/pages/GroupChat/index.jsx b/packages/rmw-shell/src/pages/GroupChat/index.tsx similarity index 91% rename from packages/rmw-shell/src/pages/GroupChat/index.jsx rename to packages/rmw-shell/src/pages/GroupChat/index.tsx index 17961d941..90b808013 100644 --- a/packages/rmw-shell/src/pages/GroupChat/index.jsx +++ b/packages/rmw-shell/src/pages/GroupChat/index.tsx @@ -1,5 +1,9 @@ import React, { useEffect, useState } from "react"; -import { useFirebaseLists, useFirebasePaths } from "@ecronix/rmw-shell"; +import { + useFirebaseLists, + useFirebasePaths, + UserRowData, +} from "@ecronix/rmw-shell"; import { ListPage } from "@ecronix/material-ui-shell"; import { useIntl } from "react-intl"; import Fab from "@mui/material/Fab"; @@ -18,9 +22,9 @@ export function GroupChatPage() { const { auth } = useAuth(); const intl = useIntl(); const navigate = useNavigate(); - const { uid = false } = useParams(); - const [selected, setSelected] = useState({}); - const [step, setStep] = useState(uid !== false ? 1 : 0); + const { uid = null } = useParams(); + const [selected, setSelected] = useState>({}); + const [step, setStep] = useState(uid !== null ? 1 : 0); const db = getDatabase(); const { name: currentName = "" } = getPath(`group_chats/${uid}`, {}) || {}; const [name, setName] = useState(""); @@ -52,7 +56,7 @@ export function GroupChatPage() { }) .filter((u) => u.key !== auth.uid); - const handleRowClick = (user) => { + const handleRowClick = (user: UserRowData) => { const key = user.key; if (!selected[key]) { @@ -104,7 +108,8 @@ export function GroupChatPage() { admins={admins} handleRowClick={handleRowClick} hasCheckbox - isChecked={selected[p.data.key]} + // isChecked={selected?[p.data.key]} + isChecked={selected?.[p.data.key]} /> ); }} diff --git a/packages/rmw-shell/src/pages/MyAccount/index.jsx b/packages/rmw-shell/src/pages/MyAccount/index.tsx similarity index 92% rename from packages/rmw-shell/src/pages/MyAccount/index.jsx rename to packages/rmw-shell/src/pages/MyAccount/index.tsx index 93d795cfc..76a84d7ae 100644 --- a/packages/rmw-shell/src/pages/MyAccount/index.jsx +++ b/packages/rmw-shell/src/pages/MyAccount/index.tsx @@ -34,6 +34,8 @@ import { deleteUser, updateCurrentUser, reload, + Auth, + User, } from "firebase/auth"; import { getDatabase, set, remove, ref } from "firebase/database"; import { useFirebaseMessaging } from "@ecronix/rmw-shell"; @@ -69,11 +71,11 @@ export function MyAccountPage() { const hasChange = displayName !== currentDisplayName || photoURL !== currentPhoroURL; - const handleImageChange = (image) => { + const handleImageChange = (image: string) => { setPhotoURL(image); }; - const getProviderIcon = (id) => { + const getProviderIcon = (id: string) => { if (id === "google.com") { return ; } @@ -90,7 +92,7 @@ export function MyAccountPage() { return null; }; - const getProvider = (provider) => { + const getProvider = (provider: string) => { if (provider.indexOf("facebook") > -1) { return new FacebookAuthProvider(); } @@ -104,6 +106,8 @@ export function MyAccountPage() { return new TwitterAuthProvider(); } if (provider.indexOf("phone") > -1) { + //@ts-ignore + // TODO provide auth return new PhoneAuthProvider(); } @@ -111,13 +115,13 @@ export function MyAccountPage() { }; const handleSave = async () => { - updateProfile(getAuth().currentUser, { displayName, photoURL }); + updateProfile(getAuth().currentUser as User, { displayName, photoURL }); updateAuth({ ...auth, displayName, photoURL }); await updateCurrentUser(getAuth(), getAuth().currentUser); - await reload(getAuth().currentUser); + await reload(getAuth().currentUser as User); }; - const isLinkedWithProvider = (provider) => { + const isLinkedWithProvider = (provider: string) => { try { return ( auth && @@ -131,16 +135,16 @@ export function MyAccountPage() { } }; - const linkUserWithPopup = (p) => { + const linkUserWithPopup = (p: string) => { const provider = getProvider(p); - linkWithPopup(getAuth().currentUser, provider).then( + linkWithPopup(getAuth().currentUser as User, provider).then( () => { updateAuth({ ...auth, ...getAuth().currentUser }); }, (e) => { console.warn(e); - }, + } ); }; @@ -178,17 +182,19 @@ export function MyAccountPage() { id: "reauthenticate_account_dialog_action", defaultMessage: "REAUTHENTICATE", }), - handleAction: (hc) => { + handleAction: (hc: () => void) => { + //@ts-ignore + // .signOut() doesn't exist on type User getAuth().currentUser.signOut(); hc(); }, }); }; - const handleDelete = async (handleClose) => { + const handleDelete = async (handleClose: () => void) => { try { - await deleteUser(getAuth().currentUser); - } catch ({ code }) { + await deleteUser(getAuth().currentUser as User); + } catch ({ code }: any) { if (code === "auth/requires-recent-login") { openReauthenticateDialog(); } @@ -310,7 +316,7 @@ export function MyAccountPage() { {email}
- {signInOptions.map((so) => { + {signInOptions.map((so: any) => { return getProviderIcon(so) ? ( false } = auth; + // TODO check since it was useQuestions() which is undefined + const { openDialog } = useQuestionsDialog(); + const { auth, isAuthGranted = () => false } = useAuth(); const { value: searchValue = "" } = search; - let submit; + let submit: (e: React.MouseEvent) => void; - const setSubmit = (s) => { + const setSubmit = (s: (e: any) => void) => { submit = s; }; @@ -42,7 +41,7 @@ export function RolePage() { const openDeleteDialog = () => { openDialog({ - handleAction: async (handleClose) => { + handleAction: async (handleClose: () => void) => { await set(ref(getDatabase(), `${path}/${uid}`), null); handleClose(); navigate(`/${path}`); @@ -142,7 +141,7 @@ export function RolePage() { > { if (newUid) { @@ -151,7 +150,8 @@ export function RolePage() { navigate(`/${path}`); } }} - Form={Form} + // TODO check - it was Form instead of FormsRole but was not imported from anywhere + Form={FormsRole} />
)} diff --git a/packages/rmw-shell/src/pages/Roles/index.jsx b/packages/rmw-shell/src/pages/Roles/index.tsx similarity index 75% rename from packages/rmw-shell/src/pages/Roles/index.jsx rename to packages/rmw-shell/src/pages/Roles/index.tsx index 8dfdf7fba..89676ec92 100644 --- a/packages/rmw-shell/src/pages/Roles/index.jsx +++ b/packages/rmw-shell/src/pages/Roles/index.tsx @@ -5,7 +5,7 @@ import ListItem from "@mui/material/ListItem"; import ListItemAvatar from "@mui/material/ListItemAvatar"; import ListItemText from "@mui/material/ListItemText"; import React from "react"; -import { ListPage } from "@ecronix/material-ui-shell"; +import { ListPage, RowProps } from "@ecronix/material-ui-shell"; import { useNavigate } from "react-router-dom"; import { useIntl } from "react-intl"; @@ -20,14 +20,15 @@ const fields = [ }, ]; -const Row = ({ data, index, style }) => { +const Row: React.FC = ({ data, index, style }) => { const { name = "", description = "", key } = data; const navigate = useNavigate(); return (
{ @@ -48,13 +49,15 @@ const Row = ({ data, index, style }) => { export function RolesPage() { const intl = useIntl(); - const navigate = useNavigate(); + // const navigate = useNavigate(); return ( + // TODO - check commented fields are not used in ListPage component { @@ -65,9 +68,9 @@ export function RolesPage() { }), }; }} - onCreateClick={() => { - navigate("/create_role"); - }} + // onCreateClick={() => { + // navigate("/create_role"); + // }} /> ); } diff --git a/packages/rmw-shell/src/pages/SignIn/index.jsx b/packages/rmw-shell/src/pages/SignIn/index.tsx similarity index 87% rename from packages/rmw-shell/src/pages/SignIn/index.jsx rename to packages/rmw-shell/src/pages/SignIn/index.tsx index ec48d84af..ad0f83e2d 100644 --- a/packages/rmw-shell/src/pages/SignIn/index.jsx +++ b/packages/rmw-shell/src/pages/SignIn/index.tsx @@ -1,12 +1,12 @@ import * as firebaseui from "firebaseui"; import { AuthUIContainer } from "@ecronix/rmw-shell"; -import { Page } from "@ecronix/material-ui-shell"; +import { Page, togglerTypes } from "@ecronix/material-ui-shell"; import React from "react"; import { Helmet } from "react-helmet"; import { useConfig } from "@ecronix/base-shell"; import { useIntl } from "react-intl"; import { useMenu } from "@ecronix/material-ui-shell"; -import { useNavigate, useLocation } from "react-router-dom"; +import { useLocation } from "react-router-dom"; export function SignInPage() { const intl = useIntl(); @@ -15,7 +15,6 @@ export function SignInPage() { const { redirectTo = "/" } = auth || {}; const { firebaseuiProps = {} } = firebase; const { toggleThis } = useMenu() || {}; - let navigate = useNavigate(); let location = useLocation(); let from = new URLSearchParams(location.search).get("from") || redirectTo; @@ -24,7 +23,7 @@ export function SignInPage() { signInFlow: "popup", callbacks: { signInSuccessWithAuthResult: () => { - toggleThis("isAuthMenuOpen", false); + toggleThis(togglerTypes.isAuthMenuOpen, false); // To avoid page reload on single page applications return false; }, @@ -35,6 +34,7 @@ export function SignInPage() { return ( + {/* @ts-ignore */} { + const getProviderIcon = (id: string) => { if (id === "password") { return ; } @@ -68,7 +68,7 @@ export function UserPage() { // eslint-disable-next-line react-hooks/exhaustive-deps }, [path]); - const user = getPath(path, {}); + const user = getPath(path); const admins = getList("admins"); const { @@ -182,7 +182,7 @@ export function UserPage() { alignItems: "center", }} > - {providerData.map((so) => { + {providerData.map((so: any) => { return getProviderIcon(so.providerId) ? ( {getProviderIcon(so.providerId)} @@ -198,7 +198,7 @@ export function UserPage() { try { set( ref(getDatabase(), `admins/${uid}`), - isAdmin ? null : true, + isAdmin ? null : true ); } catch (error) { console.warn(error); diff --git a/packages/rmw-shell/src/pages/Users/index.jsx b/packages/rmw-shell/src/pages/Users/index.tsx similarity index 91% rename from packages/rmw-shell/src/pages/Users/index.jsx rename to packages/rmw-shell/src/pages/Users/index.tsx index 06f03a6ea..b2efd96fd 100644 --- a/packages/rmw-shell/src/pages/Users/index.jsx +++ b/packages/rmw-shell/src/pages/Users/index.tsx @@ -23,7 +23,7 @@ export function UsersPage() { const { watchList, getList } = useFirebaseLists(); const intl = useIntl(); const navigate = useNavigate(); - const [list, setList] = useState([]); + const [list, setList] = useState([]); const [isLoading, setLoading] = useState(false); const { getFilter } = useFilter(); const { search = {} } = getFilter("users"); @@ -36,11 +36,11 @@ export function UsersPage() { const ref = collection(db, "users"); const q = query( ref, - where("search", "array-contains", searchValue.toLowerCase() || ""), + where("search", "array-contains", searchValue.toLowerCase() || "") ); const snap = await getDocs(q); - const tempLlist = []; + const tempLlist: any[] = []; snap.forEach((doc) => { tempLlist.push({ key: doc.id, ...doc.data() }); }); @@ -48,7 +48,7 @@ export function UsersPage() { setList(tempLlist); setLoading(false); }, - [searchValue], + [searchValue] ); useEffect(() => { @@ -65,7 +65,7 @@ export function UsersPage() { const admins = getList("admins"); - const handleRowClick = (data) => { + const handleRowClick = (data: any) => { console.log("data", data); navigate(`/users/${data.key}`); }; @@ -89,7 +89,7 @@ export function UsersPage() { id: "users_page", defaultMessage: "Users {count}", }, - { count: list.length }, + { count: list.length } ), isLoading, }; diff --git a/packages/rmw-shell/src/pages/index.js b/packages/rmw-shell/src/pages/index.ts similarity index 100% rename from packages/rmw-shell/src/pages/index.js rename to packages/rmw-shell/src/pages/index.ts diff --git a/packages/rmw-shell/src/providers/Firebase/Cols/Context.jsx b/packages/rmw-shell/src/providers/Firebase/Cols/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Cols/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/rmw-shell/src/providers/Firebase/Cols/Context.tsx b/packages/rmw-shell/src/providers/Firebase/Cols/Context.tsx new file mode 100644 index 000000000..ef0781924 --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Cols/Context.tsx @@ -0,0 +1,20 @@ +import { CollectionReference, DocumentData } from "firebase/firestore"; +import React from "react"; + +export type FirebaseColsContextType = { + watchCol: (reference: string, alias: string) => void; + unwatchCol: ( + reference: CollectionReference + ) => void; + getCol: (path: string) => void; + clearCol: (reference: string) => void; + clearAllCols: () => void; + isColLoading: (path: string) => boolean; + hasColError: (path: string) => void; + getColError: (path: string) => void; +}; +export const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/rmw-shell/src/providers/Firebase/Cols/Provider.jsx b/packages/rmw-shell/src/providers/Firebase/Cols/Provider.jsx deleted file mode 100644 index e044f7ea0..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Cols/Provider.jsx +++ /dev/null @@ -1,268 +0,0 @@ -/* eslint-disable default-case */ -import Context from './Context' -import React, { useCallback, useEffect, useReducer } from 'react' -import { collection, getFirestore, onSnapshot } from 'firebase/firestore' - -const LOADING_CHANGED = 'LOADING_CHANGED' -const ERROR = 'ERROR' -const VALUE_CHANGE = 'VALUE_CHANGED' -const CLEAR = 'CLEAR' -const CLEAR_ALL = 'CLEAR_ALL' -const CHILD_ADDED = 'CHILD_ADDED' -const CHILD_CHANGED = 'CHILD_CHANGED' -const CHILD_REMOVED = 'CHILD_REMOVED' - -function list(list = [], action) { - const { payload, type } = action - switch (type) { - case CHILD_ADDED: - return list.findIndex((d) => d.id === payload.id) === -1 - ? [...list, payload] - : [...list] - - case CHILD_CHANGED: - return list.map((child) => (payload.id === child.id ? payload : child)) - - case CHILD_REMOVED: - return list.filter((child) => payload.id !== child.id) - } -} - -function reducer(state, action) { - const { - type, - path, - value, - isLoading = false, - error = false, - hasError = false, - } = action - switch (type) { - case LOADING_CHANGED: - return { ...state, [path]: { ...state[path], isLoading } } - case ERROR: - return { - ...state, - [path]: { ...state[path], error, hasError, isLoading }, - } - case VALUE_CHANGE: - return { - ...state, - [path]: { ...state[path], value, isLoading, error, hasError }, - } - case CLEAR: - const { [path]: clearedKey, ...rest } = state - return { ...rest } - case CHILD_ADDED: - case CHILD_CHANGED: - case CHILD_REMOVED: - return { - ...state, - [path]: { - ...state[path], - - value: list(state[path].value, action), - }, - } - case CLEAR_ALL: - return {} - default: - throw new Error() - } -} - -function getInitState(persistKey) { - let persistedValues = {} - try { - persistedValues = JSON.parse(localStorage.getItem(persistKey)) || {} - } catch (error) { - console.warn(error) - } - return persistedValues -} - -const inits = {} - -const setInit = (path, unsub) => { - inits[path] = unsub -} - -const removeInit = (path) => { - inits[path] = false -} - -const getPath = (ref) => { - return ref.path -} - -const getLocation = (path) => { - if (typeof path === 'string' || path instanceof String) { - return path - } else { - return getPath(path) - } -} - -const unwatchCol = (reference) => { - const path = getLocation(reference) - inits[path] && inits[path]() - removeInit(path) -} - -const Provider = ({ children, persistKey = 'firebase_cols' }) => { - const [state, dispatch] = useReducer(reducer, getInitState(persistKey)) - const db = getFirestore() - - useEffect(() => { - try { - localStorage.setItem(persistKey, JSON.stringify(state)) - } catch (error) { - console.warn(error) - } - }, [state, persistKey]) - - const getRef = useCallback( - (path) => { - if (typeof path === 'string' || path instanceof String) { - return collection(db, path) - } else { - return path - } - }, - [db] - ) - - const watchCol = useCallback( - async (reference, alias) => { - const ref = getRef(reference) - const path = alias || getLocation(reference) - - if (path.length < 1) { - return - } - - if (inits[path]) { - // we skip multiple listeners - // only one should be active - return - } - - const handleError = (error) => { - dispatch({ - type: ERROR, - path, - isLoading: false, - error, - hasError: true, - }) - removeInit(path) - } - - const handleChange = (doc, type) => { - dispatch({ - type, - path, - payload: { id: doc.id, data: doc.data() }, - }) - } - - dispatch({ - type: LOADING_CHANGED, - path, - isLoading: true, - }) - - try { - const unsub = onSnapshot( - ref, - (snapshot) => { - setInit(path, unsub) - dispatch({ - type: LOADING_CHANGED, - path, - isLoading: false, - }) - - snapshot.docChanges().forEach((change) => { - if (change.type === 'added') { - handleChange(change.doc, CHILD_ADDED) - } - if (change.type === 'modified') { - handleChange(change.doc, CHILD_CHANGED) - } - if (change.type === 'removed') { - handleChange(change.doc, CHILD_REMOVED) - } - }) - }, - handleError - ) - } catch (error) { - handleError(error) - } - }, - [getRef] - ) - - const getCol = useCallback( - (path) => { - return state[path] && state[path].value ? state[path].value : [] - }, - [state] - ) - - const isColLoading = useCallback( - (path) => { - return state[path] ? state[path].isLoading : false - }, - [state] - ) - - const getColError = useCallback( - (path) => { - return state[path] ? state[path].error : false - }, - [state] - ) - - const hasColError = useCallback( - (path) => { - return state[path] ? state[path].hasError : false - }, - [state] - ) - - const clearCol = useCallback( - (reference) => { - const ref = getRef(reference) - const path = getLocation(reference) - - unwatchCol(ref) - dispatch({ type: CLEAR, path }) - }, - [getRef] - ) - - const clearAllCols = useCallback(() => { - dispatch({ type: CLEAR_ALL }) - }, []) - - return ( - - {children} - - ) -} - -export default Provider diff --git a/packages/rmw-shell/src/providers/Firebase/Cols/Provider.tsx b/packages/rmw-shell/src/providers/Firebase/Cols/Provider.tsx new file mode 100644 index 000000000..2e74bbda1 --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Cols/Provider.tsx @@ -0,0 +1,291 @@ +/* eslint-disable default-case */ +import Context from "./Context"; +import React, { useCallback, useEffect, useReducer } from "react"; +import { + collection, + CollectionReference, + DocumentData, + getFirestore, + onSnapshot, + QuerySnapshot, +} from "firebase/firestore"; +import { IProviderProps } from "@ecronix/material-ui-shell"; +import { ActionTypeBase } from "../.."; + +enum ActionTypes { + LOADING_CHANGED = "LOADING_CHANGED", + ERROR = "ERROR", + VALUE_CHANGE = "VALUE_CHANGED", + CLEAR = "CLEAR", + CLEAR_ALL = "CLEAR_ALL", + CHILD_ADDED = "CHILD_ADDED", + CHILD_CHANGED = "CHILD_CHANGED", + CHILD_REMOVED = "CHILD_REMOVED", +} + +type ActionType = ActionTypeBase & { + type: ActionTypes; +}; + +function list(list: DocumentData[] = [], action: ActionType) { + const { payload, type } = action; + switch (type) { + case ActionTypes.CHILD_ADDED: + return list.findIndex((d) => d.id === payload.id) === -1 + ? [...list, payload] + : [...list]; + + case ActionTypes.CHILD_CHANGED: + return list.map((child) => (payload.id === child.id ? payload : child)); + + case ActionTypes.CHILD_REMOVED: + return list.filter((child) => payload.id !== child.id); + } +} + +function reducer(state: DocumentData, action: ActionType) { + const { + type, + path, + value, + isLoading = false, + error = false, + hasError = false, + } = action; + switch (type) { + case ActionTypes.LOADING_CHANGED: + return { ...state, [path]: { ...state?.[path], isLoading } }; + case ActionTypes.ERROR: + return { + ...state, + [path]: { ...state[path], error, hasError, isLoading }, + }; + case ActionTypes.VALUE_CHANGE: + return { + ...state, + [path]: { ...state[path], value, isLoading, error, hasError }, + }; + case ActionTypes.CLEAR: + const { [path]: clearedKey, ...rest } = state; + return { ...rest }; + case ActionTypes.CHILD_ADDED: + case ActionTypes.CHILD_CHANGED: + case ActionTypes.CHILD_REMOVED: + return { + ...state, + [path]: { + ...state[path], + + value: list(state[path].value, action), + }, + }; + case ActionTypes.CLEAR_ALL: + return {}; + default: + throw new Error(); + } +} + +function getInitState(persistKey: string) { + let persistedValues = {}; + try { + const pkString = localStorage.getItem(persistKey); + persistedValues = pkString ? JSON.parse(pkString) : null; + } catch (error) { + console.warn(error); + } + return persistedValues; +} + +const inits: DocumentData = {}; + +const setInit = (path: string, unsub: any): void => { + inits[path] = unsub; +}; + +const removeInit = (path: string): void => { + inits[path] = false; +}; + +const getPath = (ref: any): string => { + return ref.path; +}; + +const getLocation = ( + path: string | CollectionReference +): string => { + if (typeof path === "string") { + return path; + } else { + return getPath(path); + } +}; + +const unwatchCol = ( + reference: CollectionReference +): void => { + const path = getLocation(reference); + inits[path] && inits[path](); + removeInit(path); +}; + +const Provider = ({ + children, + persistKey = "firebase_cols", +}: IProviderProps) => { + const [state, dispatch] = useReducer(reducer, getInitState(persistKey)); + const db = getFirestore(); + + useEffect(() => { + try { + localStorage.setItem(persistKey, JSON.stringify(state)); + } catch (error) { + console.warn(error); + } + }, [state, persistKey]); + + const getRef = useCallback( + (path: string) => { + if (typeof path === "string") { + return collection(db, path); + } else { + return path; + } + }, + [db] + ); + + const watchCol = useCallback( + async (reference: string, alias: string) => { + const ref = getRef(reference); + const path = alias || getLocation(reference); + + if (path.length < 1) { + return; + } + + if (inits[path]) { + // we skip multiple listeners + // only one should be active + return; + } + + const handleError = (error: Error): void => { + dispatch({ + type: ActionTypes.ERROR, + path, + isLoading: false, + error, + hasError: true, + }); + removeInit(path); + }; + + const handleChange = (doc: any, type: ActionTypes): void => { + dispatch({ + type, + payload: { id: doc.id, data: doc.data() }, + path: "", + }); + }; + + dispatch({ + type: ActionTypes.LOADING_CHANGED, + path, + isLoading: true, + }); + + try { + const unsub = onSnapshot( + ref, + (snapshot: QuerySnapshot) => { + setInit(path, unsub); + dispatch({ + type: ActionTypes.LOADING_CHANGED, + path, + isLoading: false, + }); + snapshot.docChanges().forEach((change) => { + if (change.type === "added") { + handleChange(change.doc, ActionTypes.CHILD_ADDED); + } + if (change.type === "modified") { + handleChange(change.doc, ActionTypes.CHILD_CHANGED); + } + if (change.type === "removed") { + handleChange(change.doc, ActionTypes.CHILD_REMOVED); + } + }); + }, + handleError + ); + } catch (error) { + handleError(error as Error); + } + }, + [getRef] + ); + + const getCol = useCallback( + (path: string) => { + return state[path] && state[path].value ? state[path].value : []; + }, + [state] + ); + + const isColLoading = useCallback( + (path: string) => { + return state[path] ? state[path].isLoading : false; + }, + [state] + ); + + const getColError = useCallback( + (path: string) => { + return state[path] ? state[path].error : false; + }, + [state] + ); + + const hasColError = useCallback( + (path: string) => { + return state[path] ? state[path].hasError : false; + }, + [state] + ); + + const clearCol = useCallback( + (reference: string) => { + const ref: CollectionReference = + getRef(reference); + const path = getLocation(reference); + + unwatchCol(ref); + dispatch({ type: ActionTypes.CLEAR, path }); + }, + [getRef] + ); + + const clearAllCols = useCallback(() => { + dispatch({ type: ActionTypes.CLEAR_ALL, path: "" }); + }, []); + + return ( + + {children} + + ); +}; + +export default Provider; diff --git a/packages/rmw-shell/src/providers/Firebase/Cols/index.jsx b/packages/rmw-shell/src/providers/Firebase/Cols/index.tsx similarity index 56% rename from packages/rmw-shell/src/providers/Firebase/Cols/index.jsx rename to packages/rmw-shell/src/providers/Firebase/Cols/index.tsx index d74d2f1b2..feaccb187 100644 --- a/packages/rmw-shell/src/providers/Firebase/Cols/index.jsx +++ b/packages/rmw-shell/src/providers/Firebase/Cols/index.tsx @@ -3,7 +3,14 @@ import Context from "./Context"; import Provider from "./Provider"; function useFirebaseCols() { - return useContext(Context); + const context = useContext(Context); + + if (context === undefined) { + throw new Error( + "useFirebaseCols must be used within a FirebaseColsContext" + ); + } + return context; } export { diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/Context.jsx b/packages/rmw-shell/src/providers/Firebase/Docs/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Docs/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/Context.tsx b/packages/rmw-shell/src/providers/Firebase/Docs/Context.tsx new file mode 100644 index 000000000..79a51389f --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Docs/Context.tsx @@ -0,0 +1,18 @@ +import { DocumentData } from "firebase/firestore"; +import React from "react"; + +export type DocsContextType = { + watchDoc: (reference: string | string[], alias: string) => void; + unwatchDoc: (reference: string) => void; + getDoc: (path: string, defaultValue: string | DocumentData) => void; + clearDoc: (reference: string) => void; + clearAllDocs: () => void; + isDocLoading: (path: string) => void; + hasDocError: (path: string) => void; + getDocError: (path: string) => void; +}; +export const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/Provider.jsx b/packages/rmw-shell/src/providers/Firebase/Docs/Provider.jsx deleted file mode 100644 index 06b097d8d..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Docs/Provider.jsx +++ /dev/null @@ -1,211 +0,0 @@ -import React, { useEffect, useReducer, useCallback } from 'react' -import Context from './Context' -import { doc, onSnapshot, getFirestore } from 'firebase/firestore' - -const LOADING_CHANGED = 'LOADING_CHANGED' -const ERROR = 'ERROR' -const VALUE_CHANGE = 'VALUE_CHANGED' -const CLEAR = 'CLEAR' -const CLEAR_ALL = 'CLEAR_ALL' - -function reducer(state, action) { - const { - type, - path, - value, - isLoading = false, - error = false, - hasError = false, - } = action - switch (type) { - case LOADING_CHANGED: - return { ...state, [path]: { ...state[path], isLoading } } - case ERROR: - return { - ...state, - [path]: { ...state[path], error, hasError, isLoading }, - } - case VALUE_CHANGE: - return { - ...state, - [path]: { ...state[path], value, isLoading, error, hasError }, - } - case CLEAR: - const { [path]: clearedKey, ...rest } = state - return { ...rest } - case CLEAR_ALL: - return {} - default: - throw new Error() - } -} - -function getInitState(persistKey) { - let persistedValues = {} - try { - persistedValues = JSON.parse(localStorage.getItem(persistKey)) || {} - } catch (error) { - console.warn(error) - } - return persistedValues -} - -const inits = {} - -const setInit = (path, unsub) => { - inits[path] = unsub -} - -const removeInit = (path) => { - inits[path] = false -} - -const Provider = ({ children, persistKey = 'firebase_docs' }) => { - const [state, dispatch] = useReducer(reducer, getInitState(persistKey)) - - useEffect(() => { - try { - localStorage.setItem(persistKey, JSON.stringify(state)) - } catch (error) { - console.warn(error) - } - }, [state, persistKey]) - - const getRef = useCallback((path) => { - const db = getFirestore() - if (typeof path === 'string' || path instanceof String) { - return doc(db, ...path.split('/')) - } else if (path instanceof Array) { - return doc(db, ...path) - } else { - return path - } - }, []) - - const getLocation = useCallback((path) => { - if (typeof path === 'string' || path instanceof String) { - return path - } else if (path instanceof Array) { - return path.join('/') - } else { - return doc(path).path - } - }, []) - - const watchDoc = useCallback( - (reference, alias) => { - const ref = getRef(reference) - const path = alias || getLocation(reference) - - if (path.length < 1) { - return - } - - if (inits[path]) { - return - } - - dispatch({ - type: LOADING_CHANGED, - path, - isLoading: true, - }) - - let unsub = onSnapshot( - ref, - (snapshot) => { - dispatch({ - type: VALUE_CHANGE, - path, - value: snapshot.data(), - isLoading: false, - }) - }, - (error) => { - dispatch({ - type: ERROR, - path, - isLoading: false, - error, - hasError: true, - }) - } - ) - setInit(path, unsub) - }, - [getLocation, getRef] - ) - - const unwatchDoc = useCallback( - (reference) => { - const path = getLocation(reference) - inits[path] && inits[path]() - removeInit(path) - }, - [getLocation] - ) - - const getDoc = useCallback( - (path, defaultValue) => { - return state[path] ? state[path].value : defaultValue - }, - [state] - ) - - const isDocLoading = useCallback( - (path) => { - return state[path] ? state[path].isLoading : false - }, - [state] - ) - - const getDocError = useCallback( - (path) => { - return state[path] ? state[path].error : false - }, - [state] - ) - - const hasDocError = useCallback( - (path) => { - return state[path] ? state[path].hasError : false - }, - [state] - ) - - const clearDoc = useCallback( - (reference) => { - const path = getLocation(reference) - unwatchDoc(path) - dispatch({ type: CLEAR, path }) - }, - [getLocation, unwatchDoc] - ) - - const clearAllDocs = useCallback(() => { - Object.keys(inits).map((k) => { - inits[k].unsub && inits[k].unsub() - return k - }) - dispatch({ type: CLEAR_ALL }) - }, []) - - return ( - - {children} - - ) -} - -export default Provider diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/Provider.tsx b/packages/rmw-shell/src/providers/Firebase/Docs/Provider.tsx new file mode 100644 index 000000000..2ca7892a4 --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Docs/Provider.tsx @@ -0,0 +1,229 @@ +import React, { useEffect, useReducer, useCallback } from "react"; +import Context from "./Context.js"; +import { + doc, + onSnapshot, + getFirestore, + DocumentData, +} from "firebase/firestore"; +import { IProviderProps } from "@ecronix/material-ui-shell"; +import { ActionTypeBase } from "../../index.js"; + +enum ActionTypes { + LOADING_CHANGED = "LOADING_CHANGED", + ERROR = "ERROR", + VALUE_CHANGE = "VALUE_CHANGED", + CLEAR = "CLEAR", + CLEAR_ALL = "CLEAR_ALL", +} + +type ActionType = ActionTypeBase & { + type: ActionTypes; +}; + +function reducer(state: DocumentData, action: ActionType) { + const { + type, + path, + value, + isLoading = false, + error = false, + hasError = false, + } = action; + switch (type) { + case ActionTypes.LOADING_CHANGED: + return { ...state, [path]: { ...state?.[path], isLoading } }; + case ActionTypes.ERROR: + return { + ...state, + [path]: { ...state[path], error, hasError, isLoading }, + }; + case ActionTypes.VALUE_CHANGE: + return { + ...state, + [path]: { ...state[path], value, isLoading, error, hasError }, + }; + case ActionTypes.CLEAR: + const { [path]: clearedKey, ...rest } = state; + return { ...rest }; + case ActionTypes.CLEAR_ALL: + return {}; + default: + throw new Error(); + } +} + +function getInitState(persistKey: string) { + let persistedValues = {}; + try { + const pkString = localStorage.getItem(persistKey); + + persistedValues = pkString ? JSON.parse(pkString) : null; + } catch (error) { + console.warn(error); + } + return persistedValues; +} + +const inits: DocumentData = {}; + +const setInit = (path: string, unsub: any) => { + inits[path] = unsub; +}; + +const removeInit = (path: string) => { + inits[path] = false; +}; + +const Provider = ({ + children, + persistKey = "firebase_docs", +}: IProviderProps) => { + const [state, dispatch] = useReducer(reducer, getInitState(persistKey)); + + useEffect(() => { + try { + localStorage.setItem(persistKey, JSON.stringify(state)); + } catch (error) { + console.warn(error); + } + }, [state, persistKey]); + + const getRef = useCallback((path: string | string[]) => { + const db = getFirestore(); + if (typeof path === "string") { + return doc(db, "/", ...path.split("/")); + } else if (path instanceof Array) { + return doc(db, "/", ...path); // TODO how to test this = added "/" as starting path per docs + } else { + return path; + } + }, []); + + const getLocation = useCallback((path: string | string[]) => { + if (typeof path === "string") { + return path; + } else if (path instanceof Array) { + return path.join("/"); + } else { + return doc(path).path; + } + }, []); + + const watchDoc = useCallback( + (reference: string | string[], alias: string) => { + const ref = getRef(reference); + const path = alias || getLocation(reference); + + if (path.length < 1) { + return; + } + + if (inits[path]) { + return; + } + + dispatch({ + type: ActionTypes.LOADING_CHANGED, + path, + isLoading: true, + }); + + let unsub = onSnapshot( + ref, + (snapshot) => { + dispatch({ + type: ActionTypes.VALUE_CHANGE, + path, + value: snapshot.data(), + isLoading: false, + }); + }, + (error) => { + dispatch({ + type: ActionTypes.ERROR, + path, + isLoading: false, + error, + hasError: true, + }); + } + ); + setInit(path, unsub); + }, + [getLocation, getRef] + ); + + const unwatchDoc = useCallback( + (reference: string) => { + const path = getLocation(reference); + inits[path] && inits[path](); + removeInit(path); + }, + [getLocation] + ); + + const getDoc = useCallback( + (path: string, defaultValue: string | DocumentData) => { + return state[path] ? state[path].value : defaultValue; + }, + [state] + ); + + const isDocLoading = useCallback( + (path: string) => { + return state[path] ? state[path].isLoading : false; + }, + [state] + ); + + const getDocError = useCallback( + (path: string) => { + return state[path] ? state[path].error : false; + }, + [state] + ); + + const hasDocError = useCallback( + (path: string) => { + return state[path] ? state[path].hasError : false; + }, + [state] + ); + + const clearDoc = useCallback( + (reference: string) => { + const path = getLocation(reference); + unwatchDoc(path); + dispatch({ type: ActionTypes.CLEAR, path }); + }, + [getLocation, unwatchDoc] + ); + + const clearAllDocs = useCallback(() => { + Object.keys(inits).map((k) => { + inits[k].unsub && inits[k].unsub(); + return k; + }); + dispatch({ type: ActionTypes.CLEAR_ALL, path: "" }); + }, []); + + return ( + + {children} + + ); +}; + +export default Provider; diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/index.jsx b/packages/rmw-shell/src/providers/Firebase/Docs/index.jsx deleted file mode 100644 index 71d95e31d..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Docs/index.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { useContext } from "react"; -import Context from "./Context"; -import Provider from "./Provider"; - -function useFirebaseDocs() { - return useContext(Context); -} - -export { - useFirebaseDocs, - Provider as FirebaseDocsProvider, - Context as FirebaseDocsContext, -}; diff --git a/packages/rmw-shell/src/providers/Firebase/Docs/index.tsx b/packages/rmw-shell/src/providers/Firebase/Docs/index.tsx new file mode 100644 index 000000000..118a938bb --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Docs/index.tsx @@ -0,0 +1,20 @@ +import { useContext } from "react"; +import Context from "./Context.js"; +import Provider from "./Provider.jsx"; + +function useFirebaseDocs() { + const context = useContext(Context); + + if (context === undefined) { + throw new Error( + "useFirebaseDocs must be used within a FirebaseDocsContext" + ); + } + return context; +} + +export { + useFirebaseDocs, + Provider as FirebaseDocsProvider, + Context as FirebaseDocsContext, +}; diff --git a/packages/rmw-shell/src/providers/Firebase/Lists/Context.jsx b/packages/rmw-shell/src/providers/Firebase/Lists/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Lists/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/rmw-shell/src/providers/Firebase/Lists/Context.tsx b/packages/rmw-shell/src/providers/Firebase/Lists/Context.tsx new file mode 100644 index 000000000..b4c753df2 --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Lists/Context.tsx @@ -0,0 +1,20 @@ +import { DatabaseReference, Query } from "firebase/database"; +import React from "react"; +export type ListsContextType = { + watchList: ( + reference: string | DatabaseReference | Query, + alias?: string + ) => void; + unwatchList: (reference: string) => void; + getList: (path: string) => any[]; + clearList: (reference: string) => void; + clearAllLists: () => void; + isListLoading: (path: string) => void; + hasListError: (path: string) => void; + getListError: (path: string) => void; +}; +export const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/rmw-shell/src/providers/Firebase/Lists/Provider.jsx b/packages/rmw-shell/src/providers/Firebase/Lists/Provider.tsx similarity index 59% rename from packages/rmw-shell/src/providers/Firebase/Lists/Provider.jsx rename to packages/rmw-shell/src/providers/Firebase/Lists/Provider.tsx index a25999af2..6f9a081f3 100644 --- a/packages/rmw-shell/src/providers/Firebase/Lists/Provider.jsx +++ b/packages/rmw-shell/src/providers/Firebase/Lists/Provider.tsx @@ -9,44 +9,56 @@ import { onChildRemoved, get, off, + DatabaseReference, + Query, } from "firebase/database"; +import { DocumentData } from "firebase/firestore"; +import { ActionTypeBase } from "../.."; +import { IProviderProps } from "@ecronix/material-ui-shell"; + +enum ActionTypes { + LOADING_CHANGED = "LOADING_CHANGED", + ERROR = "ERROR", + VALUE_CHANGE = "VALUE_CHANGED", + CLEAR = "CLEAR", + CLEAR_ALL = "CLEAR_ALL", + CHILD_ADDED = "CHILD_ADDED", + CHILD_CHANGED = "CHILD_CHANGED", + CHILD_REMOVED = "CHILD_REMOVED", +} -const LOADING_CHANGED = "LOADING_CHANGED"; -const ERROR = "ERROR"; -const VALUE_CHANGE = "VALUE_CHANGED"; -const CLEAR = "CLEAR"; -const CLEAR_ALL = "CLEAR_ALL"; -const CHILD_ADDED = "CHILD_ADDED"; -const CHILD_CHANGED = "CHILD_CHANGED"; -const CHILD_REMOVED = "CHILD_REMOVED"; +type ActionType = ActionTypeBase & { + type: ActionTypes; + path: string; +}; -const inits = {}; +const inits: DocumentData = {}; -const setInit = (path) => { +const setInit = (path: string) => { inits[path] = true; }; -const removeInit = (path) => { +const removeInit = (path: string) => { inits[path] = false; }; -function list(list = [], action) { +function list(list: DocumentData[] = [], action: ActionType) { const { payload } = action; switch (action.type) { - case CHILD_ADDED: + case ActionTypes.CHILD_ADDED: return list.findIndex((d) => d.key === payload.key) === -1 ? [...list, payload] : [...list]; - case CHILD_CHANGED: + case ActionTypes.CHILD_CHANGED: return list.map((child) => (payload.key === child.key ? payload : child)); - case CHILD_REMOVED: + case ActionTypes.CHILD_REMOVED: return list.filter((child) => payload.key !== child.key); } } -function reducer(state, action) { +function reducer(state: DocumentData, action: ActionType) { const { type, path, @@ -56,26 +68,26 @@ function reducer(state, action) { hasError = false, } = action; switch (type) { - case LOADING_CHANGED: - return { ...state, [path]: { ...state[path], isLoading } }; - case ERROR: + case ActionTypes.LOADING_CHANGED: + return { ...state, [path]: { ...state?.[path], isLoading } }; + case ActionTypes.ERROR: return { ...state, - [path]: { ...state[path], error, hasError, isLoading }, + [path]: { ...state?.[path], error, hasError, isLoading }, }; - case VALUE_CHANGE: + case ActionTypes.VALUE_CHANGE: return { ...state, - [path]: { ...state[path], value, isLoading, error, hasError }, + [path]: { ...state?.[path], value, isLoading, error, hasError }, }; - case CLEAR: + case ActionTypes.CLEAR: const { [path]: clearedKey, ...rest } = state; return { ...rest }; - case CHILD_ADDED: - case CHILD_CHANGED: - case CHILD_REMOVED: + case ActionTypes.CHILD_ADDED: + case ActionTypes.CHILD_CHANGED: + case ActionTypes.CHILD_REMOVED: console.log("state[path]", state[path]); - if (state[path]) { + if (state?.[path]) { return { ...state, //TO DO: a bug happens if state[path] is undefined @@ -85,24 +97,28 @@ function reducer(state, action) { return state; } - case CLEAR_ALL: + case ActionTypes.CLEAR_ALL: return {}; default: throw new Error(); } } -function getInitState(persistKey) { +function getInitState(persistKey: string) { let persistedValues = {}; try { - persistedValues = JSON.parse(localStorage.getItem(persistKey)) || {}; + const pkString = localStorage.getItem(persistKey); + persistedValues = pkString ? JSON.parse(pkString) : null; } catch (error) { console.warn(error); } return persistedValues; } -const Provider = ({ children, persistKey = "firebase_lists" }) => { +const Provider = ({ + children, + persistKey = "firebase_lists", +}: IProviderProps) => { const [state, dispatch] = useReducer(reducer, getInitState(persistKey)); const db = getDatabase(); @@ -115,8 +131,8 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { }, [state, persistKey]); const getRef = useCallback( - (path) => { - if (typeof path === "string" || path instanceof String) { + (path: string | DatabaseReference | Query) => { + if (typeof path === "string") { return ref(db, path); } else { return path; @@ -126,8 +142,8 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { ); const getLocation = useCallback( - (path) => { - if (typeof path === "string" || path instanceof String) { + (path: string | DatabaseReference | Query) => { + if (typeof path === "string") { return path; } else { return path.toString().substring(ref(db).root.toString().length); @@ -137,7 +153,7 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { ); const watchList = useCallback( - async (reference, alias) => { + async (reference: string | DatabaseReference | Query, alias?: string) => { const ref = getRef(reference); const path = alias || getLocation(reference); @@ -156,9 +172,9 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { // but we can use this to not change the state after the inital call // because we already have all data we got trough the once call - const handleError = (error) => { + const handleError = (error: Error) => { dispatch({ - type: ERROR, + type: ActionTypes.ERROR, path, isLoading: false, error, @@ -167,7 +183,7 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { removeInit(path); }; - const handleChange = (s, type) => { + const handleChange = (s: DocumentData, type: ActionTypes) => { if (listenForChanges) { dispatch({ type, @@ -180,18 +196,30 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { setInit(path); dispatch({ - type: LOADING_CHANGED, + type: ActionTypes.LOADING_CHANGED, path, isLoading: true, }); - onChildAdded(ref, (s) => handleChange(s, CHILD_ADDED), handleError); - onChildChanged(ref, (s) => handleChange(s, CHILD_CHANGED), handleError); - onChildRemoved(ref, (s) => handleChange(s, CHILD_REMOVED), handleError); + onChildAdded( + ref, + (s) => handleChange(s, ActionTypes.CHILD_ADDED), + handleError + ); + onChildChanged( + ref, + (s) => handleChange(s, ActionTypes.CHILD_CHANGED), + handleError + ); + onChildRemoved( + ref, + (s) => handleChange(s, ActionTypes.CHILD_REMOVED), + handleError + ); try { try { - const list = []; + const list: DocumentData[] = []; const snapshot = await get(getRef(reference)); snapshot.forEach((snap) => { @@ -199,7 +227,7 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { }); dispatch({ - type: VALUE_CHANGE, + type: ActionTypes.VALUE_CHANGE, path, value: list, isLoading: false, @@ -208,21 +236,22 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { console.log("Error loading inital data", error); } finally { dispatch({ - type: LOADING_CHANGED, + type: ActionTypes.LOADING_CHANGED, isLoading: false, + path, // TODO check if path should be here }); } listenForChanges = true; } catch (error) { - handleError(error); + handleError(error as Error); } }, [getLocation, getRef] ); const unwatchList = useCallback( - (reference) => { + (reference: string | DatabaseReference | Query) => { const ref = getRef(reference); const path = getLocation(reference); @@ -236,47 +265,47 @@ const Provider = ({ children, persistKey = "firebase_lists" }) => { ); const getList = useCallback( - (path) => { - return state[path] && state[path].value ? state[path].value : []; + (path: string): any[] => { + return state?.[path] && state[path]?.value ? state[path].value : []; }, [state] ); const isListLoading = useCallback( - (path) => { - return state[path] ? state[path].isLoading : false; + (path: string) => { + return state?.[path] ? state[path].isLoading : false; }, [state] ); const getListError = useCallback( - (path) => { - return state[path] ? state[path].error : false; + (path: string) => { + return state?.[path] ? state[path].error : false; }, [state] ); const hasListError = useCallback( - (path) => { - return state[path] ? state[path].hasError : false; + (path: string) => { + return state?.[path] ? state[path].hasError : false; }, [state] ); const clearList = useCallback( - (reference) => { + (reference: string) => { const ref = getRef(reference); const path = getLocation(reference); unwatchList(ref); - dispatch({ type: CLEAR, path }); + dispatch({ type: ActionTypes.CLEAR, path }); }, [getRef, getLocation, unwatchList] ); const clearAllLists = useCallback(() => { off(ref(db)); - dispatch({ type: CLEAR_ALL }); + dispatch({ type: ActionTypes.CLEAR_ALL, path: "" }); }, [db]); return ( diff --git a/packages/rmw-shell/src/providers/Firebase/Lists/index.jsx b/packages/rmw-shell/src/providers/Firebase/Lists/index.tsx similarity index 56% rename from packages/rmw-shell/src/providers/Firebase/Lists/index.jsx rename to packages/rmw-shell/src/providers/Firebase/Lists/index.tsx index 76d2ea70c..5f99f64a6 100644 --- a/packages/rmw-shell/src/providers/Firebase/Lists/index.jsx +++ b/packages/rmw-shell/src/providers/Firebase/Lists/index.tsx @@ -3,7 +3,14 @@ import Context from "./Context"; import Provider from "./Provider"; function useFirebaseLists() { - return useContext(Context); + const context = useContext(Context); + + if (context === undefined) { + throw new Error( + "useFirebaseLists must be used within a FirebaseListsContext" + ); + } + return context; } export { diff --git a/packages/rmw-shell/src/providers/Firebase/Messaging/Context.jsx b/packages/rmw-shell/src/providers/Firebase/Messaging/Context.jsx deleted file mode 100644 index 1f12dae7e..000000000 --- a/packages/rmw-shell/src/providers/Firebase/Messaging/Context.jsx +++ /dev/null @@ -1,5 +0,0 @@ -import React from 'react' - -export const Context = React.createContext(null) - -export default Context diff --git a/packages/rmw-shell/src/providers/Firebase/Messaging/Context.tsx b/packages/rmw-shell/src/providers/Firebase/Messaging/Context.tsx new file mode 100644 index 000000000..5fe73ca12 --- /dev/null +++ b/packages/rmw-shell/src/providers/Firebase/Messaging/Context.tsx @@ -0,0 +1,10 @@ +import React from "react"; +export type ListsContextType = { + requestPermission: (p?: { onDismiss: () => void }) => void; + token: string | null; +}; +export const Context = React.createContext( + undefined +); + +export default Context; diff --git a/packages/rmw-shell/src/providers/Firebase/Messaging/Provider.jsx b/packages/rmw-shell/src/providers/Firebase/Messaging/Provider.tsx similarity index 89% rename from packages/rmw-shell/src/providers/Firebase/Messaging/Provider.jsx rename to packages/rmw-shell/src/providers/Firebase/Messaging/Provider.tsx index 0bd36cefa..efe60c467 100644 --- a/packages/rmw-shell/src/providers/Firebase/Messaging/Provider.jsx +++ b/packages/rmw-shell/src/providers/Firebase/Messaging/Provider.tsx @@ -3,22 +3,23 @@ import Context from "./Context"; import { Button } from "@mui/material"; import { useAuth, useConfig } from "@ecronix/base-shell"; import { useIntl } from "react-intl"; -import { useSnackbar } from "notistack"; +import { SnackbarKey, useSnackbar } from "notistack"; import { SnackMessage } from "@ecronix/rmw-shell"; import { getMessaging, getToken, onMessage } from "firebase/messaging"; import { getDatabase, ref, set } from "firebase/database"; import { getApp } from "firebase/app"; +import { IProviderProps } from "@ecronix/material-ui-shell"; const isSupported = () => "Notification" in window && "serviceWorker" in navigator && "PushManager" in window; -const Provider = ({ children }) => { - const [token, setToken] = useState(false); +const Provider = ({ children }: IProviderProps) => { + const [token, setToken] = useState(null); const intl = useIntl(); const { appConfig } = useConfig(); - const { auth = {} } = useAuth(); + const { auth } = useAuth(); const { uid, notificationsDisabled = false } = auth || {}; const { firebase: firebaseConfig } = appConfig || {}; const { prod = {}, dev = {} } = firebaseConfig || {}; @@ -30,7 +31,7 @@ const Provider = ({ children }) => { const { enqueueSnackbar, closeSnackbar } = useSnackbar(); const syncToken = useCallback( - async (token) => { + async (token: string) => { if (notificationsDisabled) { return; } @@ -40,14 +41,14 @@ const Provider = ({ children }) => { if (uid) { await set( ref(getDatabase(), `notification_tokens/${uid}/${token}`), - true, + true ); } } catch (error) { console.warn(error); } }, - [uid, notificationsDisabled], + [uid, notificationsDisabled] ); const initializeMessaging = useCallback(async () => { @@ -76,9 +77,9 @@ const Provider = ({ children }) => { } }, [initializeMessaging, notificationsDisabled]); - const requestPermission = (p) => { + const requestPermission = (p?: { onDismiss: () => void }) => { const { onDismiss = () => {} } = p || {}; - const action = (key) => ( + const action = (key: SnackbarKey) => (