diff --git a/web/.browserslistrc b/web/.browserslistrc new file mode 100644 index 0000000..dc3bc09 --- /dev/null +++ b/web/.browserslistrc @@ -0,0 +1,4 @@ +> 1% +last 2 versions +not dead +not ie 11 diff --git a/web/.eslintrc.cjs b/web/.eslintrc.cjs new file mode 100644 index 0000000..9a89770 --- /dev/null +++ b/web/.eslintrc.cjs @@ -0,0 +1,43 @@ +// https://github.com/typescript-eslint/typescript-eslint/issues/251 +module.exports = { + root: true, + env: { + browser: true, + es2021: true, + node: true, + }, + extends: [ + "eslint:recommended", + "plugin:vue/vue3-recommended", + "plugin:@typescript-eslint/recommended", + "plugin:prettier/recommended", + ], + overrides: [], + parser: "vue-eslint-parser", + parserOptions: { + ecmaVersion: "latest", + extraFileExtensions: [".vue"], + parser: "@typescript-eslint/parser", + tsconfigRootDir: __dirname, + project: ["./tsconfig.node.json", "./tsconfig.json", "./tests/tsconfig.json"], + sourceType: "module", + }, + plugins: ["vue", "@typescript-eslint", "prettier"], + rules: { + // Override/add rules' settings here + "vue/valid-v-slot": [ + "error", + { + allowModifiers: true, + }, + ], + "@typescript-eslint/no-unused-vars": [ + "error", + { + argsIgnorePattern: "^_", + varsIgnorePattern: "^_", + caughtErrorsIgnorePattern: "^_", + }, + ], + }, +} diff --git a/web/.gitignore b/web/.gitignore new file mode 100644 index 0000000..8ee54e8 --- /dev/null +++ b/web/.gitignore @@ -0,0 +1,30 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +/cypress/videos/ +/cypress/screenshots/ + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo diff --git a/web/.prettierrc.test.yaml b/web/.prettierrc.test.yaml new file mode 100644 index 0000000..5dfa752 --- /dev/null +++ b/web/.prettierrc.test.yaml @@ -0,0 +1,9 @@ +$schema: "https://json.schemastore.org/prettierrc" +embeddedLanguageFormatting: "auto" +trailingComma: "es5" +tabWidth: 2 +semi: false +singleQuote: false +singleAttributePerLine: true +useTabs: false +printWidth: 100 diff --git a/web/README.md b/web/README.md new file mode 100644 index 0000000..ef72fd5 --- /dev/null +++ b/web/README.md @@ -0,0 +1,18 @@ +# Vue 3 + TypeScript + Vite + +This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` + + diff --git a/web/package-lock.json b/web/package-lock.json new file mode 100644 index 0000000..c43b330 --- /dev/null +++ b/web/package-lock.json @@ -0,0 +1,6003 @@ +{ + "name": "alphane-web", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "alphane-web", + "version": "0.1.0", + "dependencies": { + "@auth0/auth0-vue": "^2.5.0", + "@mdi/font": "^7.4.47", + "@tabler/icons-vue": "^3.36.0", + "@vueuse/core": "^13.9.0", + "@vueuse/router": "^13.9.0", + "axios": "^1.13.2", + "dompurify": "^3.3.3", + "grid-layout-plus": "^1.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "luxon": "^3.7.2", + "marked": "^17.0.5", + "md5": "^2.3.0", + "qs": "^6.14.0", + "validator": "^13.15.26", + "vue": "^3.4.21", + "vue-draggable-next": "^2.3.0", + "vue-i18n": "^11.3.0", + "vue-router": "^4.6.4", + "vue-scrollto": "^2.20.0", + "vuetify": "^3.11.4" + }, + "devDependencies": { + "@types/dompurify": "^3.0.5", + "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.21", + "@types/luxon": "^3.7.1", + "@types/md5": "^2.3.6", + "@types/qs": "^6.14.0", + "@types/validator": "^13.15.10", + "@typescript-eslint/eslint-plugin": "^8.50.1", + "@typescript-eslint/parser": "^8.50.1", + "@vitejs/plugin-vue": "^6.0.3", + "eslint": "^8.57.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-vue": "^9.33.0", + "jsdom": "^26.1.0", + "prettier": "^3.7.4", + "prettier-plugin-embed": "^0.5.1", + "prettier-plugin-sql": "^0.19.2", + "sass": "^1.97.1", + "typescript": "^5.9.3", + "vite": "^7.3.0", + "vite-plugin-vuetify": "^2.1.2", + "vitest": "^3.2.4", + "vue-tsc": "^3.2.1" + } + }, + "node_modules/@asamuzakjp/css-color": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", + "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@csstools/css-calc": "^2.1.3", + "@csstools/css-color-parser": "^3.0.9", + "@csstools/css-parser-algorithms": "^3.0.4", + "@csstools/css-tokenizer": "^3.0.3", + "lru-cache": "^10.4.3" + } + }, + "node_modules/@auth0/auth0-auth-js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/@auth0/auth0-auth-js/-/auth0-auth-js-1.9.1.tgz", + "integrity": "sha512-YY8/We7NpJyN8aDlYZI0ENRFlPsuFQ5NGETI4dkJa+BEwCibNTRlM1E9O9qc77K4TpOANZsmaADSMde2If+Alg==", + "license": "MIT", + "dependencies": { + "jose": "^6.0.8", + "openid-client": "^6.8.0" + } + }, + "node_modules/@auth0/auth0-spa-js": { + "version": "2.21.2", + "resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-2.21.2.tgz", + "integrity": "sha512-CkIzlTJeae0LbYluXgNRPs7X8+Yd7W8ya/d1Cq/AGZ0d5/gfWwgDdFv9tCQR59KhRqdmvESSJUaIQjcjD0B1aA==", + "license": "MIT", + "dependencies": { + "@auth0/auth0-auth-js": "1.9.1", + "browser-tabs-lock": "1.3.0", + "dpop": "2.1.1", + "es-cookie": "1.3.2" + } + }, + "node_modules/@auth0/auth0-vue": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/@auth0/auth0-vue/-/auth0-vue-2.7.0.tgz", + "integrity": "sha512-7Jw8jCNH0rQQkBP31QUKQDaMXHMcS3Qg3g7Ia6deYKe9/jDgYbMFBus/R8dcq8WZLAuI+06yTcvMzUi7w3WHNQ==", + "license": "MIT", + "dependencies": { + "@auth0/auth0-spa-js": "^2.10.0", + "vue": "^3.5.21" + }, + "peerDependencies": { + "vue-router": "^4.0.12 || ^5.0.0" + }, + "peerDependenciesMeta": { + "vue-router": { + "optional": true + } + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@csstools/color-helpers": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", + "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@csstools/css-calc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", + "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-color-parser": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", + "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "dependencies": { + "@csstools/color-helpers": "^5.1.0", + "@csstools/css-calc": "^2.1.4" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-parser-algorithms": "^3.0.5", + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-parser-algorithms": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", + "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@csstools/css-tokenizer": "^3.0.4" + } + }, + "node_modules/@csstools/css-tokenizer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", + "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@interactjs/types": { + "version": "1.10.27", + "resolved": "https://registry.npmjs.org/@interactjs/types/-/types-1.10.27.tgz", + "integrity": "sha512-BUdv0cvs4H5ODuwft2Xp4eL8Vmi3LcihK42z0Ft/FbVJZoRioBsxH+LlsBdK4tAie7PqlKGy+1oyOncu1nQ6eA==", + "license": "MIT" + }, + "node_modules/@intlify/core-base": { + "version": "11.4.6", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-11.4.6.tgz", + "integrity": "sha512-EOeHO95XESK9IFHgHeZXunsM/WBAoCA0DlaWODvx14vKmetAuS97t+l6Xe9hTUqntPpF93vtVSjjUDafw3wXMw==", + "license": "MIT", + "dependencies": { + "@intlify/devtools-types": "11.4.6", + "@intlify/message-compiler": "11.4.6", + "@intlify/shared": "11.4.6" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/devtools-types": { + "version": "11.4.6", + "resolved": "https://registry.npmjs.org/@intlify/devtools-types/-/devtools-types-11.4.6.tgz", + "integrity": "sha512-wowQPpNem56b2d43IJmqbrzG2FeBKe5f/kUGlpNuBmXs6OSqncF8m1+1lxHuW8ISZJF0ma2RkW3iLkw0g0G4VA==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.6", + "@intlify/shared": "11.4.6" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "11.4.6", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-11.4.6.tgz", + "integrity": "sha512-5nj3jULqeTAC1WovwMs1LQWgatTa2pM/rXN9T3XW8rdOtXW9ZF6/GLSNFTKDQmPLwclhPdgUWLJ/4w3fMeeC/Q==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "11.4.6", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "11.4.6", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-11.4.6.tgz", + "integrity": "sha512-m1p1HHAMLhqSpTRH7VnXdrN0CQ4y+9vunFkpLkbD8soIuBsnQdawZXqMCgvwI2UVF9Ww7sVaw7g9tV2VO7shoA==", + "license": "MIT", + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@juggle/resize-observer": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", + "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", + "license": "Apache-2.0" + }, + "node_modules/@mdi/font": { + "version": "7.4.47", + "resolved": "https://registry.npmjs.org/@mdi/font/-/font-7.4.47.tgz", + "integrity": "sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==", + "license": "Apache-2.0" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@pkgr/core": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.3.6.tgz", + "integrity": "sha512-SEeaJLb3qBNF/OaXnaR1NmmBbFYk1zC0ZH/52fATcRPLFg/p791YrcyFFy44Bo9sLaGuSuLp5Q6axbb/O+v/RA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/pkgr" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", + "integrity": "sha512-6o7ZLZK+BeenkZCFNDXqpbjw9bD6nuWonvS/lwQJp7NoVVxm6p3qE7qQ5jGuBjiFsgvqjD8mZAU5oWxTmbOeOg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.62.2.tgz", + "integrity": "sha512-BaH7BllCACHoH1LguOU56UItGfUWjujlO65kS9LAodViaN4bwIKd7oeW/ZHJ/4ljr/7MIiENnNy3HJ0zXv8Zkw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.62.2.tgz", + "integrity": "sha512-v39RCCvj4He82I9sFmk+M1VZ0PLM9sfsLVikjfx2hYBNALhrrOR2D3JjQA6AhlaSOgcR+RzrKY7e1+bT6SUO/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.62.2.tgz", + "integrity": "sha512-yl0y2vq3S3lHeuXhEdss6TWfKW8vkujImO12tn4ZkG/4oghr09LvdYm2RElVjokTQiUvDUGXLGsYeLqUMCKpGA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.62.2.tgz", + "integrity": "sha512-tT4pvt4qXD+vEoezupCWi+a1F0vvDiksiHc+PxRlYTOH1I6/X4id9jPxTP+Fg+545euaFT1jJVs4CEdHZAU1vw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.62.2.tgz", + "integrity": "sha512-6nU5F2wCW+qvCBhTn1pdIU3bzsIoF7EUwsCDRxilWGprQR6yd508YnH9+OKFCwpfS8pjZqDUmnCAr7exax0XCg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.62.2.tgz", + "integrity": "sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==", + "cpu": [ + "arm" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.62.2.tgz", + "integrity": "sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==", + "cpu": [ + "arm" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.62.2.tgz", + "integrity": "sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.62.2.tgz", + "integrity": "sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.62.2.tgz", + "integrity": "sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.62.2.tgz", + "integrity": "sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==", + "cpu": [ + "loong64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.62.2.tgz", + "integrity": "sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.62.2.tgz", + "integrity": "sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==", + "cpu": [ + "ppc64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.62.2.tgz", + "integrity": "sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.62.2.tgz", + "integrity": "sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.62.2.tgz", + "integrity": "sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.62.2.tgz", + "integrity": "sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.62.2.tgz", + "integrity": "sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.62.2.tgz", + "integrity": "sha512-srjEIxSH3LRnJN6THczDHWQplqEMFiAJrTab0msUryh9kwNpkICf3Ea6q6MN/2cZwRFUNx5w+h6Hpi4QuHS6Zg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.62.2.tgz", + "integrity": "sha512-8hOJnxgbyObnCm5AlRA3A931xX19xq80RjVTKgJOvEKWqJruP/Uf12IbAOaDjjEXYRewwHLfmF0YRIdK3OwKWA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.62.2.tgz", + "integrity": "sha512-mmF4AY1i0hG/bLWUctUq59gtmgaSIRa3cu/A3JFRp/sCNEme2bgDEiDS22P9FbnJB8NJNF4jPJiSP5RHQpUTDg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.62.2.tgz", + "integrity": "sha512-DZgkknc6jhHrk46V25vbAM0zZkyP0nSDkJB8/dRkLTxv470dOmWDqGoEJl/9A0dFfS7yE3REOwNDxpHwSLSt0Q==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.62.2.tgz", + "integrity": "sha512-T6xr6ucWSFto+VGajA8YH26LdpHRuP4YLHEKAtCWvJDOlnmWcDZVCI2Jmjr+IFHDlt2zRaTAKE4tfjTaWLgJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.62.2.tgz", + "integrity": "sha512-BfzEnDJOt9T8M989/lA37EcJgat01wLRnoi5dQf3QzOH7jzpqTAzdDbVfRljVr5r+jzKqpbHeyOfAaXxAd0PAA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@tabler/icons": { + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/@tabler/icons/-/icons-3.44.0.tgz", + "integrity": "sha512-Wn0AOZG9sg0L+bjfMqq4eNhC6pQjIrk94LvvWYNYkY8KH8wC3YILRzQlrnVJc4FUeMxH/AK97QsYCX35H3LndA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + } + }, + "node_modules/@tabler/icons-vue": { + "version": "3.44.0", + "resolved": "https://registry.npmjs.org/@tabler/icons-vue/-/icons-vue-3.44.0.tgz", + "integrity": "sha512-mABxdhq3SWo2ZI77w/t0reiOGNim/SEDSlfMT5PeiWA3cZwnZoQUYRiq/X6SgeTaA7LzCTX0IuvQWVf4RWOvsg==", + "license": "MIT", + "dependencies": { + "@tabler/icons": "3.44.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/codecalm" + }, + "peerDependencies": { + "vue": ">=3.0.1" + } + }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/dompurify": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz", + "integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/js-yaml": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash": { + "version": "4.17.24", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz", + "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-gW+Oib+vUtGJBtNC8V9Reww0oIpusw+4m81uncg9REGZAJfqOQHfo/nkabnc7w0QReXyPqjrbWMJk6NuAkiX3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/md5": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.6.tgz", + "integrity": "sha512-WD69gNXtRBnpknfZcb4TRQ0XJQbUPZcai/Qdhmka3sxUR3Et8NrXoeAoknG/LghYHTf4ve795rInVYHBTQdNVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/pegjs": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/@types/pegjs/-/pegjs-0.10.6.tgz", + "integrity": "sha512-eLYXDbZWXh2uxf+w8sXS8d6KSoXTswfps6fvCUuVAGN8eRpfe7h9eSRydxiSJvo9Bf+GzifsDOr9TMQlmJdmkw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/qs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.1.tgz", + "integrity": "sha512-GZHUBZR9hckSUhrxmp1nG6NwdpM9fCunJwyThLW1X3AyHgd9IlHb6VANpQQqDr2o/qQp6McZ3y/IA2rVzKzSbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/validator": { + "version": "13.15.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz", + "integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmjs.org/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.61.1.tgz", + "integrity": "sha512-ZPlVl3PB3et/59Ne0fv/sci6ZXz4T4Hp4nTJ56i/Y0gR89ARb+KphojTq6j+56E5PIezmOIOOWyY+aWQFd+IkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/type-utils": "8.61.1", + "@typescript-eslint/utils": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.61.1", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.61.1.tgz", + "integrity": "sha512-PJ5vePq5/ognBbrIcoC5+SHO5dfpeLPzP9FpLkzWrguoYQEeeSjlJpVwOpo1JRSTEi7dRcwNy4h4dzV70PqHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.61.1.tgz", + "integrity": "sha512-PrC4JYGmR241lYnfhmKGTXkFqv8+ymbTFgSAY0fVXpY82/QkMw5TZPl+vGzuDDU2QYJk9fIDOBTntF+yDv9LEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.61.1", + "@typescript-eslint/types": "^8.61.1", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.61.1.tgz", + "integrity": "sha512-L2bdIeoQS8FlKAvONAr20w6OcLXeB+qiDKbAooS9A0Ben+iSIkBef0FxqwKWYqt5sa0i4KJtxVyVmhMylKzF5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.61.1.tgz", + "integrity": "sha512-UN/H4di+OO7EWx2ovME+8t31YO+KVnK0RRKEHR3kOt21/Ay8BOq3M1OMvWs5vNiqcFCYGYoxK3MXPZzmMUE+yg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.61.1.tgz", + "integrity": "sha512-GYRicKmVK0C4fsKgaACaknOUAq9Oa2kwsjnpFhFcS/5p4Ht5IP9OVLbgIgcK4SRk92nVHFluurg1lumD9dBcLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1", + "@typescript-eslint/utils": "8.61.1", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.61.1.tgz", + "integrity": "sha512-G+CRlPqLv7Bz1IZVs03x5K59F1veqL0EJUROAdGhKsEq8qOiRiZbI+HUojPq5l0fEGOKModD9br6lObhB8zkoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.61.1.tgz", + "integrity": "sha512-u+oQD3BqYWPc8YV9Zab4vaJElJuwOLPRc10Jm1o/qS+6Qwen14HCWwx0Seo4LnSn2wxea2Ik8DxPt2/FHmuhrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.61.1", + "@typescript-eslint/tsconfig-utils": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/visitor-keys": "8.61.1", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.61.1.tgz", + "integrity": "sha512-1+P/3Dj6jvtybE1q0HQ6yBt/gq+oKJyLdEv4HdnqasaEXRSYCAsD59mXEVQnM/ULNdQxbX77tdG4jPRjIS6knA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.61.1", + "@typescript-eslint/types": "8.61.1", + "@typescript-eslint/typescript-estree": "8.61.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.61.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.61.1.tgz", + "integrity": "sha512-6fJ9MHWtK14C1DSkiMlHUSOmrVebL7150xZJBlJiL62jjhIA4JmOq6flwBgDxIdBKKdoiZRel+dfPD5MLfny3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.61.1", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vexip-ui/hooks": { + "version": "2.9.4", + "resolved": "https://registry.npmjs.org/@vexip-ui/hooks/-/hooks-2.9.4.tgz", + "integrity": "sha512-dGUiBAeHIsnSVigGSPHcuHBVqrSGW8LV+zGohvOpBfXs8Ynn5ZcSmybIWJ3G826NsicPu9rqwcJG8uvSgG4k4Q==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.0", + "@juggle/resize-observer": "^3.4.0", + "@vexip-ui/utils": "2.16.4" + }, + "peerDependencies": { + "vue": "^3.2.25" + } + }, + "node_modules/@vexip-ui/utils": { + "version": "2.16.4", + "resolved": "https://registry.npmjs.org/@vexip-ui/utils/-/utils-2.16.4.tgz", + "integrity": "sha512-KX+Q4EsuwDp6ZlRJ7OAkiYxu52D5CVM8zpqQz/FXYV+JUtzl9T3dvxgtA8gQ0wm5Sh/xT6jp8Wo4X7tLAzRh/A==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.7.tgz", + "integrity": "sha512-km+p+XdSz9Sxm5rqUbqcSfZYaAniKxWBj1KURl+Jr7UaPvvX7BmaWMdP69I5rrFDeQGyxAG7NXdc57vz+snhWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitest/expect": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.6.tgz", + "integrity": "sha512-1+7q9BtaKzEmO+fmNT3kYvoNn5Y71XWAx2Q5HRim4tTVRQVRv4uJFAQ5FbK0OPUeNP/WmVCpxYxoJdvuHVjzBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.6", + "@vitest/utils": "3.2.6", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.6.tgz", + "integrity": "sha512-EZOrpDbkKotFAP7wPAQV1UIyoGOk4oX7ynWhBhLB7v+meMHbQhU16oPpIYGTTe4oFlhpryGpgpcZP/sin3hYuw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.6", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.6.tgz", + "integrity": "sha512-lb7XXXzmm2h2ASzFnRvQpDo6onT1NmMJA3tkGTWiBFtRJ9lxGY3d3mm/Apt36gej2bkkOVLL/yTOtufDaFa/jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.6.tgz", + "integrity": "sha512-HYcoSj1w5tcgUnzoF0HcyaAQjpA1gj9ftUJ7iSJSuipc02jW9gKkigwZbjFldAfYHA1fa8UZVRftdMY5msWM9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.6", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.6.tgz", + "integrity": "sha512-H+ZjNTWGpObenh0YnlBctAPnJSI20P81PL8BPzWpx54YXLLTm8hEsWawtcYLMrwvpK48hGxLLbCS+1KRXhsKhw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.6.tgz", + "integrity": "sha512-oq6BbH68WzcWmwtBrU9nqLeaXTR4XwJF7FSLkKEZo4i6eoXcrxjcwSuTvWBIRUTC6VC72nXYunzqgZA+IKdtxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.6.tgz", + "integrity": "sha512-lI23nIs4bnT3T8NIoh+vFaz5s2/DdP0Jgt2jxwgWljvwn82cLJtyi/If+fjFyoLMGIOz0U/fKvWE0d4jsNQEfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.6", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.38.tgz", + "integrity": "sha512-s99aGxWYig9ErHbct27KXEGhrBYlRI6c4MwAgXErOAbX9xiW37/uMa+XUDO69zLz83dng8UUZ70CTOJrLrYrEQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.38", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-core/node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/@vue/compiler-core/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.38.tgz", + "integrity": "sha512-JTqp25l8aFfJYF7/KmsXZjAxJz7T+SjmTJLoXVjHtc2BrSgSiW2n9Aem/cWq1OPe68A8JL06B3eVdhlP0H4TVw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.38.tgz", + "integrity": "sha512-DuA2GiZawSEW442iw/9+Fkol8hTgb4Ke5KkhmSry65QA7YuyMbIdy8p0XZRMvNwJdgRz307W8g1CSzdvS4nuNg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.38", + "@vue/compiler-dom": "3.5.38", + "@vue/compiler-ssr": "3.5.38", + "@vue/shared": "3.5.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.15", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-sfc/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.38.tgz", + "integrity": "sha512-7s+W5Gc42FGxZMcuwl8H5B29T8BJPMdBT7KHFE+BbAuZ/iTEdTtv7z2XiMjiaUUw4w3ZcCEdHs36RuYJ2VA7bA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/language-core": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.5.tgz", + "integrity": "sha512-UkKu5nhX89fg4VhlG/FOeI10G3cj/7radKT/cy9BT4Q9qJmJlSTAc/dP63Xqs29aypN4f39xUV6PsLNk/dcD6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.0", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/reactivity": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.38.tgz", + "integrity": "sha512-pG6LV/NDNRbKizcUjFFLAfjaL8mcv4DmR9avNcUw2gDHBzZneuS2TWCmp633ynzxz9YYKNeEPK2I8Wraqy2HUQ==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.38.tgz", + "integrity": "sha512-iyW8WVfF1CpCXxncZY5Ei6rSd6oZr5DgEom//fUjRBRl56AXPD+s9ATvukRt77ZFTuYlnVA1bxY+dJB94tWVYw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.38", + "@vue/shared": "3.5.38" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.38.tgz", + "integrity": "sha512-apX2wt9sdfDshS+a2xueFZLVpt0GkRJZSoPmrW/SA4yzXTznhfcMVW59gr7h4YQeY0vJhdJkk2rsIDwgfFgC5A==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.38", + "@vue/runtime-core": "3.5.38", + "@vue/shared": "3.5.38", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.38.tgz", + "integrity": "sha512-vue8vbf2QlV4quHqzwmJy6dWfmRhP1J8l4wtZg60CL6VoKqcPY2oe7may3+1d9qfpedjK5PRLFqd5k3Isj9mUw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.38", + "@vue/shared": "3.5.38" + }, + "peerDependencies": { + "vue": "3.5.38" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.38.tgz", + "integrity": "sha512-FTW0AFZNaK5/mOqvGBwVfUlNLU38TiQn4+DQgIFUnrBBJQ1crMJ82yeGQLV5jyKFsO8yRukpbuP7x+nRbH6aug==", + "license": "MIT" + }, + "node_modules/@vuetify/loader-shared": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@vuetify/loader-shared/-/loader-shared-2.1.2.tgz", + "integrity": "sha512-X+1jBLmXHkpQEnC0vyOb4rtX2QSkBiFhaFXz8yhQqN2A4vQ6k2nChxN4Ol7VAY5KoqMdFoRMnmNdp/1qYXDQig==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "upath": "^2.0.1" + }, + "peerDependencies": { + "vue": "^3.0.0", + "vuetify": ">=3" + } + }, + "node_modules/@vueuse/core": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/core/-/core-13.9.0.tgz", + "integrity": "sha512-ts3regBQyURfCE2BcytLqzm8+MmLlo5Ln/KLoxDVcsZ2gzIwVNnQpQOL/UKV8alUqjSZOlpFZcRNsLRqj+OzyA==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "13.9.0", + "@vueuse/shared": "13.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/metadata/-/metadata-13.9.0.tgz", + "integrity": "sha512-1AFRvuiGphfF7yWixZa0KwjYH8ulyjDCC0aFgrGRz8+P4kvDFSdXLVfTk5xAN9wEuD1J6z4/myMoYbnHoX07zg==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/router": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/router/-/router-13.9.0.tgz", + "integrity": "sha512-7AYay8Pv/0fC4D0eygbIyZuLyVs+9D7dsnO5D8aqat9qcOz91v/XFWR667WE1+p+OkU0ib+FjQUdnTVBNoIw8g==", + "license": "MIT", + "dependencies": { + "@vueuse/shared": "13.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0", + "vue-router": "^4.0.0" + } + }, + "node_modules/@vueuse/shared": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/@vueuse/shared/-/shared-13.9.0.tgz", + "integrity": "sha512-e89uuTLMh0U5cZ9iDpEI2senqPGfbPRTHM/0AaQkcxnpqjkZqDYP8rpfm7edOz8s+pOCOROEy1PIveSW8+fL5g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "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/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.18.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.18.0.tgz", + "integrity": "sha512-E32NzpYKp++W7XRe52rHiXV2ehxmh3wbdgO7MHeFM+vqxLBYHzt0ElkiImtOBxtOmyp0yoC8C6uESVV84Y2/hw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.5", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/bezier-easing": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", + "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==", + "license": "MIT" + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "5.0.6", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.6.tgz", + "integrity": "sha512-kLpxurY4Z4r9sgMsyG0Z9uzsBlgiU/EFKhj/h91/8yHu0edo7XuixOIH3VcJ8kkxs6/jPzoI6U9Vj3WqbMQ94g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/browser-tabs-lock": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/browser-tabs-lock/-/browser-tabs-lock-1.3.0.tgz", + "integrity": "sha512-g6nHaobTiT0eMZ7jh16YpD2kcjAp+PInbiVq3M1x6KKaEIVhT4v9oURNIpZLOZ3LQbQ3XYfNhMAb/9hzNLIWrw==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "lodash": ">=4.17.21" + } + }, + "node_modules/cac": { + "version": "6.7.14", + "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", + "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT" + }, + "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==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssstyle": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", + "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@asamuzakjp/css-color": "^3.2.0", + "rrweb-cssom": "^0.8.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/data-urls": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", + "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decimal.js": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", + "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", + "dev": true, + "license": "MIT" + }, + "node_modules/dedent": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.2.tgz", + "integrity": "sha512-WzMx3mW98SN+zn3hgemf4OzdmyNhhhKz5Ay0pUfQiMQ3e1g+xmTJWp/pKdwKVXhdSkAEGIIzqeuWrL3mV/AXbA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/discontinuous-range": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz", + "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dompurify": { + "version": "3.4.11", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.11.tgz", + "integrity": "sha512-zhlUV12GsaRzMsf9q5M254YhA4+VuF0fG+QFqu6aYpoGlKtz+w8//jBcGVYBgQkR5GHjUomejY84AV+/uPbWdw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, + "node_modules/dpop": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/dpop/-/dpop-2.1.1.tgz", + "integrity": "sha512-J0Of2JTiM4h5si0tlbPQ/lkqfZ5wAEVkKYBhkwyyANnPJfWH4VsR5uIkZ+T+OSPIwDYUg1fbd5Mmodd25HjY1w==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/entities": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", + "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-cookie": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz", + "integrity": "sha512-UTlYYhXGLOy05P/vKVT2Ui7WtC7NiRzGtJyAKKn32g5Gvcjn7KAClLPWlipCtxIus934dFg9o9jXiBL0nP+t9Q==", + "license": "MIT" + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "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==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/esbuild": { + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "devOptional": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.6.tgz", + "integrity": "sha512-ifetmTcxWfz+4qRW3pH/ujdTq2jQIj59AxJMIN26K5avYgU8dxycUETQonWiW+wPrYXA0j3Try0l1CnwVQtDqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.1", + "synckit": "^0.11.13" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-plugin-prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.33.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.33.0.tgz", + "integrity": "sha512-174lJKuNsuDIlLpjeXc5E2Tss8P44uIimAfGD0b90k0NoirJqpG7stLuU9Vp/9ioTOrQdWVREc4mRd1BD+CvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "globals": "^13.24.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.15", + "semver": "^7.6.3", + "vue-eslint-parser": "^9.4.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-stringify": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fast-stringify/-/fast-stringify-4.0.0.tgz", + "integrity": "sha512-lE2DIivBaLysf6hK5WH/VfMgqRbvBVHcpGVVTmA5Zi8oWIjq9YxIt6lYGdUgP1HNSXxTIat7HEIDnrSvXSeKQw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "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==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", + "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/grid-layout-plus": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/grid-layout-plus/-/grid-layout-plus-1.1.1.tgz", + "integrity": "sha512-7CWehJubrVC8Ps5QFUlnDsp0kiREvKfi3Pdjp21EyY8BNzSusqI3Utcxvu1Y9UUKe3YExvbhJzIxHK6rorbRaQ==", + "license": "MIT", + "dependencies": { + "@vexip-ui/hooks": "^2.8.0", + "@vexip-ui/utils": "^2.16.1", + "interactjs": "^1.10.27" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/html-encoding-sniffer": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", + "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "whatwg-encoding": "^3.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/immutable": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.6.tgz", + "integrity": "sha512-q1swsS8K7L8usSHuOqF2TAoCCkonYz0SG38wLAggaa4Wml70zixIvt2ql4coQ2C2B3hTjltJry4r6bULwgAXLQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/interactjs": { + "version": "1.10.27", + "resolved": "https://registry.npmjs.org/interactjs/-/interactjs-1.10.27.tgz", + "integrity": "sha512-y/8RcCftGAF24gSp76X2JS3XpHiUvDQyhF8i7ujemBz77hwiHDuJzftHx7thY8cxGogwGiPJ+o97kWB6eAXnsA==", + "license": "MIT", + "dependencies": { + "@interactjs/types": "1.10.27" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-potential-custom-element-name": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", + "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jose": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.2.3.tgz", + "integrity": "sha512-YYVDInQKFJfR/xa3ojUTl8c2KoTwiL1R5Wg9YCydwH0x0B9grbzlg5HC7mMjCtUJjbQ/YnGEZIhI5tCgfTb4Hw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", + "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsdom": { + "version": "26.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", + "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssstyle": "^4.2.1", + "data-urls": "^5.0.0", + "decimal.js": "^10.5.0", + "html-encoding-sniffer": "^4.0.0", + "http-proxy-agent": "^7.0.2", + "https-proxy-agent": "^7.0.6", + "is-potential-custom-element-name": "^1.0.1", + "nwsapi": "^2.2.16", + "parse5": "^7.2.1", + "rrweb-cssom": "^0.8.0", + "saxes": "^6.0.0", + "symbol-tree": "^3.2.4", + "tough-cookie": "^5.1.1", + "w3c-xmlserializer": "^5.0.0", + "webidl-conversions": "^7.0.0", + "whatwg-encoding": "^3.1.1", + "whatwg-mimetype": "^4.0.0", + "whatwg-url": "^14.1.1", + "ws": "^8.18.0", + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "canvas": "^3.0.0" + }, + "peerDependenciesMeta": { + "canvas": { + "optional": true + } + } + }, + "node_modules/jsdom/node_modules/agent-base": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.4.tgz", + "integrity": "sha512-MnA+YT8fwfJPgBx3m60MNqakm30XOkyIoH1y6huTQvC0PwZG7ki8NacLBcrPbNoo8vEZy7Jpuk7+jMO+CUovTQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/jsdom/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsox": { + "version": "1.2.125", + "resolved": "https://registry.npmjs.org/jsox/-/jsox-1.2.125.tgz", + "integrity": "sha512-HIf1uwublnXZsy7p3yHTrhzMzrLO6xKnqXytT9pEil5QxaXi8eyer7Is4luF5hYSV4kD3v03Y32FWoAeVYTghQ==", + "dev": true, + "license": "MIT", + "bin": { + "jsox": "lib/cli.js" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/luxon": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/luxon/-/luxon-3.7.2.tgz", + "integrity": "sha512-vtEhXh/gNjI9Yg1u4jX/0YVPMvxzHuGgCm6tC5kZyb08yjGWGnqAjGJvcXbqQR2P3MyMEFnRbpcdFS6PBcLqew==", + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/marked": { + "version": "17.0.6", + "resolved": "https://registry.npmjs.org/marked/-/marked-17.0.6.tgz", + "integrity": "sha512-gB0gkNafnonOw0obSTEGZTT86IuhILt2Wfx0mWH/1Au83kybTayroZ/V6nS25mN7u8ASy+5fMhgB3XPNrOZdmA==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/micro-memoize": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/micro-memoize/-/micro-memoize-5.1.1.tgz", + "integrity": "sha512-QDwluos8YeMijiKxZGwaV4f4tzj0soS6+xcsJhJ3+4wdEIHMyKbIKVUziebOgWX3e6yiijdoaHo+9tyhbnaWXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-equals": "^5.3.3", + "fast-stringify": "^4.0.0" + } + }, + "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==", + "license": "MIT", + "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==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/moo": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.3.tgz", + "integrity": "sha512-m2fmM2dDm7GZQsY7KK2cme8agi+AAljILjQnof7p1ZMDe6dQ4bdnSMx0cPppudoeNv5hEFQirN6u+O4fDE0IWA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "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==", + "license": "MIT" + }, + "node_modules/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.13", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.13.tgz", + "integrity": "sha512-sPdqC6ByMVVGvF1ynvvMo0/o+oD1VX7DaHhijt1bFgjvBkHBib4t49GoNDhf2NDta4oeUNlaGbSt5K7qjZ955Q==", + "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/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/nearley": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz", + "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "commander": "^2.19.0", + "moo": "^0.5.0", + "railroad-diagrams": "^1.0.0", + "randexp": "0.4.6" + }, + "bin": { + "nearley-railroad": "bin/nearley-railroad.js", + "nearley-test": "bin/nearley-test.js", + "nearley-unparse": "bin/nearley-unparse.js", + "nearleyc": "bin/nearleyc.js" + }, + "funding": { + "type": "individual", + "url": "https://nearley.js.org/#give-to-nearley" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT", + "optional": true + }, + "node_modules/node-sql-parser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-5.4.0.tgz", + "integrity": "sha512-jVe6Z61gPcPjCElPZ6j8llB3wnqGcuQzefim1ERsqIakxnEy5JlzV7XKdO1KmacRG5TKwPc4vJTgSRQ0LfkbFw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/pegjs": "^0.10.0", + "big-integer": "^1.6.48" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nwsapi": { + "version": "2.2.24", + "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", + "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", + "dev": true, + "license": "MIT" + }, + "node_modules/oauth4webapi": { + "version": "3.8.6", + "resolved": "https://registry.npmjs.org/oauth4webapi/-/oauth4webapi-3.8.6.tgz", + "integrity": "sha512-iwemM91xz8nryHti2yTmg5fhyEMVOkOXwHNqbvcATjyajb5oQxCQzrNOA6uElRHuMhQQTKUyFKV9y/CNyg25BQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/openid-client": { + "version": "6.8.4", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-6.8.4.tgz", + "integrity": "sha512-QSw0BA08piujetEwfZsHoTrDpMEha7GDZDicQqVwX4u0ChCjefvjDB++TZ8BTg76UpwhzIQgdvvfgfl3HpCSAw==", + "license": "MIT", + "dependencies": { + "jose": "^6.2.2", + "oauth4webapi": "^3.8.5" + }, + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/package-up/-/package-up-5.0.0.tgz", + "integrity": "sha512-MQEgDUvXCa3sGvqHg3pzHO8e9gqTCMPVrWUko3vPQGntwegmFo52mZb2abIVTjFnUcW0BcPz0D93jV5Cas1DWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up-simple": "^1.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse5": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", + "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "entities": "^6.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "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.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.8.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.4.tgz", + "integrity": "sha512-N2MylSdi48+5N/6S5j+maeHbUSIzzZ5uOcX5Hm4QpV8Dkb1HFjfAKTKX6yNPJQD9AhcT3ifHNB66tWTTJDi11Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-embed": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/prettier-plugin-embed/-/prettier-plugin-embed-0.5.1.tgz", + "integrity": "sha512-2Ege8gIlLNTvHElUeU5XcFsD7/dbDXkQA6H9TczHSJAGxB58nNjjifk/dlRMS5E29eqQx/z+ToA4ZVMWzjME/A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.8", + "dedent": "^1.7.1", + "micro-memoize": "^5.1.1", + "package-up": "^5.0.0", + "tiny-jsonc": "^1.0.2", + "type-fest": "^5.3.1" + } + }, + "node_modules/prettier-plugin-embed/node_modules/type-fest": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-5.7.0.tgz", + "integrity": "sha512-1URUxUqfHFM1c+zfSPsa3gnkO7Aq21qyH75SIduNYz4SzY964rn1X2vCMQaHSHhktiw+0kPa2iyb6PUpXqB6Vg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "dependencies": { + "tagged-tag": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prettier-plugin-sql": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/prettier-plugin-sql/-/prettier-plugin-sql-0.19.2.tgz", + "integrity": "sha512-DAu1Jcanpvs32OAOXsqaVXOpPs4nFLVkB3XwzRiZZVNL5/c+XdlNxWFMiMpMhYhmCG5BW3srK8mhikCOv5tPfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsox": "^1.2.123", + "node-sql-parser": "^5.3.10", + "sql-formatter": "^15.6.5", + "tslib": "^2.8.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + }, + "peerDependencies": { + "prettier": "^3.0.3" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.15.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.2.tgz", + "integrity": "sha512-Rzq0KEyX/w/tEybncDgdkZrJgVUsUMk3xjh3t5bv3S1HTAtg+uOYt72+ZfwiQwKdysThkTBdL/rTi6HDmX9Ddw==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "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/railroad-diagrams": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz", + "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/randexp": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz", + "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "discontinuous-range": "1.0.0", + "ret": "~0.1.10" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/ret": { + "version": "0.1.15", + "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", + "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.62.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.62.2.tgz", + "integrity": "sha512-RFnrW4lhXA3s3eqHDZvN654g8OTjzRfqpIRJYczCGB6HzphckVAi/Qh4tbPUbRuDi7s1Llv8g/NspLkttY3gTA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.9" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.62.2", + "@rollup/rollup-android-arm64": "4.62.2", + "@rollup/rollup-darwin-arm64": "4.62.2", + "@rollup/rollup-darwin-x64": "4.62.2", + "@rollup/rollup-freebsd-arm64": "4.62.2", + "@rollup/rollup-freebsd-x64": "4.62.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.62.2", + "@rollup/rollup-linux-arm-musleabihf": "4.62.2", + "@rollup/rollup-linux-arm64-gnu": "4.62.2", + "@rollup/rollup-linux-arm64-musl": "4.62.2", + "@rollup/rollup-linux-loong64-gnu": "4.62.2", + "@rollup/rollup-linux-loong64-musl": "4.62.2", + "@rollup/rollup-linux-ppc64-gnu": "4.62.2", + "@rollup/rollup-linux-ppc64-musl": "4.62.2", + "@rollup/rollup-linux-riscv64-gnu": "4.62.2", + "@rollup/rollup-linux-riscv64-musl": "4.62.2", + "@rollup/rollup-linux-s390x-gnu": "4.62.2", + "@rollup/rollup-linux-x64-gnu": "4.62.2", + "@rollup/rollup-linux-x64-musl": "4.62.2", + "@rollup/rollup-openbsd-x64": "4.62.2", + "@rollup/rollup-openharmony-arm64": "4.62.2", + "@rollup/rollup-win32-arm64-msvc": "4.62.2", + "@rollup/rollup-win32-ia32-msvc": "4.62.2", + "@rollup/rollup-win32-x64-gnu": "4.62.2", + "@rollup/rollup-win32-x64-msvc": "4.62.2", + "fsevents": "~2.3.2" + } + }, + "node_modules/rrweb-cssom": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", + "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "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", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "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, + "license": "MIT" + }, + "node_modules/sass": { + "version": "1.101.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.101.0.tgz", + "integrity": "sha512-OL3GoQyoUdDt843DpVmDO6y2k1sc5IhUDSpu8XucEI+35neq5QivZ1iuegnpraEVTJXlQGK1gl27zKcTLEPbQw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/saxes": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", + "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", + "dev": true, + "license": "ISC", + "dependencies": { + "xmlchars": "^2.2.0" + }, + "engines": { + "node": ">=v12.22.7" + } + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "license": "MIT", + "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, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, + "node_modules/sortablejs": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.7.tgz", + "integrity": "sha512-Kk8wLQPlS+yi1ZEf48a4+fzHa4yxjC30M/Sr2AnQu+f/MPwvvX9XjZ6OWejiz8crBsLwSq8GHqaxaET7u6ux0A==", + "license": "MIT", + "peer": true + }, + "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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sql-formatter": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/sql-formatter/-/sql-formatter-15.8.1.tgz", + "integrity": "sha512-nT2r90kTEYBuse9fe4r1Rp78v1mOBD35KsGc07Vo9eQSVa1TcTSnCS0zouf6BCmdzvmqBsBW+cYuBoYkHO/OWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "nearley": "^2.20.1" + }, + "bin": { + "sql-formatter": "bin/sql-formatter-cli.cjs" + } + }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strip-literal": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.1.0.tgz", + "integrity": "sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "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, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/symbol-tree": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", + "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", + "dev": true, + "license": "MIT" + }, + "node_modules/synckit": { + "version": "0.11.13", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.13.tgz", + "integrity": "sha512-eNRKgb3z66Yp3D2CixVujOUvXLFUTij/zVnV8KRyvFdQwpz7I5DS8UfRkTeLzb64u+dkzDSdelE24izu+zSSUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.3.6" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/synckit" + } + }, + "node_modules/tagged-tag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/tagged-tag/-/tagged-tag-1.0.0.tgz", + "integrity": "sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tiny-jsonc": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tiny-jsonc/-/tiny-jsonc-1.0.2.tgz", + "integrity": "sha512-f5QDAfLq6zIVSyCZQZhhyl0QS6MvAyTxgz4X4x3+EoCktNWEYJ6PeoEA97fyb98njpBNNi88ybpD7m+BDFXaCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tldts": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", + "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tldts-core": "^6.1.86" + }, + "bin": { + "tldts": "bin/cli.js" + } + }, + "node_modules/tldts-core": { + "version": "6.1.86", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", + "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tough-cookie": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", + "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tldts": "^6.1.32" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/tr46": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", + "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.3.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "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, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/upath": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/upath/-/upath-2.0.1.tgz", + "integrity": "sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validator": { + "version": "13.15.35", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz", + "integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vite": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.5.tgz", + "integrity": "sha512-KuOaNhcnGFN2zIPGA7wRmzF+lJA1sea7rHq17aiJ++9lzY1WWG6Jpwqwe1KNbRVPIqHmr8GLYx7jbrQcN/7/ww==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/vite-plugin-vuetify": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/vite-plugin-vuetify/-/vite-plugin-vuetify-2.1.3.tgz", + "integrity": "sha512-Q4SC/4TqbNvaZIFb9YsfBqkGlYHbJJJ6uU3CnRBZqLUF3s5eCMVZAaV4GkTbehIH/bhSj42lMXztOwc71u6rVw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@vuetify/loader-shared": "^2.1.2", + "debug": "^4.3.3", + "upath": "^2.0.1" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": ">=5", + "vue": "^3.0.0", + "vuetify": ">=3" + } + }, + "node_modules/vitest": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.6.tgz", + "integrity": "sha512-xejya+bT/j/+R/AGa1XOfRxLmNUlLtlwjRsFUILF+xHfzElmGcmFydy2gqqIrd62ptIEfwVMofd19uNWD9L7Nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.6", + "@vitest/mocker": "3.2.6", + "@vitest/pretty-format": "^3.2.6", + "@vitest/runner": "3.2.6", + "@vitest/snapshot": "3.2.6", + "@vitest/spy": "3.2.6", + "@vitest/utils": "3.2.6", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.6", + "@vitest/ui": "3.2.6", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.38", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.38.tgz", + "integrity": "sha512-vAMKHfImQlYSy0C+PBue4s3ERZ2xGKfgZg5GXAsLInq1dyh2H78ILVP5sK0KPFPVW4kv+OGCIvBEondcjpZp7A==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.38", + "@vue/compiler-sfc": "3.5.38", + "@vue/runtime-dom": "3.5.38", + "@vue/server-renderer": "3.5.38", + "@vue/shared": "3.5.38" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-draggable-next": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/vue-draggable-next/-/vue-draggable-next-2.3.0.tgz", + "integrity": "sha512-ymbY0UIwfSdg0iDN/iyNNwUrTqZ/6KbPryzsvTNXBLuDCuOBdNijSK8yynNtmiSj6RapTPQfjLGQdJrZkzBd2w==", + "license": "MIT", + "peerDependencies": { + "sortablejs": "^1.14.0", + "vue": "^3.5.17" + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-i18n": { + "version": "11.4.6", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-11.4.6.tgz", + "integrity": "sha512-l0gE7Rfy0phCa5ChKYkOq543Wgd39BCK6hkktfr1Ed4D99oRkgPK9ffShASZdeC8OJxGfdWmpYoAaAH6iLEuIg==", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "11.4.6", + "@intlify/devtools-types": "11.4.6", + "@intlify/shared": "11.4.6", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 22" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.6.4", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.6.4.tgz", + "integrity": "sha512-Hz9q5sa33Yhduglwz6g9skT8OBPii+4bFn88w6J+J4MfEo4KRRpmiNG/hHHkdbRFlLBOqxN8y8gf2Fb0MTUgVg==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.6.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/vue-scrollto": { + "version": "2.20.0", + "resolved": "https://registry.npmjs.org/vue-scrollto/-/vue-scrollto-2.20.0.tgz", + "integrity": "sha512-7i+AGKJTThZnMEkhIPgrZjyAX+fXV7/rGdg+CV283uZZwCxwiMXaBLTmIc5RTA4uwGnT+E6eJle3mXQfM2OD3A==", + "license": "MIT", + "dependencies": { + "bezier-easing": "2.1.0" + } + }, + "node_modules/vue-tsc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.5.tgz", + "integrity": "sha512-Rzh/G2MmNlMSAMTiQEjDrsb4dgB/jbtEM47rVN2NtidF1dfb/q4w4QvpQBtW5+y3y5H27Hjh7deVwk+YB02fNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.5" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/vuetify": { + "version": "3.12.8", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.12.8.tgz", + "integrity": "sha512-gvmOWeLd6CG7LVh2Qonft5YrIb7MpbKZglRjg0ItEloSbu6hfUII2RZmRSVxGKYdiXTf7J1hI3BRSHr8J9LkxA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/johnleider" + }, + "peerDependencies": { + "typescript": ">=4.7", + "vite-plugin-vuetify": ">=2.1.0", + "vue": "^3.5.0", + "webpack-plugin-vuetify": ">=3.1.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vite-plugin-vuetify": { + "optional": true + }, + "webpack-plugin-vuetify": { + "optional": true + } + } + }, + "node_modules/w3c-xmlserializer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", + "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "xml-name-validator": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/w3c-xmlserializer/node_modules/xml-name-validator": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", + "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", + "dev": true, + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-url": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", + "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tr46": "^5.1.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "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, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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, + "license": "ISC" + }, + "node_modules/ws": { + "version": "8.21.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", + "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/web/package.json b/web/package.json new file mode 100644 index 0000000..eb4167f --- /dev/null +++ b/web/package.json @@ -0,0 +1,63 @@ +{ + "name": "alphane-web", + "private": true, + "version": "0.1.0", + "type": "module", + "scripts": { + "start": "vite", + "build": "vue-tsc && vite build", + "preview": "vite preview", + "test": "vitest", + "lint": "eslint . --ext .js,.ts,.vue --ignore-path ../.gitignore", + "check-types": "vue-tsc --noEmit" + }, + "dependencies": { + "@auth0/auth0-vue": "^2.5.0", + "@mdi/font": "^7.4.47", + "@tabler/icons-vue": "^3.36.0", + "@vueuse/core": "^13.9.0", + "@vueuse/router": "^13.9.0", + "axios": "^1.13.2", + "dompurify": "^3.3.3", + "grid-layout-plus": "^1.1.1", + "js-yaml": "^4.1.0", + "lodash": "^4.17.21", + "luxon": "^3.7.2", + "marked": "^17.0.5", + "md5": "^2.3.0", + "qs": "^6.14.0", + "validator": "^13.15.26", + "vue": "^3.4.21", + "vue-draggable-next": "^2.3.0", + "vue-i18n": "^11.3.0", + "vue-router": "^4.6.4", + "vue-scrollto": "^2.20.0", + "vuetify": "^3.11.4" + }, + "devDependencies": { + "@types/dompurify": "^3.0.5", + "@types/js-yaml": "^4.0.9", + "@types/lodash": "^4.17.21", + "@types/luxon": "^3.7.1", + "@types/md5": "^2.3.6", + "@types/qs": "^6.14.0", + "@types/validator": "^13.15.10", + "@typescript-eslint/eslint-plugin": "^8.50.1", + "@typescript-eslint/parser": "^8.50.1", + "@vitejs/plugin-vue": "^6.0.3", + "eslint": "^8.57.1", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-vue": "^9.33.0", + "jsdom": "^26.1.0", + "prettier": "^3.7.4", + "prettier-plugin-embed": "^0.5.1", + "prettier-plugin-sql": "^0.19.2", + "sass": "^1.97.1", + "typescript": "^5.9.3", + "vite": "^7.3.0", + "vite-plugin-vuetify": "^2.1.2", + "vitest": "^3.2.4", + "vue-tsc": "^3.2.1" + } +} \ No newline at end of file diff --git a/web/public/Logo.png b/web/public/Logo.png new file mode 100644 index 0000000..df593a1 Binary files /dev/null and b/web/public/Logo.png differ diff --git a/web/public/Logo.svg b/web/public/Logo.svg new file mode 100644 index 0000000..571edb1 --- /dev/null +++ b/web/public/Logo.svg @@ -0,0 +1,9 @@ + +WRAP + +Workflow : Routing : Approvals + + + diff --git a/web/public/SplashImage.png b/web/public/SplashImage.png new file mode 100644 index 0000000..af85145 Binary files /dev/null and b/web/public/SplashImage.png differ diff --git a/web/public/favicon.ico b/web/public/favicon.ico new file mode 100644 index 0000000..5aebb70 Binary files /dev/null and b/web/public/favicon.ico differ diff --git a/web/public/yukon.svg b/web/public/yukon.svg new file mode 100644 index 0000000..fc4a4ac --- /dev/null +++ b/web/public/yukon.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/web/src/App.vue b/web/src/App.vue new file mode 100644 index 0000000..3327592 --- /dev/null +++ b/web/src/App.vue @@ -0,0 +1,113 @@ + + + diff --git a/web/src/api/api-error.ts b/web/src/api/api-error.ts new file mode 100644 index 0000000..3c80112 --- /dev/null +++ b/web/src/api/api-error.ts @@ -0,0 +1,12 @@ +export class ApiError extends Error { + public readonly name = "ApiError" + + constructor( + message: string, + public readonly status: number + ) { + super(message) + } +} + +export default ApiError diff --git a/web/src/api/base-api.ts b/web/src/api/base-api.ts new file mode 100644 index 0000000..625d8dc --- /dev/null +++ b/web/src/api/base-api.ts @@ -0,0 +1,44 @@ +/** Keep in sync with api/src/controllers/base-controller.ts#ModelOrder */ +export type ModelOrder = + | [string, string] + | [string, string, string] + | [string, string, string, string] + | [string, string, string, string, string] + | [string, string, string, string, string, string] + +export type Policy = { + show: boolean + create: boolean + update: boolean + destroy: boolean +} + +export type WhereOptions = { + [K in Attributes]?: Model[K] | Model[K][] +} + +export type FiltersOptions = Partial + +export type QueryOptions = Partial<{ + where: WhereOptions + filters: FiltersOptions + order: ModelOrder[] + page: number + perPage: number +}> + +// Keep in sync with api/src/controllers/base-controller.ts +export const MAX_PER_PAGE = 1000 + +export type ApiResponseError = { field?: string; text: string } + +export type ApiResponseLegacy = { + data: T + errors: ApiResponseError[] + messages?: string[] +} + +export type ApiResponse = { + errors: ApiResponseError[] + messages?: string[] +} & TPayload diff --git a/web/src/api/current-user-api.ts b/web/src/api/current-user-api.ts new file mode 100644 index 0000000..ce67e1b --- /dev/null +++ b/web/src/api/current-user-api.ts @@ -0,0 +1,23 @@ +import http from "@/api/http-client" + +import { type Policy } from "@/api/base-api" +import { UserRoles, type User } from "@/api/users-api" + +export { UserRoles } + +export type UserAsShow = Pick< + User, + "id" | "email" | "firstName" | "lastName" | "displayName" | "roles" | "createdAt" | "updatedAt" +> + +export const currentUserApi = { + async get(): Promise<{ + user: UserAsShow + policy: Policy + }> { + const { data } = await http.get(`/api/current-user`) + return data + }, +} + +export default currentUserApi diff --git a/web/src/api/http-client.ts b/web/src/api/http-client.ts new file mode 100644 index 0000000..3556ae9 --- /dev/null +++ b/web/src/api/http-client.ts @@ -0,0 +1,46 @@ +import qs from "qs" +import axios from "axios" + +import { API_BASE_URL } from "@/config" +import auth0 from "@/plugins/auth0-plugin" +import ApiError from "@/api/api-error" + +export const httpClient = axios.create({ + baseURL: API_BASE_URL, + headers: { + "Content-Type": "application/json", + }, + paramsSerializer: { + serialize: (params) => { + return qs.stringify(params, { + arrayFormat: "indices", + strictNullHandling: true, + }) + }, + }, +}) + +httpClient.interceptors.request.use(async (config) => { + // Only add the Authorization header to requests that start with "/api" + if (config.url?.startsWith("/api")) { + const accessToken = await auth0.getAccessTokenSilently() + config.headers["Authorization"] = `Bearer ${accessToken}` + } + + return config +}) + +// Any status codes that falls outside the range of 2xx causes this function to trigger +httpClient.interceptors.response.use(null, async (error) => { + if (error?.error === "login_required") { + throw new ApiError("You must be logged in to access this endpoint", 401) + } else if (error?.response?.data?.message) { + throw new ApiError(error.response.data.message, error.response.status) + } else if (error.message) { + throw new ApiError(error.message, error.response?.status || 500) + } else { + throw new ApiError("An unknown error occurred", error.response?.status || 500) + } +}) + +export default httpClient diff --git a/web/src/api/status-api.ts b/web/src/api/status-api.ts new file mode 100644 index 0000000..bced29f --- /dev/null +++ b/web/src/api/status-api.ts @@ -0,0 +1,18 @@ +import http from "@/api/http-client" + +export type Status = { + RELEASE_TAG: string + GIT_COMMIT_HASH: string +} + +export const statusApi = { + /** + * Note: This is a public API route, and not protected by authentication + */ + async get(): Promise { + const { data } = await http.get("/_status") + return data + }, +} + +export default statusApi diff --git a/web/src/api/users-api.ts b/web/src/api/users-api.ts new file mode 100644 index 0000000..960890c --- /dev/null +++ b/web/src/api/users-api.ts @@ -0,0 +1,81 @@ +import http from "@/api/http-client" +import { + type FiltersOptions, + type ModelOrder, + type Policy, + type WhereOptions, +} from "@/api/base-api" + +/** Keep in sync with api/src/models/user.ts */ +export enum UserRoles { + SYSTEM_ADMIN = "system_admin", + USER = "user", +} + +export type User = { + id: number + email: string + firstName: string + lastName: string + displayName: string + roles: UserRoles[] + createdAt: string + updatedAt: string +} + +export type UserAsShow = Omit & {} + +export type UserWhereOptions = WhereOptions + +export type UserFiltersOptions = FiltersOptions<{ + search: string | string[] +}> + +export type UserQueryOptions = { + where?: UserWhereOptions + filters?: UserFiltersOptions + order?: ModelOrder[] + page?: number + perPage?: number +} + +export const usersApi = { + UserRoles, + async list(params: UserQueryOptions = {}): Promise<{ + users: User[] + totalCount: number + }> { + const { data } = await http.get("/api/users", { + params, + }) + return data + }, + async get(userId: number): Promise<{ + user: User + policy: Policy + }> { + const { data } = await http.get(`/api/users/${userId}`) + return data + }, + async create(attributes: Partial): Promise<{ + user: User + }> { + const { data } = await http.post("/api/users", attributes) + return data + }, + async update( + userId: number, + attributes: Partial + ): Promise<{ + user: User + }> { + const { data } = await http.patch(`/api/users/${userId}`, attributes) + return data + }, + async delete(userId: number): Promise { + const { data } = await http.delete(`/api/users/${userId}`) + return data + }, +} + +export default usersApi diff --git a/web/src/assets/app_logo_big.png b/web/src/assets/app_logo_big.png new file mode 100644 index 0000000..64d19e5 Binary files /dev/null and b/web/src/assets/app_logo_big.png differ diff --git a/web/src/assets/app_logo_small.png b/web/src/assets/app_logo_small.png new file mode 100644 index 0000000..713f514 Binary files /dev/null and b/web/src/assets/app_logo_small.png differ diff --git a/web/src/assets/app_logo_splash.png b/web/src/assets/app_logo_splash.png new file mode 100644 index 0000000..3d8eb69 Binary files /dev/null and b/web/src/assets/app_logo_splash.png differ diff --git a/web/src/components/common/AppBreadcrumbs.vue b/web/src/components/common/AppBreadcrumbs.vue new file mode 100644 index 0000000..ab1d14f --- /dev/null +++ b/web/src/components/common/AppBreadcrumbs.vue @@ -0,0 +1,55 @@ + + + + + + + + diff --git a/web/src/components/common/AppCard.vue b/web/src/components/common/AppCard.vue new file mode 100644 index 0000000..51c3d3e --- /dev/null +++ b/web/src/components/common/AppCard.vue @@ -0,0 +1,46 @@ + + + diff --git a/web/src/components/common/AppLogo.vue b/web/src/components/common/AppLogo.vue new file mode 100644 index 0000000..75426c4 --- /dev/null +++ b/web/src/components/common/AppLogo.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/web/src/components/common/AppSnackbar.vue b/web/src/components/common/AppSnackbar.vue new file mode 100644 index 0000000..49e3112 --- /dev/null +++ b/web/src/components/common/AppSnackbar.vue @@ -0,0 +1,82 @@ + + + diff --git a/web/src/components/common/CollapsibleCard.vue b/web/src/components/common/CollapsibleCard.vue new file mode 100644 index 0000000..a4d7fa9 --- /dev/null +++ b/web/src/components/common/CollapsibleCard.vue @@ -0,0 +1,50 @@ + + + diff --git a/web/src/components/common/ConfirmDialog.vue b/web/src/components/common/ConfirmDialog.vue new file mode 100644 index 0000000..5a0044d --- /dev/null +++ b/web/src/components/common/ConfirmDialog.vue @@ -0,0 +1,77 @@ + + + diff --git a/web/src/components/common/DescriptionElement.vue b/web/src/components/common/DescriptionElement.vue new file mode 100644 index 0000000..65e4f5b --- /dev/null +++ b/web/src/components/common/DescriptionElement.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/web/src/components/common/HeaderActionsCard.vue b/web/src/components/common/HeaderActionsCard.vue new file mode 100644 index 0000000..547a2d0 --- /dev/null +++ b/web/src/components/common/HeaderActionsCard.vue @@ -0,0 +1,73 @@ + + + diff --git a/web/src/components/common/HeaderActionsCardBody.vue b/web/src/components/common/HeaderActionsCardBody.vue new file mode 100644 index 0000000..09e9f75 --- /dev/null +++ b/web/src/components/common/HeaderActionsCardBody.vue @@ -0,0 +1,74 @@ + + + diff --git a/web/src/components/common/HeaderActionsFormCard.vue b/web/src/components/common/HeaderActionsFormCard.vue new file mode 100644 index 0000000..b2ea960 --- /dev/null +++ b/web/src/components/common/HeaderActionsFormCard.vue @@ -0,0 +1,101 @@ + + + diff --git a/web/src/components/common/PageLoader.vue b/web/src/components/common/PageLoader.vue new file mode 100644 index 0000000..fcb2961 --- /dev/null +++ b/web/src/components/common/PageLoader.vue @@ -0,0 +1,17 @@ + + + diff --git a/web/src/components/common/PercentageTextField.vue b/web/src/components/common/PercentageTextField.vue new file mode 100644 index 0000000..47cfb9b --- /dev/null +++ b/web/src/components/common/PercentageTextField.vue @@ -0,0 +1,85 @@ + + + diff --git a/web/src/components/common/ResponsiveDialog.vue b/web/src/components/common/ResponsiveDialog.vue new file mode 100644 index 0000000..b8d5d00 --- /dev/null +++ b/web/src/components/common/ResponsiveDialog.vue @@ -0,0 +1,83 @@ + + + diff --git a/web/src/components/common/StringDateInput.vue b/web/src/components/common/StringDateInput.vue new file mode 100644 index 0000000..178eb8f --- /dev/null +++ b/web/src/components/common/StringDateInput.vue @@ -0,0 +1,70 @@ + + + diff --git a/web/src/components/layout/DefaultAppBar.vue b/web/src/components/layout/DefaultAppBar.vue new file mode 100644 index 0000000..2a9a279 --- /dev/null +++ b/web/src/components/layout/DefaultAppBar.vue @@ -0,0 +1,40 @@ + + + diff --git a/web/src/components/layout/DefaultSideBar.vue b/web/src/components/layout/DefaultSideBar.vue new file mode 100644 index 0000000..100d1cd --- /dev/null +++ b/web/src/components/layout/DefaultSideBar.vue @@ -0,0 +1,70 @@ + + + diff --git a/web/src/components/layout/ExactingBreadcrumbs.vue b/web/src/components/layout/ExactingBreadcrumbs.vue new file mode 100644 index 0000000..53716e3 --- /dev/null +++ b/web/src/components/layout/ExactingBreadcrumbs.vue @@ -0,0 +1,69 @@ + + + + + + + diff --git a/web/src/components/layout/ProfileMenu.vue b/web/src/components/layout/ProfileMenu.vue new file mode 100644 index 0000000..6a0e913 --- /dev/null +++ b/web/src/components/layout/ProfileMenu.vue @@ -0,0 +1,160 @@ + + + diff --git a/web/src/components/layout/SearchMenu.vue b/web/src/components/layout/SearchMenu.vue new file mode 100644 index 0000000..46c2304 --- /dev/null +++ b/web/src/components/layout/SearchMenu.vue @@ -0,0 +1,59 @@ + + + diff --git a/web/src/components/users/UserEditCardForm.vue b/web/src/components/users/UserEditCardForm.vue new file mode 100644 index 0000000..ea12861 --- /dev/null +++ b/web/src/components/users/UserEditCardForm.vue @@ -0,0 +1,196 @@ + + + diff --git a/web/src/components/users/UserProfileCard.vue b/web/src/components/users/UserProfileCard.vue new file mode 100644 index 0000000..247d7d6 --- /dev/null +++ b/web/src/components/users/UserProfileCard.vue @@ -0,0 +1,86 @@ + + + diff --git a/web/src/components/users/UserRoleSelect.vue b/web/src/components/users/UserRoleSelect.vue new file mode 100644 index 0000000..b3e51ff --- /dev/null +++ b/web/src/components/users/UserRoleSelect.vue @@ -0,0 +1,30 @@ + + + diff --git a/web/src/components/users/UsersDataTableServer.vue b/web/src/components/users/UsersDataTableServer.vue new file mode 100644 index 0000000..33741fb --- /dev/null +++ b/web/src/components/users/UsersDataTableServer.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/web/src/config.ts b/web/src/config.ts new file mode 100644 index 0000000..1f98d72 --- /dev/null +++ b/web/src/config.ts @@ -0,0 +1,47 @@ +import { stripTrailingSlash } from "@/utils/strip-trailing-slash" + +export const ENVIRONMENT = import.meta.env.MODE + +const prodConfig = { + domain: "https://dev-7mdjzcgwirhocfwm.ca.auth0.com", + clientId: "TRlKzdNBynpo9tU1RSmnF0p8d3IEam4J", + audience: "alphane-api", + apiBaseUrl: "", + webSocketBaseUrl: "", + applicationName: "ALPHANE", +} + +const devConfig = { + domain: "https://dev-7mdjzcgwirhocfwm.ca.auth0.com", + clientId: "TRlKzdNBynpo9tU1RSmnF0p8d3IEam4J", + audience: "alphane-api", + apiBaseUrl: "http://localhost:3000", + webSocketBaseUrl: "ws://localhost:3000", + applicationName: "ALPHANE", +} + +const localProductionConfig = { + domain: "https://dev-7mdjzcgwirhocfwm.ca.auth0.com", + clientId: "TRlKzdNBynpo9tU1RSmnF0p8d3IEam4J", + audience: "alphane-api", + apiBaseUrl: "http://localhost:8080", + webSocketBaseUrl: "ws://localhost:8080", + applicationName: "ALPHANE (production)", +} + +let config = prodConfig + +if (ENVIRONMENT === "production" && window.location.host === "localhost:8080") { + config = localProductionConfig +} else if (window.location.host === "localhost:8080") { + config = devConfig +} + +export const APPLICATION_NAME = config.applicationName + +export const API_BASE_URL = config.apiBaseUrl +export const WEB_SOCKET_BASE_URL = config.webSocketBaseUrl + +export const AUTH0_DOMAIN = stripTrailingSlash(config.domain) +export const AUTH0_AUDIENCE = config.audience +export const AUTH0_CLIENT_ID = config.clientId diff --git a/web/src/directives/index.ts b/web/src/directives/index.ts new file mode 100644 index 0000000..6e3408c --- /dev/null +++ b/web/src/directives/index.ts @@ -0,0 +1,5 @@ +import { visible } from "./visible" + +export default { + visible, +} diff --git a/web/src/directives/visible.ts b/web/src/directives/visible.ts new file mode 100644 index 0000000..41a1b65 --- /dev/null +++ b/web/src/directives/visible.ts @@ -0,0 +1,27 @@ +import { DirectiveBinding } from "vue" + +/** + * Shows or hides an element using visibility property based on a boolean value. + * + * This makes helps loaders avoid downshift flickering when they trigger. + * + * See https://vuejs.org/guide/reusability/custom-directives.html#function-shorthand + * + * @usage + * ```html + * + * ``` + */ +export function visible(el: HTMLElement, binding: DirectiveBinding) { + if (binding.value) { + el.style.visibility = "visible" + } else { + el.style.visibility = "hidden" + } +} + +export default visible diff --git a/web/src/layouts/AdministrationLayout.vue b/web/src/layouts/AdministrationLayout.vue new file mode 100644 index 0000000..e8789e6 --- /dev/null +++ b/web/src/layouts/AdministrationLayout.vue @@ -0,0 +1,49 @@ + + + diff --git a/web/src/layouts/DefaultLayout.vue b/web/src/layouts/DefaultLayout.vue new file mode 100644 index 0000000..96aea7d --- /dev/null +++ b/web/src/layouts/DefaultLayout.vue @@ -0,0 +1,22 @@ + + + diff --git a/web/src/layouts/LayoutWithBreadcrumbs.vue b/web/src/layouts/LayoutWithBreadcrumbs.vue new file mode 100644 index 0000000..aa81ecd --- /dev/null +++ b/web/src/layouts/LayoutWithBreadcrumbs.vue @@ -0,0 +1,69 @@ + + + diff --git a/web/src/layouts/ProfileLayout.vue b/web/src/layouts/ProfileLayout.vue new file mode 100644 index 0000000..463b357 --- /dev/null +++ b/web/src/layouts/ProfileLayout.vue @@ -0,0 +1,33 @@ + + + + + diff --git a/web/src/layouts/logo/AppLogo.vue b/web/src/layouts/logo/AppLogo.vue new file mode 100644 index 0000000..9985c18 --- /dev/null +++ b/web/src/layouts/logo/AppLogo.vue @@ -0,0 +1,50 @@ + + + + + diff --git a/web/src/locales/en.js b/web/src/locales/en.js new file mode 100644 index 0000000..e146645 --- /dev/null +++ b/web/src/locales/en.js @@ -0,0 +1,8 @@ +export default { + user: { + roles: { + system_admin: "System Admin", + user: "User", + }, + }, +} diff --git a/web/src/main.ts b/web/src/main.ts new file mode 100644 index 0000000..a28f7a1 --- /dev/null +++ b/web/src/main.ts @@ -0,0 +1,25 @@ +import { createApp } from "vue" + +// Plugins +import vuetify from "@/plugins/vuetify-plugin" +import auth0 from "@/plugins/auth0-plugin" +import vueI18nPlugin from "@/plugins/vue-i18n-plugin" + +import "@/scss/style.scss" +import VueScrollTo from "vue-scrollto" +import directives from "@/directives" +import router from "@/router" + +import App from "@/App.vue" + +const app = createApp(App) +app.use(router).use(vuetify).use(auth0).use(vueI18nPlugin) + +app.directive("visible", directives.visible) + +app.mount("#app") + +app.use(VueScrollTo, { + duration: 1000, + easing: "ease", +}) diff --git a/web/src/pages/CallbackPage.vue b/web/src/pages/CallbackPage.vue new file mode 100644 index 0000000..28a099a --- /dev/null +++ b/web/src/pages/CallbackPage.vue @@ -0,0 +1,23 @@ + + + diff --git a/web/src/pages/DashboardPage.vue b/web/src/pages/DashboardPage.vue new file mode 100644 index 0000000..114c46a --- /dev/null +++ b/web/src/pages/DashboardPage.vue @@ -0,0 +1,16 @@ + + + diff --git a/web/src/pages/ProfilePage.vue b/web/src/pages/ProfilePage.vue new file mode 100644 index 0000000..5ee1be1 --- /dev/null +++ b/web/src/pages/ProfilePage.vue @@ -0,0 +1,27 @@ + + + + + diff --git a/web/src/pages/SignInPage.vue b/web/src/pages/SignInPage.vue new file mode 100644 index 0000000..1122518 --- /dev/null +++ b/web/src/pages/SignInPage.vue @@ -0,0 +1,115 @@ + + + diff --git a/web/src/pages/StatusPage.vue b/web/src/pages/StatusPage.vue new file mode 100644 index 0000000..8bf3efb --- /dev/null +++ b/web/src/pages/StatusPage.vue @@ -0,0 +1,93 @@ + + + diff --git a/web/src/pages/administration/AdministrationDashboardPage.vue b/web/src/pages/administration/AdministrationDashboardPage.vue new file mode 100644 index 0000000..9a9dc8e --- /dev/null +++ b/web/src/pages/administration/AdministrationDashboardPage.vue @@ -0,0 +1,118 @@ + + + diff --git a/web/src/pages/administration/SettingsPage.vue b/web/src/pages/administration/SettingsPage.vue new file mode 100644 index 0000000..25f351b --- /dev/null +++ b/web/src/pages/administration/SettingsPage.vue @@ -0,0 +1,14 @@ + + + diff --git a/web/src/pages/administration/UsersPage.vue b/web/src/pages/administration/UsersPage.vue new file mode 100644 index 0000000..7dedbee --- /dev/null +++ b/web/src/pages/administration/UsersPage.vue @@ -0,0 +1,46 @@ + + + diff --git a/web/src/pages/administration/users/UserEditPage.vue b/web/src/pages/administration/users/UserEditPage.vue new file mode 100644 index 0000000..d68a3e3 --- /dev/null +++ b/web/src/pages/administration/users/UserEditPage.vue @@ -0,0 +1,70 @@ + + + + + diff --git a/web/src/pages/administration/users/UserNewPage.vue b/web/src/pages/administration/users/UserNewPage.vue new file mode 100644 index 0000000..3ee6a05 --- /dev/null +++ b/web/src/pages/administration/users/UserNewPage.vue @@ -0,0 +1,353 @@ + + + diff --git a/web/src/pages/errors/ForbiddenPage.vue b/web/src/pages/errors/ForbiddenPage.vue new file mode 100644 index 0000000..a8baa60 --- /dev/null +++ b/web/src/pages/errors/ForbiddenPage.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/web/src/pages/errors/InternalServerErrorPage.vue b/web/src/pages/errors/InternalServerErrorPage.vue new file mode 100644 index 0000000..f0af657 --- /dev/null +++ b/web/src/pages/errors/InternalServerErrorPage.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/web/src/pages/errors/NotFoundPage.vue b/web/src/pages/errors/NotFoundPage.vue new file mode 100644 index 0000000..9ab6e0c --- /dev/null +++ b/web/src/pages/errors/NotFoundPage.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/web/src/pages/errors/UnauthorizedPage.vue b/web/src/pages/errors/UnauthorizedPage.vue new file mode 100644 index 0000000..91ff9de --- /dev/null +++ b/web/src/pages/errors/UnauthorizedPage.vue @@ -0,0 +1,79 @@ + + + + + diff --git a/web/src/pages/profile/ProfileEditPage.vue b/web/src/pages/profile/ProfileEditPage.vue new file mode 100644 index 0000000..f49184a --- /dev/null +++ b/web/src/pages/profile/ProfileEditPage.vue @@ -0,0 +1,46 @@ + + + + + diff --git a/web/src/plugins/auth0-plugin.ts b/web/src/plugins/auth0-plugin.ts new file mode 100644 index 0000000..ca8e12f --- /dev/null +++ b/web/src/plugins/auth0-plugin.ts @@ -0,0 +1,14 @@ +import { createAuth0 } from "@auth0/auth0-vue" + +import { AUTH0_AUDIENCE, AUTH0_CLIENT_ID, AUTH0_DOMAIN, ENVIRONMENT } from "@/config" + +// See https://auth0.github.io/auth0-vue/#md:add-login-to-your-application +export default createAuth0({ + domain: AUTH0_DOMAIN, + clientId: AUTH0_CLIENT_ID, + authorizationParams: { + audience: AUTH0_AUDIENCE, + redirect_uri: `${window.location.origin}/callback`, + }, + cacheLocation: ENVIRONMENT === "development" ? "localstorage" : "memory", +}) diff --git a/web/src/plugins/vue-i18n-plugin.ts b/web/src/plugins/vue-i18n-plugin.ts new file mode 100644 index 0000000..741d0e5 --- /dev/null +++ b/web/src/plugins/vue-i18n-plugin.ts @@ -0,0 +1,13 @@ +import { createI18n } from "vue-i18n" + +// I'd prefer to use yaml, or even json, but I can't get them to import at the moment +// This might be a TypeScript issue, or I might need a yaml plugin. +import en from "@/locales/en.js" + +export default createI18n({ + legacy: false, // support composition api + locale: "en", + messages: { + en, + }, +}) diff --git a/web/src/plugins/vuetify-plugin.ts b/web/src/plugins/vuetify-plugin.ts new file mode 100644 index 0000000..d0c9cee --- /dev/null +++ b/web/src/plugins/vuetify-plugin.ts @@ -0,0 +1,86 @@ +/** + * plugins/vuetify.js + * + * Framework documentation: https://vuetifyjs.com` + */ + +// Styles +import "@mdi/font/css/materialdesignicons.css" +import "vuetify/styles" + +// ComposablesF +import { createVuetify } from "vuetify" +import * as components from "vuetify/components" +import * as directives from "vuetify/directives" +import * as labsComponents from "vuetify/labs/components" + +import { + DARK_BLUE_THEME, + DARK_AQUA_THEME, + DARK_ORANGE_THEME, + DARK_PURPLE_THEME, + DARK_GREEN_THEME, + DARK_CYAN_THEME, +} from "@/theme/DarkTheme" + +// https://vuetifyjs.com/en/introduction/why-vuetify/#feature-guides +export default createVuetify({ + components: { + ...components, + ...labsComponents, + }, + directives, + theme: { + defaultTheme: "DARK_AQUA_THEME", + themes: { + DARK_BLUE_THEME, + DARK_AQUA_THEME, + DARK_ORANGE_THEME, + DARK_PURPLE_THEME, + DARK_GREEN_THEME, + DARK_CYAN_THEME, + }, + }, + defaults: { + VCard: { + rounded: "md", + }, + VTextField: { + variant: "outlined", + density: "comfortable", + color: "primary", + }, + VTextarea: { + variant: "outlined", + density: "comfortable", + color: "primary", + }, + VFileInput: { + variant: "outlined", + density: "comfortable", + color: "primary", + prependIcon: null, + }, + VSelect: { + variant: "outlined", + density: "comfortable", + color: "primary", + }, + VCombobox: { + variant: "outlined", + density: "comfortable", + color: "primary", + }, + VAutocomplete: { + variant: "outlined", + density: "comfortable", + color: "primary", + }, + VListItem: { + minHeight: "45px", + }, + VTooltip: { + location: "top", + }, + }, +}) diff --git a/web/src/router.ts b/web/src/router.ts new file mode 100644 index 0000000..b26128e --- /dev/null +++ b/web/src/router.ts @@ -0,0 +1,152 @@ +import { createRouter, createWebHistory, type RouteRecordRaw } from "vue-router" +import { authGuard } from "@auth0/auth0-vue" + +import { APPLICATION_NAME } from "@/config" +import administrationRoutes from "@/routes/administration-routes" +import { authorizationGuard } from "@/utils/authorization-guards" + +const routes: RouteRecordRaw[] = [ + { + path: "/", + name: "SignInPage", + component: () => import("@/pages/SignInPage.vue"), + meta: { requiresAuth: false }, + }, + { + path: "/callback", + name: "CallbackPage", + component: () => import("@/pages/CallbackPage.vue"), + meta: { requiresAuth: false }, + }, + { + path: "/", + component: () => import("@/layouts/DefaultLayout.vue"), + children: [ + { + path: "", + redirect: "sign-in", + }, + { + name: "DashboardPage", + path: "dashboard", + component: () => import("@/pages/DashboardPage.vue"), + meta: { + title: "Dashboard", + }, + }, + { + path: "", + component: () => import("@/layouts/LayoutWithBreadcrumbs.vue"), + children: [ + { + path: "profile", + component: () => import("@/layouts/ProfileLayout.vue"), + meta: { + title: "Profile", + }, + children: [ + { + path: "", + name: "ProfilePage", + redirect: { name: "profile/ProfileEditPage" }, + }, + ], + }, + + { + path: "profile/edit", + name: "profile/ProfileEditPage", + component: () => import("@/pages/profile/ProfileEditPage.vue"), + meta: { + title: "Edit Profile", + }, + }, + ], + }, + ], + }, + ...administrationRoutes, + { + name: "StatusPage", + path: "/status", + component: () => import("@/pages/StatusPage.vue"), + meta: { + title: "Status", + requiresAuth: false, + }, + }, + { + path: "/errors/unauthorized", + name: "errors/UnauthorizedPage", + component: () => import("@/pages/errors/UnauthorizedPage.vue"), + meta: { + title: "Unauthorized", + requiresAuth: false, + }, + }, + { + path: "/errors/forbidden", + name: "errors/ForbiddenPage", + component: () => import("@/pages/errors/ForbiddenPage.vue"), + meta: { + title: "Forbidden", + requiresAuth: false, + }, + }, + { + path: "/errors/internal-server-error", + name: "errors/InternalServerErrorPage", + component: () => import("@/pages/errors/InternalServerErrorPage.vue"), + meta: { + title: "Internal Server Error", + requiresAuth: false, + }, + }, + { + path: "/errors/not-found", + name: "errors/NotFoundPage", + component: () => import("@/pages/errors/NotFoundPage.vue"), + meta: { + title: "Not Found", + requiresAuth: false, + }, + }, + { + path: "/:pathMatch(.*)*", + redirect: "/errors/not-found", + }, +] + +const router = createRouter({ + history: createWebHistory(), + routes, +}) + +router.onError((error, to) => { + if ( + error.message.includes("Failed to fetch dynamically imported module") || + error.message.includes("Importing a module script failed") + ) { + window.location.href = to.fullPath + } +}) + +router.beforeEach(async (to) => { + if (to.meta && to.meta.title) { + document.title = `${APPLICATION_NAME} - ${to.meta.title}` + } else { + document.title = APPLICATION_NAME + } + + if (to.meta.requiresAuth === false) return true + + const isAuthenticated = await authGuard(to) + if (!isAuthenticated) return false + + const isAuthorized = await authorizationGuard(to) + if (!isAuthorized) return "/errors/forbidden" + + return true +}) + +export default router diff --git a/web/src/routes/administration-routes.ts b/web/src/routes/administration-routes.ts new file mode 100644 index 0000000..2e38182 --- /dev/null +++ b/web/src/routes/administration-routes.ts @@ -0,0 +1,50 @@ +import { RouteRecordRaw } from "vue-router" + +import { isSystemAdmin } from "@/utils/authorization-guards" + +export const administrationRoutes: Readonly = [ + { + path: "/administration", + component: () => import("@/layouts/AdministrationLayout.vue"), + meta: { + guards: [isSystemAdmin], + }, + children: [ + { + path: "", + name: "administration/AdministrationDashboardPage", + component: () => import("@/pages/administration/AdministrationDashboardPage.vue"), + }, + { + path: "users", + name: "administration/UsersPage", + component: () => import("@/pages/administration/UsersPage.vue"), + }, + { + path: "users/new", + name: "administration/users/UserNewPage", + component: () => import("@/pages/administration/users/UserNewPage.vue"), + props: true, + }, + { + path: "users/:userId", + name: "administration/users/UserPage", + component: () => import("@/pages/administration/users/UserEditPage.vue"), + props: true, + }, + { + path: "users/:userId/edit", + name: "administration/users/UserEditPage", + component: () => import("@/pages/administration/users/UserEditPage.vue"), + props: true, + }, + { + path: "settings", + name: "administration/SettingsPage", + component: () => import("@/pages/administration/SettingsPage.vue"), + }, + ], + }, +] + +export default administrationRoutes diff --git a/web/src/scss/_override.scss b/web/src/scss/_override.scss new file mode 100644 index 0000000..c9e294c --- /dev/null +++ b/web/src/scss/_override.scss @@ -0,0 +1,204 @@ +@use "./variables" as *; + +html { + .bg-success { + color: $white !important; + } + + .bg-primary { + color: $white !important; + } + + .bg-secondary { + color: $white !important; + } + + .bg-warning { + color: $white !important; + } + + .bg-secondary-gradient { + background: linear-gradient(287deg, rgb(var(--v-theme-primary)) .54%, #1bcaff 100.84%); + } +} + + + + +.border, +.v-divider { + border-color: rgba(var(--v-border-color)) !important; +} + +.avtar-border { + border: 2px solid rgb(var(--v-theme-surface)) !important; +} + +.subtext { + font-size: $font-size-root; + line-height: 1.75rem; +} + +.v-dialog { + &.dialog-mw { + max-width: 800px; + } +} + +.round-40 { + height: 40px; + width: 40px; +} + +.round-56 { + height: 56px; + width: 56px; +} + +.round-48 { + height: 48px; + width: 48px; +} + +.round-30 { + height: 30px; + width: 30px; +} + +.lh-0 { + line-height: 0 !important; +} + + +.lh-28 { + line-height: 28px !important; +} + +.lh-32 { + line-height: 32px !important; +} + +.space-p-96 { + padding: 96px 0 !important; + +} + +.ps-96 { + padding-inline-start: 96px !important; +} + +.pt-96 { + padding-top: 96px !important; +} + +.end-0 { + inset-inline-end: 0; +} + +.top-0 { + top: 0; +} + +.no-scrollbar { + height: calc(100vh - 350px); +} + +.msg-chat-height { + height: calc(-500px + 100vh); +} + +@media screen and (max-width:991px) { + .overflow-x-reposive { + overflow-x: scroll; + overflow-y: hidden; + } + + .border-m-none { + border: 0 !important + } +} + +@media screen and (max-height:767px) { + .msg-chat-height { + height: calc(-315px + 100vh); + } + +} + +.max-h-600 { + max-height: 600px; + height: calc(100vh - 100px); +} + + +.custom-hover-primary { + .iconify { + color: rgb(255, 255, 255) !important; + + @media screen and (max-width:991px) { + color: rgba(var(--v-theme-textPrimary), 0.8) !important + } + } + + &:hover { + background-color: rgba(var(--v-theme-lightprimary), 0.1); + + .iconify { + @media screen and (max-width:991px) { + color: rgb(var(--v-theme-primary)) !important + } + } + } +} +.custom-hover-primary-white { + .iconify { + color: rgb(255, 255, 255) !important; + + + } + + &:hover { + background-color: rgba(var(--v-theme-lightprimary), 0.1); + + } +} + +.no-icon { + + .v-input__prepend, + .v-input__append { + display: none !important; + } +} + +.bg-white { + background-color: rgb(255, 255, 255) !important; +} + +.v-badge { + &.x-small-badge { + .v-badge__badge { + height: 6px !important; + width: 6px !important; + } + + } +} + +.one-line { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 1; +} + +.two-line { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; +} + +.z-1 { + z-index: 1; +} \ No newline at end of file diff --git a/web/src/scss/_variables.scss b/web/src/scss/_variables.scss new file mode 100644 index 0000000..7fe2161 --- /dev/null +++ b/web/src/scss/_variables.scss @@ -0,0 +1,150 @@ +@use "sass:math"; +@use "sass:map"; +@use "sass:meta"; +@use "vuetify/lib/styles/tools/functions" as *; + +// Custom Variables +// colors +$white: #fff !default; + +// cards +$card-title-size: 18px !default; + +$body-font-family: "Overpass", sans-serif !default; +$border-radius-root: 10px; +$btn-font-weight: 400 !default; +$btn-letter-spacing: 0 !default; + +// Global Shadow +$box-shadow: + rgba(145 158 171 / 30%) 0px 0px 2px 0px, + rgba(145 158 171 / 12%) 0px 12px 24px -4px; + +// Global Radius as per breakeven point + +@forward "vuetify/settings" with ( + $color-pack: false !default, + // Global font size and border radius + $font-size-root: 1rem, + $border-radius-root: $border-radius-root, + $body-font-family: $body-font-family, + $heading-font-family: $body-font-family !default, + $button-height: 40px, + // 👉 Typography + $typography: ( + "h1": ( + "size": 2.25rem, + "weight": 600, + "line-height": 2.75rem, + "font-family": inherit, + ), + "h2": ( + "size": 1.875rem, + "weight": 500, + "line-height": 2.25rem, + "font-family": inherit, + ), + "h3": ( + "size": 1.5rem, + "weight": 500, + "line-height": 2rem, + "font-family": inherit, + ), + "h4": ( + "size": 1.3125rem, + "weight": 500, + "line-height": 1.6rem, + "font-family": inherit, + ), + "h5": ( + "size": 1.125rem, + "weight": 500, + "line-height": 1.6rem, + "font-family": inherit, + ), + "h6": ( + "size": 1rem, + "weight": 500, + "line-height": 1.2rem, + "font-family": inherit, + ), + "subtitle-1": ( + "size": 0.875rem, + "weight": 400, + "line-height": 1.1rem, + "font-family": inherit, + ), + "subtitle-2": ( + "size": 0.75rem, + "weight": 400, + "line-height": 1rem, + "font-family": inherit, + ), + "body-1": ( + "size": 0.875rem, + "weight": 400, + "font-family": inherit, + ), + "body-2": ( + "size": 0.75rem, + "weight": 400, + "font-family": inherit, + ), + "button": ( + "size": 0.875rem, + "weight": 500, + "font-family": inherit, + "text-transform": capitalize, + ), + "caption": ( + "size": 0.75rem, + "weight": 400, + "font-family": inherit, + ), + "overline": ( + "size": 0.75rem, + "weight": 500, + "font-family": inherit, + "text-transform": uppercase, + ), + ) + !default, + // 👉 Button + $button-border-radius: $border-radius-root !default, + $button-text-letter-spacing: 0 !default, + $button-text-transform: capitalize, + $button-elevation: ( + "default": 0, + "hover": 4, + "active": 8, + ) + !default, + + // 👉 Tooltip + $tooltip-background-color: #212121 !default, + $tooltip-text-color: rgb(var(--v-theme-on-primary)) !default, + $tooltip-font-size: 0.75rem !default, + $tooltip-border-radius: 4px !default, + $tooltip-padding: 4px 8px !default, + + // 👉 Rounded + $rounded: ( + 0: 0, + "sm": $border-radius-root * 0.5, + null: $border-radius-root, + "md": $border-radius-root * 1, + "lg": $border-radius-root * 2, + "xl": $border-radius-root * 6, + "pill": 9999px, + "circle": 50%, + ), + + // 👉 Card + // $card-color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity)) !default, + $card-elevation: 10 !default, + $card-title-line-height: 1.6 !default, + $card-text-padding: 24px !default, + $card-item-padding: 30px 30px 24px !default, + $card-actions-padding: 10px 24px 24px !default, + $card-subtitle-opacity: 1 !default // $card-border-color $border-color-root +); diff --git a/web/src/scss/components/_VAlert.scss b/web/src/scss/components/_VAlert.scss new file mode 100644 index 0000000..8415aed --- /dev/null +++ b/web/src/scss/components/_VAlert.scss @@ -0,0 +1,24 @@ +.single-line-alert { + .v-alert__close, + .v-alert__prepend { + align-self: center !important; + } +} + +@media (max-width: 500px) { + .single-line-alert { + display: flex; + flex-wrap: wrap; + + .v-alert__append { + margin-inline-start: 0px; + } + .v-alert__close { + margin-left: auto; + } + .v-alert__content { + width: 100%; + margin-top: 5px; + } + } +} diff --git a/web/src/scss/components/_VBreadcrumb.scss b/web/src/scss/components/_VBreadcrumb.scss new file mode 100644 index 0000000..81b4ad1 --- /dev/null +++ b/web/src/scss/components/_VBreadcrumb.scss @@ -0,0 +1,9 @@ + +.v-breadcrumbs{ + .v-breadcrumbs-divider{ + padding: 0 0 !important; + } + .v-breadcrumbs-item--link{ + text-decoration: none; + } +} diff --git a/web/src/scss/components/_VButtons.scss b/web/src/scss/components/_VButtons.scss new file mode 100644 index 0000000..dd2183e --- /dev/null +++ b/web/src/scss/components/_VButtons.scss @@ -0,0 +1,22 @@ +.v-btn-group .v-btn { + height: inherit !important; +} + +.v-btn-group { + border-color: rgb(var(--v-theme-borderColor)) !important; +} +.v-btn{ + text-transform: capitalize; + letter-spacing: 0; + border-radius: 30px; + + &.v-btn--variant-elevated{ + box-shadow: none !important; + } + .v-btn--slim{ + padding: 0 15px; + } +} +.v-btn--elevated:hover{ + box-shadow: none; +} diff --git a/web/src/scss/components/_VCard.scss b/web/src/scss/components/_VCard.scss new file mode 100644 index 0000000..3bf5eb6 --- /dev/null +++ b/web/src/scss/components/_VCard.scss @@ -0,0 +1,69 @@ +// Outline Card +.v-card--variant-outlined { + border-color: rgba(var(--v-theme-borderColor)) !important; +} + +.v-card--variant-elevated, +.v-card--variant-flat { + color: rgb(var(--v-theme-textPrimary)); +} + +.card-hover { + transition: box-shadow 300ms cubic-bezier(0.4, 0, 0.2, 1) 0ms; + &:hover { + scale: 1.01; + transition: all 0.1s ease-in 0s; + } +} + +.v-card { + width: 100%; + overflow: visible; + .color-inherits { + color: inherit; + } + .feature-card { + .v-responsive__content { + height: 100%; + } + } + .v-timeline-divider__before,.v-timeline-divider__after { + background: rgba(var(--v-border-color), 1); + } + .v-card-text{ + padding: 24px 24px; + } + .v-card-item{ + padding: 24px 24px; + } +} + +// Theme cards +.cardBordered { + .v-card { + box-shadow: none !important; + border: 1px solid rgb(var(--v-theme-borderColor)); + } +} + +.elevation-o-card{ + .v-card-item{ + padding: 0.625rem 1rem; + } +} + +.card-title{ + font-size: 18px; + font-weight: 500; + color:rgb(var(--v-theme-textPrimary)); +} +.card-subtitle{ + font-size: 14px; + font-weight: 400; + color:rgb(var(--v-theme-textSecondary)); +} +.dark-card-title{ + font-size: 18px; + font-weight: 500; + color:rgb(var(--v-theme-textPrimary)); +} \ No newline at end of file diff --git a/web/src/scss/components/_VCarousel.scss b/web/src/scss/components/_VCarousel.scss new file mode 100644 index 0000000..42306be --- /dev/null +++ b/web/src/scss/components/_VCarousel.scss @@ -0,0 +1,3 @@ +.theme-carousel .v-carousel__progress { + position: absolute; +} diff --git a/web/src/scss/components/_VDatatable.scss b/web/src/scss/components/_VDatatable.scss new file mode 100644 index 0000000..a2c9214 --- /dev/null +++ b/web/src/scss/components/_VDatatable.scss @@ -0,0 +1,3 @@ +.v-pagination__item--is-active .v-btn__overlay { + opacity: 0.15 !important; +} \ No newline at end of file diff --git a/web/src/scss/components/_VDatatables.scss b/web/src/scss/components/_VDatatables.scss new file mode 100644 index 0000000..0ccafd9 --- /dev/null +++ b/web/src/scss/components/_VDatatables.scss @@ -0,0 +1,99 @@ +.v-table { + + &.datatabels { + + &.productlist { + .v-data-table-header__content span { + color: rgb(var(--v-theme-textPrimary)); + } + + .v-toolbar { + .v-input__control { + max-width: 300px; + } + + .v-toolbar__content { + height: auto !important; + } + } + + thead tr th:first-child { + padding-left: 0px !important; + } + + tbody tr td:first-child { + padding-left: 0px !important; + } + tbody tr td{ + padding: 15px; + } + + } + + .v-selection-control--dirty .v-selection-control__input>.v-icon { + color: rgb(var(--v-theme-primary)); + } + } + +} + + +@media screen and (max-width:1368px) { + + .v-table { + + &.datatabels { + + &.productlist { + .v-data-table-header__content span { + color: rgb(var(--v-theme-textPrimary)); + } + + table { + tbody { + tr { + + td { + padding: 14px 5px !important; + + &:first-child { + padding-left: 15px !important; + } + } + } + } + + thead { + tr { + th { + padding: 14px 5px !important; + + &:first-child { + padding-left: 15px !important; + } + } + } + } + } + + + } + } + + } + +} + +.v-pagination { + .v-pagination__list { + .v-pagination__item--is-active { + .v-btn { + .v-btn__overlay { + opacity: 0; + } + + background-color: rgb(var(--v-theme-grey100)) !important; + } + } + } +} \ No newline at end of file diff --git a/web/src/scss/components/_VExpansionpanel.scss b/web/src/scss/components/_VExpansionpanel.scss new file mode 100644 index 0000000..de59dc7 --- /dev/null +++ b/web/src/scss/components/_VExpansionpanel.scss @@ -0,0 +1,6 @@ +.v-expansion-panel-title__overlay{ + background: rgba(var(--v-theme-primary)); +} +.v-expansion-panel:not(:first-child)::after { + border-color: transparent !important; +} \ No newline at end of file diff --git a/web/src/scss/components/_VField.scss b/web/src/scss/components/_VField.scss new file mode 100644 index 0000000..a3dad00 --- /dev/null +++ b/web/src/scss/components/_VField.scss @@ -0,0 +1,29 @@ +@use "../variables" as *; + +.v-field--variant-outlined .v-field__outline__start.v-locale--is-ltr, +.v-locale--is-ltr .v-field--variant-outlined .v-field__outline__start { + border-radius: $border-radius-root 0 0 $border-radius-root; +} + +.v-field--variant-outlined .v-field__outline__end.v-locale--is-ltr, +.v-locale--is-ltr .v-field--variant-outlined .v-field__outline__end { + border-radius: 0 $border-radius-root $border-radius-root 0; +} + +.v-field { + font-size: 14px; + color: rgba(var(--v-theme-textPrimary)); +} + +// select outlined +.v-field--variant-outlined .v-field__outline__start, +.v-field--variant-outlined .v-field__outline__notch::before, +.v-field--variant-outlined .v-field__outline__notch::after, +.v-field--variant-outlined .v-field__outline__end { + opacity: 1; +} + + +.v-field--active .v-label.v-field-label{ + color: rgb(var(--v-theme-textPrimary)); +} \ No newline at end of file diff --git a/web/src/scss/components/_VInput.scss b/web/src/scss/components/_VInput.scss new file mode 100644 index 0000000..77ad91a --- /dev/null +++ b/web/src/scss/components/_VInput.scss @@ -0,0 +1,35 @@ +// variant +.v-input--density-default, +.v-field--variant-solo, +.v-field--variant-filled { + --v-input-control-height: 51px; + --v-input-padding-top: 14px; +} + +// comfortable +.v-input--density-comfortable { + --v-input-control-height: 44px; +} + +// compact +.v-input--density-compact { + --v-input-padding-top: 10px; +} +.v-label { + font-size: 14px; + opacity: 0.7; + font-weight: 500 !important; +} +.v-switch .v-label, +.v-checkbox .v-label { + opacity: 1; +} + +.v-text-field__suffix { + opacity: 1; + padding-left: 20px; +} + +.shadow-none .v-field--variant-solo { + box-shadow: none !important; +} diff --git a/web/src/scss/components/_VLabs.scss b/web/src/scss/components/_VLabs.scss new file mode 100644 index 0000000..633d421 --- /dev/null +++ b/web/src/scss/components/_VLabs.scss @@ -0,0 +1,18 @@ +.v-time-picker-clock{ + background: rgb(var(--v-theme-grey100)) ; +} +.v-time-picker-controls__ampm__btn.v-btn.v-btn--density-default{ + border: 0 !important; +} +.v-stepper-header,.v-stepper.v-sheet{ + box-shadow: none !important; +} + +.v-time-picker-controls__time__btn.v-btn--density-default.v-btn { + width: 55px !important; + height: 55px !important; + font-size: 30px; +} +.v-time-picker-controls__time__separator { + font-size: 36px !important; +} \ No newline at end of file diff --git a/web/src/scss/components/_VList.scss b/web/src/scss/components/_VList.scss new file mode 100644 index 0000000..1f88ca7 --- /dev/null +++ b/web/src/scss/components/_VList.scss @@ -0,0 +1,34 @@ +.v-list.theme-list { + .v-list-item:hover > .v-list-item__overlay { + opacity: 1; + z-index: 1; + } + .v-list-item--variant-text { + .v-list-item__overlay { + background: rgb(var(--v-theme-hoverColor)); + } + } + + .v-list-item__prepend, + .v-list-item__content { + z-index: 2; + } + + .v-list-item__overlay { + background-color: rgb(var(--v-theme-hoverColor)); + } + .v-list-item.v-list-item--active{ + .v-list-item__overlay{ + opacity: 1; + } + } + + .mail-items{ + min-height: 40px !important; + margin-bottom: 5px !important; + } +} + +.v-list-item-title{ + font-size: 14px; +} diff --git a/web/src/scss/components/_VNavigationDrawer.scss b/web/src/scss/components/_VNavigationDrawer.scss new file mode 100644 index 0000000..9994ae9 --- /dev/null +++ b/web/src/scss/components/_VNavigationDrawer.scss @@ -0,0 +1,3 @@ +.v-navigation-drawer__scrim.fade-transition-leave-to { + display: none; +} diff --git a/web/src/scss/components/_VSelectionControl.scss b/web/src/scss/components/_VSelectionControl.scss new file mode 100644 index 0000000..5c080a9 --- /dev/null +++ b/web/src/scss/components/_VSelectionControl.scss @@ -0,0 +1,6 @@ +// For checkbox & radios +.v-selection-control__input > .v-icon.mdi-checkbox-blank-outline, +.v-selection-control__input > .v-icon.mdi-radiobox-blank { + color: rgb(var(--v-theme-inputBorder)); + opacity: 1; +} diff --git a/web/src/scss/components/_VShadow.scss b/web/src/scss/components/_VShadow.scss new file mode 100644 index 0000000..e834869 --- /dev/null +++ b/web/src/scss/components/_VShadow.scss @@ -0,0 +1,33 @@ +@use "../variables" as *; + +.elevation-9 { + box-shadow: rgb(0 0 0 / 5%) 0px 9px 17.5px !important; +} + +.elevation-10 { + box-shadow: $box-shadow !important; +} +.elevation-1 { + box-shadow:0px 12px 30px -2px rgba(58,75,116,0.14) !important +} +.elevation-2 { + box-shadow:0px 24px 24px -12px rgba(0, 0, 0, .05) !important +} +.elevation-3 { + box-shadow: rgba(145,158,171,0.2) 0px 0px 2px 0px, rgba(145,158,171,0.12) 0px 12px 24px -4px !important; +} +.elevation-4{ + box-shadow: 0px 12px 12px -6px rgba(0,0,0,0.15) !important; +} +.elevation-5 +{ + box-shadow: 1px 0 7px rgba(0, 0, 0, .05)!important; +} + +.primary-shadow { + box-shadow: rgba(var(--v-theme-primary), 0.30) 0px 12px 14px 0px; + &:hover { + box-shadow: none; + } +} + diff --git a/web/src/scss/components/_VStepper.scss b/web/src/scss/components/_VStepper.scss new file mode 100644 index 0000000..06e5f17 --- /dev/null +++ b/web/src/scss/components/_VStepper.scss @@ -0,0 +1,8 @@ +.v-stepper-item--selected .v-stepper-item__avatar.v-avatar, .v-stepper-item--complete .v-stepper-item__avatar.v-avatar { + background: rgb(var(--v-theme-primary)) !important; +} + +.v-stepper-item__avatar.v-avatar { + background: rgba(var(--v-theme-primary), var(--v-medium-emphasis-opacity)) !important; + color: rgb(var(--v-theme-on-primary)) !important; +} \ No newline at end of file diff --git a/web/src/scss/components/_VSwitch.scss b/web/src/scss/components/_VSwitch.scss new file mode 100644 index 0000000..ce58d9b --- /dev/null +++ b/web/src/scss/components/_VSwitch.scss @@ -0,0 +1,48 @@ +.v-selection-control.v-selection-control--density-default { + .v-switch__track, + .v-switch__thumb { + background-color: rgb(var(--v-theme-grey200)); + } + &.v-selection-control--dirty { + .v-selection-control__wrapper.text-primary { + .v-switch__track { + background-color: rgba(var(--v-theme-primary), 0.6); + } + .v-switch__thumb { + background-color: rgb(var(--v-theme-primary)); + } + } + .v-selection-control__wrapper.text-secondary { + .v-switch__track { + background-color: rgba(var(--v-theme-secondary), 0.6); + } + .v-switch__thumb { + background-color: rgb(var(--v-theme-secondary)); + } + } + .v-selection-control__wrapper.text-warning { + .v-switch__track { + background-color: rgba(var(--v-theme-warning), 0.6); + } + .v-switch__thumb { + background-color: rgb(var(--v-theme-warning)); + } + } + .v-selection-control__wrapper.text-error { + .v-switch__track { + background-color: rgba(var(--v-theme-error), 0.6); + } + .v-switch__thumb { + background-color: rgb(var(--v-theme-error)); + } + } + .v-selection-control__wrapper.text-success { + .v-switch__track { + background-color: rgba(var(--v-theme-success), 0.6); + } + .v-switch__thumb { + background-color: rgb(var(--v-theme-success)); + } + } + } +} diff --git a/web/src/scss/components/_VTable.scss b/web/src/scss/components/_VTable.scss new file mode 100644 index 0000000..61a5c0b --- /dev/null +++ b/web/src/scss/components/_VTable.scss @@ -0,0 +1,99 @@ +.v-table .v-table__wrapper > table > tbody > tr:not(:last-child) > td, +.v-table .v-table__wrapper > table > tbody > tr:not(:last-child) > th, +.v-table .v-table__wrapper > table > thead > tr:last-child > th { + border-bottom: thin solid rgba(var(--v-border-color)) !important; +} + +.v-data-table{ + th.v-data-table__th{ + font-size:16px; + color: rgba(var(--v-theme-on-surface), var(--v-medium-emphasis-opacity)); + } + td.v-data-table__td{ + font-size: 14px; + text-wrap: nowrap; + } + .v-data-table-footer{ + padding: 15px 8px; + } + .v-data-table-header__sort-badge{ + background-color:rgb(var(--v-theme-borderColor)) !important; + } + .tdhead{ + font-size:16px; + } +} +@media screen and (max-width:767px) { + .v-data-table-footer{ + justify-content: center; + } +} + +.v-table { + + + &.ticket-table { + + table { + thead { + th { + font-weight: 600 !important; + } + } + + tbody { + tr { + + td { + padding: 16px 16px !important; + } + } + } + } + + } + + &.invoice-table { + .v-table__wrapper { + table { + thead { + th { + font-weight: 600 !important; + padding: 0px 24px !important; + + &:first-child { + padding-left: 0 !important; + } + + &:last-child { + padding-right: 0 !important; + } + + } + } + + tbody { + tr { + + td { + padding: 8px 24px !important; + + &:first-child { + padding-left: 0 !important; + } + + &:last-child { + padding-right: 0 !important; + } + } + } + } + } + } + + + } + + + +} \ No newline at end of file diff --git a/web/src/scss/components/_VTabs.scss b/web/src/scss/components/_VTabs.scss new file mode 100644 index 0000000..9932645 --- /dev/null +++ b/web/src/scss/components/_VTabs.scss @@ -0,0 +1,14 @@ +@use "../variables" as *; + +.theme-tab { + &.v-tabs { + .v-tab { + border-radius: $border-radius-root !important; + min-width: auto !important; + &.v-slide-group-item--active { + background: rgb(var(--v-theme-primary)); + + } + } + } +} \ No newline at end of file diff --git a/web/src/scss/components/_VTextField.scss b/web/src/scss/components/_VTextField.scss new file mode 100644 index 0000000..bbc52a7 --- /dev/null +++ b/web/src/scss/components/_VTextField.scss @@ -0,0 +1,13 @@ +.v-text-field input { + font-size: 0.875rem; +} +.v-field__outline { + color: rgb(var(--v-theme-inputBorder)); + --v-field-border-opacity: 1 !important; +} +.input { + .v-field--variant-outlined { + background-color: rgba(0, 0, 0, 0.025); + } +} + diff --git a/web/src/scss/components/_VTextarea.scss b/web/src/scss/components/_VTextarea.scss new file mode 100644 index 0000000..b611c41 --- /dev/null +++ b/web/src/scss/components/_VTextarea.scss @@ -0,0 +1,7 @@ +.v-textarea input { + font-size: 0.875rem; + font-weight: 500; + &::placeholder { + color: rgba(0, 0, 0, 0.38); + } +} diff --git a/web/src/scss/front/_general.scss b/web/src/scss/front/_general.scss new file mode 100644 index 0000000..46d795b --- /dev/null +++ b/web/src/scss/front/_general.scss @@ -0,0 +1,597 @@ +@use "../variables" as *; + +@keyframes slideup { + 0% { + transform: translate3d(0, 0, 0); + } + + 100% { + transform: translate3d(0px, -100%, 0px); + } +} + +.animateDown { + animation: 35s linear 0s infinite normal none running slideDown; +} + +@keyframes slideDown { + 0% { + transform: translate3d(0, -100%, 0); + } + + 100% { + transform: translate3d(0px, 0, 0px); + } +} + +// OfferBar +.offerbar { + position: relative; + top: 0; + width: 100%; + z-index: 999; + + .white-btn { + background-color: rgba(var(--v-theme-surface), 0.15); + font-weight: 700; + height: 25px; + } + + + + &:before { + background-repeat: no-repeat; + content: ''; + position: absolute; + background-image: url('@/assets/images/front-pages/background/left-shape.png'); + bottom: 0; + height: 40px; + left: 0; + width: 325px; + } + + &:after { + background-repeat: no-repeat; + content: ''; + position: absolute; + background-image: url('@/assets/images/front-pages/background/right-shape.png'); + bottom: 0; + right: 17%; + width: 325px; + top: 0; + background-size: contain; + } +} + +// +// frameworks +// +.slider-group { + animation: slide 45s linear infinite; +} + +.marquee1-group { + animation: marquee 45s linear infinite; +} + +.marquee2-group { + animation: marquee2 45s linear infinite; +} + + +@keyframes slide { + 0% { + transform: translate3d(0, 0, 0); + } + + 100% { + transform: translate3d(-100%, 0, 0); + } +} + +@keyframes marquee { + 0% { + transform: translate3d(0, 0, 0); + } + + 100% { + transform: translate3d(-2086px, 0, 0); + } +} + +@keyframes marquee2 { + 0% { + transform: translate3d(-2086px, 0, 0) + } + + 100% { + transform: translate3d(0, 0, 0) + } +} + +.front-wraper { + overflow: hidden; + + .underline-link { + text-underline-offset: 4px; + } + + .underline-link-6 { + text-underline-offset: 6px; + text-decoration-thickness: 2px; + } + + .main-banner { + min-width: 1300px; + overflow: hidden; + max-height: 700px; + height: calc(100vh - 100px); + + img { + max-width: 100%; + height: auto; + + } + } + + .team { + &:hover { + .intro { + opacity: 1; + } + } + + .intro { + opacity: 0; + bottom: 16px; + inset-inline-start: .75rem; + inset-inline-end: .75rem; + transition: 0.5s; + } + } + + // Revenue Products + .feature-tabs { + .v-slide-group__content { + gap: 16px; + padding-bottom: 56px; + } + + + + .v-btn { + background-color: rgba(var(--v-theme-surface)); + padding: 16px 24px; + border-radius: 12px !important; + font-size: 16px; + box-shadow: 0px 24px 24px -12px rgba(0, 0, 0, .05); + } + + .v-tab--selected { + background-color: rgba(var(--v-theme-primary)); + box-shadow: 0px 24px 24px -12px rgba(99, 91, 255, .15); + + .v-btn__content { + color: #fff; + + .v-tab__slider { + display: none; + } + } + } + } + + .v-container { + &.max-width-1218 { + max-width: 1218px !important; + } + + } + + .v-container { + &.max-width-800 { + max-width: 800px !important; + } + + &.max-width-1000 { + max-width: 1000px !important; + } + } + + .max-w-600 { + max-width: 600px !important; + } + + .template { + .left-widget { + position: absolute; + top: 96px; + inset-inline-start: -40px; + max-height: 400px; + width: auto; + } + + .right-widget { + position: absolute; + top: 96px; + inset-inline-end: -40px; + max-height: 400px; + width: auto; + } + } + + + .feature-tabs { + .v-tab__slider { + top: 0; + bottom: unset; + } + + &.v-tabs--density-default { + --v-tabs-height: auto; + } + } + + .feature-tabs-expansion { + + .v-expansion-panel-text__wrapper { + padding: 0px 0px 16px; + } + + .v-expansion-panel-title { + padding: 16px 0px; + } + + .v-expansion-panel { + background-color: transparent !important; + } + + .v-expansion-panel--active:not(:first-child), + .v-expansion-panel--active+.v-expansion-panel { + margin-top: 0; + } + } + + .leader-slider { + .carousel__slide { + padding: 0 15px; + } + + .carousel__viewport { + margin: 0 -15px; + padding-bottom: 30px; + } + + .carousel__prev, + .carousel__next { + top: -85px; + width: 100%; + justify-content: end; + margin: 0; + transform: none; + display: flex; + justify-content: center + } + + .carousel__next { + height: 48px; + width: 48px; + border-radius: 50%; + background: rgb(var(--v-theme-lightprimary)); + + } + + .carousel__prev { + height: 48px; + width: 48px; + border-radius: 50%; + background: rgb(var(--v-theme-lightprimary)); + right: 65px; + left: unset; + } + } + + .our-template { + .carousel__slide { + padding: 0 15px 40px; + } + + .carousel__viewport { + margin: 0 -106px; + } + } + + .testimonials { + + .carousel__prev, + .carousel__next { + width: 100%; + justify-content: end; + margin: 0; + transform: translateY(75px); + display: flex; + justify-content: center; + bottom: 0; + } + + .carousel__next { + height: 32px; + width: 32px; + border-radius: 50%; + background: rgb(var(--v-theme-background)); + left: -60%; + } + + .carousel__prev { + height: 32px; + width: 32px; + border-radius: 50%; + background: rgb(var(--v-theme-background)); + right: 65px; + left: -74%; + } + + .carousel { + padding-bottom: 25px; + } + + .slide-counter { + position: relative; + bottom: -4px; + left: 50px; + z-index: 2; + font-size: 15px; + opacity: 0.7; + } + } + + .social-icon { + svg { + path { + fill: rgb(255, 255, 255); + + &:hover { + fill: rgb(var(--v-theme-primary)); + } + } + } + } + + .package { + .v-list-item { + min-height: 35px !important; + } + } + + .lp-faq { + .v-expansion-panel-title__icon { + .v-icon { + font-size: 20px; + opacity: 0.5 + } + } + + .v-expansion-panels:not(.v-expansion-panels--variant-accordion)> :first-child:not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--before-active) { + border-bottom-left-radius: 8px !important; + border-bottom-right-radius: 8px !important; + } + + .v-expansion-panels:not(.v-expansion-panels--variant-accordion)> :not(:first-child):not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--after-active) { + border-top-left-radius: 8px !important; + border-top-right-radius: 8px !important; + } + + .v-expansion-panels:not(.v-expansion-panels--variant-accordion)> :not(:first-child):not(:last-child):not(.v-expansion-panel--active):not(.v-expansion-panel--before-active) { + border-bottom-left-radius: 8px !important; + border-bottom-right-radius: 8px !important; + } + + .v-expansion-panel--active:not(:first-child), + .v-expansion-panel--active+.v-expansion-panel { + margin-top: 0px !important; + } + } + + + .animted-img { + position: absolute; + z-index: 9; + top: 0%; + animation: mover 5s infinite alternate; + } + + .animted-img-2 { + position: absolute; + z-index: 9; + top: -35px; + inset-inline-end: 15px; + animation: mover 5s infinite alternate; + } + + @keyframes mover { + 0% { + transform: translateY(0); + } + + 100% { + transform: translateY(-10px); + } + } + + .carousel__pagination { + .carousel__pagination-button { + padding: 6px; + + &::after { + height: 8px; + width: 8px; + border-radius: 50%; + background-color: transparent; + background-color: rgb(var(--v-theme-textPrimary)); + opacity: 0.25; + } + + &:hover { + &::after { + background-color: #000; + opacity: 1; + } + } + } + + .carousel__pagination-button--active { + &::after { + background-color: #000; + opacity: 1; + } + } + } + + .carousel { + z-index: 2; + } +} + + + +.v-btn--size-default { + &.nav-links { + font-size: $font-size-root !important; + + .v-btn__overlay { + display: none; + } + + &:hover { + color: rgb(var(--v-theme-primary)) !important; + } + } +} + + + +.light-primary { + background-color: rgb(var(--v-theme-primary), 0.1); +} + +.announce-close { + position: absolute; + right: 15px; + +} + +.text-align-start{ + text-align: start; +} + +@media screen and (max-width:1199px) { + .ps-96 { + padding-inline-start: 60px !important; + } + + .space-p-96 { + padding: 55px 0 !important; + } + + .pt-96 { + padding-top: 55px !important; + } + + .offerbar { + &:after { + background-image: none; + } + } + + .offerbar:after, + .offerbar:before { + display: none; + } + +} + +@media screen and (max-width:1024px) { + .front-wraper .testimonials .slide-counter { + left: 67px; + } + + .space-p-96 { + padding: 40px 0 !important; + } + + .pt-96 { + padding-top: 40px !important; + } + + .front-wraper .bg-collection { + background-image: none; + } + + + + .front-wraper .our-template .carousel__viewport { + margin: 0 0px; + } + + .ps-96 { + padding-inline-start: 20px !important; + padding-inline-end: 20px !important; + } + +} + +@media screen and (max-width:991px) { + .text-align-start{ + text-align: center; + } +} + +@media screen and (max-width:767px) { + .technology { + .round-54 { + height: 45px; + width: 45px; + + img { + height: 22px; + } + } + } + + .front-wraper { + .display-2 { + font-size: 32px; + line-height: normal; + } + + .display-1 { + font-size: 32px; + line-height: normal; + } + } + + .front-wraper .leader-slider .carousel__viewport { + margin: 0 0px; + } + + .announce-close { + bottom: 8px; + } + + .text-48 { + font-size: 30px !important; + line-height: 40px !important; + } + + .text-56 { + font-size: 35px !important; + line-height: 40px !important; + } + + .team { + .intro { + opacity: 1 !important; + } + } + +} \ No newline at end of file diff --git a/web/src/scss/front/_header.scss b/web/src/scss/front/_header.scss new file mode 100644 index 0000000..0952c88 --- /dev/null +++ b/web/src/scss/front/_header.scss @@ -0,0 +1,104 @@ +@use "../variables" as *; + +.front-lp-header { + + .v-toolbar{ + background: rgb(var(--v-theme-surface)); + } + + &.v-app-bar .v-toolbar__content { + padding: 0; + + } + + .v-toolbar__content { + background: transparent !important; + box-shadow: none !important; + } + + &.v-toolbar { + background: transparent !important; + top: 0 !important; + } + + .v-toolbar { + background: transparent !important; + } + + &.sticky-header { + position: fixed !important; + top: 0 !important; + transition: 0.5s; + background-color: rgba(var(--v-theme-surface)) !important; + box-shadow: 0 4px 29px -11px #3a4b7424 !important; + + } + +} +// +// mega menu +// +.white-btn{ + background-color: #769CFF; +} +.front_wrapper { + + &.v-menu .v-overlay__content { + margin: 0 auto; + left: 0 !important; + right: 0; + } + .megamenu { + &::before { + content: ''; + position: absolute; + top: 0px; + left: 0px; + width: 100%; + height: 96%; + background-color: rgba(55, 114, 255, 0.2); + border-radius: 7px; + opacity: 0; + } + .v-btn { + top: 50%; + transform: translateY(-50%); + z-index: 1; + left: 0; + right: 0; + min-width: 100px; + opacity: 0; + font-size: 13px; + } + &:hover { + &::before, + .v-btn { + opacity: 1; + } + } + } +} +.lp-drawer { + &.v-navigation-drawer { + top: 0 !important; + height: 100% !important; + z-index: 1007 !important; + } +} + +.lp-mobile-sidebar { + .v-list { + .v-list-item__content { + overflow: inherit; + } + } + .v-list-group__items .v-list-item { + padding-inline-start: 25px !important; + } +} + +.v-btn--size-default { + &.nav-links { + font-size: $font-size-root !important; + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_container.scss b/web/src/scss/layout/_container.scss new file mode 100644 index 0000000..d9fc39a --- /dev/null +++ b/web/src/scss/layout/_container.scss @@ -0,0 +1,40 @@ +html { + overflow-y: auto; +} +.v-main{ + background:rgb(var(--v-theme-background)) !important; ; +} +@media (max-width: 1279px) { + .v-main { + margin: 0 10px; + } +} + +.cursor-pointer { + cursor: pointer; +} + +.page-wrapper { + min-height: calc(100vh - 100px); + padding: 24px; + // border-radius: $border-radius-root; + @media screen and (max-width: 767px) { + padding: 20px 10px; + } +} + +.maxWidth { + max-width: 1200px; + margin: 0 auto; +} + +.fixed-width { + max-width: 1300px; +} + +.right-pos-img { + position: absolute; + right: 0; + top: 0; + height: 100%; +} diff --git a/web/src/scss/layout/_customizer.scss b/web/src/scss/layout/_customizer.scss new file mode 100644 index 0000000..1e3b9af --- /dev/null +++ b/web/src/scss/layout/_customizer.scss @@ -0,0 +1,93 @@ +.v-btn.customizer-btn { + position: fixed; + bottom: 30px; + right: 30px; + border-radius: 50%; + // .icon-tabler-settings { + // animation: progress-circular-rotate 1.4s linear infinite; + // transform-origin: center center; + // transition: all 0.2s ease-in-out; + // } +} + +.btn-group-custom { + &.v-btn-group { + height: 66px !important; + overflow: unset !important; + .v-btn { + height: 66px !important; + padding: 0 20px; + border: 1px solid rgb(var(--v-theme-borderColor), 0.7) !important; + transition: all 0.1s ease-in 0s; + &:hover { + transform: scale(1.05); + } + &.text-primary { + .v-btn__overlay { + background: transparent !important; + } + .icon { + color: rgb(var(--v-theme-primary)) !important; + fill: rgb(var(--v-theme-primary), 0.2); + } + color: rgb(var(--v-theme-primary)) !important; + } + } + } +} + +.hover-btns { + transition: all 0.1s ease-in 0s; + &:hover { + transform: scale(1.05); + } +} +// all theme colors +.v-avatar.themeBlue, +.v-avatar.themeDarkBlue { + background: #1e88e5; +} +.v-avatar.themeAqua, +.v-avatar.themeDarkAqua { + background: #0074ba; +} + +.v-avatar.themePurple, +.v-avatar.themeDarkPurple { + background: #763ebd; +} +.v-avatar.themeGreen, +.v-avatar.themeDarkGreen { + background: #0a7ea4; +} + +.v-avatar.themeCyan, +.v-avatar.themeDarkCyan { + background: #01c0c8; +} + +.v-avatar.themeOrange, +.v-avatar.themeDarkOrange { + background: #fa896b; +} + + +.DARK_BLUE_THEME, .DARK_AQUA_THEME, .DARK_ORANGE_THEME, .DARK_PURPLE_THEME, .DARK_GREEN_THEME, .DARK_CYAN_THEME { + .togglethemeBlue { + display: block !important; + } + + .togglethemeDarkBlue { + display: none !important; + } +} + +.BLUE_THEME, .AQUA_THEME, .ORANGE_THEME, .PURPLE_THEME, .GREEN_THEME, .CYAN_THEME { + .togglethemeDarkBlue { + display: block !important; + } + + .togglethemeBlue { + display: none !important; + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_dark.scss b/web/src/scss/layout/_dark.scss new file mode 100644 index 0000000..feb2a94 --- /dev/null +++ b/web/src/scss/layout/_dark.scss @@ -0,0 +1,81 @@ +// theme : dark +div[class*='v-theme--DARK_'] { + .smallCap { + color: rgb(var(--v-theme-textSecondary)); + } + + .elevation-10 { + box-shadow: rgb(145 158 171 / 30%) 0px 0px 2px 0px, rgb(145 158 171 / 2%) 0px 12px 24px -4px !important; + } + .v-field__outline{ + --v-field-border-opacity: 0.38 !important; + } + + .front-wraper{ + .bg-background{ + background-color: rgb(var(--v-theme-hoverColor)) !important; + } + + .front-dark{ + &.bg-textPrimary{ + background-color: rgb(var(--v-theme-surface)) !important; + } + } + .bg-textPrimary{ + background-color: rgb(var(--v-theme-textSecondary)) !important; + } + } + + + #vector-map .dxm-layers path { + fill: #7C8FAC !important; + } + + .svgMap-map-wrapper { + .svgMap-country { + stroke: #878585; + fill: #1A2537 !important; + + &#svgMap-map-country-IN { + fill: rgb(var(--v-theme-secondary)) !important; + } + + &#svgMap-map-country-AF { + fill: rgb(var(--v-theme-purple)) !important; + } + + &#svgMap-map-country-US { + fill: rgb(var(--v-theme-primary)) !important; + } + } + + .svgMap-map-controls-zoom { + background: #c9d6de !important; + } + .svgMap-control-button{ + background-color: rgb(var(--v-theme-textSecondary)) !important; + } + + } + .dark-card-title{ + color:rgb(var(--v-theme-surface)); + } + + .fc{ + .fc-button-primary:not(:disabled).fc-button-active { + background-color: rgb(var(--v-theme-grey100)); + } + .fc-button-group { + >.fc-button { + &:hover,&:focus{ + background-color: rgba(var(--v-theme-grey100)); + color: #fff; + .fc-icon{ + color: #fff; + } + } + } + } + } + +} diff --git a/web/src/scss/layout/_horizontal.scss b/web/src/scss/layout/_horizontal.scss new file mode 100644 index 0000000..87273e0 --- /dev/null +++ b/web/src/scss/layout/_horizontal.scss @@ -0,0 +1,231 @@ +@use "../variables" as *; + +.horizontalLayout { + .v-main { + margin: 0 16px !important; + + @media screen and (max-width: 767px) { + margin: 0 10px !important; + } + } +} + +.horizontal-header { + &.v-app-bar .v-toolbar__content { + padding: 0; + display: flex; + justify-content: space-between; + } + + .maxWidth { + @media screen and (max-width: 1199px) { + padding: 0 8px !important; + } + } + +} + +.ddMenu { + &.ddLevel-1 { + .navItem { + .navItemLink { + .dot { + height: 6px; + width: 6px; + background-color: rgb(var(--v-theme-textSecondary)); + border-radius: 50%; + margin-inline-end: 8px !important; + } + } + + &:hover { + .dot { + background-color: rgb(var(--v-theme-secondary)); + } + } + } + } + + &.ddLevel-2 { + .navItem { + .navItemLink { + .dot { + height: 6px; + width: 6px; + background-color: rgb(var(--v-theme-textSecondary)); + border-radius: 50%; + margin-inline-end: 8px !important; + } + } + + &:hover { + .dot { + background-color: rgb(var(--v-theme-secondary)); + } + } + } + } +} + + +.horizontalMenu { + .v-toolbar__content { + max-width: 1270px; + margin: 0 auto; + } + + .navItem:has(.ddMenu.ddLevel-1 li a.router-link-active) { + background-color: rgb(var(--v-theme-secondary)) !important; + border-radius: 9999px; + + .navcollapse { + color: rgba(255, 255, 255); + } + } + +} + +.mobile-menu { + .v-navigation-drawer { + margin-top: -70px !important; + height: 100vh !important; + z-index: 2000 !important; + } +} + +@media (min-width: 960px) { + .horizontalMenu { + margin-top: 65px; + margin-bottom: -70px; + + .maxWidth { + .horizontal-navbar { + max-width: 1160px; + } + } + } + + .horizontal-navbar { + padding: 16px 0; + margin: 0px auto; + align-items: center; + display: flex; + z-index: 11; + font-size: 0.875rem; + position: relative; + + ul { + padding: 0px; + margin: 0px; + } + + .ddMenu { + li { + a { + color: rgb(var(--v-theme-textPrimary)) !important; + } + } + } + + li { + list-style: none; + + a { + text-decoration: none; + display: flex; + align-items: center; + padding: 10px 13px; + height: 40px; + + .navIcon { + margin-right: 10px; + display: flex; + } + + .ddIcon { + margin-top: 2px; + } + + &.router-link-exact-active { + background-color: transparent; + color: rgba(var(--v-theme-secondary)) !important; + + .dot { + background-color: rgb(var(--v-theme-secondary)) !important; + } + + } + + } + } + + .navItem { + position: relative; + + .single-link { + &:hover { + color: rgb(var(--v-theme-secondary)) !important; + } + } + + + .ddMenu { + .navItem { + .navcollapse { + &:hover { + color: rgb(var(--v-theme-secondary)) !important; + } + } + } + } + + + } + + .ddMenu { + position: absolute; + width: 230px; + display: none; + top: 40px; + padding: 10px; + z-index: 1; + background-color: rgb(var(--v-theme-surface)); + box-shadow: $box-shadow; + border-radius: $border-radius-root; + + li { + margin-bottom: 3px; + } + } + + .ddLevel-2, + .ddLevel-3 { + top: -5px; + left: 212px; + } + + .navItem:hover { + + >.ddMenu { + display: block; + } + } + + >li:hover { + background-color: rgb(var(--v-theme-lightprimary)); + border-radius: 9999px; + + >.navItemLink { + color: rgb(var(--v-theme-secondary)); + opacity: 1; + } + } + + .router-link-exact-active { + color: rgb(var(--v-theme-secondary)); + font-weight: 500; + background-color: rgb(var(--v-theme-lightprimary)); + border-radius: $border-radius-root; + } + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_reboot.scss b/web/src/scss/layout/_reboot.scss new file mode 100644 index 0000000..f4e4321 --- /dev/null +++ b/web/src/scss/layout/_reboot.scss @@ -0,0 +1,109 @@ +.h-100 { + height: 100%; +} + +.w-100 { + width: 100%; +} + +.h-100vh { + height: 100vh; +} + +.gap-2 { + gap: 8px; +} + +.gap-3 { + gap: 16px; +} + +.gap-4 { + gap: 24px; +} + +.text-white { + color: rgb(255, 255, 255) !important; +} + +// border +.border-bottom { + border-bottom: 1px solid rgba(0, 0, 0, .05); +} + +.opacity-1 { + opacity: 1 !important; +} + +.opacity-50 { + opacity: 0.5; +} + +.z-auto.v-card { + z-index: auto; +} + +.obj-cover { + object-fit: cover; +} + +.cursor-move { + cursor: move; +} + +body { + cursor: default; +} + +input:not([type="checkbox"]):not([type="radio"]):not([type="button"]):not([type="submit"]):not([type="reset"]):not([type="file"]):not([type="range"]):not([type="color"]), +textarea, +[contenteditable="true"] { + cursor: text; +} + +//Date time picker +input[type="date"], +input[type="time"] { + display: block !important; +} + +input[type="date"]::-webkit-calendar-picker-indicator, +input[type="time"]::-webkit-calendar-picker-indicator { + display: block !important; +} + +.ProseMirror { + min-height: 150px; +} + +.upload-btn-wrapper { + width: 150px; + height: 140px; + margin: 0 auto; + box-shadow: 0 0.5rem 1.5rem 0.5rem rgba(0, 0, 0, 0.075); + + input[type=file] { + position: absolute; + left: 0; + top: 0; + opacity: 0; + height: 100%; + width: 100%; + } +} + +.bg-transparent { + background-color: transparent !important; +} +.bg-dark{ + background-color: rgba(0, 0, 0, .08); +} +.bg-white-opacity{ + background-color: rgba(255, 255, 255, 0.2); +} + +@media screen and (max-width:1368px) and (min-width:1200px) { + .space-20 { + padding: 30px 20px !important; + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_rtl.scss b/web/src/scss/layout/_rtl.scss new file mode 100644 index 0000000..b245ee8 --- /dev/null +++ b/web/src/scss/layout/_rtl.scss @@ -0,0 +1,341 @@ +.v-locale--is-rtl { + .customizer-btn { + left: 30px; + right: unset; + } + + .horizontal-navbar .icon-box { + margin-left: 12px; + } + + + + .bg-img-1 { + position: absolute; + bottom: 0; + left: 0; + right: unset !important; + transform: scaleX(-1); + } + + .ml-1 { + margin-left: unset !important; + margin-right: 4px; + } + + .ml-2 { + margin-left: unset !important; + margin-right: 8px; + } + + .mr-1 { + margin-right: unset !important; + margin-left: 4px; + } + + .mr-2 { + margin-right: unset !important; + margin-left: 8px; + } + + .mr-sm-2 { + margin-right: unset !important; + margin-left: 8px; + } + + .mr-3 { + margin-right: unset !important; + margin-left: 12px !important; + } + + .mr-4 { + margin-right: unset !important; + margin-left: 16px !important; + } + + .ml-3 { + margin-left: unset !important; + margin-right: 12px !important; + } + + .mr-auto { + margin-left: auto !important; + margin-right: unset !important; + } + + .ml-4 { + margin-left: unset !important; + margin-right: 16px; + } + + .ml-sm-4 { + margin-left: unset !important; + margin-right: 16px; + } + + .ml-md-4 { + margin-left: unset !important; + margin-right: 16px; + } + + .ml-sm-3 { + margin-left: unset !important; + margin-right: 12px; + } + + + .ml-5 { + margin-left: unset !important; + margin-right: 20px; + } + + .ml-6 { + margin-left: unset !important; + margin-right: 24px; + } + + .ml-10 { + margin-left: unset !important; + margin-right: 40px; + } + + .pl-1 { + padding-left: unset !important; + padding-right: 4px !important; + } + + .pl-2 { + padding-left: unset !important; + padding-right: 8px !important; + } + + .pr-2 { + padding-left: 8px !important; + } + + .pr-4 { + padding-left: 16px !important; + padding-right: unset !important; + } + + .pl-4 { + padding-left: unset !important; + padding-right: 16px !important; + } + + .right-pos-img { + right: unset; + left: 0; + transform: scaleX(-1); + top: 0; + } + + .badg-dotDetail { + left: 0; + right: -8px; + } + + .text-right { + text-align: left !important; + } + + .text-sm-right, + .text-md-right { + text-align: left !important; + } + + .text-sm-left { + text-align: right !important; + } + + .text-left { + text-align: right !important; + } + + .ml-auto, + .ml-sm-auto { + margin-left: unset !important; + margin-right: auto !important; + } + + .justify-start { + justify-content: flex-end !important; + } + + .vertical-table .v-table>.v-table__wrapper>table>tbody>tr>th { + border-left: thin solid rgba(var(--v-border-color), 1) !important; + } + + .authentication .auth-header { + left: unset; + right: 0; + } + + .horizontal-navbar li a { + padding: 10px 13px; + } + + .horizontal-navbar { + li { + margin-right: 0; + margin-left: 15px; + } + } + + // &.v-menu .v-overlay__content, + // &.search_popup .v-overlay__content, + // &.language_dropdown .v-overlay__content, + // &.notification_popup .v-overlay__content, + // &.profile_popup .v-overlay__content { + // left: inherit; + // } + + .related-Product { + .carousel__prev.navarrow { + top: 0; + right: unset !important; + left: 0; + } + + .carousel__next.navarrow { + top: 0; + right: unset !important; + left: 45px; + } + } + + //RTL mode minisidebar hover to active scrollbar + .ps--active-y>.ps__rail-y { + right: unset !important; + left: 0; + } + + //RTL mode sidebar scrollbar on right side + .left-customizer { + .ps__rail-y { + right: 0 !important; + } + } + + .horizontal-navbar .ddMenu { + padding: 10px 15px 10px 0px; + } + + .v-list-group__items { + .iconClass { + position: relative; + left: unset; + right: -2px; + } + } + + @media (min-width: 960px) { + + .horizontal-navbar .ddLevel-2, + .horizontal-navbar .ddLevel-3 { + top: -5px; + right: 212px; + } + + .horizontal-navbar li a .navIcon { + margin-right: 0; + margin-left: 10px; + } + } + + .leftSidebar .profile-name h5 { + direction: ltr; + } + + .horizontal-navbar { + .ddMenu { + .navItemLink { + padding-right: 15px; + } + } + } + + @media screen and (max-width:1279px) { + .mini-sidebar { + .v-navigation-drawer.v-navigation-drawer--right { + width: 270px !important; + } + + .v-navigation-drawer.v-navigation-drawer--left { + width: 320px !important; + } + } + + } + + .rtlImg { + transform: scaleX(-1); + } + + .marquee1-group { + animation: marquee-rtl 45s linear infinite; + } + + .marquee2-group { + animation: marquee2-rtl 45s linear infinite; + } + + @keyframes marquee-rtl { + 0% { + transform: translate3d(0, 0, 0); + } + + 100% { + transform: translate3d(2086px, 0, 0); + } + } + + @keyframes marquee2-rtl { + 0% { + transform: translate3d(2086px, 0, 0); + } + + 100% { + transform: translate3d(0, 0, 0); + } + } + + .front-wraper { + .testimonials { + .slide-counter { + left: -50px; + } + + .carousel__prev { + right: -74%; + left: unset; + + .rtlnav { + transform: scaleX(-1); + } + } + + .carousel__next { + right: -60%; + left: unset; + + .rtlnav { + transform: scaleX(-1); + } + + } + } + } + + //For Rtl Chart + .rtl-me-n7 { + margin-inline-start: -28px !important; + margin-inline-end: unset !important; + } + + .profile-img::before { + left: unset; + right: 14px; + } + +} \ No newline at end of file diff --git a/web/src/scss/layout/_sidebar.scss b/web/src/scss/layout/_sidebar.scss new file mode 100644 index 0000000..b1d279c --- /dev/null +++ b/web/src/scss/layout/_sidebar.scss @@ -0,0 +1,374 @@ +@use "../variables" as *; + +/*This is for the logo*/ +.leftSidebar { + box-shadow: 0 3px 4px 0 rgba(0, 0, 0, .03), 0 0 1px 0 rgba(0, 0, 0, .1); + + .logo { + padding-left: 7px; + } + + .mini-icon { + display: none; + } + + .mini-text { + display: block; + } + + .profile { + background: url("@/assets/images/backgrounds/user-info.jpg") no-repeat; + } + + .profile-name { + background: rgba(0, 0, 0, 0.5); + margin-top: -6px; + height: 35px; + + h5 { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; + } + } + + .v-list--density-default .v-list-subheader { + padding-inline-start: 0 !important; + } +} + +.verticalLayout { + .logo { + width: 250px; + + @media screen and (max-width:1024px) { + width: auto; + } + } +} + +/*This is for the Vertical sidebar*/ +.scrollnavbar { + height: 100%; + + .userbottom { + position: fixed; + bottom: 0px; + width: 100%; + } + + .smallCap { + padding: 3px 12px 12px 0px !important; + font-size: 0.875rem; + font-weight: 500; + margin-top: 24px; + color: rgb(var(--v-theme-textPrimary)); + + &:first-child { + margin-top: 0 !important; + } + } + + + + /*General Menu css*/ + .v-list-group__items .v-list-item, + .v-list-item { + border-radius: $border-radius-root; + padding-inline-start: calc(14px + var(--indent-padding) / 10) !important; + + margin: 0 0 2px; + + + + &:hover { + color: rgb(var(--v-theme-secondary)); + + } + + + + .v-list-item__prepend { + margin-inline-end: 13px; + } + + .v-list-item__append { + font-size: 0.875rem; + + .v-icon { + margin-inline-start: 13px; + } + } + + .v-list-item-title { + font-size: 0.875rem; + } + } + + .v-list-group__items { + .v-list-item { + min-height: 35px !important; + padding-inline-start: calc(12px + var(--indent-padding) / 10) !important; + + .v-list-item__prepend .dot { + height: 6px; + width: 6px; + background-color: rgb(var(--v-theme-textSecondary)); + border-radius: 50%; + margin-inline-end: 8px !important; + opacity: 0; + } + + .v-list-item-title { + font-size: 14px !important; + } + + &:hover { + color: rgb(var(--v-theme-secondary)); + + .v-list-item__prepend .dot { + background-color: rgb(var(--v-theme-secondary)); + } + } + + &.v-list-item--active { + .v-list-item__prepend .dot { + background-color: rgb(var(--v-theme-secondary)); + } + } + + } + } + + /*This is for the dropdown*/ + .v-list { + color: rgb(var(--v-theme-textPrimary)); + + >.v-list-item.v-list-item--active, + .v-list-item--active>.v-list-item__overlay { + background: rgb(var(--v-theme-secondary)); + color: white; + } + + >.v-list-group { + position: relative; + + >.v-list-item--active, + >.v-list-item--active:hover { + background: rgb(var(--v-theme-secondary)); + color: white; + } + + .v-list-group__items .v-list-item.v-list-item--active, + .v-list-group__items .v-list-item.v-list-item--active>.v-list-item__overlay { + background: transparent; + color: rgb(var(--v-theme-secondary)); + } + } + } +} + +.v-navigation-drawer--rail { + + .scrollnavbar .v-list .v-list-group__items, + .hide-menu { + opacity: 1; + } + + .leftPadding { + margin-left: 0px; + } +} + +@media only screen and (min-width: 1170px) { + .mini-sidebar { + .logo { + width: 40px; + overflow: hidden; + padding-left: 0; + } + + .profile-logout { + opacity: 0; + width: 0; + } + + .scrollnavbar { + .smallCap { + padding: 3px 12px 12px 12px !important; + } + } + + .leftSidebar .v-list--density-default .v-list-subheader { + padding-inline-start: 15px !important; + } + + .mini-icon { + display: block; + } + + .sidebarchip.hide-menu { + opacity: 0; + } + + .mini-text { + display: none; + } + + .v-list { + padding: 14px !important; + } + + .v-list-group__items { + .iconClass { + position: relative; + left: -2px; + } + } + + .leftSidebar:hover { + box-shadow: $box-shadow !important; + + .mini-icon { + display: none; + } + + .sidebarchip.hide-menu { + opacity: 1; + } + + .mini-text { + display: block; + } + + .profile-logout { + opacity: 1; + width: auto; + } + + .scrollnavbar { + .smallCap { + padding: 3px 12px 12px 0px !important; + } + } + + .v-list-group__items { + .iconClass { + position: relative; + left: 0px; + } + } + + .v-list--density-default .v-list-subheader { + padding-inline-start: 0px !important; + } + .v-list-group__items { + .v-list-item { + .v-list-item__prepend .dot { + opacity:0; + } + } + } + } + + .v-navigation-drawer--expand-on-hover:hover { + .logo { + width: 100%; + } + + .v-list .v-list-group__items, + .hide-menu { + opacity: 1; + } + } + + .profile-img { + margin-left: 0; + + &::before { + left: 12px; + } + } + + .menu-toggle { + margin-left: 24px; + } + + .v-list-group__items { + .v-list-item { + .v-list-item__prepend .dot { + opacity: 1; + } + } + } + + } +} + +// scrollbar +.ps__rail-y { + z-index: 9; +} + +.profile-img { + margin-left: 14px; + + &::before { + -webkit-animation: 2.5s blow 0s linear infinite; + animation: 2.5s blow 0s linear infinite; + position: absolute; + content: ""; + width: 50px; + height: 50px; + top: 40px; + border-radius: 50%; + z-index: 0; + left: 26px; + } + + @-webkit-keyframes blow { + 0% { + box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.1); + opacity: 1; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + + 50% { + box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); + opacity: 1; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + + 100% { + box-shadow: 0 0 0 20px rgba(0, 0, 0, 0.1); + opacity: 0; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + } + + @keyframes blow { + 0% { + box-shadow: 0 0 0 0px rgba(0, 0, 0, 0.1); + opacity: 1; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + + 50% { + box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1); + opacity: 1; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + + 100% { + box-shadow: 0 0 0 20px rgba(0, 0, 0, 0.1); + opacity: 0; + -webkit-transform: scale3d(1, 1, 0.5); + transform: scale3d(1, 1, 0.5); + } + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_text.scss b/web/src/scss/layout/_text.scss new file mode 100644 index 0000000..0c58315 --- /dev/null +++ b/web/src/scss/layout/_text.scss @@ -0,0 +1,98 @@ +$sizes: ( + 'display-1': 44px, + 'display-2': 40px, + 'display-3': 30px, + 'h1': 36px, + 'h2': 30px, + 'h3': 21px, + 'h4': 18px, + 'h5': 16px, + 'h6': 14px, + 'text-10': 10px, + 'text-12': 12px, + 'text-13': 13px, + 'text-14': 14px, + 'text-15': 15px, + 'text-16': 16px, + 'text-17': 17px, + 'text-18': 18px, + 'text-20': 20px, + 'text-22': 22px, + 'text-24': 24px, + 'text-28': 28px, + 'text-34': 34px, + 'text-40': 40px, + 'text-44': 44px, + 'text-48': 48px, + 'text-50': 50px, + 'text-52': 52px, + 'text-56': 56px, + 'text-64': 64px, + 'body-text-1': 10px +); + +@each $pixel, $size in $sizes { + .#{$pixel} { + font-size: $size; + line-height: $size + 10; + } +} + +$height: ( + 'h-10': 10px, + 'h-12': 12px, + 'h-15': 15px, +); + +@each $pixel, $size in $height { + .#{$pixel} { + height: $size; + width: $size ; + } +} + +.textSecondary { + color: rgb(var(--v-theme-textSecondary)) !important; +} + +.textPrimary { + color: rgb(var(--v-theme-textPrimary)) !important; +} + +// line height + +.lh-md { + line-height: 1.57; +} +.lh-normal{ + line-height: normal; +} + +.font-weight-semibold { + font-weight: 600; +} + +// hover text +.text-hover-primary { + color: rgb(var(--v-theme-textPrimary)); + + &:hover { + color: rgb(var(--v-theme-primary)); + } +} + +.link { + color: rgb(var(--v-theme-textSecondary)); + text-decoration: none; + + &:hover { + color: rgb(var(--v-theme-primary)); + } +} + +.hover-primary { + &:hover { + color: rgb(var(--v-theme-primary)) !important; + opacity: 1; + } +} \ No newline at end of file diff --git a/web/src/scss/layout/_topbar.scss b/web/src/scss/layout/_topbar.scss new file mode 100644 index 0000000..762e4f2 --- /dev/null +++ b/web/src/scss/layout/_topbar.scss @@ -0,0 +1,110 @@ +.v-app-bar { + .v-toolbar__content { + padding: 0 15px; + > .v-btn:first-child { + margin-inline-start: 0; + } + .v-btn { + color: rgba(var(--v-theme-textsurface)) !important; + } + } +} + +.custom-text-primary { + &.v-list-item:hover > .v-list-item__overlay { + display: none; + } + .custom-title { + color: rgb(var(--v-theme-textPrimary)) !important; + } + &:hover { + .custom-title { + color: rgb(var(--v-theme-primary)) !important; + } + } +} +@media screen and (max-width:1279px) { + .mini-sidebar { + .v-navigation-drawer.v-navigation-drawer--left { + width: 270px !important; + } + } +} + + +.notify { + position: relative; + top: -20px; + right: -8px; + + .heartbit { + position: absolute; + top: -5px; + right: -2px; + height: 18px; + width: 18px; + z-index: 10; + border: 2px solid rgb(var(--v-theme-error)); + border-radius: 70px; + animation: heartbit 1s ease-out; + -moz-animation: heartbit 1s ease-out; + -moz-animation-iteration-count: infinite; + -o-animation: heartbit 1s ease-out; + -o-animation-iteration-count: infinite; + -webkit-animation: heartbit 1s ease-out; + -webkit-animation-iteration-count: infinite; + animation-iteration-count: infinite; + } + + .point { + width: 4px; + height: 4px; + border-radius: 30px; + position: absolute; + right: 5px; + top: 2px; + background-color: rgb(var(--v-theme-error)); + position: absolute; + } + } + + @keyframes heartbit { + 0% { + transform: scale(0); + opacity: 0; + } + + 25% { + transform: scale(0.1); + opacity: 0.1; + } + + 50% { + transform: scale(0.5); + opacity: 0.3; + } + + 75% { + transform: scale(0.8); + opacity: 0.5; + } + + 100% { + transform: scale(1); + opacity: 0; + } + } + + .v-menu.mobile_popup .v-overlay__content { + width: 100%; +} + + @media (max-width: 1199px) { + .main-head{ + &.v-app-bar .v-toolbar__content{ + width: 100%; + justify-content: space-between; + padding: 0 10px; + } + } +} \ No newline at end of file diff --git a/web/src/scss/pages/_apps.scss b/web/src/scss/pages/_apps.scss new file mode 100644 index 0000000..7825ec5 --- /dev/null +++ b/web/src/scss/pages/_apps.scss @@ -0,0 +1,240 @@ +// +// common +// + +.inside-left-sidebar { + .left-part { + width: 240px; + } +} + +// +//Full Calendar +.fc { + .fc-button-group { + >.fc-button { + display: flex; + align-items: center; + padding: 7px 10px; + border: 0; + font-size: 14px; + background-color: rgba(var(--v-theme-grey200)); + color: rgba(var(--v-theme-textPrimary)); + .fc-icon{ + color: rgba(var(--v-theme-textPrimary)); + font-size: 20px; + } + &:hover,&:focus{ + background-color: rgba(var(--v-theme-textPrimary)); + color: #fff; + .fc-icon{ + color: #fff; + } + } + } + .fc-button-primary:not(:disabled):active{ + background-color: rgba(var(--v-theme-textPrimary)); + } + .fc-button-primary:not(:disabled).fc-button-active { + background-color: rgb(var(--v-theme-textPrimary)); + } + } + .fc-today-button{ + padding: 7px 20px; + border: 0; + background-color: rgba(var(--v-theme-primary)); + } + + .fc-prev-button{ + border-radius: 30px 0 0 30px; + } + .fc-toolbar-title{ + font-weight: 600; + } + .fc-event-title{ + font-size: 14px; + padding: 3px 6px; + } + + .fc-button { + font-size: 14px; + font-weight: 500; + text-transform: capitalize; + + .fc-icon { + font-size: 1.5em; + vertical-align: unset; + } + } + .fc-daygrid-day-number{ + color: rgba(var(--v-theme-textSecondary)); + font-size: 15px; + } + + .fc-button-primary { + background: rgb(var(--v-theme-primary)); + border-color: rgb(var(--v-theme-primary)); + + color: #fff; + + &:hover { + background-color: rgb(var(--v-theme-primary)); + border-color: rgb(var(--v-theme-primary)); + } + + &:not(:disabled).fc-button-active { + background-color: rgb(var(--v-theme-primary)); + border-color: rgb(var(--v-theme-primary)); + + &:focus { + box-shadow: none; + } + } + + &:not(:disabled) { + &:active { + background-color: rgb(var(--v-theme-primary)); + border-color: rgb(var(--v-theme-primary)); + + &:focus { + box-shadow: none; + } + } + } + + &:disabled { + background-color: rgb(var(--v-theme-primary)); + border-color: rgb(var(--v-theme-primary)); + opacity: 1; + } + } + + .fc-col-header-cell-cushion { + display: inline-block; + padding: 10px 5px; + font-size: 14px; + font-weight: 600; + } + .fc-button-primary:not(:disabled).fc-button-active{ + background-color: rgb(var(--v-theme-textPrimary)); + } +} + +.fc-theme-standard { + td { + border: 1px solid rgba(var(--v-border-color), 1) !important; + } + + th { + border: 1px solid rgba(var(--v-border-color), 1) !important; + border-bottom: 0 !important; + background-color: rgba(var(--v-theme-grey200)); + height: 56px; + vertical-align: middle; + color: rgba(var(--v-theme-textSecondary)); + } + + .fc-scrollgrid { + border: 0 !important; + } +} + +.fc-h-event { + background-color: rgb(var(--v-theme-primary)); + border: 0; + display: block; +} + +.fc-direction-ltr { + .fc-button-group { + >.fc-button { + &:not(:last-child) { + border-bottom-left-radius: 30px; + border-top-left-radius: 30px; + } + + &:not(:first-child) { + border-bottom-right-radius: 30px; + border-top-right-radius: 30px; + margin-left: -1px; + } + } + } +} + +.fc-button-group { + .fc-dayGridMonth-button { + border-bottom-right-radius: 0px !important; + border-top-right-radius: 0px !important; + padding: 7px 20px !important; + } + + .fc-timeGridDay-button { + border-bottom-left-radius: 0px !important; + border-top-left-radius: 0px !important; + padding: 7px 20px !important; + } + + .fc-timeGridWeek-button { + border-radius: 0 !important; + padding: 7px 20px !important; + } +} + +.fc-today-button { + border-radius: 30px !important; + font-size: 14px; +} + +@media screen and (max-width:600px) { + .fc { + .fc-toolbar { + display: block; + text-align: center; + } + } + + .fc-toolbar-chunk { + .fc-toolbar-title { + margin: 15px 0; + } + } +} + +.customTab { + .v-btn { + &.v-tab-item--selected { + background-color: rgb(var(--v-theme-lightprimary)) !important; + + .icon { + background-color: rgb(var(--v-theme-primary)) !important; + color: #fff !important; + } + } + } +} + +.email-items { + padding: 0px 24px 12px; + + &.selected-email { + .email-title { + color: rgb(var(--v-theme-primary)) !important; + } + } + + &:hover { + background-color: rgb(var(--v-theme-hoverColor)); + + .email-title { + color: rgb(var(--v-theme-primary)) !important; + } + + } +} + +.email-content { + p { + margin: 10px 0; + } +} \ No newline at end of file diff --git a/web/src/scss/pages/_authentication.scss b/web/src/scss/pages/_authentication.scss new file mode 100644 index 0000000..63f6b3a --- /dev/null +++ b/web/src/scss/pages/_authentication.scss @@ -0,0 +1,90 @@ +.authentication{ + &::before{ + content: ""; + position: absolute; + height: 100%; + width: 100%; + opacity: 0.3; + left: 0; + top: 0; + bottom: 0; + background: radial-gradient(rgb(210, 241, 223), rgb(211, 215, 250), rgb(186, 216, 244)) 0% 0% / 400% 400%; + } + + @media screen and (max-width:1280px){ + .auth-header{ + position: unset; + } + } +} +.mw-450{ + max-width: 450px; + width: 100%;; +} +.auth-header{ + position: absolute; + top: 0; + left: 0; +} +.verification{ + .v-field__input{ + text-align: center; + } +} +.auth-divider{ + span{ + z-index: 1; + } + &::before{ + position: absolute; + width: 100%; + border-top: thin solid rgb(var(--v-theme-borderColor)); + top: 50%; + content: ""; + transform: translateY(50%); + left: 0; + } + &::after + { + position: absolute; + width: 100%; + border-top: thin solid rgb(var(--v-theme-borderColor)); + top: 50%; + content: ""; + transform: translateY(50%); + right: 0; + } +} + +@media (min-width: 1536px){ + .auth{ + .v-col-lg-7{ + flex: 0 0 66.66%; + max-width: 66.66%; + } + .v-col-lg-5{ + flex: 0 0 33.33%; + max-width: 33.33%; + } + } + +} +@media screen and (max-width:1280px){ + .mh-100{ + height: 100% !important; + } +} + +@media screen and (max-width:600px){ + .mw-100{ + width: 100%; + padding: 0 15px; + } +} + +.auth{ + .v-switch .v-label, .v-checkbox .v-label { + opacity: 0.7; + font-weight: 400 !important; + } +} \ No newline at end of file diff --git a/web/src/scss/pages/_dashboards.scss b/web/src/scss/pages/_dashboards.scss new file mode 100644 index 0000000..e222a21 --- /dev/null +++ b/web/src/scss/pages/_dashboards.scss @@ -0,0 +1,227 @@ +.month-table { + &.custom-px-0 { + thead { + tr { + th:first-child { + padding-left: 0 !important; + } + + th:last-child { + padding-right: 0 !important; + } + } + } + + tr.month-item { + td:first-child { + padding-left: 0 !important; + } + + td:last-child { + padding-right: 0 !important; + } + } + } + + tr.month-item { + td { + padding-top: 16px !important; + padding-bottom: 16px !important; + } + + &:hover { + background: transparent !important; + } + } + + tr.month-item-0 { + td { + padding-top: 12px !important; + padding-bottom: 12px !important; + } + + &:hover { + background: transparent !important; + } + } + + tr.month-item-hover { + + td { + padding-top: 12px !important; + padding-bottom: 12px !important; + } + + border-left: 4px solid transparent; + + &:hover { + border-left: 4px solid rgba(var(--v-theme-primary)) !important; + } + } + + +} + + +.no-line { + + .v-table .v-table__wrapper>table>tbody>tr:not(:last-child)>td { + border-bottom: 0 !important; + } + + .v-table .v-table__wrapper>table>tbody>tr>td { + padding: 12px; + } +} + +.recent-transaction { + .line { + width: 2px; + height: 35px; + } +} + + +.chip-label { + width: 80px; + justify-content: center; +} + +// +// Apex Chart +// + +body { + .apexcharts-tooltip { + border-radius: 16px; + } + + .apexcharts-tooltip-marker { + border-radius: 4px; + width: 12px; + height: 4px; + } + + .apexcharts-tooltip.apexcharts-theme-dark { + background: rgba(17, 28, 45, 0.8); + + .apexcharts-tooltip-title { + border-bottom: 0; + background: rgba(17, 28, 45, 0.7); + } + } + + .apexcharts-tooltip-series-group { + padding: 0 14px; + } + + .apexcharts-tooltip-title { + padding: 10px 14px; + } +} + +.profile-activity { + + .v-tab { + + &.v-btn { + border: 1px dashed rgba(var(--v-theme-borderColor)); + border-radius: 8px; + min-width: 90px; + overflow: hidden; + padding: 15px 20px; + overflow: hidden; + + .v-btn__content { + display: block; + } + + &.v-tab--selected{ + border: 1px solid rgba(var(--v-theme-borderColor)); + border-bottom: 2px solid; + } + .v-tab__slider{ + opacity: 0; + } + } + + } + + .v-slide-group__content { + gap: 16px; + } +} + +.comment-box { + border-bottom: 1px solid rgba(var(--v-theme-borderColor)); + padding-bottom: 20px; + margin-bottom: 20px; + cursor: pointer; + + &:last-child { + border-bottom: 0; + padding-bottom: 0px; + margin-bottom: 0px; + } + + .comment-action { + opacity: 0; + transition: 0.5s; + } + + &:hover { + .comment-action { + opacity: 1; + } + } +} + +.todo-list { + border-bottom: 1px solid rgba(var(--v-theme-borderColor)); + padding-bottom: 25px; + margin-bottom: 25px; + cursor: pointer; + + &:last-child { + border-bottom: 0; + padding-bottom: 20px; + margin-bottom: 20px; + } + +} + +.progress-cards { + border-inline-end: 1px solid rgba(var(--v-theme-borderColor)); + + &:last-child { + border: 0; + } + + @media screen and (max-width:991px) { + border-inline-end: 0 !important + } +} + +.notification { + border-bottom: 1px solid rgba(var(--v-theme-borderColor)); + + &:last-child { + border: 0; + } +} + + +.earning-cards { + @media screen and (max-width:991px){ + .w-25{ + width: 100% !important; + &.border-e{ + border: 0 !important; + } + .mobile-border{ + border-bottom:1px solid rgba(var(--v-theme-borderColor)); + padding-bottom: 8px !important; + } + } + } +} \ No newline at end of file diff --git a/web/src/scss/pages/_datatable.scss b/web/src/scss/pages/_datatable.scss new file mode 100644 index 0000000..a540915 --- /dev/null +++ b/web/src/scss/pages/_datatable.scss @@ -0,0 +1,48 @@ +@use "../variables" as *; + +.customize-table { + border-radius: $border-radius-root; + .vue3-easy-data-table__main, + .vue3-easy-data-table__footer { + border-radius: $border-radius-root; + } + white-space: nowrap; + --easy-table-border: 1px solid rgb(var(--v-theme-inputBorder), 0.1); + --easy-table-row-border: 1px solid rgb(var(--v-theme-inputBorder), 0.1); + + --easy-table-header-font-size: 14px; + --easy-table-header-height: 50px; + --easy-table-header-font-color: rgb(var(--v-theme-textPrimary)); + --easy-table-header-background-color: rgb(var(--v-theme-surface)); + + --easy-table-header-item-padding: 10px 15px; + + --easy-table-body-even-row-font-color: rgb(var(--v-theme-surface)); + --easy-table-body-even-row-background-color: rgba(0, 0, 0, 0.02); + + --easy-table-body-row-font-color: rgb(var(--v-theme-textPrimary)); + --easy-table-body-row-background-color: rgb(var(--v-theme-surface)); + --easy-table-body-row-height: 50px; + --easy-table-body-row-font-size: 14px; + + --easy-table-body-row-hover-font-color: rgb(var(--v-theme-textPrimary)); + --easy-table-body-row-hover-background-color: rgba(0, 0, 0, 0.02); + + --easy-table-body-item-padding: 15px; + + --easy-table-footer-background-color: rgb(var(--v-theme-surface)); + --easy-table-footer-font-color: rgb(var(--v-theme-textPrimary)); + --easy-table-footer-font-size: 14px; + --easy-table-footer-padding: 0px 10px; + --easy-table-footer-height: 50px; + + --easy-table-rows-per-page-selector-width: 70px; + --easy-table-rows-per-page-selector-option-padding: 10px; + + --easy-table-scrollbar-track-color: #; + --easy-table-scrollbar-color: #; + --easy-table-scrollbar-thumb-color: #4c5d7a; + --easy-table-scrollbar-corner-color: #; + + --easy-table-loading-mask-background-color: #; +} diff --git a/web/src/scss/pages/_editor.scss b/web/src/scss/pages/_editor.scss new file mode 100644 index 0000000..0076bfc --- /dev/null +++ b/web/src/scss/pages/_editor.scss @@ -0,0 +1,61 @@ +.ProseMirror { + padding: 20px; + border: 1px solid rgb(var(--v-theme-inputBorder), 0.3); + border-radius: 0 0 12px 12px; + &.ProseMirror-focused { + outline-color: rgb(var(--v-theme-primary), 0.3) !important; + } + > * + * { + margin-top: 0.75em; + } + + ul, + ol { + padding: 0 1rem; + } + + h1, + h2, + h3, + h4, + h5, + h6 { + line-height: 1.1; + } + + code { + background-color: rgba(#616161, 0.1); + color: #616161; + } + + pre { + background: #0d0d0d; + color: #fff; + font-family: 'JetBrainsMono', monospace; + padding: 0.75rem 1rem; + border-radius: 0.5rem; + + code { + color: inherit; + padding: 0; + background: none; + font-size: 0.8rem; + } + } + + img { + max-width: 100%; + height: auto; + } + + blockquote { + padding-left: 1rem; + border-left: 2px solid rgba(#0d0d0d, 0.1); + } + + hr { + border: none; + border-top: 2px solid rgba(#0d0d0d, 0.1); + margin: 2rem 0; + } +} diff --git a/web/src/scss/style.scss b/web/src/scss/style.scss new file mode 100644 index 0000000..7edb098 --- /dev/null +++ b/web/src/scss/style.scss @@ -0,0 +1,91 @@ +@use "./variables"; +@use "vuetify/styles.scss"; +@use "./override"; +@use "./layout/text"; +@use "./layout/reboot"; +@use "./layout/container"; +@use "./layout/sidebar"; +@use "./layout/rtl"; +@use "./layout/topbar"; +@use "./layout/horizontal"; +@use "./layout/dark"; +@use "./layout/customizer"; + +@use "./theme/themeColors"; + +@use "./components/VDatatable"; +@use "./components/VAlert"; +@use "./components/VButtons"; +@use "./components/VBreadcrumb"; +@use "./components/VCard"; +@use "./components/VCarousel"; +@use "./components/VField"; +@use "./components/VList"; +@use "./components/VInput"; +@use "./components/VNavigationDrawer"; +@use "./components/VShadow"; +@use "./components/VSwitch"; +@use "./components/VSelectionControl"; +@use "./components/VTextField"; +@use "./components/VTextarea"; +@use "./components/VTabs"; +@use "./components/VTable"; +@use "./components/VExpansionpanel"; +@use "./components/VDatatables"; +@use "./components/VStepper"; +@use "./components/VLabs"; + +@use "./front/header"; +@use "./front/general"; + +@use "./pages/datatable"; +@use "./pages/dashboards"; +@use "./pages/editor"; +@use "./pages/authentication"; +@use "./pages/apps"; + +//@use 'vue3-perfect-scrollbar/dist/vue3-perfect-scrollbar.css'; + +.small-stat-card { + border: 1px solid #25334355; + background-color: #152332; + border-radius: 8px; +} + +.small-stat-card .v-card-subtitle { + padding: 8px 14px 4px; + font-size: 13px; + border-bottom: 1px solid #253343; +} +.small-stat-card .v-card-text { + font-size: 20px; + padding: 9px 14px 10px; +} + +.small-stat-card.bg-error { + background-color: #cf667925 !important; + border: 1px solid #cf667955 !important; +} +.small-stat-card.bg-error .v-card-subtitle { + border-bottom: 1px solid #cf667955; +} + +.small-stat-card.bg-warning { + background-color: #fb8c0025 !important; + border: 1px solid #fb8c0055 !important; +} +.small-stat-card.bg-warning .v-card-subtitle { + border-bottom: 1px solid #fb8c0055; +} +.small-stat-card .text-warning { + color: #fb8c00de !important; +} + +.row-clickable tbody tr { + cursor: pointer; +} + +.v-data-table-rows-loading, +.v-data-table-rows-no-data { + text-align: left; +} diff --git a/web/src/scss/theme/_themeColors.scss b/web/src/scss/theme/_themeColors.scss new file mode 100644 index 0000000..6e3c2ae --- /dev/null +++ b/web/src/scss/theme/_themeColors.scss @@ -0,0 +1,59 @@ +// Light Theme Colors +.v-theme--AQUA_THEME { + --v-theme-primary: 0, 116, 186; + --v-theme-secondary: 71, 215, 188; + --v-theme-lightprimary: 229, 241, 248; + --v-theme-lightsecondary: 237, 251, 247; +} + +.v-theme--PURPLE_THEME { + --v-theme-primary: 118, 62, 189; + --v-theme-secondary: 148, 208, 214; + --v-theme-lightprimary: 242, 236, 249; + --v-theme-lightsecondary: 237, 248, 250; +} + +.v-theme--GREEN_THEME { + --v-theme-primary: 10, 126, 164; + --v-theme-secondary: 204, 218, 78; + --v-theme-lightprimary: 230, 242, 246; + --v-theme-lightsecondary: 250, 251, 239; +} + +.v-theme--CYAN_THEME { + --v-theme-primary: 1, 192, 200; + --v-theme-secondary: 251, 150, 120; + --v-theme-lightprimary: 235, 249, 250; + --v-theme-lightsecondary: 255, 245, 242; +} + +.v-theme--ORANGE_THEME { + --v-theme-primary: 250, 137, 107; + --v-theme-secondary: 0, 116, 186; + --v-theme-lightprimary: 251, 242, 239; + --v-theme-lightsecondary: 239, 249, 255; +} + +.v-theme--DARK_AQUA_THEME{ + --v-theme-primary: 0, 116, 186; + --v-theme-secondary: 71, 215, 188; +} + +.v-theme--DARK_PURPLE_THEME { + --v-theme-primary: 118, 62, 189; + --v-theme-secondary: 148, 208, 214; +} + +.v-theme--DARK_GREEN_THEME { + --v-theme-primary: 10, 126, 164; + --v-theme-secondary: 204, 218, 78; +} + +.v-theme--DARK_CYAN_THEME { + --v-theme-primary: 1, 192, 200; + --v-theme-secondary: 251, 150, 120; +} +.v-theme--DARK_ORANGE_THEME { + --v-theme-primary: 250, 137, 107; + --v-theme-secondary: 0, 116, 186; +} \ No newline at end of file diff --git a/web/src/theme/DarkTheme.ts b/web/src/theme/DarkTheme.ts new file mode 100644 index 0000000..16fed7f --- /dev/null +++ b/web/src/theme/DarkTheme.ts @@ -0,0 +1,191 @@ +import type { ThemeTypes } from "./ThemeTypes" + +const DARK_BLUE_THEME: ThemeTypes = { + name: "DARK_BLUE_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#1B84FF", + secondary: "#0cb9c5", + lightprimary: "#253662", + lightsecondary: "#1C455D", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#2a3447", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#2a3447", + grey100: "#333F55", + grey200: "#465670", + }, +} + +const DARK_AQUA_THEME: ThemeTypes = { + name: "DARK_AQUA_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#0074BA", + info: "#725af2", + secondary: "#47D7BC", + lightprimary: "#103247", + lightsecondary: "#0C4339", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#171c23", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#171c23", + grey100: "#333F55", + grey200: "#465670", + }, +} + +const DARK_PURPLE_THEME: ThemeTypes = { + name: "DARK_PURPLE_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#763EBD", + secondary: "#95CFD5", + lightprimary: "#26153C", + lightsecondary: "#09454B", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#171c23", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#171c23", + grey100: "#333F55", + grey200: "#465670", + }, +} + +const DARK_GREEN_THEME: ThemeTypes = { + name: "DARK_GREEN_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#0A7EA4", + secondary: "#CCDA4E", + lightprimary: "#05313F", + lightsecondary: "#282917", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#171c23", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#171c23", + grey100: "#333F55", + grey200: "#465670", + }, +} + +const DARK_CYAN_THEME: ThemeTypes = { + name: "DARK_CYAN_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#01C0C8", + secondary: "#FB9678", + lightprimary: "#003638", + lightsecondary: "#40241C", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#171c23", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#171c23", + grey100: "#333F55", + grey200: "#465670", + }, +} + +const DARK_ORANGE_THEME: ThemeTypes = { + name: "DARK_ORANGE_THEME", + dark: true, + variables: { + "border-color": "#333F55", + "border-opacity": 1, + }, + colors: { + primary: "#FA896B", + secondary: "#0074BA", + lightprimary: "#402E32", + lightsecondary: "#082E45", + lightsuccess: "#1B3C48", + lighterror: "#4B313D", + lightwarning: "#4D3A2A", + lightinfo: "#223662", + textPrimary: "#EAEFF4", + textSecondary: "#7C8FAC", + borderColor: "#333F55", + inputBorder: "#465670", + containerBg: "#171c23", + background: "#192838", + surface: "#152332", + hoverColor: "#333f55", + "on-surface-variant": "#171c23", + grey100: "#333F55", + grey200: "#465670", + }, +} + +export { + DARK_BLUE_THEME, + DARK_AQUA_THEME, + DARK_ORANGE_THEME, + DARK_PURPLE_THEME, + DARK_GREEN_THEME, + DARK_CYAN_THEME, +} diff --git a/web/src/theme/LightTheme.ts b/web/src/theme/LightTheme.ts new file mode 100644 index 0000000..28231e7 --- /dev/null +++ b/web/src/theme/LightTheme.ts @@ -0,0 +1,40 @@ +import type { ThemeTypes } from "./ThemeTypes" + +const BLUE_THEME: ThemeTypes = { + name: "BLUE_THEME", + dark: false, + variables: { + "border-color": "#ebf1f6", + "border-opacity": 1, + }, + colors: { + primary: "#1B84FF", + secondary: "#43CED7", + info: "#2CABE3", + success: "#2CD07E", + accent: "#FFAB91", + warning: "#F6C000", + error: "#F8285A", + purple: "#725AF2", + indigo: "#6610f2", + lightprimary: "#EDF5FD", + lightsecondary: "#F2FCFC", + lightsuccess: "#EDFDF2", + lighterror: "#FFF0F4", + lightwarning: "#FFFCF0", + lightinfo: "#E4F5FF", + textPrimary: "#3A4752", + textSecondary: "#768B9E", + borderColor: "#ebf1f6", + inputBorder: "#DFE5EF", + containerBg: "#ffffff", + background: "#eef5f9", + hoverColor: "#f6f9fc", + surface: "#fff", + "on-surface-variant": "#fff", + grey100: "#F2F6FA", + grey200: "#EAEFF4", + }, +} + +export { BLUE_THEME } diff --git a/web/src/theme/ThemeTypes.ts b/web/src/theme/ThemeTypes.ts new file mode 100644 index 0000000..b7a3c68 --- /dev/null +++ b/web/src/theme/ThemeTypes.ts @@ -0,0 +1,33 @@ +export type ThemeTypes = { + name: string + dark: boolean + variables?: object + colors: { + primary?: string + secondary?: string + info?: string + success?: string + accent?: string + warning?: string + error?: string + purple?: string + indigo?: string + lightprimary?: string + lightsecondary?: string + lightsuccess?: string + lighterror?: string + lightinfo?: string + lightwarning?: string + textPrimary?: string + textSecondary?: string + borderColor?: string + hoverColor?: string + inputBorder?: string + containerBg?: string + background?: string + surface?: string + "on-surface-variant"?: string + grey100?: string + grey200?: string + } +} diff --git a/web/src/use/use-breadcrumbs.ts b/web/src/use/use-breadcrumbs.ts new file mode 100644 index 0000000..36b12e0 --- /dev/null +++ b/web/src/use/use-breadcrumbs.ts @@ -0,0 +1,95 @@ +import { reactive, toRefs, watch, MaybeRefOrGetter, toValue } from "vue" +import { RouteLocationRaw } from "vue-router" +import { cloneDeep, isUndefined } from "lodash" + +export type Breadcrumb = { + title?: string + disabled?: boolean + exact?: boolean + to: RouteLocationRaw +} + +// Global state for breadcrumbs +const state = reactive<{ + title?: string + baseCrumb: Breadcrumb + breadcrumbs: Breadcrumb[] + showBackButton: boolean +}>({ + title: "Default", + baseCrumb: { + title: "Dashboard", + to: { + name: "DashboardPage", + }, + }, + breadcrumbs: [], + showBackButton: false, +}) + +// TODO: Consider supporting config option for setting base crumb? +export function useBreadcrumbs( + title?: MaybeRefOrGetter, + breadcrumbs?: MaybeRefOrGetter, + options?: MaybeRefOrGetter<{ + baseCrumb?: Breadcrumb + }>, + isGrounded?: MaybeRefOrGetter, + showBackButton?: MaybeRefOrGetter +) { + watch( + () => toValue(title), + (newTitle) => { + if (isUndefined(newTitle)) return + + state.title = newTitle + }, + { + immediate: true, + } + ) + + watch( + () => toValue(showBackButton), + (newShowBackButton) => { + state.showBackButton = newShowBackButton ?? false + }, + { + immediate: true, + } + ) + + watch( + () => cloneDeep(toValue(breadcrumbs)), + (newBreadcrumbs) => { + if (isUndefined(newBreadcrumbs)) return + + state.breadcrumbs = [state.baseCrumb, ...newBreadcrumbs] + }, + { + immediate: true, + deep: true, + } + ) + + watch( + () => cloneDeep(toValue(options)), + (newOptions) => { + if (isUndefined(newOptions)) return + + if (!isUndefined(newOptions.baseCrumb)) { + state.baseCrumb = newOptions.baseCrumb + } + }, + { + immediate: true, + deep: true, + } + ) + + return { + ...toRefs(state), + } +} + +export default useBreadcrumbs diff --git a/web/src/use/use-current-user.ts b/web/src/use/use-current-user.ts new file mode 100644 index 0000000..cf8597e --- /dev/null +++ b/web/src/use/use-current-user.ts @@ -0,0 +1,74 @@ +import { computed, reactive, toRefs } from "vue" +import { DateTime } from "luxon" + +import currentUserApi, { UserRoles, type UserAsShow } from "@/api/current-user-api" + +export { UserRoles, type UserAsShow } + +// TODO: consider sending this with every api request? +export const CURRENT_USERS_TIMEZONE = DateTime.local().zoneName + +// Global state +const state = reactive<{ + currentUser: UserAsShow | null + isLoading: boolean + isErrored: boolean + isCached: boolean +}>({ + currentUser: null, + isLoading: false, + isErrored: false, + isCached: false, +}) + +type State = typeof state +type LoadedState = Omit & { + currentUser: Exclude +} + +export function useCurrentUser() { + type StateOrLoadedState = IsLoaded extends true ? LoadedState : State + + const isReady = computed(() => state.isCached && !state.isLoading && !state.isErrored) + + const isSystemAdmin = computed(() => { + return state.currentUser?.roles.includes(UserRoles.SYSTEM_ADMIN) + }) + + async function fetch(): Promise { + state.isLoading = true + try { + const { user } = await currentUserApi.get() + state.isErrored = false + state.currentUser = user + state.isCached = true + return user + } catch (error) { + console.error("Failed to fetch current user:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + // Needs to be called during logout or current user will persist. + function reset() { + state.currentUser = null + state.isLoading = false + state.isErrored = false + state.isCached = false + } + + return { + ...toRefs(state as StateOrLoadedState), + isReady, + fetch, + refresh: fetch, + reset, + // helpers + isSystemAdmin, + } +} + +export default useCurrentUser diff --git a/web/src/use/use-interface.ts b/web/src/use/use-interface.ts new file mode 100644 index 0000000..17f169f --- /dev/null +++ b/web/src/use/use-interface.ts @@ -0,0 +1,46 @@ +import { reactive, toRefs, watch } from "vue" + +// Global state for breadcrumbs +const state = reactive<{ + sidebarDrawer: boolean + sidebarMini: boolean +}>({ + sidebarDrawer: false, + sidebarMini: false, +}) + +/* watch( + state, + (newValue) => { + console.log("Sidebar drawer state changed:", newValue) + }, + { deep: true } +) */ + +export function useInterface() { + function setSidebarDrawer(value: boolean) { + state.sidebarDrawer = value + } + + function setSidebarMini(value: boolean) { + state.sidebarMini = value + } + + function toggleSidebarDrawer() { + state.sidebarDrawer = !state.sidebarDrawer + } + + function toggleSidebarMini() { + state.sidebarMini = !state.sidebarMini + } + + return { + ...toRefs(state), + setSidebarDrawer, + setSidebarMini, + toggleSidebarDrawer, + toggleSidebarMini, + } +} + +export default useInterface diff --git a/web/src/use/use-notifications.ts b/web/src/use/use-notifications.ts new file mode 100644 index 0000000..78f9f5c --- /dev/null +++ b/web/src/use/use-notifications.ts @@ -0,0 +1,71 @@ +import { type Ref, reactive, toRefs, ref, unref, watch } from "vue" + +import notificationsApi, { + NotificationSourceTypes, + type Notification, + type NotificationWhereOptions, + type NotificationFiltersOptions, +} from "@/api/notifications-api" + +export { + NotificationSourceTypes, + type Notification, + type NotificationWhereOptions, + type NotificationFiltersOptions, +} + +export function useNotifications( + queryOptions: Ref<{ + where?: Record + page?: number + perPage?: number + }> = ref({}), + { skipWatchIf = () => false }: { skipWatchIf?: () => boolean } = {} +) { + const state = reactive<{ + notifications: Notification[] + totalCount: number + isLoading: boolean + isErrored: boolean + }>({ + notifications: [], + totalCount: 0, + isLoading: false, + isErrored: false, + }) + + async function fetch(): Promise { + state.isLoading = true + try { + const { notifications, totalCount } = await notificationsApi.list(unref(queryOptions)) + state.isErrored = false + state.notifications = notifications + state.totalCount = totalCount + return notifications + } catch (error) { + console.error("Failed to fetch notifications:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + watch( + () => unref(queryOptions), + async () => { + if (skipWatchIf()) return + + await fetch() + }, + { deep: true, immediate: true } + ) + + return { + ...toRefs(state), + fetch, + refresh: fetch, + } +} + +export default useNotifications diff --git a/web/src/use/use-snack.ts b/web/src/use/use-snack.ts new file mode 100644 index 0000000..fa319b7 --- /dev/null +++ b/web/src/use/use-snack.ts @@ -0,0 +1,69 @@ +import { reactive, toRef, ToRef } from "vue" +import { VSnackbar } from "vuetify/components" + +type VSnackbarProps = VSnackbar["$props"] + +const state = reactive<{ + message: string + options: VSnackbarProps +}>({ + message: "", + options: {}, +}) + +/** + * @example + * const snack = useSnack() + * snack("Hello world", { color: "success" }) + * + * @example + * const snack = useSnack() + * snack.success("Hello world") + */ +export function useSnack(defaultOptions: VSnackbarProps = {}): { + (message: string, options?: VSnackbarProps): void + message: ToRef + options: ToRef + notify: (message: string, options?: VSnackbarProps) => void + reset: () => void + success: (message: string, options?: VSnackbarProps) => void + error: (message: string, options?: VSnackbarProps) => void + info: (message: string, options?: VSnackbarProps) => void + warning: (message: string, options?: VSnackbarProps) => void +} { + const notify = (message: string, options: VSnackbarProps = {}) => { + state.message = message + state.options = { ...defaultOptions, ...options } + } + + notify.message = toRef(state, "message") + notify.options = toRef(state, "options") + + notify.notify = notify + + notify.reset = () => { + state.message = "" + state.options = {} + } + + notify.success = (message: string, options: VSnackbarProps = {}) => { + notify(message, { color: "success", ...options }) + } + + notify.error = (message: string, options: VSnackbarProps = {}) => { + notify(message, { color: "error", ...options }) + } + + notify.info = (message: string, options: VSnackbarProps = {}) => { + notify(message, { color: "info", ...options }) + } + + notify.warning = (message: string, options: VSnackbarProps = {}) => { + notify(message, { color: "warning", ...options }) + } + + // @ts-expect-error - VSnackbarProps definition is probably not infinte + return notify +} + +export default useSnack diff --git a/web/src/use/use-status.ts b/web/src/use/use-status.ts new file mode 100644 index 0000000..ee5ff89 --- /dev/null +++ b/web/src/use/use-status.ts @@ -0,0 +1,47 @@ +import { reactive, toRefs } from "vue" + +import statusApi, { type Status } from "@/api/status-api" + +export { type Status } + +export function useStatus() { + const state = reactive<{ + releaseTag: null | string + gitCommitHash: null | string + isLoading: boolean + isErrored: boolean + }>({ + releaseTag: null, + gitCommitHash: null, + isLoading: false, + isErrored: false, + }) + + async function fetch(): Promise { + state.isLoading = true + try { + const status = await statusApi.get() + state.isErrored = false + state.releaseTag = status.RELEASE_TAG + state.gitCommitHash = status.GIT_COMMIT_HASH + return status + } catch (error) { + console.error("Failed to fetch status:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + // Fetch status immediately + fetch() + + return { + ...toRefs(state), + fetch, + refresh: fetch, + } +} + +export default useStatus diff --git a/web/src/use/use-user.ts b/web/src/use/use-user.ts new file mode 100644 index 0000000..76effb3 --- /dev/null +++ b/web/src/use/use-user.ts @@ -0,0 +1,113 @@ +import { type Ref, reactive, toRefs, unref, watch } from "vue" +import { isNil } from "lodash" + +import { type Policy } from "@/api/base-api" +import usersApi, { type User } from "@/api/users-api" + +export { type User } + +export function useUser(id: Ref) { + const state = reactive<{ + user: User | null + policy: Policy | null + isLoading: boolean + isErrored: boolean + }>({ + user: null, + policy: null, + isLoading: false, + isErrored: false, + }) + + async function fetch(): Promise { + const staticId = unref(id) + if (isNil(staticId)) { + throw new Error("id is required") + } + + state.isLoading = true + try { + const { user, policy } = await usersApi.get(staticId) + state.isErrored = false + state.user = user + state.policy = policy + return user + } catch (error) { + console.error("Failed to fetch user:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + async function save(): Promise { + const staticId = unref(id) + if (isNil(staticId)) { + throw new Error("id is required") + } + + if (isNil(state.user)) { + throw new Error("No user to save") + } + + state.isLoading = true + try { + const { user } = await usersApi.update(staticId, state.user) + state.isErrored = false + state.user = user + return user + } catch (error) { + console.error("Failed to save user:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + async function directorySync() { + const staticId = unref(id) + if (isNil(staticId)) { + throw new Error("id is required") + } + + if (isNil(state.user)) { + throw new Error("No user to save") + } + + state.isLoading = true + try { + const { user } = await usersApi.directorySync(staticId) + state.isErrored = false + state.user = user + return user + } catch (error) { + console.error("Failed to sync user:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + watch( + () => unref(id), + async (newId) => { + if (isNil(newId)) return + + await fetch() + }, + { immediate: true } + ) + + return { + ...toRefs(state), + fetch, + refresh: fetch, + save, + directorySync, + } +} + +export default useUser diff --git a/web/src/use/use-users.ts b/web/src/use/use-users.ts new file mode 100644 index 0000000..8660299 --- /dev/null +++ b/web/src/use/use-users.ts @@ -0,0 +1,62 @@ +import { type Ref, reactive, toRefs, ref, unref, watch } from "vue" + +import usersApi, { + type User, + type UserWhereOptions, + type UserFiltersOptions, + type UserQueryOptions, +} from "@/api/users-api" + +export { type User, type UserWhereOptions, type UserFiltersOptions, type UserQueryOptions } + +export function useUsers( + queryOptions: Ref = ref({}), + { skipWatchIf = () => false }: { skipWatchIf?: () => boolean } = {} +) { + const state = reactive<{ + users: User[] + totalCount: number + isLoading: boolean + isErrored: boolean + }>({ + users: [], + totalCount: 0, + isLoading: false, + isErrored: false, + }) + + async function fetch(): Promise { + state.isLoading = true + try { + const { users, totalCount } = await usersApi.list(unref(queryOptions)) + state.isErrored = false + state.users = users + state.totalCount = totalCount + return users + } catch (error) { + console.error("Failed to fetch users:", error) + state.isErrored = true + throw error + } finally { + state.isLoading = false + } + } + + watch( + () => [skipWatchIf(), unref(queryOptions)], + async ([skip]) => { + if (skip) return + + await fetch() + }, + { deep: true, immediate: true } + ) + + return { + ...toRefs(state), + fetch, + refresh: fetch, + } +} + +export default useUsers diff --git a/web/src/use/utils/use-page-title.ts b/web/src/use/utils/use-page-title.ts new file mode 100644 index 0000000..ab469b8 --- /dev/null +++ b/web/src/use/utils/use-page-title.ts @@ -0,0 +1,22 @@ +import { MaybeRefOrGetter, ref, toValue, watch } from "vue" +import { isNil, isEmpty } from "lodash" + +import { APPLICATION_NAME } from "@/config" + +export function usePageTitle(title: MaybeRefOrGetter = ref(null)) { + watch( + () => toValue(title), + (newTitle) => { + if (!isNil(newTitle) && !isEmpty(newTitle)) { + document.title = `${APPLICATION_NAME} - ${newTitle}` + } else { + document.title = APPLICATION_NAME + } + }, + { + immediate: true, + } + ) +} + +export default usePageTitle diff --git a/web/src/use/utils/use-route-query-enhanced.ts b/web/src/use/utils/use-route-query-enhanced.ts new file mode 100644 index 0000000..13981aa --- /dev/null +++ b/web/src/use/utils/use-route-query-enhanced.ts @@ -0,0 +1,32 @@ +import { computed, MaybeRefOrGetter, Ref } from "vue" +import { useRouteQuery } from "@vueuse/router" +import { RouteParamValueRaw } from "vue-router" + +type RouteQueryValueRaw = RouteParamValueRaw | string[] + +/** + * Enhanced useRouteQuery with parse and stringify transformations + * + * See https://github.com/vueuse/vueuse/blob/0f11df11962f5f2e912d66c8544bc6767630780a/packages/router/useRouteQuery/index.ts + */ +export function useRouteQueryEnhanced( + name: string, + defaultValue: MaybeRefOrGetter, + options: { + parse: (value: T) => K + stringify: (value: K) => T + } +): Ref { + const query = useRouteQuery(name, defaultValue) + + return computed({ + get() { + return options.parse(query.value) + }, + set(value: K) { + query.value = options.stringify(value) + }, + }) +} + +export default useRouteQueryEnhanced diff --git a/web/src/use/utils/use-route-query-pagination.ts b/web/src/use/utils/use-route-query-pagination.ts new file mode 100644 index 0000000..5371095 --- /dev/null +++ b/web/src/use/utils/use-route-query-pagination.ts @@ -0,0 +1,41 @@ +import { useRouteQuery } from "@vueuse/router" + +import { integerTransformer } from "@/utils/use-route-query-transformers" + +const DEFAULT_PAGE = 1 +const DEFAULT_PER_PAGE = 10 + +/** + * Usage: use in conjunction with EnhancedPagination component. + * @param {Object} [options] - Options object. + * @param {number} [options.page=1] - Initial page number. Default is 1. + * @param {number} [options.perPage=10] - Initial items per page. Default is 10. + */ +export function useRouteQueryPagination({ + page = DEFAULT_PAGE, + perPage = DEFAULT_PER_PAGE, + routeQuerySuffix = "", +}: { + page?: number + perPage?: number + routeQuerySuffix?: string +} = {}) { + const queryPage = useRouteQuery(`page${routeQuerySuffix}`, page.toString(), { + transform: integerTransformer, + }) + + const queryPerPage = useRouteQuery( + `perPage${routeQuerySuffix}`, + perPage.toString(), + { + transform: integerTransformer, + } + ) + + return { + page: queryPage, + perPage: queryPerPage, + } +} + +export default useRouteQueryPagination diff --git a/web/src/use/utils/use-vuetify-color-classes-as-specific-color-classes.ts b/web/src/use/utils/use-vuetify-color-classes-as-specific-color-classes.ts new file mode 100644 index 0000000..152f2bc --- /dev/null +++ b/web/src/use/utils/use-vuetify-color-classes-as-specific-color-classes.ts @@ -0,0 +1,25 @@ +import { computed, Ref, toValue } from "vue" +import { isNil, isEmpty } from "lodash" + +/** + * Returns a computed ref that returns a specific color class based on the provided color classes. + * Given + * "red" could be used produce "text-red" or "bg-red" or "border-red" + */ +export function useVuetifyColorClassesAsSpecificColorClasses( + colorClasses: Ref, + prefix: string = "text" +) { + const textColorClass = computed(() => { + const colorClassesValues = toValue(colorClasses) + if (isNil(colorClassesValues)) return "" + if (isEmpty(colorClassesValues)) return "" + + const normalizedClass = colorClassesValues.split(" ").join("-") + return `${prefix}-${normalizedClass}` + }) + + return textColorClass +} + +export default useVuetifyColorClassesAsSpecificColorClasses diff --git a/web/src/use/utils/use-vuetify-color-name-to-hex-value.ts b/web/src/use/utils/use-vuetify-color-name-to-hex-value.ts new file mode 100644 index 0000000..b951904 --- /dev/null +++ b/web/src/use/utils/use-vuetify-color-name-to-hex-value.ts @@ -0,0 +1,12 @@ +import { useTheme } from "vuetify" + +/** + * Useful for setting the color of a tabler icon. + */ +export function useVuetifyColorNameToHexValue(colorName: string) { + const theme = useTheme() + + return theme.current.value.colors[colorName] +} + +export default useVuetifyColorNameToHexValue diff --git a/web/src/use/utils/use-vuetify-slot-names-pass-through.ts b/web/src/use/utils/use-vuetify-slot-names-pass-through.ts new file mode 100644 index 0000000..7c220ae --- /dev/null +++ b/web/src/use/utils/use-vuetify-slot-names-pass-through.ts @@ -0,0 +1,26 @@ +import { ComputedRef, computed, useSlots } from "vue" + +type ComponentWithSlots = { + $slots: { + [key: string]: unknown + } +} + +type SlotNamesExtractor = T extends ComponentWithSlots ? keyof T["$slots"] & string : never + +export function useVuetifySlotNamesPassThrough< + Component extends ComponentWithSlots = never, + SlotNames extends SlotNamesExtractor = SlotNamesExtractor, +>(slotsToPassThrough: SlotNames[]): ComputedRef { + const wrappedSlotNames = new Set(slotsToPassThrough) + + const slots = useSlots() + + return computed(() => { + return Object.keys(slots).filter((slotName): slotName is SlotNames => + wrappedSlotNames.has(slotName as SlotNames) + ) + }) +} + +export default useVuetifySlotNamesPassThrough diff --git a/web/src/use/utils/use-vuetify-sort-by-to-safe-route-query.ts b/web/src/use/utils/use-vuetify-sort-by-to-safe-route-query.ts new file mode 100644 index 0000000..03d6508 --- /dev/null +++ b/web/src/use/utils/use-vuetify-sort-by-to-safe-route-query.ts @@ -0,0 +1,53 @@ +import { isEmpty, isNil, isString } from "lodash" +import { Ref } from "vue" + +import { VDataTable } from "vuetify/components" + +import useRouteQueryEnhanced from "@/use/utils/use-route-query-enhanced" + +export type SortItem = VDataTable["sortBy"][0] + +/** + * Must not conflict with web/src/use/utils/use-vuetify-sort-by-to-sequelize-safe-order.ts SEPARATOR. + */ +const SEPARATOR = "_" + +export function useVuetifySortByToSafeRouteQuery( + name: string, + defaultValue?: SortItem[] | undefined +): Ref { + function parse(newSortBy: string[] | string | undefined): SortItem[] | undefined { + if (isNil(newSortBy) || isEmpty(newSortBy)) { + return + } + + if (isString(newSortBy)) { + newSortBy = [newSortBy] + } + + return newSortBy.map((entry) => { + const [key, order] = entry.split(SEPARATOR) + return { key, order } as SortItem + }) + } + + function stringify(sortByValue: SortItem[] | undefined): string[] | undefined { + if (isNil(sortByValue) || isEmpty(sortByValue)) { + return + } + + return sortByValue.map(({ key, order }) => `${key}${SEPARATOR}${order}`) + } + + const defaultValueString = stringify(defaultValue) + return useRouteQueryEnhanced( + name, + defaultValueString, + { + parse, + stringify, + } + ) +} + +export default useVuetifySortByToSafeRouteQuery diff --git a/web/src/use/utils/use-vuetify-sort-by-to-sequelize-safe-order.ts b/web/src/use/utils/use-vuetify-sort-by-to-sequelize-safe-order.ts new file mode 100644 index 0000000..558925b --- /dev/null +++ b/web/src/use/utils/use-vuetify-sort-by-to-sequelize-safe-order.ts @@ -0,0 +1,61 @@ +import { isEmpty, isNil } from "lodash" +import { computed, ComputedRef, Ref, toValue } from "vue" + +import { type ModelOrder } from "@/api/base-api" +import { type SortItem } from "@/use/utils/use-vuetify-sort-by-to-safe-route-query" + +/** + * Must not conflict with web/src/use/utils/use-vuetify-sort-by-to-safe-route-query.ts SEPARATOR + */ +const SEPARATOR = "." + +/** + * Converts content of the form [ + * { key: "attribute", order: "asc" }, + * { key: "attribute", order: "desc" }, + * { key: "nested.associated.attribute", order: "asc" }, + * { key: "nested.associated.attribute", order: "desc" }, + * ] + * + * to the form [ + * [ "attribute", "ASC" ], + * [ "attribute", "DESC" ], + * [ "nested", "associated", "attribute", "ASC" ], + * [ "nested", "associated", "attribute", "DESC" ], + * ] + */ +export function useVuetifySortByToSequelizeSafeOrder( + sortBy: Ref +): ComputedRef { + const order = computed(() => { + const sortByValue = toValue(sortBy) + if (isNil(sortByValue) || isEmpty(sortByValue)) { + return undefined + } + + return sortByValue.map(({ key: column, order }) => { + let direction: "ASC" | "DESC" = "ASC" + if (order === true) { + direction = "ASC" + } else if (order === false) { + direction = "DESC" + } else if (order === "desc") { + direction = "DESC" + } else if (order === "asc") { + direction = "ASC" + } + + const nestedAssociatedModelAttributes = column.split(SEPARATOR) as + | [string, string] + | [string, string, string] + | [string, string, string, string] + | [string, string, string, string, string] + + return [...nestedAssociatedModelAttributes, direction] + }) + }) + + return order +} + +export default useVuetifySortByToSequelizeSafeOrder diff --git a/web/src/utils/authorization-guards/authorization-guard.ts b/web/src/utils/authorization-guards/authorization-guard.ts new file mode 100644 index 0000000..ad34b8f --- /dev/null +++ b/web/src/utils/authorization-guards/authorization-guard.ts @@ -0,0 +1,37 @@ +import { type RouteLocationNormalized } from "vue-router" +import { isEmpty, isNil } from "lodash" + +import useCurrentUser, { type UserAsShow } from "@/use/use-current-user" + +export async function authorizationGuard(to: RouteLocationNormalized) { + const guardGroups = to.matched + .map((record) => record.meta.guards as ((user: UserAsShow) => boolean)[] | undefined) + .filter((g): g is ((user: UserAsShow) => boolean)[] => !isNil(g) && !isEmpty(g)) + + if (guardGroups.length === 0) return true + + const { currentUser, fetch } = useCurrentUser() + if (isNil(currentUser.value)) { + await fetch() + } + + if (isNil(currentUser.value)) { + throw new Error("No current user") + } + + // AND across matched records (every level must pass), OR within each + // record's guards array (any guard at that level satisfies it). + for (const guards of guardGroups) { + const passes = guards.some((guard) => { + if (typeof guard !== "function") { + throw new Error(`Guard ${guard} is not a function`) + } + return guard(currentUser.value as UserAsShow) + }) + if (!passes) return false + } + + return true +} + +export default authorizationGuard diff --git a/web/src/utils/authorization-guards/index.ts b/web/src/utils/authorization-guards/index.ts new file mode 100644 index 0000000..121f9c4 --- /dev/null +++ b/web/src/utils/authorization-guards/index.ts @@ -0,0 +1,2 @@ +export { authorizationGuard } from "./authorization-guard" +export { isSystemAdmin } from "./user-guards" diff --git a/web/src/utils/authorization-guards/user-guards.ts b/web/src/utils/authorization-guards/user-guards.ts new file mode 100644 index 0000000..b445fb3 --- /dev/null +++ b/web/src/utils/authorization-guards/user-guards.ts @@ -0,0 +1,6 @@ +import { UserRoles } from "@/api/users-api" +import { type UserAsShow } from "@/api/current-user-api" + +export function isSystemAdmin(user: UserAsShow): boolean { + return user.roles.includes(UserRoles.SYSTEM_ADMIN) ?? false +} diff --git a/web/src/utils/debounce-with-args-cache.ts b/web/src/utils/debounce-with-args-cache.ts new file mode 100644 index 0000000..ac25d6a --- /dev/null +++ b/web/src/utils/debounce-with-args-cache.ts @@ -0,0 +1,57 @@ +import { debounce } from "lodash" + +type DebounceableFunction = Parameters["0"] + +/** + * @example + * ``` + * const usersApi = { + * async get(userId, params = {}) { + * console.trace(`usersApi.get: Fetching user: ${userId} with params:`, params) + * const { data } = await http.get(`/api/users/${userId}`, { params }) + * return data + * }, + * } + * + * usersApi.get = debounceWithArgsCache(usersApi.get, 300, 10) + * + * usersApi.get(1, { role: "admin" }) + * usersApi.get(2, { role: "user" }) + * usersApi.get(1, { role: "admin" }) + * setTimeout(() => usersApi.get(1, { role: "admin" }), 400) + * ``` + */ +export function debounceWithArgsCache( + fn: DebounceableFunction, + { + wait = 300, + leading = true, + trailing = true, + cacheSize = 10, + }: { wait?: number; leading?: boolean; trailing?: boolean; cacheSize?: number } +) { + const invocationCache = new Map() + + return (...args: unknown[]) => { + const argsKey = JSON.stringify(args) + + if (invocationCache.has(argsKey)) { + const debouncedFn = invocationCache.get(argsKey) + const result = debouncedFn(...args) + return result + } + + if (invocationCache.size >= cacheSize) { + const oldestInvocation = invocationCache.keys().next().value + invocationCache.delete(oldestInvocation) + } + + const debouncedFn = debounce(fn, wait, { leading, trailing }) + invocationCache.set(argsKey, debouncedFn) + + const result = debouncedFn(...args) + return result + } +} + +export default debounceWithArgsCache diff --git a/web/src/utils/formatters/format-bytes.ts b/web/src/utils/formatters/format-bytes.ts new file mode 100644 index 0000000..3186eb0 --- /dev/null +++ b/web/src/utils/formatters/format-bytes.ts @@ -0,0 +1,13 @@ +export function formatBytes(bytes: number, decimals = 2) { + if (bytes === 0) return "0 Bytes" + + const k = 1024 + const dm = decimals < 0 ? 0 : decimals + const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"] + + const i = Math.floor(Math.log(bytes) / Math.log(k)) + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i] +} + +export default formatBytes diff --git a/web/src/utils/formatters/format-date-long.ts b/web/src/utils/formatters/format-date-long.ts new file mode 100644 index 0000000..eb9f03d --- /dev/null +++ b/web/src/utils/formatters/format-date-long.ts @@ -0,0 +1,21 @@ +import { isNil, isEmpty } from "lodash" +import { DateTime } from "luxon" + +/** + * Note: \u00A0d is a non-breaking space, and permits date to wrap like this: + * November 07, 72024 + * @ 710:21 AM + */ +export function formatDateLong(input: string | Date | undefined): string { + if (isNil(input) || isEmpty(input)) { + return "" + } else if (typeof input == "string") { + return DateTime.fromISO(input).toLocal().toFormat("MMMM\u00A0dd,\u00A0yyyy @\u00A0t") + } else if (input instanceof Date) { + return DateTime.fromJSDate(input).toLocal().toFormat("MMMM\u00A0dd,\u00A0yyyy @\u00A0t") + } else { + return "" + } +} + +export default formatDateLong diff --git a/web/src/utils/formatters/format-date-words.ts b/web/src/utils/formatters/format-date-words.ts new file mode 100644 index 0000000..4e3f111 --- /dev/null +++ b/web/src/utils/formatters/format-date-words.ts @@ -0,0 +1,16 @@ +import { isNil, isEmpty } from "lodash" +import { DateTime } from "luxon" + +export function formatDateWords(input: string | Date | undefined): string { + if (isNil(input) || isEmpty(input)) { + return "" + } else if (typeof input == "string") { + return DateTime.fromISO(input).toLocal().toFormat("MMMM dd, yyyy") + } else if (input instanceof Date) { + return DateTime.fromJSDate(input).toLocal().toFormat("MMMM dd, yyyy") + } else { + return "" + } +} + +export default formatDateWords diff --git a/web/src/utils/formatters/format-date.ts b/web/src/utils/formatters/format-date.ts new file mode 100644 index 0000000..cf6bf2b --- /dev/null +++ b/web/src/utils/formatters/format-date.ts @@ -0,0 +1,18 @@ +import { isNil, isEmpty } from "lodash" +import { DateTime } from "luxon" + +export function formatDate(input: string | Date | undefined): string { + if (isNil(input) || isEmpty(input)) { + return "" + } else if (typeof input == "string") { + const parsed = DateTime.fromISO(input, { zone: "utc" }) + const isMidnight = parsed.hour === 0 && parsed.minute === 0 && parsed.second === 0 + return isMidnight ? parsed.toFormat("yyyy-MM-dd") : parsed.toLocal().toFormat("yyyy-MM-dd") + } else if (input instanceof Date) { + return DateTime.fromJSDate(input).toLocal().toFormat("yyyy-MM-dd") + } else { + return "" + } +} + +export default formatDate diff --git a/web/src/utils/formatters/format-number-in-string-to-fixed-decimal.ts b/web/src/utils/formatters/format-number-in-string-to-fixed-decimal.ts new file mode 100644 index 0000000..755ae23 --- /dev/null +++ b/web/src/utils/formatters/format-number-in-string-to-fixed-decimal.ts @@ -0,0 +1,24 @@ +import { isNil } from "lodash" + +/** + * Extracts the numeric part of a string and formats it to desired decimal places + * + * Ex. -15.030000000000001 Cycles => -15.03 Cycles + * + * NOTE: number of decimals defaults to 2 + */ +export function formatNumberInStringToFixedDecimal( + input: string | null | undefined, + decimals: number = 2 +): string { + if (isNil(input) || decimals < 0) { + console.warn( + `formatNumberInStringToFixedDecimal received invalid input: input=${input}, decimals=${decimals}` + ) + return "" + } + + return input.replace(/([-+]?\d[\d,]*\.?\d*)/, (match) => { + return parseFloat(match.replace(/,/g, "")).toFixed(decimals) + }) +} diff --git a/web/src/utils/formatters/format-relative.ts b/web/src/utils/formatters/format-relative.ts new file mode 100644 index 0000000..7fe65bf --- /dev/null +++ b/web/src/utils/formatters/format-relative.ts @@ -0,0 +1,16 @@ +import { isNil, isEmpty } from "lodash" +import { DateTime } from "luxon" + +export function formatRelative(input: string | Date | undefined): string { + if (isNil(input) || isEmpty(input)) { + return "" + } else if (typeof input == "string") { + return DateTime.fromISO(input).toLocal().toRelative() ?? "" + } else if (input instanceof Date) { + return DateTime.fromJSDate(input).toLocal().toRelative() ?? "" + } else { + return "" + } +} + +export default formatRelative diff --git a/web/src/utils/formatters/index.ts b/web/src/utils/formatters/index.ts new file mode 100644 index 0000000..60a99f3 --- /dev/null +++ b/web/src/utils/formatters/index.ts @@ -0,0 +1,6 @@ +export { formatBytes } from "./format-bytes" +export { formatDate } from "./format-date" +export { formatDateLong } from "./format-date-long" +export { formatRelative } from "./format-relative" +export { formatDateWords } from "./format-date-words" + diff --git a/web/src/utils/safe-json-parse.ts b/web/src/utils/safe-json-parse.ts new file mode 100644 index 0000000..136f19a --- /dev/null +++ b/web/src/utils/safe-json-parse.ts @@ -0,0 +1,14 @@ +export function safeJsonParse(values: string): unknown | null { + try { + return JSON.parse(values) + } catch (error) { + if (error instanceof SyntaxError) { + return null + } else { + console.warn(`Unexpected json parsing error: ${error}`, { error }) + return null + } + } +} + +export default safeJsonParse diff --git a/web/src/utils/sleep.ts b/web/src/utils/sleep.ts new file mode 100644 index 0000000..0c1353d --- /dev/null +++ b/web/src/utils/sleep.ts @@ -0,0 +1,3 @@ +export function sleep(milliseconds: number) { + return new Promise((resolve) => setTimeout(resolve, milliseconds)) +} diff --git a/web/src/utils/strip-trailing-slash.ts b/web/src/utils/strip-trailing-slash.ts new file mode 100644 index 0000000..94279ee --- /dev/null +++ b/web/src/utils/strip-trailing-slash.ts @@ -0,0 +1,3 @@ +export function stripTrailingSlash(url: string) { + return url.endsWith("/") ? url.slice(0, -1) : url +} diff --git a/web/src/utils/use-route-query-transformers/boolean-transformer.ts b/web/src/utils/use-route-query-transformers/boolean-transformer.ts new file mode 100644 index 0000000..7d927f3 --- /dev/null +++ b/web/src/utils/use-route-query-transformers/boolean-transformer.ts @@ -0,0 +1,22 @@ +import { isNil } from "lodash" + +export const booleanTransformer = { + get(value: boolean | string | null | undefined): boolean { + if (isNil(value)) return false + if (typeof value === "string") { + return value === "true" + } + + return value + }, + set(value: boolean | string | null | undefined): string { + if (isNil(value)) return "false" + if (typeof value === "boolean") { + return value.toString() + } + + return value + }, +} + +export default booleanTransformer diff --git a/web/src/utils/use-route-query-transformers/index.ts b/web/src/utils/use-route-query-transformers/index.ts new file mode 100644 index 0000000..23590a6 --- /dev/null +++ b/web/src/utils/use-route-query-transformers/index.ts @@ -0,0 +1,4 @@ +export { booleanTransformer } from "./boolean-transformer" +export { integerTransformer } from "./integer-transformer" +export { integerTransformerLegacy } from "./integer-transformer-legacy" +export { stringTransformer } from "./string-transformer" diff --git a/web/src/utils/use-route-query-transformers/integer-transformer-legacy.ts b/web/src/utils/use-route-query-transformers/integer-transformer-legacy.ts new file mode 100644 index 0000000..2faa83a --- /dev/null +++ b/web/src/utils/use-route-query-transformers/integer-transformer-legacy.ts @@ -0,0 +1,9 @@ +import { isNil } from "lodash" + +export function integerTransformerLegacy(value: string | null | undefined): number | null { + if (isNil(value)) return null + + return parseInt(value) +} + +export default integerTransformerLegacy diff --git a/web/src/utils/use-route-query-transformers/integer-transformer.ts b/web/src/utils/use-route-query-transformers/integer-transformer.ts new file mode 100644 index 0000000..d41c9a2 --- /dev/null +++ b/web/src/utils/use-route-query-transformers/integer-transformer.ts @@ -0,0 +1,27 @@ +import { isNil } from "lodash" + +function integerGet( + value: T +): number | (T & undefined) | (T & null) { + if (isNil(value)) return value + if (typeof value === "number") return value + + return parseInt(value, 10) +} + +function integerSet( + value: T +): string | (T & undefined) | (T & null) { + if (isNil(value)) return value + if (typeof value === "number") return value.toString() + if (typeof value === "string") return value + + return "" +} + +export const integerTransformer = { + get: integerGet, + set: integerSet, +} as const + +export default integerTransformer diff --git a/web/src/utils/use-route-query-transformers/string-transformer.ts b/web/src/utils/use-route-query-transformers/string-transformer.ts new file mode 100644 index 0000000..761923e --- /dev/null +++ b/web/src/utils/use-route-query-transformers/string-transformer.ts @@ -0,0 +1,16 @@ +import { isNil } from "lodash" + +export const stringTransformer = { + get(value: string | null | undefined) { + if (isNil(value)) return "" + + return value + }, + set(value: string | null | undefined) { + if (isNil(value)) return "" + + return value + }, +} + +export default stringTransformer diff --git a/web/src/utils/utility-types.ts b/web/src/utils/utility-types.ts new file mode 100644 index 0000000..5219ce9 --- /dev/null +++ b/web/src/utils/utility-types.ts @@ -0,0 +1,5 @@ +export type VueHtmlClass = string | Record | (string | Record)[] + +export type SetIntersection = { + [K in keyof T[number]]: K extends keyof T[0] ? Extract : never +} diff --git a/web/src/utils/validators/email.ts b/web/src/utils/validators/email.ts new file mode 100644 index 0000000..2eca2d3 --- /dev/null +++ b/web/src/utils/validators/email.ts @@ -0,0 +1,7 @@ +import isEmail from "validator/lib/isEmail" + +export function email(value: string) { + if (isEmail(value)) return true + + return "Invalid email" +} diff --git a/web/src/utils/validators/index.ts b/web/src/utils/validators/index.ts new file mode 100644 index 0000000..d628dcc --- /dev/null +++ b/web/src/utils/validators/index.ts @@ -0,0 +1,4 @@ +export { email } from "./email" +export { minimum } from "./minimum" +export { required } from "./required" +export { requiredFile } from "./required-file" diff --git a/web/src/utils/validators/minimum.ts b/web/src/utils/validators/minimum.ts new file mode 100644 index 0000000..0330c7a --- /dev/null +++ b/web/src/utils/validators/minimum.ts @@ -0,0 +1,13 @@ +import { isString } from "lodash" + +export function minimum(length: number) { + return (v: unknown): boolean | string => { + if (isString(v) && v.length < length) { + return `Must be at least ${length} characters` + } + + return true + } +} + +export default minimum diff --git a/web/src/utils/validators/required-file.ts b/web/src/utils/validators/required-file.ts new file mode 100644 index 0000000..1d7d583 --- /dev/null +++ b/web/src/utils/validators/required-file.ts @@ -0,0 +1,20 @@ +export function requiredFile(v: unknown): boolean | string { + // Handle File object + if (v instanceof File) { + return true + } + + // Handle null or undefined + if (v === null || v === undefined) { + return "File is required" + } + + // Handle empty array (when file input is cleared) + if (Array.isArray(v) && v.length === 0) { + return "File is required" + } + + return "File is required" +} + +export default requiredFile diff --git a/web/src/utils/validators/required.ts b/web/src/utils/validators/required.ts new file mode 100644 index 0000000..8391522 --- /dev/null +++ b/web/src/utils/validators/required.ts @@ -0,0 +1,15 @@ +import { isArray, isEmpty, isString, isNull, isObject, isUndefined } from "lodash" + +export function required(v: unknown): boolean | string { + if (isNull(v) || isUndefined(v)) { + return "This field is required" + } + + if ((isArray(v) || isString(v) || isObject(v)) && isEmpty(v)) { + return "This field is required" + } + + return true +} + +export default required diff --git a/web/src/vite-env.d.ts b/web/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/web/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/web/tests/setup.ts b/web/tests/setup.ts new file mode 100644 index 0000000..55b92b1 --- /dev/null +++ b/web/tests/setup.ts @@ -0,0 +1,7 @@ +import { mockHttpClient } from "@/tests/support/mock-http-client" +import { mockCurrentUserApi } from "@/tests/support/mock-current-user-api" + +beforeEach(() => { + mockHttpClient() + mockCurrentUserApi() +}) diff --git a/web/tests/support/index.ts b/web/tests/support/index.ts new file mode 100644 index 0000000..16dc4b1 --- /dev/null +++ b/web/tests/support/index.ts @@ -0,0 +1,2 @@ +export { mockCurrentUserApi } from "./mock-current-user-api" +export { mockHttpClient } from "./mock-http-client" diff --git a/web/tests/support/mock-current-user-api.ts b/web/tests/support/mock-current-user-api.ts new file mode 100644 index 0000000..a9da4f6 --- /dev/null +++ b/web/tests/support/mock-current-user-api.ts @@ -0,0 +1,54 @@ +import { merge } from "lodash" + +import { type Policy } from "@/api/base-api" +import currentUserApi, { type UserAsShow } from "@/api/current-user-api" + +export const DEFAULT_USER: UserAsShow = { + id: 1, + email: "default-mock-user@example.com", + firstName: null, + lastName: null, + displayName: null, + title: null, + isActive: true, + emailNotificationsEnabled: true, + createdAt: "1970-01-01T00:00:00.000Z", + updatedAt: "1970-01-01T00:00:00.000Z", +} +export const DEFAULT_POLICY: Policy = { + show: true, + create: false, + update: true, + destroy: false, +} + +/** + * Usage: + * At the top section of a test file import: + * import { mockCurrentUserApi } from "@/tests/support" + * + * Then where you want to set the current user: + * mockCurrentUserApi({ user, policy }) + * + * Note that all values for user and policy are optional as minium safe defaults are provided. + * Note that order of operations matters. This file must be imported before any file that imports currentUserApi. + * As such this file has been imported and mocked in the pre-test run "web/tests/setup.ts" file. + * + * @param currentUserApiGetResponseWithDefaults - The response to set for the current user + */ +export function mockCurrentUserApi( + currentUserApiGetResponseWithDefaults: { user?: UserAsShow; policy?: Policy } = {} +) { + vi.mock("@/api/current-user-api") + + const userWithDefaults = merge({}, DEFAULT_USER, currentUserApiGetResponseWithDefaults.user) + const policyWithDefaults = merge({}, DEFAULT_POLICY, currentUserApiGetResponseWithDefaults.policy) + + const mockedCurrentUserApi = vi.mocked(currentUserApi, true) + mockedCurrentUserApi.get.mockResolvedValue({ + user: userWithDefaults, + policy: policyWithDefaults, + }) +} + +export default mockCurrentUserApi diff --git a/web/tests/support/mock-http-client.ts b/web/tests/support/mock-http-client.ts new file mode 100644 index 0000000..330a79f --- /dev/null +++ b/web/tests/support/mock-http-client.ts @@ -0,0 +1,40 @@ +import httpClient from "@/api/http-client" + +vi.mock("@/api/http-client") + +/** + * Usage: + * At the top section of a test file import: + * import { mockHttpClient } from "@/tests/support" + * + * Then where you want to set the http client: + * mockHttpClient() + * + * Note that order of operations matters. This file must be imported before any file that imports httpClient. + * As such this file has been imported and mocked in the pre-test run "web/tests/setup.ts" file. + * + * @returns The mocked http client + */ +export function mockHttpClient() { + const httpClientMock = vi.mocked(httpClient, true) + + httpClientMock.get.mockResolvedValue({ + data: {}, + }) + httpClientMock.post.mockResolvedValue({ + data: {}, + }) + httpClientMock.put.mockResolvedValue({ + data: {}, + }) + httpClientMock.patch.mockResolvedValue({ + data: {}, + }) + httpClientMock.delete.mockResolvedValue({ + data: {}, + }) + + return httpClientMock +} + +export default mockHttpClient diff --git a/web/tests/tsconfig.json b/web/tests/tsconfig.json new file mode 100644 index 0000000..4e08243 --- /dev/null +++ b/web/tests/tsconfig.json @@ -0,0 +1,12 @@ +{ + "extends": "./../tsconfig.json", + "compilerOptions": { + "baseUrl": "./../", + "types": ["vitest/globals"], + "paths": { + "@/tests/*": ["./tests/*"], + "@/*": ["./src/*"] + } + }, + "include": ["../src/**/*", "../tests/**/*", ""] +} diff --git a/web/tests/utils/authorization-guards/authorization-guard.test.ts b/web/tests/utils/authorization-guards/authorization-guard.test.ts new file mode 100644 index 0000000..09ad5c9 --- /dev/null +++ b/web/tests/utils/authorization-guards/authorization-guard.test.ts @@ -0,0 +1,41 @@ +import { type RouteLocationNormalized } from "vue-router" + +import authorizationGuard from "@/utils/authorization-guards/authorization-guard" + +describe("web/src/utils/authorization-guards/authorization-guard.ts", () => { + describe("authorizationGuard", () => { + test("when there are no guards, returns true", async () => { + const to = { + meta: {}, + } as unknown as RouteLocationNormalized + + const result = await authorizationGuard(to) + + expect(result).toBe(true) + }) + + test("when all guards return true, returns true", async () => { + const to = { + meta: { + guards: [() => true, () => true, () => true], + }, + } as unknown as RouteLocationNormalized + + const result = await authorizationGuard(to) + + expect(result).toBe(true) + }) + + test("when any guard returns false, returns false", async () => { + const to = { + meta: { + guards: [() => true, () => false, () => true], + }, + } as unknown as RouteLocationNormalized + + const result = await authorizationGuard(to) + + expect(result).toBe(false) + }) + }) +}) diff --git a/web/tsconfig.json b/web/tsconfig.json new file mode 100644 index 0000000..416ec29 --- /dev/null +++ b/web/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "allowJs": true, + "target": "ESNext", + "useDefineForClassFields": true, + "module": "ESNext", + "moduleResolution": "Node", + "strict": true, + "jsx": "preserve", + "resolveJsonModule": true, + "isolatedModules": true, + "esModuleInterop": true, + "lib": ["ESNext", "DOM"], + "skipLibCheck": true, + "noEmit": true, + "paths": { + "@/*": ["./src/*", "./dist/*"] + } + }, + "include": [ + "src/**/*.ts", + "src/**/*.d.ts", + "src/**/*.tsx", + "src/**/*.vue", + "src/**/*.js", + ".eslintrc.cjs" + ], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/web/tsconfig.node.json b/web/tsconfig.node.json new file mode 100644 index 0000000..77ae975 --- /dev/null +++ b/web/tsconfig.node.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "allowJs": true, + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "allowSyntheticDefaultImports": true, + "outDir": "./dist" + }, + "include": ["vite.config.js"] +} diff --git a/web/vite.config.js b/web/vite.config.js new file mode 100644 index 0000000..1c13544 --- /dev/null +++ b/web/vite.config.js @@ -0,0 +1,45 @@ +/// +import { fileURLToPath, URL } from "node:url" + +// Plugins +import vue from "@vitejs/plugin-vue" +import vuetify from "vite-plugin-vuetify" + +// Utilities +import { defineConfig } from "vite" + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + // https://github.com/vuetifyjs/vuetify-loader/tree/next/packages/vite-plugin + vuetify({ + autoImport: true, + }), + ], + build: { + outDir: "./dist", + }, + define: { "process.env": {} }, + resolve: { + alias: { + "@/tests": fileURLToPath(new URL("./tests", import.meta.url)), + "@": fileURLToPath(new URL("./src", import.meta.url)), + }, + extensions: [".js", ".json", ".jsx", ".mjs", ".ts", ".tsx", ".vue"], + }, + server: { + port: 8080, + }, + test: { + environment: "jsdom", + globals: true, // https://vitest.dev/config/#globals + setupFiles: ["./tests/setup.ts"], + // Mocking + clearMocks: true, + mockReset: true, + restoreMocks: true, + unstubEnvs: true, + unstubGlobals: true, + }, +})