adds eslint

This commit is contained in:
geoffsee
2025-06-24 17:29:52 -04:00
committed by Geoff Seemueller
parent 9698fc6f3b
commit 02c3253343
169 changed files with 4896 additions and 4804 deletions

41
.eslintignore Normal file
View File

@@ -0,0 +1,41 @@
# Dependencies
node_modules
.pnp
.pnp.js
# Build outputs
dist
build
out
.next
.nuxt
.cache
# Test coverage
coverage
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# TypeScript
*.d.ts

49
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,49 @@
module.exports = {
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2021,
sourceType: 'module',
project: './tsconfig.json',
},
env: {
browser: true,
node: true,
es6: true,
},
globals: {
Bun: 'readonly',
},
plugins: ['@typescript-eslint', 'import', 'prettier'],
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
'prettier',
],
rules: {
'prettier/prettier': 'error',
'@typescript-eslint/explicit-module-boundary-types': 'off',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
'import/order': [
'error',
{
'newlines-between': 'always',
alphabetize: { order: 'asc', caseInsensitive: true },
groups: ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'],
},
],
},
settings: {
'import/resolver': {
node: {
extensions: ['.js', '.jsx', '.ts', '.tsx'],
moduleDirectory: ['node_modules', 'packages/*/node_modules'],
},
},
},
ignorePatterns: ['node_modules', 'dist', 'build', '*.d.ts', '*.min.js'],
};

47
.prettierignore Normal file
View File

@@ -0,0 +1,47 @@
# Dependencies
node_modules
.pnp
.pnp.js
# Build outputs
dist
build
out
.next
.nuxt
.cache
# Test coverage
coverage
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Environment variables
.env
.env.local
.env.development.local
.env.test.local
.env.production.local
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
# Package files
package-lock.json
yarn.lock
pnpm-lock.yaml
bun.lock
# Generated files
CHANGELOG.md

19
.prettierrc.cjs Normal file
View File

@@ -0,0 +1,19 @@
module.exports = {
semi: true,
singleQuote: true,
trailingComma: 'all',
printWidth: 100,
tabWidth: 2,
useTabs: false,
bracketSpacing: true,
arrowParens: 'avoid',
endOfLine: 'lf',
overrides: [
{
files: '*.{json,yml,yaml,md}',
options: {
tabWidth: 2,
},
},
],
};

331
bun.lock
View File

@@ -4,7 +4,14 @@
"": { "": {
"devDependencies": { "devDependencies": {
"@types/bun": "latest", "@types/bun": "latest",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"happy-dom": "^18.0.1", "happy-dom": "^18.0.1",
"prettier": "^3.2.5",
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5", "typescript": "^5",
@@ -65,6 +72,8 @@
"name": "@open-gsio/worker", "name": "@open-gsio/worker",
"dependencies": { "dependencies": {
"@cloudflare/vite-plugin": "^1.3.1", "@cloudflare/vite-plugin": "^1.3.1",
"@open-gsio/client": "workspace:*",
"@open-gsio/server": "workspace:*",
"vite": "6.3.5", "vite": "6.3.5",
"wrangler": "^4.18.0", "wrangler": "^4.18.0",
}, },
@@ -435,8 +444,22 @@
"@esbuild/win32-x64": ["@esbuild/win32-x64@0.23.1", "", { "os": "win32", "cpu": "x64" }, "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg=="], "@esbuild/win32-x64": ["@esbuild/win32-x64@0.23.1", "", { "os": "win32", "cpu": "x64" }, "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg=="],
"@eslint-community/eslint-utils": ["@eslint-community/eslint-utils@4.7.0", "", { "dependencies": { "eslint-visitor-keys": "^3.4.3" }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw=="],
"@eslint-community/regexpp": ["@eslint-community/regexpp@4.12.1", "", {}, "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ=="],
"@eslint/eslintrc": ["@eslint/eslintrc@2.1.4", "", { "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" } }, "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ=="],
"@eslint/js": ["@eslint/js@8.57.1", "", {}, "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q=="],
"@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="], "@fastify/busboy": ["@fastify/busboy@2.1.1", "", {}, "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA=="],
"@humanwhocodes/config-array": ["@humanwhocodes/config-array@0.13.0", "", { "dependencies": { "@humanwhocodes/object-schema": "^2.0.3", "debug": "^4.3.1", "minimatch": "^3.0.5" } }, "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw=="],
"@humanwhocodes/module-importer": ["@humanwhocodes/module-importer@1.0.1", "", {}, "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA=="],
"@humanwhocodes/object-schema": ["@humanwhocodes/object-schema@2.0.3", "", {}, "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA=="],
"@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="], "@img/sharp-darwin-arm64": ["@img/sharp-darwin-arm64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-arm64": "1.0.4" }, "os": "darwin", "cpu": "arm64" }, "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ=="],
"@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="], "@img/sharp-darwin-x64": ["@img/sharp-darwin-x64@0.33.5", "", { "optionalDependencies": { "@img/sharp-libvips-darwin-x64": "1.0.4" }, "os": "darwin", "cpu": "x64" }, "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q=="],
@@ -535,6 +558,8 @@
"@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="], "@pkgjs/parseargs": ["@pkgjs/parseargs@0.11.0", "", {}, "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg=="],
"@pkgr/core": ["@pkgr/core@0.2.7", "", {}, "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg=="],
"@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="], "@polka/url": ["@polka/url@1.0.0-next.28", "", {}, "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw=="],
"@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="], "@popperjs/core": ["@popperjs/core@2.11.8", "", {}, "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A=="],
@@ -589,6 +614,8 @@
"@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.39.0", "", { "os": "win32", "cpu": "x64" }, "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug=="], "@rollup/rollup-win32-x64-msvc": ["@rollup/rollup-win32-x64-msvc@4.39.0", "", { "os": "win32", "cpu": "x64" }, "sha512-yAkUOkIKZlK5dl7u6dg897doBgLXmUHhIINM2c+sND3DZwnrdQkkSiDh7N75Ll4mM4dxSkYfXqU9fW3lLkMFug=="],
"@rtsao/scc": ["@rtsao/scc@1.1.0", "", {}, "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g=="],
"@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="], "@shikijs/core": ["@shikijs/core@1.29.2", "", { "dependencies": { "@shikijs/engine-javascript": "1.29.2", "@shikijs/engine-oniguruma": "1.29.2", "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "@types/hast": "^3.0.4", "hast-util-to-html": "^9.0.4" } }, "sha512-vju0lY9r27jJfOY4Z7+Rt/nIOjzJpZ3y+nYpqtUZInVoXQ/TJZcfGnNOGnKjFdVZb8qexiCuSlZRKcGfhhTTZQ=="],
"@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="], "@shikijs/engine-javascript": ["@shikijs/engine-javascript@1.29.2", "", { "dependencies": { "@shikijs/types": "1.29.2", "@shikijs/vscode-textmate": "^10.0.1", "oniguruma-to-es": "^2.2.0" } }, "sha512-iNEZv4IrLYPv64Q6k7EPpOCE/nuvGiKl7zxdq0WFuRPF5PAE9PRo2JGq/d8crLusM59BRemJ4eOqrFrC4wiQ+A=="],
@@ -629,6 +656,8 @@
"@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="], "@types/hast": ["@types/hast@3.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ=="],
"@types/json5": ["@types/json5@0.0.29", "", {}, "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ=="],
"@types/lodash": ["@types/lodash@4.17.16", "", {}, "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g=="], "@types/lodash": ["@types/lodash@4.17.16", "", {}, "sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g=="],
"@types/lodash.mergewith": ["@types/lodash.mergewith@4.6.9", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw=="], "@types/lodash.mergewith": ["@types/lodash.mergewith@4.6.9", "", { "dependencies": { "@types/lodash": "*" } }, "sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw=="],
@@ -655,6 +684,22 @@
"@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="], "@types/whatwg-mimetype": ["@types/whatwg-mimetype@3.0.2", "", {}, "sha512-c2AKvDT8ToxLIOUlN51gTiHXflsfIFisS4pO7pDPoKouJCESkhZnEy623gwP9laCy5lnLDAw1vAzu2vM2YLOrA=="],
"@typescript-eslint/eslint-plugin": ["@typescript-eslint/eslint-plugin@7.18.0", "", { "dependencies": { "@eslint-community/regexpp": "^4.10.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/type-utils": "7.18.0", "@typescript-eslint/utils": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "@typescript-eslint/parser": "^7.0.0", "eslint": "^8.56.0" } }, "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw=="],
"@typescript-eslint/parser": ["@typescript-eslint/parser@7.18.0", "", { "dependencies": { "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg=="],
"@typescript-eslint/scope-manager": ["@typescript-eslint/scope-manager@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0" } }, "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA=="],
"@typescript-eslint/type-utils": ["@typescript-eslint/type-utils@7.18.0", "", { "dependencies": { "@typescript-eslint/typescript-estree": "7.18.0", "@typescript-eslint/utils": "7.18.0", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA=="],
"@typescript-eslint/types": ["@typescript-eslint/types@7.18.0", "", {}, "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ=="],
"@typescript-eslint/typescript-estree": ["@typescript-eslint/typescript-estree@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "@typescript-eslint/visitor-keys": "7.18.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", "minimatch": "^9.0.4", "semver": "^7.6.0", "ts-api-utils": "^1.3.0" } }, "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA=="],
"@typescript-eslint/utils": ["@typescript-eslint/utils@7.18.0", "", { "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@typescript-eslint/scope-manager": "7.18.0", "@typescript-eslint/types": "7.18.0", "@typescript-eslint/typescript-estree": "7.18.0" }, "peerDependencies": { "eslint": "^8.56.0" } }, "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw=="],
"@typescript-eslint/visitor-keys": ["@typescript-eslint/visitor-keys@7.18.0", "", { "dependencies": { "@typescript-eslint/types": "7.18.0", "eslint-visitor-keys": "^3.4.3" } }, "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg=="],
"@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="], "@ungap/structured-clone": ["@ungap/structured-clone@1.3.0", "", {}, "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g=="],
"@vitejs/plugin-react": ["@vitejs/plugin-react@4.3.4", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug=="], "@vitejs/plugin-react": ["@vitejs/plugin-react@4.3.4", "", { "dependencies": { "@babel/core": "^7.26.0", "@babel/plugin-transform-react-jsx-self": "^7.25.9", "@babel/plugin-transform-react-jsx-source": "^7.25.9", "@types/babel__core": "^7.20.5", "react-refresh": "^0.14.2" }, "peerDependencies": { "vite": "^4.2.0 || ^5.0.0 || ^6.0.0" } }, "sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug=="],
@@ -687,24 +732,38 @@
"acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="], "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="],
"acorn-jsx": ["acorn-jsx@5.3.2", "", { "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ=="],
"acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="], "acorn-walk": ["acorn-walk@8.3.2", "", {}, "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A=="],
"agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="], "agent-base": ["agent-base@7.1.3", "", {}, "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw=="],
"agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="], "agentkeepalive": ["agentkeepalive@4.6.0", "", { "dependencies": { "humanize-ms": "^1.2.1" } }, "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ=="],
"ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="], "ajv": ["ajv@6.12.6", "", { "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" } }, "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g=="],
"ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="], "ansi-regex": ["ansi-regex@5.0.1", "", {}, "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="],
"ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="], "ansi-styles": ["ansi-styles@4.3.0", "", { "dependencies": { "color-convert": "^2.0.1" } }, "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg=="],
"argparse": ["argparse@2.0.1", "", {}, "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="],
"aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="], "aria-hidden": ["aria-hidden@1.2.4", "", { "dependencies": { "tslib": "^2.0.0" } }, "sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A=="],
"aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="], "aria-query": ["aria-query@5.3.2", "", {}, "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw=="],
"array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="], "array-buffer-byte-length": ["array-buffer-byte-length@1.0.2", "", { "dependencies": { "call-bound": "^1.0.3", "is-array-buffer": "^3.0.5" } }, "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw=="],
"array-includes": ["array-includes@3.1.9", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.24.0", "es-object-atoms": "^1.1.1", "get-intrinsic": "^1.3.0", "is-string": "^1.1.1", "math-intrinsics": "^1.1.0" } }, "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ=="],
"array-union": ["array-union@2.1.0", "", {}, "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw=="],
"array.prototype.findlastindex": ["array.prototype.findlastindex@1.2.6", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.4", "define-properties": "^1.2.1", "es-abstract": "^1.23.9", "es-errors": "^1.3.0", "es-object-atoms": "^1.1.1", "es-shim-unscopables": "^1.1.0" } }, "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ=="],
"array.prototype.flat": ["array.prototype.flat@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg=="],
"array.prototype.flatmap": ["array.prototype.flatmap@1.3.3", "", { "dependencies": { "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-shim-unscopables": "^1.0.2" } }, "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg=="],
"arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="], "arraybuffer.prototype.slice": ["arraybuffer.prototype.slice@1.0.4", "", { "dependencies": { "array-buffer-byte-length": "^1.0.1", "call-bind": "^1.0.8", "define-properties": "^1.2.1", "es-abstract": "^1.23.5", "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "is-array-buffer": "^3.0.4" } }, "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ=="],
"as-table": ["as-table@1.0.55", "", { "dependencies": { "printable-characters": "^1.0.42" } }, "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ=="], "as-table": ["as-table@1.0.55", "", { "dependencies": { "printable-characters": "^1.0.42" } }, "sha512-xvsWESUJn0JN421Xb9MQw6AsMHRCUknCe0Wjlxvjud80mU4E6hQf1A6NzQKcYNmYw62MfzEtXc+badstZP3JpQ=="],
@@ -733,7 +792,7 @@
"blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="], "blake3-wasm": ["blake3-wasm@2.1.5", "", {}, "sha512-F1+K8EbfOZE49dtoPtmxUQrpXaBIl3ICvasLh+nJta0xkz+9kF/7uet9fLnwKqhDrmj6g+6K3Tw9yQPUg2ka5g=="],
"brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="], "brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
"braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="], "braces": ["braces@3.0.3", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
@@ -763,7 +822,7 @@
"chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="], "chai": ["chai@5.2.0", "", { "dependencies": { "assertion-error": "^2.0.1", "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" } }, "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw=="],
"chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="], "chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="], "character-entities-html4": ["character-entities-html4@2.1.0", "", {}, "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA=="],
@@ -831,6 +890,8 @@
"deep-equal": ["deep-equal@2.2.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "isarray": "^2.0.5", "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", "which-typed-array": "^1.1.13" } }, "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA=="], "deep-equal": ["deep-equal@2.2.3", "", { "dependencies": { "array-buffer-byte-length": "^1.0.0", "call-bind": "^1.0.5", "es-get-iterator": "^1.1.3", "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", "isarray": "^2.0.5", "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", "which-typed-array": "^1.1.13" } }, "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA=="],
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
"deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="], "deepmerge": ["deepmerge@4.3.1", "", {}, "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A=="],
"define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="],
@@ -849,6 +910,10 @@
"devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="], "devlop": ["devlop@1.1.0", "", { "dependencies": { "dequal": "^2.0.0" } }, "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA=="],
"dir-glob": ["dir-glob@3.0.1", "", { "dependencies": { "path-type": "^4.0.0" } }, "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA=="],
"doctrine": ["doctrine@3.0.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w=="],
"dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="], "dom-accessibility-api": ["dom-accessibility-api@0.6.3", "", {}, "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w=="],
"dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="], "dompurify": ["dompurify@3.2.5", "", { "optionalDependencies": { "@types/trusted-types": "^2.0.7" } }, "sha512-mLPd29uoRe9HpvwP2TxClGQBzGXeEC/we/q+bFlmPPmj2p2Ugl3r6ATu/UU1v77DXNcehiBg9zsr1dREyA/dJQ=="],
@@ -885,6 +950,8 @@
"es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="], "es-set-tostringtag": ["es-set-tostringtag@2.1.0", "", { "dependencies": { "es-errors": "^1.3.0", "get-intrinsic": "^1.2.6", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA=="],
"es-shim-unscopables": ["es-shim-unscopables@1.1.0", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw=="],
"es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="], "es-to-primitive": ["es-to-primitive@1.3.0", "", { "dependencies": { "is-callable": "^1.2.7", "is-date-object": "^1.0.5", "is-symbol": "^1.0.4" } }, "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g=="],
"esbuild": ["esbuild@0.23.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.23.1", "@esbuild/android-arm": "0.23.1", "@esbuild/android-arm64": "0.23.1", "@esbuild/android-x64": "0.23.1", "@esbuild/darwin-arm64": "0.23.1", "@esbuild/darwin-x64": "0.23.1", "@esbuild/freebsd-arm64": "0.23.1", "@esbuild/freebsd-x64": "0.23.1", "@esbuild/linux-arm": "0.23.1", "@esbuild/linux-arm64": "0.23.1", "@esbuild/linux-ia32": "0.23.1", "@esbuild/linux-loong64": "0.23.1", "@esbuild/linux-mips64el": "0.23.1", "@esbuild/linux-ppc64": "0.23.1", "@esbuild/linux-riscv64": "0.23.1", "@esbuild/linux-s390x": "0.23.1", "@esbuild/linux-x64": "0.23.1", "@esbuild/netbsd-x64": "0.23.1", "@esbuild/openbsd-arm64": "0.23.1", "@esbuild/openbsd-x64": "0.23.1", "@esbuild/sunos-x64": "0.23.1", "@esbuild/win32-arm64": "0.23.1", "@esbuild/win32-ia32": "0.23.1", "@esbuild/win32-x64": "0.23.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg=="], "esbuild": ["esbuild@0.23.1", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.23.1", "@esbuild/android-arm": "0.23.1", "@esbuild/android-arm64": "0.23.1", "@esbuild/android-x64": "0.23.1", "@esbuild/darwin-arm64": "0.23.1", "@esbuild/darwin-x64": "0.23.1", "@esbuild/freebsd-arm64": "0.23.1", "@esbuild/freebsd-x64": "0.23.1", "@esbuild/linux-arm": "0.23.1", "@esbuild/linux-arm64": "0.23.1", "@esbuild/linux-ia32": "0.23.1", "@esbuild/linux-loong64": "0.23.1", "@esbuild/linux-mips64el": "0.23.1", "@esbuild/linux-ppc64": "0.23.1", "@esbuild/linux-riscv64": "0.23.1", "@esbuild/linux-s390x": "0.23.1", "@esbuild/linux-x64": "0.23.1", "@esbuild/netbsd-x64": "0.23.1", "@esbuild/openbsd-arm64": "0.23.1", "@esbuild/openbsd-x64": "0.23.1", "@esbuild/sunos-x64": "0.23.1", "@esbuild/win32-arm64": "0.23.1", "@esbuild/win32-ia32": "0.23.1", "@esbuild/win32-x64": "0.23.1" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg=="],
@@ -893,6 +960,30 @@
"escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="],
"eslint": ["eslint@8.57.1", "", { "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" } }, "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA=="],
"eslint-config-prettier": ["eslint-config-prettier@9.1.0", "", { "peerDependencies": { "eslint": ">=7.0.0" }, "bin": { "eslint-config-prettier": "bin/cli.js" } }, "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw=="],
"eslint-import-resolver-node": ["eslint-import-resolver-node@0.3.9", "", { "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", "resolve": "^1.22.4" } }, "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g=="],
"eslint-module-utils": ["eslint-module-utils@2.12.1", "", { "dependencies": { "debug": "^3.2.7" } }, "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw=="],
"eslint-plugin-import": ["eslint-plugin-import@2.32.0", "", { "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", "array.prototype.findlastindex": "^1.2.6", "array.prototype.flat": "^1.3.3", "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.12.1", "hasown": "^2.0.2", "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", "object.fromentries": "^2.0.8", "object.groupby": "^1.0.3", "object.values": "^1.2.1", "semver": "^6.3.1", "string.prototype.trimend": "^1.0.9", "tsconfig-paths": "^3.15.0" }, "peerDependencies": { "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA=="],
"eslint-plugin-prettier": ["eslint-plugin-prettier@5.5.0", "", { "dependencies": { "prettier-linter-helpers": "^1.0.0", "synckit": "^0.11.7" }, "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" }, "optionalPeers": ["@types/eslint", "eslint-config-prettier"] }, "sha512-8qsOYwkkGrahrgoUv76NZi23koqXOGiiEzXMrT8Q7VcYaUISR+5MorIUxfWqYXN0fN/31WbSrxCxFkVQ43wwrA=="],
"eslint-scope": ["eslint-scope@7.2.2", "", { "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" } }, "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg=="],
"eslint-visitor-keys": ["eslint-visitor-keys@3.4.3", "", {}, "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag=="],
"espree": ["espree@9.6.1", "", { "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", "eslint-visitor-keys": "^3.4.1" } }, "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ=="],
"esquery": ["esquery@1.6.0", "", { "dependencies": { "estraverse": "^5.1.0" } }, "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg=="],
"esrecurse": ["esrecurse@4.3.0", "", { "dependencies": { "estraverse": "^5.2.0" } }, "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag=="],
"estraverse": ["estraverse@5.3.0", "", {}, "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA=="],
"estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="], "estree-walker": ["estree-walker@3.0.3", "", { "dependencies": { "@types/estree": "^1.0.0" } }, "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g=="],
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="], "esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
@@ -907,10 +998,14 @@
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="], "fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
"fast-diff": ["fast-diff@1.3.0", "", {}, "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw=="],
"fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="], "fast-glob": ["fast-glob@3.3.3", "", { "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.8" } }, "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg=="],
"fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="], "fast-json-stable-stringify": ["fast-json-stable-stringify@2.1.0", "", {}, "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="],
"fast-levenshtein": ["fast-levenshtein@2.0.6", "", {}, "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="],
"fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="], "fast-uri": ["fast-uri@3.0.6", "", {}, "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw=="],
"fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="], "fastq": ["fastq@1.19.1", "", { "dependencies": { "reusify": "^1.0.4" } }, "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ=="],
@@ -919,12 +1014,18 @@
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="], "fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
"file-entry-cache": ["file-entry-cache@6.0.1", "", { "dependencies": { "flat-cache": "^3.0.4" } }, "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg=="],
"filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="], "filelist": ["filelist@1.0.4", "", { "dependencies": { "minimatch": "^5.0.1" } }, "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q=="],
"fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="], "fill-range": ["fill-range@7.1.1", "", { "dependencies": { "to-regex-range": "^5.0.1" } }, "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg=="],
"find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="], "find-root": ["find-root@1.1.0", "", {}, "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="],
"find-up": ["find-up@5.0.0", "", { "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" } }, "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng=="],
"flat-cache": ["flat-cache@3.2.0", "", { "dependencies": { "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" } }, "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw=="],
"flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="], "flatted": ["flatted@3.3.3", "", {}, "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg=="],
"focus-lock": ["focus-lock@1.3.6", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg=="], "focus-lock": ["focus-lock@1.3.6", "", { "dependencies": { "tslib": "^2.0.3" } }, "sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg=="],
@@ -973,18 +1074,22 @@
"glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="], "glob": ["glob@10.4.5", "", { "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^3.1.2", "minimatch": "^9.0.4", "minipass": "^7.1.2", "package-json-from-dist": "^1.0.0", "path-scurry": "^1.11.1" }, "bin": { "glob": "dist/esm/bin.mjs" } }, "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg=="],
"glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="], "glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
"glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="], "glob-to-regexp": ["glob-to-regexp@0.4.1", "", {}, "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="],
"globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="], "globals": ["globals@13.24.0", "", { "dependencies": { "type-fest": "^0.20.2" } }, "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ=="],
"globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="],
"globby": ["globby@11.1.0", "", { "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.2.9", "ignore": "^5.2.0", "merge2": "^1.4.1", "slash": "^3.0.0" } }, "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g=="],
"gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="],
"graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="], "graceful-fs": ["graceful-fs@4.2.11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
"graphemer": ["graphemer@1.4.0", "", {}, "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag=="],
"happy-dom": ["happy-dom@18.0.1", "", { "dependencies": { "@types/node": "^20.0.0", "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" } }, "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA=="], "happy-dom": ["happy-dom@18.0.1", "", { "dependencies": { "@types/node": "^20.0.0", "@types/whatwg-mimetype": "^3.0.2", "whatwg-mimetype": "^3.0.0" } }, "sha512-qn+rKOW7KWpVTtgIUi6RVmTBZJSe2k0Db0vh1f7CWrWclkkc7/Q+FrOfkZIb2eiErLyqu5AXEzE7XthO9JVxRA=="],
"has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="], "has-bigints": ["has-bigints@1.1.0", "", {}, "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg=="],
@@ -1023,8 +1128,12 @@
"idb": ["idb@7.1.1", "", {}, "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="], "idb": ["idb@7.1.1", "", {}, "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ=="],
"ignore": ["ignore@5.3.2", "", {}, "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g=="],
"import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="], "import-fresh": ["import-fresh@3.3.1", "", { "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" } }, "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ=="],
"imurmurhash": ["imurmurhash@0.1.4", "", {}, "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA=="],
"indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="], "indent-string": ["indent-string@4.0.0", "", {}, "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg=="],
"inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="], "inflight": ["inflight@1.0.6", "", { "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA=="],
@@ -1075,6 +1184,8 @@
"is-obj": ["is-obj@1.0.1", "", {}, "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="], "is-obj": ["is-obj@1.0.1", "", {}, "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg=="],
"is-path-inside": ["is-path-inside@3.0.3", "", {}, "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ=="],
"is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="], "is-potential-custom-element-name": ["is-potential-custom-element-name@1.0.1", "", {}, "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ=="],
"is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="], "is-regex": ["is-regex@1.2.1", "", { "dependencies": { "call-bound": "^1.0.2", "gopd": "^1.2.0", "has-tostringtag": "^1.0.2", "hasown": "^2.0.2" } }, "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g=="],
@@ -1125,17 +1236,23 @@
"js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="], "js-tokens": ["js-tokens@4.0.0", "", {}, "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="],
"js-yaml": ["js-yaml@4.1.0", "", { "dependencies": { "argparse": "^2.0.1" }, "bin": { "js-yaml": "bin/js-yaml.js" } }, "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA=="],
"jsdom": ["jsdom@24.1.3", "", { "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.12", "parse5": "^7.1.2", "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^2.11.2" }, "optionalPeers": ["canvas"] }, "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ=="], "jsdom": ["jsdom@24.1.3", "", { "dependencies": { "cssstyle": "^4.0.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.0", "html-encoding-sniffer": "^4.0.0", "http-proxy-agent": "^7.0.2", "https-proxy-agent": "^7.0.5", "is-potential-custom-element-name": "^1.0.1", "nwsapi": "^2.2.12", "parse5": "^7.1.2", "rrweb-cssom": "^0.7.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", "tough-cookie": "^4.1.4", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.0.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^2.11.2" }, "optionalPeers": ["canvas"] }, "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ=="],
"jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="], "jsesc": ["jsesc@3.1.0", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA=="],
"json-buffer": ["json-buffer@3.0.1", "", {}, "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ=="],
"json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="], "json-parse-even-better-errors": ["json-parse-even-better-errors@2.3.1", "", {}, "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="],
"json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="],
"json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="], "json-schema-traverse": ["json-schema-traverse@0.4.1", "", {}, "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="],
"json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="], "json-stable-stringify-without-jsonify": ["json-stable-stringify-without-jsonify@1.0.1", "", {}, "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="],
"json5": ["json5@1.0.2", "", { "dependencies": { "minimist": "^1.2.0" }, "bin": { "json5": "lib/cli.js" } }, "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA=="],
"jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="], "jsonfile": ["jsonfile@6.1.0", "", { "dependencies": { "universalify": "^2.0.0" }, "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ=="],
@@ -1143,14 +1260,22 @@
"katex": ["katex@0.16.21", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A=="], "katex": ["katex@0.16.21", "", { "dependencies": { "commander": "^8.3.0" }, "bin": { "katex": "cli.js" } }, "sha512-XvqR7FgOHtWupfMiigNzmh+MgUVmDGU2kXZm899ZkPfcuoPuFxyHmXsgATDpFZDAXCI8tvinaVcDo8PIIJSo4A=="],
"keyv": ["keyv@4.5.4", "", { "dependencies": { "json-buffer": "3.0.1" } }, "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw=="],
"leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="], "leven": ["leven@3.1.0", "", {}, "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A=="],
"levn": ["levn@0.4.1", "", { "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" } }, "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ=="],
"lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="], "lines-and-columns": ["lines-and-columns@1.2.4", "", {}, "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="],
"locate-path": ["locate-path@6.0.0", "", { "dependencies": { "p-locate": "^5.0.0" } }, "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw=="],
"lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="], "lodash": ["lodash@4.17.21", "", {}, "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="],
"lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="], "lodash.debounce": ["lodash.debounce@4.0.8", "", {}, "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow=="],
"lodash.merge": ["lodash.merge@4.6.2", "", {}, "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ=="],
"lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="], "lodash.mergewith": ["lodash.mergewith@4.6.2", "", {}, "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ=="],
"lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="], "lodash.sortby": ["lodash.sortby@4.7.0", "", {}, "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA=="],
@@ -1207,7 +1332,9 @@
"miniflare": ["miniflare@4.20250525.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250525.0", "ws": "8.18.0", "youch": "3.3.4", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-F5XRDn9WqxUaHphUT8qwy5WXC/3UwbBRJTdjjP5uwHX82vypxIlHNyHziZnplPLhQa1kbSdIY7wfuP1XJyyYZw=="], "miniflare": ["miniflare@4.20250525.0", "", { "dependencies": { "@cspotcode/source-map-support": "0.8.1", "acorn": "8.14.0", "acorn-walk": "8.3.2", "exit-hook": "2.2.1", "glob-to-regexp": "0.4.1", "sharp": "^0.33.5", "stoppable": "1.1.0", "undici": "^5.28.5", "workerd": "1.20250525.0", "ws": "8.18.0", "youch": "3.3.4", "zod": "3.22.3" }, "bin": { "miniflare": "bootstrap.js" } }, "sha512-F5XRDn9WqxUaHphUT8qwy5WXC/3UwbBRJTdjjP5uwHX82vypxIlHNyHziZnplPLhQa1kbSdIY7wfuP1XJyyYZw=="],
"minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="], "minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"minimist": ["minimist@1.2.8", "", {}, "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA=="],
"minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="], "minipass": ["minipass@7.1.2", "", {}, "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw=="],
@@ -1231,6 +1358,8 @@
"nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="], "nanoid": ["nanoid@3.3.11", "", { "bin": { "nanoid": "bin/nanoid.cjs" } }, "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w=="],
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
"node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="], "node-domexception": ["node-domexception@1.0.0", "", {}, "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ=="],
"node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="], "node-fetch": ["node-fetch@2.7.0", "", { "dependencies": { "whatwg-url": "^5.0.0" }, "peerDependencies": { "encoding": "^0.1.0" }, "optionalPeers": ["encoding"] }, "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A=="],
@@ -1249,6 +1378,12 @@
"object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="], "object.assign": ["object.assign@4.1.7", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0", "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw=="],
"object.fromentries": ["object.fromentries@2.0.8", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2", "es-object-atoms": "^1.0.0" } }, "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ=="],
"object.groupby": ["object.groupby@1.0.3", "", { "dependencies": { "call-bind": "^1.0.7", "define-properties": "^1.2.1", "es-abstract": "^1.23.2" } }, "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ=="],
"object.values": ["object.values@1.2.1", "", { "dependencies": { "call-bind": "^1.0.8", "call-bound": "^1.0.3", "define-properties": "^1.2.1", "es-object-atoms": "^1.0.0" } }, "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA=="],
"ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="], "ohash": ["ohash@2.0.11", "", {}, "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ=="],
"once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="], "once": ["once@1.4.0", "", { "dependencies": { "wrappy": "1" } }, "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w=="],
@@ -1257,8 +1392,14 @@
"openai": ["openai@5.0.1", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-Do6vxhbDv7cXhji/4ct1lrpZYMAOmjYbhyA9LJTuG7OfpbWMpuS+EIXkRT7R+XxpRB1OZhU/op4FU3p3uxU6gw=="], "openai": ["openai@5.0.1", "", { "peerDependencies": { "ws": "^8.18.0", "zod": "^3.23.8" }, "optionalPeers": ["ws", "zod"], "bin": { "openai": "bin/cli" } }, "sha512-Do6vxhbDv7cXhji/4ct1lrpZYMAOmjYbhyA9LJTuG7OfpbWMpuS+EIXkRT7R+XxpRB1OZhU/op4FU3p3uxU6gw=="],
"optionator": ["optionator@0.9.4", "", { "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" } }, "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g=="],
"own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="], "own-keys": ["own-keys@1.0.1", "", { "dependencies": { "get-intrinsic": "^1.2.6", "object-keys": "^1.1.1", "safe-push-apply": "^1.0.0" } }, "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg=="],
"p-limit": ["p-limit@3.1.0", "", { "dependencies": { "yocto-queue": "^0.1.0" } }, "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ=="],
"p-locate": ["p-locate@5.0.0", "", { "dependencies": { "p-limit": "^3.0.2" } }, "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw=="],
"package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="], "package-json-from-dist": ["package-json-from-dist@1.0.1", "", {}, "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="],
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="], "parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
@@ -1267,6 +1408,8 @@
"parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="], "parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="],
"path-exists": ["path-exists@4.0.0", "", {}, "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="],
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
"path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="], "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
@@ -1291,6 +1434,12 @@
"postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="], "postcss": ["postcss@8.5.3", "", { "dependencies": { "nanoid": "^3.3.8", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A=="],
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
"prettier": ["prettier@3.6.0", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-ujSB9uXHJKzM/2GBuE0hBOUgC77CN3Bnpqa+g80bkv3T3A93wL/xlzDATHhnhkzifz/UE2SNOvmbTz5hSkDlHw=="],
"prettier-linter-helpers": ["prettier-linter-helpers@1.0.0", "", { "dependencies": { "fast-diff": "^1.1.2" } }, "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w=="],
"pretty-bytes": ["pretty-bytes@6.1.1", "", {}, "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ=="], "pretty-bytes": ["pretty-bytes@6.1.1", "", {}, "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ=="],
"pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="], "pretty-format": ["pretty-format@27.5.1", "", { "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", "react-is": "^17.0.1" } }, "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ=="],
@@ -1375,6 +1524,8 @@
"reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="], "reusify": ["reusify@1.1.0", "", {}, "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw=="],
"rimraf": ["rimraf@3.0.2", "", { "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" } }, "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA=="],
"rollup": ["rollup@4.39.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.39.0", "@rollup/rollup-android-arm64": "4.39.0", "@rollup/rollup-darwin-arm64": "4.39.0", "@rollup/rollup-darwin-x64": "4.39.0", "@rollup/rollup-freebsd-arm64": "4.39.0", "@rollup/rollup-freebsd-x64": "4.39.0", "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", "@rollup/rollup-linux-arm-musleabihf": "4.39.0", "@rollup/rollup-linux-arm64-gnu": "4.39.0", "@rollup/rollup-linux-arm64-musl": "4.39.0", "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", "@rollup/rollup-linux-riscv64-gnu": "4.39.0", "@rollup/rollup-linux-riscv64-musl": "4.39.0", "@rollup/rollup-linux-s390x-gnu": "4.39.0", "@rollup/rollup-linux-x64-gnu": "4.39.0", "@rollup/rollup-linux-x64-musl": "4.39.0", "@rollup/rollup-win32-arm64-msvc": "4.39.0", "@rollup/rollup-win32-ia32-msvc": "4.39.0", "@rollup/rollup-win32-x64-msvc": "4.39.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g=="], "rollup": ["rollup@4.39.0", "", { "dependencies": { "@types/estree": "1.0.7" }, "optionalDependencies": { "@rollup/rollup-android-arm-eabi": "4.39.0", "@rollup/rollup-android-arm64": "4.39.0", "@rollup/rollup-darwin-arm64": "4.39.0", "@rollup/rollup-darwin-x64": "4.39.0", "@rollup/rollup-freebsd-arm64": "4.39.0", "@rollup/rollup-freebsd-x64": "4.39.0", "@rollup/rollup-linux-arm-gnueabihf": "4.39.0", "@rollup/rollup-linux-arm-musleabihf": "4.39.0", "@rollup/rollup-linux-arm64-gnu": "4.39.0", "@rollup/rollup-linux-arm64-musl": "4.39.0", "@rollup/rollup-linux-loongarch64-gnu": "4.39.0", "@rollup/rollup-linux-powerpc64le-gnu": "4.39.0", "@rollup/rollup-linux-riscv64-gnu": "4.39.0", "@rollup/rollup-linux-riscv64-musl": "4.39.0", "@rollup/rollup-linux-s390x-gnu": "4.39.0", "@rollup/rollup-linux-x64-gnu": "4.39.0", "@rollup/rollup-linux-x64-musl": "4.39.0", "@rollup/rollup-win32-arm64-msvc": "4.39.0", "@rollup/rollup-win32-ia32-msvc": "4.39.0", "@rollup/rollup-win32-x64-msvc": "4.39.0", "fsevents": "~2.3.2" }, "bin": { "rollup": "dist/bin/rollup" } }, "sha512-thI8kNc02yNvnmJp8dr3fNWJ9tCONDhp6TV35X6HkKGGs9E6q7YWCHbe5vKiTa7TAiNcFEmXKj3X/pG2b3ci0g=="],
"rrweb-cssom": ["rrweb-cssom@0.7.1", "", {}, "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg=="], "rrweb-cssom": ["rrweb-cssom@0.7.1", "", {}, "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg=="],
@@ -1395,7 +1546,7 @@
"scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="], "scheduler": ["scheduler@0.23.2", "", { "dependencies": { "loose-envify": "^1.1.0" } }, "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ=="],
"semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="], "semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="], "serialize-javascript": ["serialize-javascript@6.0.2", "", { "dependencies": { "randombytes": "^2.1.0" } }, "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g=="],
@@ -1429,6 +1580,8 @@
"sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="], "sirv": ["sirv@3.0.1", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A=="],
"slash": ["slash@3.0.0", "", {}, "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q=="],
"smob": ["smob@1.5.0", "", {}, "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig=="], "smob": ["smob@1.5.0", "", {}, "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig=="],
"source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="], "source-map": ["source-map@0.5.7", "", {}, "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ=="],
@@ -1467,14 +1620,18 @@
"stringify-object": ["stringify-object@3.3.0", "", { "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" } }, "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw=="], "stringify-object": ["stringify-object@3.3.0", "", { "dependencies": { "get-own-enumerable-property-symbols": "^3.0.0", "is-obj": "^1.0.1", "is-regexp": "^1.0.0" } }, "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw=="],
"strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="], "strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "strip-ansi-cjs": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"strip-bom": ["strip-bom@3.0.0", "", {}, "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA=="],
"strip-comments": ["strip-comments@2.0.1", "", {}, "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw=="], "strip-comments": ["strip-comments@2.0.1", "", {}, "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw=="],
"strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="], "strip-indent": ["strip-indent@3.0.0", "", { "dependencies": { "min-indent": "^1.0.0" } }, "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ=="],
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
"stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="], "stylis": ["stylis@4.2.0", "", {}, "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="],
"supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="], "supports-color": ["supports-color@7.2.0", "", { "dependencies": { "has-flag": "^4.0.0" } }, "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw=="],
@@ -1483,6 +1640,8 @@
"symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="], "symbol-tree": ["symbol-tree@3.2.4", "", {}, "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw=="],
"synckit": ["synckit@0.11.8", "", { "dependencies": { "@pkgr/core": "^0.2.4" } }, "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A=="],
"temp-dir": ["temp-dir@2.0.0", "", {}, "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="], "temp-dir": ["temp-dir@2.0.0", "", {}, "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg=="],
"tempy": ["tempy@0.6.0", "", { "dependencies": { "is-stream": "^2.0.0", "temp-dir": "^2.0.0", "type-fest": "^0.16.0", "unique-string": "^2.0.0" } }, "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw=="], "tempy": ["tempy@0.6.0", "", { "dependencies": { "is-stream": "^2.0.0", "temp-dir": "^2.0.0", "type-fest": "^0.16.0", "unique-string": "^2.0.0" } }, "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw=="],
@@ -1491,6 +1650,8 @@
"test-exclude": ["test-exclude@7.0.1", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^9.0.4" } }, "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg=="], "test-exclude": ["test-exclude@7.0.1", "", { "dependencies": { "@istanbuljs/schema": "^0.1.2", "glob": "^10.4.1", "minimatch": "^9.0.4" } }, "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg=="],
"text-table": ["text-table@0.2.0", "", {}, "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw=="],
"tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="], "tinybench": ["tinybench@2.9.0", "", {}, "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg=="],
"tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="], "tinyexec": ["tinyexec@0.3.2", "", {}, "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA=="],
@@ -1519,9 +1680,15 @@
"trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="], "trim-lines": ["trim-lines@3.0.1", "", {}, "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg=="],
"ts-api-utils": ["ts-api-utils@1.4.3", "", { "peerDependencies": { "typescript": ">=4.2.0" } }, "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw=="],
"tsconfig-paths": ["tsconfig-paths@3.15.0", "", { "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", "minimist": "^1.2.6", "strip-bom": "^3.0.0" } }, "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg=="],
"tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="],
"type-fest": ["type-fest@0.16.0", "", {}, "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg=="], "type-check": ["type-check@0.4.0", "", { "dependencies": { "prelude-ls": "^1.2.1" } }, "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew=="],
"type-fest": ["type-fest@0.20.2", "", {}, "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ=="],
"typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="], "typed-array-buffer": ["typed-array-buffer@1.0.3", "", { "dependencies": { "call-bound": "^1.0.3", "es-errors": "^1.3.0", "is-typed-array": "^1.1.14" } }, "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw=="],
@@ -1569,6 +1736,8 @@
"update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="], "update-browserslist-db": ["update-browserslist-db@1.1.3", "", { "dependencies": { "escalade": "^3.2.0", "picocolors": "^1.1.1" }, "peerDependencies": { "browserslist": ">= 4.21.0" }, "bin": { "update-browserslist-db": "cli.js" } }, "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw=="],
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
"url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="], "url-parse": ["url-parse@1.5.10", "", { "dependencies": { "querystringify": "^2.1.1", "requires-port": "^1.0.0" } }, "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ=="],
"use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="], "use-callback-ref": ["use-callback-ref@1.3.3", "", { "dependencies": { "tslib": "^2.0.0" }, "peerDependencies": { "@types/react": "*", "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" }, "optionalPeers": ["@types/react"] }, "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg=="],
@@ -1621,6 +1790,8 @@
"why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="], "why-is-node-running": ["why-is-node-running@2.3.0", "", { "dependencies": { "siginfo": "^2.0.0", "stackback": "0.0.2" }, "bin": { "why-is-node-running": "cli.js" } }, "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w=="],
"word-wrap": ["word-wrap@1.2.5", "", {}, "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA=="],
"workbox-background-sync": ["workbox-background-sync@7.3.0", "", { "dependencies": { "idb": "^7.0.1", "workbox-core": "7.3.0" } }, "sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg=="], "workbox-background-sync": ["workbox-background-sync@7.3.0", "", { "dependencies": { "idb": "^7.0.1", "workbox-core": "7.3.0" } }, "sha512-PCSk3eK7Mxeuyatb22pcSx9dlgWNv3+M8PqPaYDokks8Y5/FX4soaOqj3yhAZr5k6Q5JWTOMYgaJBpbw11G9Eg=="],
"workbox-broadcast-update": ["workbox-broadcast-update@7.3.0", "", { "dependencies": { "workbox-core": "7.3.0" } }, "sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA=="], "workbox-broadcast-update": ["workbox-broadcast-update@7.3.0", "", { "dependencies": { "workbox-core": "7.3.0" } }, "sha512-T9/F5VEdJVhwmrIAE+E/kq5at2OY6+OXXgOWQevnubal6sO92Gjo24v6dCVwQiclAF5NS3hlmsifRrpQzZCdUA=="],
@@ -1673,6 +1844,8 @@
"yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="], "yaml": ["yaml@1.10.2", "", {}, "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg=="],
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
"youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="], "youch": ["youch@3.3.4", "", { "dependencies": { "cookie": "^0.7.1", "mustache": "^4.2.0", "stacktracey": "^2.1.8" } }, "sha512-UeVBXie8cA35DS6+nBkls68xaBBXCye0CNznrhszZjTbRVnJKQuNsyLKBTTL4ln1o1rh2PKtv35twV7irj5SEg=="],
"zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="], "zod": ["zod@3.24.2", "", {}, "sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ=="],
@@ -1681,24 +1854,20 @@
"@anthropic-ai/sdk/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "@anthropic-ai/sdk/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
"@apideck/better-ajv-errors/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
"@asamuzakjp/css-color/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="], "@asamuzakjp/css-color/lru-cache": ["lru-cache@10.4.3", "", {}, "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ=="],
"@babel/core/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], "@babel/core/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
"@babel/core/convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="], "@babel/core/convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
"@babel/core/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@babel/core/json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"@babel/helper-annotate-as-pure/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/helper-annotate-as-pure/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/helper-create-class-features-plugin/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="], "@babel/helper-create-class-features-plugin/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="],
"@babel/helper-create-class-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/helper-create-regexp-features-plugin/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="], "@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets": ["@babel/helper-compilation-targets@7.27.2", "", { "dependencies": { "@babel/compat-data": "^7.27.2", "@babel/helper-validator-option": "^7.27.1", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", "semver": "^6.3.1" } }, "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ=="],
"@babel/helper-define-polyfill-provider/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], "@babel/helper-define-polyfill-provider/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
@@ -1769,6 +1938,8 @@
"@babel/plugin-transform-classes/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="], "@babel/plugin-transform-classes/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="],
"@babel/plugin-transform-classes/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-computed-properties/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], "@babel/plugin-transform-computed-properties/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
"@babel/plugin-transform-computed-properties/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], "@babel/plugin-transform-computed-properties/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
@@ -1879,23 +2050,25 @@
"@babel/preset-env/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/preset-env/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/preset-env/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/preset-modules/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="], "@babel/preset-modules/@babel/helper-plugin-utils": ["@babel/helper-plugin-utils@7.27.1", "", {}, "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw=="],
"@babel/template/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], "@babel/template/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
"@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="], "@babel/traverse/@babel/code-frame": ["@babel/code-frame@7.26.2", "", { "dependencies": { "@babel/helper-validator-identifier": "^7.25.9", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" } }, "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ=="],
"@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "@babel/types/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="], "@cloudflare/vite-plugin/ws": ["ws@8.18.0", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw=="],
"@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="], "@cspotcode/source-map-support/@jridgewell/trace-mapping": ["@jridgewell/trace-mapping@0.3.9", "", { "dependencies": { "@jridgewell/resolve-uri": "^3.0.3", "@jridgewell/sourcemap-codec": "^1.4.10" } }, "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ=="],
"@isaacs/cliui/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"@open-gsio/client/@types/bun": ["@types/bun@1.2.16", "", { "dependencies": { "bun-types": "1.2.16" } }, "sha512-1aCZJ/6nSiViw339RsaNhkNoEloLaPzZhxMOYEa7OzRzO41IGg5n/7I43/ZIAW/c+Q6cT12Vf7fOZOoVIzb5BQ=="], "@open-gsio/client/@types/bun": ["@types/bun@1.2.16", "", { "dependencies": { "bun-types": "1.2.16" } }, "sha512-1aCZJ/6nSiViw339RsaNhkNoEloLaPzZhxMOYEa7OzRzO41IGg5n/7I43/ZIAW/c+Q6cT12Vf7fOZOoVIzb5BQ=="],
"@open-gsio/scripts/@types/bun": ["@types/bun@1.2.16", "", { "dependencies": { "bun-types": "1.2.16" } }, "sha512-1aCZJ/6nSiViw339RsaNhkNoEloLaPzZhxMOYEa7OzRzO41IGg5n/7I43/ZIAW/c+Q6cT12Vf7fOZOoVIzb5BQ=="], "@open-gsio/scripts/@types/bun": ["@types/bun@1.2.17", "", { "dependencies": { "bun-types": "1.2.17" } }, "sha512-l/BYs/JYt+cXA/0+wUhulYJB6a6p//GTPiJ7nV+QHa8iiId4HZmnu/3J/SowP5g0rTiERY2kfGKXEK5Ehltx4Q=="],
"@rollup/plugin-babel/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="], "@rollup/plugin-babel/@rollup/pluginutils": ["@rollup/pluginutils@3.1.0", "", { "dependencies": { "@types/estree": "0.0.39", "estree-walker": "^1.0.1", "picomatch": "^2.2.2" }, "peerDependencies": { "rollup": "^1.20.0||^2.0.0" } }, "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg=="],
@@ -1905,19 +2078,23 @@
"@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="], "@rollup/pluginutils/estree-walker": ["estree-walker@2.0.2", "", {}, "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="],
"@surma/rollup-plugin-off-main-thread/json5": ["json5@2.2.3", "", { "bin": { "json5": "lib/cli.js" } }, "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg=="],
"@surma/rollup-plugin-off-main-thread/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="], "@surma/rollup-plugin-off-main-thread/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="],
"@testing-library/dom/aria-query": ["aria-query@5.1.3", "", { "dependencies": { "deep-equal": "^2.0.5" } }, "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ=="], "@testing-library/dom/aria-query": ["aria-query@5.1.3", "", { "dependencies": { "deep-equal": "^2.0.5" } }, "sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ=="],
"@testing-library/dom/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="], "@testing-library/dom/dom-accessibility-api": ["dom-accessibility-api@0.5.16", "", {}, "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg=="],
"@testing-library/jest-dom/chalk": ["chalk@3.0.0", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg=="],
"@types/node-fetch/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "@types/node-fetch/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
"babel-plugin-polyfill-corejs2/@babel/compat-data": ["@babel/compat-data@7.27.3", "", {}, "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw=="], "@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"babel-plugin-polyfill-corejs2/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="], "@typescript-eslint/typescript-estree/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"babel-plugin-polyfill-corejs2/@babel/compat-data": ["@babel/compat-data@7.27.3", "", {}, "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw=="],
"bun-types/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "bun-types/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
@@ -1925,6 +2102,16 @@
"data-urls/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], "data-urls/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
"eslint-import-resolver-node/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-module-utils/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-plugin-import/debug": ["debug@3.2.7", "", { "dependencies": { "ms": "^2.1.1" } }, "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ=="],
"eslint-plugin-import/doctrine": ["doctrine@2.1.0", "", { "dependencies": { "esutils": "^2.0.2" } }, "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw=="],
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
"filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="], "filelist/minimatch": ["minimatch@5.1.6", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g=="],
"framesync/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="], "framesync/tslib": ["tslib@2.4.0", "", {}, "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ=="],
@@ -1933,12 +2120,10 @@
"get-source/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "get-source/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"glob/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"isomorphic-dompurify/jsdom": ["jsdom@26.0.0", "", { "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.1", "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.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.1.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw=="], "isomorphic-dompurify/jsdom": ["jsdom@26.0.0", "", { "dependencies": { "cssstyle": "^4.2.1", "data-urls": "^5.0.0", "decimal.js": "^10.4.3", "form-data": "^4.0.1", "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.0.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^7.0.0", "whatwg-encoding": "^3.1.1", "whatwg-mimetype": "^4.0.0", "whatwg-url": "^14.1.0", "ws": "^8.18.0", "xml-name-validator": "^5.0.0" }, "peerDependencies": { "canvas": "^3.0.0" }, "optionalPeers": ["canvas"] }, "sha512-BZYDGVAIriBWTpIxYzrXjv3E/4u8+/pSG5bQdIYCbNCGOvsPkDQfTVLAIXAf9ETdCpduCVTkDe2NNZ8NIwUVzw=="],
"jake/chalk": ["chalk@4.1.2", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
"jake/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
"jsdom/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], "jsdom/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
"jsonfile/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="], "jsonfile/universalify": ["universalify@2.0.1", "", {}, "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw=="],
@@ -1947,6 +2132,8 @@
"magicast/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "magicast/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"make-dir/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "micromatch/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], "miniflare/acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="],
@@ -1967,18 +2154,26 @@
"regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="], "regjsparser/jsesc": ["jsesc@3.0.2", "", { "bin": { "jsesc": "bin/jsesc" } }, "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g=="],
"rimraf/glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
"sharp/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="], "simple-swizzle/is-arrayish": ["is-arrayish@0.3.2", "", {}, "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ=="],
"source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="], "source-map-support/source-map": ["source-map@0.6.1", "", {}, "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="],
"string-width/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "string-width-cjs/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"string-width-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="], "tempy/type-fest": ["type-fest@0.16.0", "", {}, "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg=="],
"strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="], "terser/commander": ["commander@2.20.3", "", {}, "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="],
"test-exclude/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
"vike/semver": ["semver@7.7.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA=="],
"vike/sirv": ["sirv@2.0.4", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ=="], "vike/sirv": ["sirv@2.0.4", "", { "dependencies": { "@polka/url": "^1.0.0-next.24", "mrmime": "^2.0.0", "totalist": "^3.0.0" } }, "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ=="],
"vite/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="], "vite/esbuild": ["esbuild@0.25.4", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.25.4", "@esbuild/android-arm": "0.25.4", "@esbuild/android-arm64": "0.25.4", "@esbuild/android-x64": "0.25.4", "@esbuild/darwin-arm64": "0.25.4", "@esbuild/darwin-x64": "0.25.4", "@esbuild/freebsd-arm64": "0.25.4", "@esbuild/freebsd-x64": "0.25.4", "@esbuild/linux-arm": "0.25.4", "@esbuild/linux-arm64": "0.25.4", "@esbuild/linux-ia32": "0.25.4", "@esbuild/linux-loong64": "0.25.4", "@esbuild/linux-mips64el": "0.25.4", "@esbuild/linux-ppc64": "0.25.4", "@esbuild/linux-riscv64": "0.25.4", "@esbuild/linux-s390x": "0.25.4", "@esbuild/linux-x64": "0.25.4", "@esbuild/netbsd-arm64": "0.25.4", "@esbuild/netbsd-x64": "0.25.4", "@esbuild/openbsd-arm64": "0.25.4", "@esbuild/openbsd-x64": "0.25.4", "@esbuild/sunos-x64": "0.25.4", "@esbuild/win32-arm64": "0.25.4", "@esbuild/win32-ia32": "0.25.4", "@esbuild/win32-x64": "0.25.4" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q=="],
@@ -1987,6 +2182,8 @@
"workbox-build/@rollup/plugin-replace": ["@rollup/plugin-replace@2.4.2", "", { "dependencies": { "@rollup/pluginutils": "^3.1.0", "magic-string": "^0.25.7" }, "peerDependencies": { "rollup": "^1.20.0 || ^2.0.0" } }, "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg=="], "workbox-build/@rollup/plugin-replace": ["@rollup/plugin-replace@2.4.2", "", { "dependencies": { "@rollup/pluginutils": "^3.1.0", "magic-string": "^0.25.7" }, "peerDependencies": { "rollup": "^1.20.0 || ^2.0.0" } }, "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg=="],
"workbox-build/ajv": ["ajv@8.17.1", "", { "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2" } }, "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g=="],
"workbox-build/glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="], "workbox-build/glob": ["glob@7.2.3", "", { "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" } }, "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q=="],
"workbox-build/pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="], "workbox-build/pretty-bytes": ["pretty-bytes@5.6.0", "", {}, "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg=="],
@@ -1999,12 +2196,14 @@
"wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="], "wrap-ansi/ansi-styles": ["ansi-styles@6.2.1", "", {}, "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug=="],
"wrap-ansi/strip-ansi": ["strip-ansi@7.1.0", "", { "dependencies": { "ansi-regex": "^6.0.1" } }, "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ=="],
"wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="], "wrap-ansi-cjs/string-width": ["string-width@4.2.3", "", { "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", "strip-ansi": "^6.0.1" } }, "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g=="],
"wrap-ansi-cjs/strip-ansi": ["strip-ansi@6.0.1", "", { "dependencies": { "ansi-regex": "^5.0.1" } }, "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A=="],
"@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], "@anthropic-ai/sdk/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"@apideck/better-ajv-errors/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"@babel/core/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "@babel/core/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@babel/helper-annotate-as-pure/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-annotate-as-pure/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -2017,18 +2216,20 @@
"@babel/helper-create-class-features-plugin/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/helper-create-class-features-plugin/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.27.3", "", {}, "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw=="], "@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets/@babel/compat-data": ["@babel/compat-data@7.27.3", "", {}, "sha512-V42wFfx1ymFte+ecf6iXghnnP8kWTO+ZLXIyZq+1LAXHHvTZdVxicn4yiVYdYMGaCO3tmqub11AorKkv+iodqw=="],
"@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/helper-define-polyfill-provider/@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/helper-member-expression-to-functions/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/helper-member-expression-to-functions/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/helper-member-expression-to-functions/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/helper-member-expression-to-functions/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
"@babel/helper-member-expression-to-functions/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], "@babel/helper-member-expression-to-functions/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
"@babel/helper-member-expression-to-functions/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-member-expression-to-functions/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-member-expression-to-functions/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-optimise-call-expression/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-optimise-call-expression/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -2041,6 +2242,8 @@
"@babel/helper-remap-async-to-generator/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/helper-remap-async-to-generator/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/helper-remap-async-to-generator/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-replace-supers/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/helper-replace-supers/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/helper-replace-supers/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/helper-replace-supers/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2049,12 +2252,16 @@
"@babel/helper-replace-supers/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/helper-replace-supers/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/helper-replace-supers/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
"@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], "@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
"@babel/helper-skip-transparent-expression-wrappers/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-skip-transparent-expression-wrappers/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-skip-transparent-expression-wrappers/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-wrap-function/@babel/template/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/helper-wrap-function/@babel/template/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2063,6 +2270,8 @@
"@babel/helper-wrap-function/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/helper-wrap-function/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
"@babel/helper-wrap-function/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/helper-wrap-function/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-wrap-function/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/plugin-bugfix-firefox-class-in-computed-class-key/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-bugfix-firefox-class-in-computed-class-key/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
@@ -2073,6 +2282,8 @@
"@babel/plugin-bugfix-firefox-class-in-computed-class-key/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-bugfix-firefox-class-in-computed-class-key/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-bugfix-firefox-class-in-computed-class-key/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2081,6 +2292,8 @@
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2089,6 +2302,8 @@
"@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-async-generator-functions/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-async-generator-functions/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="], "@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="],
"@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
@@ -2097,8 +2312,6 @@
"@babel/plugin-transform-classes/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/plugin-transform-classes/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/plugin-transform-classes/@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/plugin-transform-classes/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-transform-classes/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/plugin-transform-classes/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/plugin-transform-classes/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2115,8 +2328,6 @@
"@babel/plugin-transform-function-name/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/plugin-transform-function-name/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/plugin-transform-function-name/@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/plugin-transform-function-name/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-transform-function-name/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
"@babel/plugin-transform-function-name/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="], "@babel/plugin-transform-function-name/@babel/traverse/@babel/parser": ["@babel/parser@7.27.3", "", { "dependencies": { "@babel/types": "^7.27.3" }, "bin": "./bin/babel-parser.js" }, "sha512-xyYxRj6+tLNDTWi0KCBcZ9V7yg3/lwL9DWh9Uwh/RIVlIfFidggcgxKX3GCXwCiswwcGRawBKbEg2LG/Y8eJhw=="],
@@ -2125,6 +2336,8 @@
"@babel/plugin-transform-function-name/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-function-name/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-function-name/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], "@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
"@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="], "@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="],
@@ -2143,6 +2356,8 @@
"@babel/plugin-transform-modules-systemjs/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-systemjs/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-modules-systemjs/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="], "@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/helper-module-imports": ["@babel/helper-module-imports@7.27.1", "", { "dependencies": { "@babel/traverse": "^7.27.1", "@babel/types": "^7.27.1" } }, "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w=="],
"@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="], "@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse": ["@babel/traverse@7.27.3", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.27.3", "@babel/parser": "^7.27.3", "@babel/template": "^7.27.2", "@babel/types": "^7.27.3", "debug": "^4.3.1", "globals": "^11.1.0" } }, "sha512-lId/IfN/Ye1CIu8xG7oKBHXd2iNb2aW1ilPszzGcJug6M8RCKfVNcYhpI5+bMvFYjK7lXIM0R+a+6r8xhHp2FQ=="],
@@ -2151,15 +2366,15 @@
"@babel/plugin-transform-object-rest-spread/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="], "@babel/plugin-transform-object-rest-spread/@babel/helper-compilation-targets/@babel/helper-validator-option": ["@babel/helper-validator-option@7.27.1", "", {}, "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg=="],
"@babel/plugin-transform-object-rest-spread/@babel/helper-compilation-targets/semver": ["semver@6.3.1", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA=="],
"@babel/template/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "@babel/template/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "@babel/traverse/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"@isaacs/cliui/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"@open-gsio/client/@types/bun/bun-types": ["bun-types@1.2.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A=="], "@open-gsio/client/@types/bun/bun-types": ["bun-types@1.2.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A=="],
"@open-gsio/scripts/@types/bun/bun-types": ["bun-types@1.2.16", "", { "dependencies": { "@types/node": "*" } }, "sha512-ciXLrHV4PXax9vHvUrkvun9VPVGOVwbbbBF/Ev1cXz12lyEZMoJpIJABOfPcN9gDJRaiKF9MVbSygLg4NXu3/A=="], "@open-gsio/scripts/@types/bun/bun-types": ["bun-types@1.2.17", "", { "dependencies": { "@types/node": "*" } }, "sha512-ElC7ItwT3SCQwYZDYoAH+q6KT4Fxjl8DtZ6qDulUFBmXA8YB4xo+l54J9ZJN+k2pphfn9vk7kfubeSd5QfTVJQ=="],
"@rollup/plugin-babel/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="], "@rollup/plugin-babel/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="],
@@ -2171,16 +2386,20 @@
"@types/node-fetch/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], "@types/node-fetch/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"bun-types/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], "bun-types/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"filelist/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"glob/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"isomorphic-dompurify/jsdom/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="], "isomorphic-dompurify/jsdom/rrweb-cssom": ["rrweb-cssom@0.8.0", "", {}, "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw=="],
"isomorphic-dompurify/jsdom/tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="], "isomorphic-dompurify/jsdom/tough-cookie": ["tough-cookie@5.1.2", "", { "dependencies": { "tldts": "^6.1.32" } }, "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A=="],
"isomorphic-dompurify/jsdom/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="], "isomorphic-dompurify/jsdom/whatwg-mimetype": ["whatwg-mimetype@4.0.0", "", {}, "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg=="],
"jake/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
"magicast/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "magicast/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="], "node-fetch/whatwg-url/tr46": ["tr46@0.0.3", "", {}, "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="],
@@ -2189,6 +2408,10 @@
"parse-json/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="], "parse-json/@babel/code-frame/@babel/helper-validator-identifier": ["@babel/helper-validator-identifier@7.25.9", "", {}, "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="],
"string-width/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"test-exclude/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
"vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="], "vite/esbuild/@esbuild/aix-ppc64": ["@esbuild/aix-ppc64@0.25.4", "", { "os": "aix", "cpu": "ppc64" }, "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q=="],
"vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="], "vite/esbuild/@esbuild/android-arm": ["@esbuild/android-arm@0.25.4", "", { "os": "android", "cpu": "arm" }, "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ=="],
@@ -2241,7 +2464,7 @@
"workbox-build/@rollup/plugin-replace/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="], "workbox-build/@rollup/plugin-replace/magic-string": ["magic-string@0.25.9", "", { "dependencies": { "sourcemap-codec": "^1.4.8" } }, "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ=="],
"workbox-build/glob/minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="], "workbox-build/ajv/json-schema-traverse": ["json-schema-traverse@1.0.0", "", {}, "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="],
"workbox-build/source-map/whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="], "workbox-build/source-map/whatwg-url": ["whatwg-url@7.1.0", "", { "dependencies": { "lodash.sortby": "^4.7.0", "tr46": "^1.0.1", "webidl-conversions": "^4.0.2" } }, "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg=="],
@@ -2295,6 +2518,8 @@
"wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="], "wrap-ansi-cjs/string-width/emoji-regex": ["emoji-regex@8.0.0", "", {}, "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="],
"wrap-ansi/strip-ansi/ansi-regex": ["ansi-regex@6.1.0", "", {}, "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA=="],
"@babel/helper-create-class-features-plugin/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-create-class-features-plugin/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/helper-remap-async-to-generator/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/helper-remap-async-to-generator/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -2313,6 +2538,8 @@
"@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="], "@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/traverse/@babel/template": ["@babel/template@7.27.2", "", { "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/parser": "^7.27.2", "@babel/types": "^7.27.1" } }, "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw=="],
"@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/plugin-transform-async-to-generator/@babel/helper-module-imports/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@babel/plugin-transform-classes/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/plugin-transform-classes/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -2331,6 +2558,8 @@
"@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-modules-amd/@babel/helper-module-transforms/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="], "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/generator": ["@babel/generator@7.27.3", "", { "dependencies": { "@babel/parser": "^7.27.3", "@babel/types": "^7.27.3", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" } }, "sha512-xnlJYj5zepml8NXtjkG0WquFUv8RskFqyFcVgTBp5k+NaA/8uw/K+OSVf8AMGw5e9HKP2ETd5xpK5MLZQD6b4Q=="],
@@ -2341,6 +2570,8 @@
"@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-modules-commonjs/@babel/helper-module-transforms/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@babel/plugin-transform-modules-systemjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-systemjs/@babel/helper-module-transforms/@babel/helper-module-imports/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@babel/plugin-transform-modules-systemjs/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/plugin-transform-modules-systemjs/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
@@ -2355,9 +2586,9 @@
"@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="], "@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse/@babel/types": ["@babel/types@7.27.3", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1" } }, "sha512-Y1GkI4ktrtvmawoSq+4FCVHNryea6uR+qUQy0AGxLSsjCX0nVmkYQMBLHDkXZuo5hGx7eYdnIaslsdBFm7zbUw=="],
"@open-gsio/client/@types/bun/bun-types/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse/globals": ["globals@11.12.0", "", {}, "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA=="],
"@open-gsio/scripts/@types/bun/bun-types/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="], "@open-gsio/client/@types/bun/bun-types/@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
"workbox-build/@rollup/plugin-replace/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="], "workbox-build/@rollup/plugin-replace/@rollup/pluginutils/@types/estree": ["@types/estree@0.0.39", "", {}, "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw=="],
@@ -2365,8 +2596,6 @@
"workbox-build/@rollup/plugin-replace/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="], "workbox-build/@rollup/plugin-replace/@rollup/pluginutils/picomatch": ["picomatch@2.3.1", "", {}, "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA=="],
"workbox-build/glob/minimatch/brace-expansion": ["brace-expansion@1.1.11", "", { "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA=="],
"workbox-build/source-map/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="], "workbox-build/source-map/whatwg-url/tr46": ["tr46@1.0.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA=="],
"workbox-build/source-map/whatwg-url/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="], "workbox-build/source-map/whatwg-url/webidl-conversions": ["webidl-conversions@4.0.2", "", {}, "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg=="],
@@ -2386,7 +2615,5 @@
"@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="], "@babel/plugin-transform-modules-umd/@babel/helper-module-transforms/@babel/traverse/@babel/types/@babel/helper-string-parser": ["@babel/helper-string-parser@7.27.1", "", {}, "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA=="],
"@open-gsio/client/@types/bun/bun-types/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="], "@open-gsio/client/@types/bun/bun-types/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
"@open-gsio/scripts/@types/bun/bun-types/@types/node/undici-types": ["undici-types@5.26.5", "", {}, "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="],
} }
} }

View File

@@ -19,14 +19,24 @@
"deploy:secrets": "wrangler secret bulk secrets.json -c packages/cloudflare-workers/open-gsio/wrangler.jsonc", "deploy:secrets": "wrangler secret bulk secrets.json -c packages/cloudflare-workers/open-gsio/wrangler.jsonc",
"openai:local:mlx": "packages/scripts/start_inference_server.sh mlx-omni-server", "openai:local:mlx": "packages/scripts/start_inference_server.sh mlx-omni-server",
"openai:local:ollama": "packages/scripts/start_inference_server.sh ollama", "openai:local:ollama": "packages/scripts/start_inference_server.sh ollama",
"openai:local:configure": "packages/scripts/configure_local_inference.sh" "openai:local:configure": "packages/scripts/configure_local_inference.sh",
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
"lint:fix": "eslint . --ext .js,.jsx,.ts,.tsx --fix",
"format": "prettier --write \"**/*.{js,jsx,ts,tsx,json,md}\"",
"format:check": "prettier --check \"**/*.{js,jsx,ts,tsx,json,md}\""
}, },
"devDependencies": { "devDependencies": {
"@types/bun": "latest", "@types/bun": "latest",
"happy-dom": "^18.0.1" "@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^7.0.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-prettier": "^5.1.3",
"happy-dom": "^18.0.1",
"prettier": "^3.2.5"
}, },
"peerDependencies": { "peerDependencies": {
"typescript": "^5" "typescript": "^5"
}, }
"packageManager": "pnpm@10.10.0+sha512.d615db246fe70f25dcfea6d8d73dee782ce23e2245e3c4f6f888249fb568149318637dca73c2c5c8ef2a4ca0d5657fb9567188bfab47f566d1ee6ce987815c39"
} }

View File

@@ -1,2 +1,2 @@
// for future use // for future use
export {} export {};

View File

@@ -1,8 +1,8 @@
#!/usr/bin/env bun #!/usr/bin/env bun
/* eslint-env node */
import fs from "fs"; import fs from 'fs';
import {parseArgs} from "util"; import { parseArgs } from 'util';
const { positionals } = parseArgs({ const { positionals } = parseArgs({
args: Bun.argv, args: Bun.argv,
@@ -11,7 +11,7 @@ const {positionals} = parseArgs({
allowPositionals: true, allowPositionals: true,
}); });
const currentDate = new Date().toISOString().split("T")[0]; const currentDate = new Date().toISOString().split('T')[0];
const host = positionals[2]; const host = positionals[2];
@@ -25,12 +25,12 @@ Disallow: /assets
Sitemap: https://${host}/sitemap.xml Sitemap: https://${host}/sitemap.xml
`; `;
const robotsTxtPath = "./public/robots.txt"; const robotsTxtPath = './public/robots.txt';
fs.writeFile(robotsTxtPath, robotsTxtTemplate, (err) => { fs.writeFile(robotsTxtPath, robotsTxtTemplate, err => {
if (err) { if (err) {
console.error("Error writing robots.txt:", err); console.error('Error writing robots.txt:', err);
process.exit(1); process.exit(1);
} }
console.log("robots.txt created successfully:", currentDate); console.log('robots.txt created successfully:', currentDate);
}); });

View File

@@ -1,8 +1,7 @@
#!/usr/bin/env bun #!/usr/bin/env bun
import fs from "fs"; import fs from 'fs';
import {parseArgs} from "util"; import { parseArgs } from 'util';
const { positionals } = parseArgs({ const { positionals } = parseArgs({
args: Bun.argv, args: Bun.argv,
@@ -11,7 +10,7 @@ const {positionals} = parseArgs({
allowPositionals: true, allowPositionals: true,
}); });
const currentDate = new Date().toISOString().split("T")[0]; const currentDate = new Date().toISOString().split('T')[0];
const host = positionals[2]; const host = positionals[2];
@@ -30,12 +29,12 @@ const sitemapTemplate = `<?xml version="1.0" encoding="UTF-8"?>
</url> </url>
</urlset>`; </urlset>`;
const sitemapPath = "./public/sitemap.xml"; const sitemapPath = './public/sitemap.xml';
fs.writeFile(sitemapPath, sitemapTemplate, (err) => { fs.writeFile(sitemapPath, sitemapTemplate, err => {
if (err) { if (err) {
console.error("Error writing sitemap file:", err); console.error('Error writing sitemap file:', err);
process.exit(1); process.exit(1);
} }
console.log("Sitemap updated successfully with current date:", currentDate); console.log('Sitemap updated successfully with current date:', currentDate);
}); });

View File

@@ -1,4 +1,4 @@
import { renderPage } from "vike/server"; import { renderPage } from 'vike/server';
// This is what makes SSR possible. It is consumed by @open-gsio/server // This is what makes SSR possible. It is consumed by @open-gsio/server
export default renderPage; export default renderPage;

View File

@@ -1,7 +1,8 @@
import React from "react"; import { IconButton } from '@chakra-ui/react';
import { IconButton } from "@chakra-ui/react"; import { LucideHammer } from 'lucide-react';
import { LucideHammer } from "lucide-react"; import React from 'react';
import { toolbarButtonZIndex } from "./toolbar/Toolbar";
import { toolbarButtonZIndex } from './toolbar/Toolbar';
export default function BuiltWithButton() { export default function BuiltWithButton() {
return ( return (
@@ -12,12 +13,12 @@ export default function BuiltWithButton() {
bg="transparent" bg="transparent"
stroke="text.accent" stroke="text.accent"
color="text.accent" color="text.accent"
onClick={() => alert("Built by Geoff Seemueller")} onClick={() => alert('Built by Geoff Seemueller')}
_hover={{ _hover={{
bg: "transparent", bg: 'transparent',
svg: { svg: {
stroke: "accent.secondary", stroke: 'accent.secondary',
transition: "stroke 0.3s ease-in-out", transition: 'stroke 0.3s ease-in-out',
}, },
}} }}
zIndex={toolbarButtonZIndex} zIndex={toolbarButtonZIndex}

View File

@@ -1,10 +1,12 @@
import { getColorThemes } from "../layout/theme/color-themes"; import { Center, IconButton, VStack } from '@chakra-ui/react';
import { Center, IconButton, VStack } from "@chakra-ui/react"; import { Circle } from 'lucide-react';
import userOptionsStore from "../stores/UserOptionsStore"; import React from 'react';
import { Circle } from "lucide-react";
import { toolbarButtonZIndex } from "./toolbar/Toolbar"; import { getColorThemes } from '../layout/theme/color-themes';
import React from "react"; import userOptionsStore from '../stores/UserOptionsStore';
import { useIsMobile } from "./contexts/MobileContext";
import { useIsMobile } from './contexts/MobileContext';
import { toolbarButtonZIndex } from './toolbar/Toolbar';
export function ThemeSelectionOptions() { export function ThemeSelectionOptions() {
const children = []; const children = [];
@@ -24,11 +26,11 @@ export function ThemeSelectionOptions() {
size={!isMobile ? 16 : 20} size={!isMobile ? 16 : 20}
stroke="transparent" stroke="transparent"
style={{ style={{
background: `conic-gradient(${theme.colors.background.primary.startsWith("#") ? theme.colors.background.primary : theme.colors.background.secondary} 0 50%, ${theme.colors.text.secondary} 50% 100%)`, background: `conic-gradient(${theme.colors.background.primary.startsWith('#') ? theme.colors.background.primary : theme.colors.background.secondary} 0 50%, ${theme.colors.text.secondary} 50% 100%)`,
borderRadius: "50%", borderRadius: '50%',
boxShadow: "0 0 0.5px 0.25px #fff", boxShadow: '0 0 0.5px 0.25px #fff',
cursor: "pointer", cursor: 'pointer',
transition: "background 0.2s", transition: 'background 0.2s',
}} }}
/> />
} }
@@ -38,7 +40,7 @@ export function ThemeSelectionOptions() {
color="transparent" color="transparent"
_hover={{ _hover={{
svg: { svg: {
transition: "stroke 0.3s ease-in-out", // Smooth transition effect transition: 'stroke 0.3s ease-in-out', // Smooth transition effect
}, },
}} }}
zIndex={toolbarButtonZIndex} zIndex={toolbarButtonZIndex}
@@ -47,7 +49,7 @@ export function ThemeSelectionOptions() {
} }
return ( return (
<VStack align={!isMobile ? "end" : "start"} p={1.2}> <VStack align={!isMobile ? 'end' : 'start'} p={1.2}>
<Center>{children}</Center> <Center>{children}</Center>
</VStack> </VStack>
); );

View File

@@ -1,11 +1,9 @@
import { motion } from "framer-motion"; import { Box, Center, VStack } from '@chakra-ui/react';
import { Box, Center, VStack } from "@chakra-ui/react"; import { motion } from 'framer-motion';
import {
welcome_home_text,
welcome_home_tip,
} from "../static-data/welcome_home_text";
import {renderMarkdown} from "./markdown/MarkdownComponent";
import { welcome_home_text, welcome_home_tip } from '../static-data/welcome_home_text';
import { renderMarkdown } from './markdown/MarkdownComponent';
function WelcomeHomeMessage({ visible }) { function WelcomeHomeMessage({ visible }) {
const containerVariants = { const containerVariants = {
@@ -45,33 +43,19 @@ function WelcomeHomeMessage({ visible }) {
<Center> <Center>
<VStack spacing={8} align="center" maxW="400px"> <VStack spacing={8} align="center" maxW="400px">
{/* Welcome Message */} {/* Welcome Message */}
<Box <Box fontSize="sm" fontStyle="italic" textAlign="center" color="text.secondary" mt={4}>
fontSize="sm"
fontStyle="italic"
textAlign="center"
color="text.secondary"
mt={4}
>
<motion.div <motion.div
variants={containerVariants} variants={containerVariants}
initial="hidden" initial="hidden"
animate={visible ? "visible" : "hidden"} animate={visible ? 'visible' : 'hidden'}
> >
<Box userSelect={"none"}> <Box userSelect={'none'}>
<motion.div variants={textVariants}> <motion.div variants={textVariants}>{renderMarkdown(welcome_home_text)}</motion.div>
{renderMarkdown(welcome_home_text)}
</motion.div>
</Box> </Box>
</motion.div> </motion.div>
</Box> </Box>
<motion.div variants={textVariants}> <motion.div variants={textVariants}>
<Box <Box fontSize="sm" fontStyle="italic" textAlign="center" color="text.secondary" mt={1}>
fontSize="sm"
fontStyle="italic"
textAlign="center"
color="text.secondary"
mt={1}
>
{renderMarkdown(welcome_home_tip)} {renderMarkdown(welcome_home_tip)}
</Box> </Box>
</motion.div> </motion.div>

View File

@@ -1,8 +1,9 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react'; import { render, screen, fireEvent } from '@testing-library/react';
import { ThemeSelectionOptions } from '../ThemeSelection'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import userOptionsStore from '../../stores/UserOptionsStore'; import userOptionsStore from '../../stores/UserOptionsStore';
import * as MobileContext from '../contexts/MobileContext'; import * as MobileContext from '../contexts/MobileContext';
import { ThemeSelectionOptions } from '../ThemeSelection';
// Mock dependencies // Mock dependencies
vi.mock('../../layout/theme/color-themes', () => ({ vi.mock('../../layout/theme/color-themes', () => ({
@@ -11,27 +12,27 @@ vi.mock('../../layout/theme/color-themes', () => ({
name: 'light', name: 'light',
colors: { colors: {
background: { primary: '#ffffff', secondary: '#f0f0f0' }, background: { primary: '#ffffff', secondary: '#f0f0f0' },
text: { secondary: '#333333' } text: { secondary: '#333333' },
} },
}, },
{ {
name: 'dark', name: 'dark',
colors: { colors: {
background: { primary: '#121212', secondary: '#1e1e1e' }, background: { primary: '#121212', secondary: '#1e1e1e' },
text: { secondary: '#e0e0e0' } text: { secondary: '#e0e0e0' },
} },
} },
] ],
})); }));
vi.mock('../../stores/UserOptionsStore', () => ({ vi.mock('../../stores/UserOptionsStore', () => ({
default: { default: {
selectTheme: vi.fn() selectTheme: vi.fn(),
} },
})); }));
vi.mock('../toolbar/Toolbar', () => ({ vi.mock('../toolbar/Toolbar', () => ({
toolbarButtonZIndex: 100 toolbarButtonZIndex: 100,
})); }));
describe('ThemeSelectionOptions', () => { describe('ThemeSelectionOptions', () => {
@@ -46,7 +47,7 @@ describe('ThemeSelectionOptions', () => {
render(<ThemeSelectionOptions />); render(<ThemeSelectionOptions />);
// Should render 2 theme buttons (from our mock) // Should render 2 theme buttons (from our mock)
const buttons = screen.getAllByRole("button") const buttons = screen.getAllByRole('button');
expect(buttons).toHaveLength(2); expect(buttons).toHaveLength(2);
}); });

View File

@@ -1,12 +1,13 @@
import { describe, it, expect } from 'vitest';
import { render, screen } from '@testing-library/react'; import { render, screen } from '@testing-library/react';
import WelcomeHomeMessage from '../WelcomeHome'; import { describe, it, expect } from 'vitest';
import { welcome_home_text, welcome_home_tip } from '../../static-data/welcome_home_text'; import { welcome_home_text, welcome_home_tip } from '../../static-data/welcome_home_text';
import { renderMarkdown } from '../markdown/MarkdownComponent'; import { renderMarkdown } from '../markdown/MarkdownComponent';
import WelcomeHomeMessage from '../WelcomeHome';
// Mock the renderMarkdown function // Mock the renderMarkdown function
vi.mock('../markdown/MarkdownComponent', () => ({ vi.mock('../markdown/MarkdownComponent', () => ({
renderMarkdown: vi.fn((text) => `Rendered: ${text}`), renderMarkdown: vi.fn(text => `Rendered: ${text}`),
})); }));
describe('WelcomeHomeMessage', () => { describe('WelcomeHomeMessage', () => {

View File

@@ -1,14 +1,14 @@
import React from "react"; import { Grid, GridItem, Image, Text } from '@chakra-ui/react';
import { Grid, GridItem, Image, Text } from "@chakra-ui/react"; import React from 'react';
const fontSize = "md"; const fontSize = 'md';
function AboutComponent() { function AboutComponent() {
return ( return (
<Grid <Grid
templateColumns="1fr" templateColumns="1fr"
gap={4} gap={4}
maxW={["100%", "100%", "100%"]} maxW={['100%', '100%', '100%']}
mx="auto" mx="auto"
className="about-container" className="about-container"
> >
@@ -17,22 +17,22 @@ function AboutComponent() {
src="/me.png" src="/me.png"
alt="Geoff Seemueller" alt="Geoff Seemueller"
borderRadius="full" borderRadius="full"
boxSize={["120px", "150px"]} boxSize={['120px', '150px']}
objectFit="cover" objectFit="cover"
/> />
</GridItem> </GridItem>
<GridItem <GridItem
colSpan={1} colSpan={1}
maxW={["100%", "100%", "container.md"]} maxW={['100%', '100%', 'container.md']}
justifySelf="center" justifySelf="center"
minH={"100%"} minH={'100%'}
> >
<Grid templateColumns="1fr" gap={4} overflowY={"auto"}> <Grid templateColumns="1fr" gap={4} overflowY={'auto'}>
<GridItem> <GridItem>
<Text fontSize={fontSize}> <Text fontSize={fontSize}>
If you're interested in collaborating on innovative projects that If you're interested in collaborating on innovative projects that push technological
push technological boundaries and create real value, I'd be keen boundaries and create real value, I'd be keen to connect and explore potential
to connect and explore potential opportunities. opportunities.
</Text> </Text>
</GridItem> </GridItem>
</Grid> </Grid>

View File

@@ -1,30 +1,26 @@
import React, { useEffect, useRef, useState } from "react"; import { Box, Grid, GridItem } from '@chakra-ui/react';
import { observer } from "mobx-react-lite"; import { observer } from 'mobx-react-lite';
import { Box, Grid, GridItem } from "@chakra-ui/react"; import React, { useEffect, useRef, useState } from 'react';
import ChatMessages from "./messages/ChatMessages";
import ChatInput from "./input/ChatInput"; import menuState from '../../stores/AppMenuStore';
import chatStore from "../../stores/ClientChatStore"; import chatStore from '../../stores/ClientChatStore';
import menuState from "../../stores/AppMenuStore"; import WelcomeHome from '../WelcomeHome';
import WelcomeHome from "../WelcomeHome";
import ChatInput from './input/ChatInput';
import ChatMessages from './messages/ChatMessages';
const Chat = observer(({ height, width }) => { const Chat = observer(({ height, width }) => {
const scrollRef = useRef(); const scrollRef = useRef();
const [isAndroid, setIsAndroid] = useState(false); const [isAndroid, setIsAndroid] = useState(false);
useEffect(() => { useEffect(() => {
if (typeof window !== "undefined") { if (typeof window !== 'undefined') {
setIsAndroid(/android/i.test(window.navigator.userAgent)); setIsAndroid(/android/i.test(window.navigator.userAgent));
} }
}, []); }, []);
return ( return (
<Grid <Grid templateRows="1fr auto" templateColumns="1fr" height={height} width={width} gap={0}>
templateRows="1fr auto"
templateColumns="1fr"
height={height}
width={width}
gap={0}
>
<GridItem alignSelf="center" hidden={!(chatStore.items.length < 1)}> <GridItem alignSelf="center" hidden={!(chatStore.items.length < 1)}>
<WelcomeHome visible={chatStore.items.length < 1} /> <WelcomeHome visible={chatStore.items.length < 1} />
</GridItem> </GridItem>
@@ -35,32 +31,17 @@ const Chat = observer(({ height, width }) => {
maxH="100%" maxH="100%"
ref={scrollRef} ref={scrollRef}
// If there are attachments, use "100px". Otherwise, use "128px" on Android, "73px" elsewhere. // If there are attachments, use "100px". Otherwise, use "128px" on Android, "73px" elsewhere.
pb={ pb={isAndroid ? '128px' : '73px'}
isAndroid
? "128px"
: "73px"
}
alignSelf="flex-end" alignSelf="flex-end"
> >
<ChatMessages scrollRef={scrollRef} /> <ChatMessages scrollRef={scrollRef} />
</GridItem> </GridItem>
<GridItem <GridItem position="relative" bg="background.primary" zIndex={1000} width="100%">
position="relative" <Box w="100%" display="flex" justifyContent="center" mx="auto" hidden={menuState.isOpen}>
bg="background.primary"
zIndex={1000}
width="100%"
>
<Box
w="100%"
display="flex"
justifyContent="center"
mx="auto"
hidden={menuState.isOpen}
>
<ChatInput <ChatInput
input={chatStore.input} input={chatStore.input}
setInput={(value) => chatStore.setInput(value)} setInput={value => chatStore.setInput(value)}
handleSendMessage={chatStore.sendMessage} handleSendMessage={chatStore.sendMessage}
isLoading={chatStore.isLoading} isLoading={chatStore.isLoading}
/> />

View File

@@ -1,16 +1,17 @@
import React from "react"; import { observer } from 'mobx-react-lite';
import { observer } from "mobx-react-lite"; import React from 'react';
import clientChatStore from "../../stores/ClientChatStore";
import clientChatStore from '../../stores/ClientChatStore';
export const IntermediateStepsComponent = observer(({ hidden }) => { export const IntermediateStepsComponent = observer(({ hidden }) => {
return ( return (
<div hidden={hidden}> <div hidden={hidden}>
{clientChatStore.intermediateSteps.map((step, index) => { {clientChatStore.intermediateSteps.map((step, index) => {
switch (step.kind) { switch (step.kind) {
case "web-search": { case 'web-search': {
return <WebSearchResult key={index} data={step.data} />; return <WebSearchResult key={index} data={step.data} />;
} }
case "tool-result": case 'tool-result':
return <ToolResult key={index} data={step.data} />; return <ToolResult key={index} data={step.data} />;
default: default:
return <GenericStep key={index} data={step.data} />; return <GenericStep key={index} data={step.data} />;
@@ -45,7 +46,7 @@ export const GenericStep = ({ data }) => {
return ( return (
<div className="generic-step"> <div className="generic-step">
<h3>Generic Step</h3> <h3>Generic Step</h3>
<p>{data.description || "No additional information provided."}</p> <p>{data.description || 'No additional information provided.'}</p>
</div> </div>
); );
}; };

View File

@@ -1,5 +1,3 @@
import React, { useRef } from "react";
import { observer } from "mobx-react-lite";
import { import {
Box, Box,
Divider, Divider,
@@ -11,8 +9,10 @@ import {
Portal, Portal,
Text, Text,
useDisclosure, useDisclosure,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import { ChevronRight } from "lucide-react"; import { ChevronRight } from 'lucide-react';
import { observer } from 'mobx-react-lite';
import React, { useRef } from 'react';
const FlyoutSubMenu: React.FC<{ const FlyoutSubMenu: React.FC<{
title: string; title: string;
@@ -23,15 +23,7 @@ const FlyoutSubMenu: React.FC<{
parentIsOpen: boolean; parentIsOpen: boolean;
setMenuState?: (state) => void; setMenuState?: (state) => void;
}> = observer( }> = observer(
({ ({ title, flyoutMenuOptions, onClose, handleSelect, isSelected, parentIsOpen, setMenuState }) => {
title,
flyoutMenuOptions,
onClose,
handleSelect,
isSelected,
parentIsOpen,
setMenuState,
}) => {
const { isOpen, onOpen, onClose: onSubMenuClose } = useDisclosure(); const { isOpen, onOpen, onClose: onSubMenuClose } = useDisclosure();
const menuRef = new useRef(); const menuRef = new useRef();
@@ -41,9 +33,9 @@ const FlyoutSubMenu: React.FC<{
placement="right-start" placement="right-start"
isOpen={isOpen && parentIsOpen} isOpen={isOpen && parentIsOpen}
closeOnBlur={true} closeOnBlur={true}
lazyBehavior={"keepMounted"} lazyBehavior={'keepMounted'}
isLazy={true} isLazy={true}
onClose={(e) => { onClose={e => {
onSubMenuClose(); onSubMenuClose();
}} }}
closeOnSelect={false} closeOnSelect={false}
@@ -54,12 +46,12 @@ const FlyoutSubMenu: React.FC<{
ref={menuRef} ref={menuRef}
bg="background.tertiary" bg="background.tertiary"
color="text.primary" color="text.primary"
_hover={{ bg: "rgba(0, 0, 0, 0.05)" }} _hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
_focus={{ bg: "rgba(0, 0, 0, 0.1)" }} _focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
> >
<HStack width={"100%"} justifyContent={"space-between"}> <HStack width={'100%'} justifyContent={'space-between'}>
<Text>{title}</Text> <Text>{title}</Text>
<ChevronRight size={"1rem"} /> <ChevronRight size={'1rem'} />
</HStack> </HStack>
</MenuButton> </MenuButton>
<Portal> <Portal>
@@ -67,7 +59,7 @@ const FlyoutSubMenu: React.FC<{
key={title} key={title}
maxHeight={56} maxHeight={56}
overflowY="scroll" overflowY="scroll"
visibility={"visible"} visibility={'visible'}
minWidth="180px" minWidth="180px"
bg="background.tertiary" bg="background.tertiary"
boxShadow="lg" boxShadow="lg"
@@ -77,43 +69,35 @@ const FlyoutSubMenu: React.FC<{
left="100%" left="100%"
bottom={-10} bottom={-10}
sx={{ sx={{
"::-webkit-scrollbar": { '::-webkit-scrollbar': {
width: "8px", width: '8px',
}, },
"::-webkit-scrollbar-thumb": { '::-webkit-scrollbar-thumb': {
background: "background.primary", background: 'background.primary',
borderRadius: "4px", borderRadius: '4px',
}, },
"::-webkit-scrollbar-track": { '::-webkit-scrollbar-track': {
background: "background.tertiary", background: 'background.tertiary',
}, },
}} }}
> >
{flyoutMenuOptions.map((item, index) => ( {flyoutMenuOptions.map((item, index) => (
<Box key={"itemflybox" + index}> <Box key={'itemflybox' + index}>
<MenuItem <MenuItem
key={"itemfly" + index} key={'itemfly' + index}
onClick={() => { onClick={() => {
onSubMenuClose(); onSubMenuClose();
onClose(); onClose();
handleSelect(item); handleSelect(item);
}} }}
bg={ bg={isSelected(item) ? 'background.secondary' : 'background.tertiary'}
isSelected(item) _hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
? "background.secondary" _focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
: "background.tertiary"
}
_hover={{ bg: "rgba(0, 0, 0, 0.05)" }}
_focus={{ bg: "rgba(0, 0, 0, 0.1)" }}
> >
{item.name} {item.name}
</MenuItem> </MenuItem>
{index < flyoutMenuOptions.length - 1 && ( {index < flyoutMenuOptions.length - 1 && (
<Divider <Divider key={item.name + '-divider'} color="text.tertiary" w={'100%'} />
key={item.name + "-divider"}
color="text.tertiary"
w={"100%"}
/>
)} )}
</Box> </Box>
))} ))}

View File

@@ -1,4 +1,3 @@
import React, {useCallback, useEffect, useRef, useState} from "react";
import { import {
Box, Box,
Button, Button,
@@ -12,38 +11,33 @@ import {
Text, Text,
useDisclosure, useDisclosure,
useOutsideClick, useOutsideClick,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import {observer} from "mobx-react-lite"; import { ChevronDown, Copy, RefreshCcw, Settings } from 'lucide-react';
import {ChevronDown, Copy, RefreshCcw, Settings} from "lucide-react"; import { observer } from 'mobx-react-lite';
import clientChatStore from "../../../stores/ClientChatStore"; import React, { useCallback, useEffect, useRef, useState } from 'react';
import FlyoutSubMenu from "./FlyoutSubMenu";
import {useIsMobile} from "../../contexts/MobileContext"; import { useIsMobile as useIsMobileUserAgent } from '../../../hooks/_IsMobileHook';
import {useIsMobile as useIsMobileUserAgent} from "../../../hooks/_IsMobileHook"; import clientChatStore from '../../../stores/ClientChatStore';
import {formatConversationMarkdown} from "../lib/exportConversationAsMarkdown"; import { useIsMobile } from '../../contexts/MobileContext';
import { formatConversationMarkdown } from '../lib/exportConversationAsMarkdown';
import FlyoutSubMenu from './FlyoutSubMenu';
export const MsM_commonButtonStyles = { export const MsM_commonButtonStyles = {
bg: "transparent", bg: 'transparent',
color: "text.primary", color: 'text.primary',
borderRadius: "full", borderRadius: 'full',
padding: 2, padding: 2,
border: "none", border: 'none',
_hover: {bg: "rgba(255, 255, 255, 0.2)"}, _hover: { bg: 'rgba(255, 255, 255, 0.2)' },
_active: {bg: "rgba(255, 255, 255, 0.3)"}, _active: { bg: 'rgba(255, 255, 255, 0.3)' },
_focus: {boxShadow: "none"}, _focus: { boxShadow: 'none' },
}; };
const InputMenu: React.FC<{ isDisabled?: boolean }> = observer( const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(({ isDisabled }) => {
({isDisabled}) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const isMobileUserAgent = useIsMobileUserAgent(); const isMobileUserAgent = useIsMobileUserAgent();
const { const { isOpen, onOpen, onClose, onToggle, getDisclosureProps, getButtonProps } = useDisclosure();
isOpen,
onOpen,
onClose,
onToggle,
getDisclosureProps,
getButtonProps,
} = useDisclosure();
const [controlledOpen, setControlledOpen] = useState<boolean>(false); const [controlledOpen, setControlledOpen] = useState<boolean>(false);
const [supportedModels, setSupportedModels] = useState<any[]>([]); const [supportedModels, setSupportedModels] = useState<any[]>([]);
@@ -53,14 +47,16 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
}, [isOpen]); }, [isOpen]);
useEffect(() => { useEffect(() => {
fetch("/api/models").then(response => response.json()).then((models) => { fetch('/api/models')
.then(response => response.json())
.then(models => {
setSupportedModels(models); setSupportedModels(models);
}).catch((err) => { })
console.error("Could not fetch models: ", err); .catch(err => {
console.error('Could not fetch models: ', err);
}); });
}, []); }, []);
const handleClose = useCallback(() => { const handleClose = useCallback(() => {
onClose(); onClose();
}, [isOpen]); }, [isOpen]);
@@ -69,14 +65,12 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
navigator.clipboard navigator.clipboard
.writeText(formatConversationMarkdown(clientChatStore.items)) .writeText(formatConversationMarkdown(clientChatStore.items))
.then(() => { .then(() => {
window.alert( window.alert('Conversation copied to clipboard. \n\nPaste it somewhere safe!');
"Conversation copied to clipboard. \n\nPaste it somewhere safe!",
);
onClose(); onClose();
}) })
.catch((err) => { .catch(err => {
console.error("Could not copy text to clipboard: ", err); console.error('Could not copy text to clipboard: ', err);
window.alert("Failed to copy conversation. Please try again."); window.alert('Failed to copy conversation. Please try again.');
}); });
}, [onClose]); }, [onClose]);
@@ -108,7 +102,7 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
closeOnSelect={false} closeOnSelect={false}
closeOnBlur={isOpen && !isMobileUserAgent} closeOnBlur={isOpen && !isMobileUserAgent}
isLazy={true} isLazy={true}
lazyBehavior={"unmount"} lazyBehavior={'unmount'}
> >
{isMobile ? ( {isMobile ? (
<MenuButton <MenuButton
@@ -117,8 +111,8 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
icon={<Settings size={20} />} icon={<Settings size={20} />}
isDisabled={isDisabled} isDisabled={isDisabled}
aria-label="Settings" aria-label="Settings"
_hover={{bg: "rgba(255, 255, 255, 0.2)"}} _hover={{ bg: 'rgba(255, 255, 255, 0.2)' }}
_focus={{boxShadow: "none"}} _focus={{ boxShadow: 'none' }}
{...MsM_commonButtonStyles} {...MsM_commonButtonStyles}
/> />
) : ( ) : (
@@ -143,14 +137,14 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
border="none" border="none"
borderRadius="md" borderRadius="md"
boxShadow="lg" boxShadow="lg"
minW={"10rem"} minW={'10rem'}
ref={menuRef} ref={menuRef}
> >
<FlyoutSubMenu <FlyoutSubMenu
title="Text Models" title="Text Models"
flyoutMenuOptions={supportedModels.map((modelData) => ({ flyoutMenuOptions={supportedModels.map(modelData => ({
name: modelData.id.split('/').pop() || modelData.id, name: modelData.id.split('/').pop() || modelData.id,
value: modelData.id value: modelData.id,
}))} }))}
onClose={onClose} onClose={onClose}
parentIsOpen={isOpen} parentIsOpen={isOpen}
@@ -164,11 +158,11 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
bg="background.tertiary" bg="background.tertiary"
color="text.primary" color="text.primary"
onClick={handleCopyConversation} onClick={handleCopyConversation}
_hover={{bg: "rgba(0, 0, 0, 0.05)"}} _hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
_focus={{bg: "rgba(0, 0, 0, 0.1)"}} _focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
> >
<Flex align="center"> <Flex align="center">
<Copy size="16px" style={{marginRight: "8px"}}/> <Copy size="16px" style={{ marginRight: '8px' }} />
<Box>Export</Box> <Box>Export</Box>
</Flex> </Flex>
</MenuItem> </MenuItem>
@@ -177,21 +171,20 @@ const InputMenu: React.FC<{ isDisabled?: boolean }> = observer(
bg="background.tertiary" bg="background.tertiary"
color="text.primary" color="text.primary"
onClick={() => { onClick={() => {
clientChatStore.setActiveConversation("conversation:new"); clientChatStore.setActiveConversation('conversation:new');
onClose(); onClose();
}} }}
_hover={{bg: "rgba(0, 0, 0, 0.05)"}} _hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
_focus={{bg: "rgba(0, 0, 0, 0.1)"}} _focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
> >
<Flex align="center"> <Flex align="center">
<RefreshCcw size="16px" style={{marginRight: "8px"}}/> <RefreshCcw size="16px" style={{ marginRight: '8px' }} />
<Box>New</Box> <Box>New</Box>
</Flex> </Flex>
</MenuItem> </MenuItem>
</MenuList> </MenuList>
</Menu> </Menu>
); );
}, });
);
export default InputMenu; export default InputMenu;

View File

@@ -1,34 +1,28 @@
import React, { useEffect, useRef, useState } from "react"; import { Box, Button, Grid, GridItem, useBreakpointValue } from '@chakra-ui/react';
import { import { observer } from 'mobx-react-lite';
Box, import React, { useEffect, useRef, useState } from 'react';
Button,
Grid, import { useMaxWidth } from '../../../hooks/useMaxWidth';
GridItem, import chatStore from '../../../stores/ClientChatStore';
useBreakpointValue, import userOptionsStore from '../../../stores/UserOptionsStore';
} from "@chakra-ui/react"; import InputMenu from '../input-menu/InputMenu';
import { observer } from "mobx-react-lite";
import chatStore from "../../../stores/ClientChatStore"; import SendButton from './ChatInputSendButton';
import InputMenu from "../input-menu/InputMenu"; import InputTextarea from './ChatInputTextArea';
import InputTextarea from "./ChatInputTextArea";
import SendButton from "./ChatInputSendButton";
import { useMaxWidth } from "../../../hooks/useMaxWidth";
import userOptionsStore from "../../../stores/UserOptionsStore";
const ChatInput = observer(() => { const ChatInput = observer(() => {
const inputRef = useRef<HTMLTextAreaElement>(null); const inputRef = useRef<HTMLTextAreaElement>(null);
const containerRef = useRef<HTMLDivElement>(null); const containerRef = useRef<HTMLDivElement>(null);
const maxWidth = useMaxWidth(); const maxWidth = useMaxWidth();
const [inputValue, setInputValue] = useState<string>(""); const [inputValue, setInputValue] = useState<string>('');
const [containerHeight, setContainerHeight] = useState(56); const [containerHeight, setContainerHeight] = useState(56);
const [containerBorderRadius, setContainerBorderRadius] = useState(9999); const [containerBorderRadius, setContainerBorderRadius] = useState(9999);
const [shouldFollow, setShouldFollow] = useState<boolean>( const [shouldFollow, setShouldFollow] = useState<boolean>(userOptionsStore.followModeEnabled);
userOptionsStore.followModeEnabled,
);
const [couldFollow, setCouldFollow] = useState<boolean>(chatStore.isLoading); const [couldFollow, setCouldFollow] = useState<boolean>(chatStore.isLoading);
const [inputWidth, setInputWidth] = useState<string>("50%"); const [inputWidth, setInputWidth] = useState<string>('50%');
useEffect(() => { useEffect(() => {
setShouldFollow(chatStore.isLoading && userOptionsStore.followModeEnabled); setShouldFollow(chatStore.isLoading && userOptionsStore.followModeEnabled);
@@ -42,8 +36,8 @@ const ChatInput = observer(() => {
useEffect(() => { useEffect(() => {
if (containerRef.current) { if (containerRef.current) {
const observer = new ResizeObserver((entries) => { const observer = new ResizeObserver(entries => {
for (let entry of entries) { for (const entry of entries) {
const newHeight = entry.target.clientHeight; const newHeight = entry.target.clientHeight;
setContainerHeight(newHeight); setContainerHeight(newHeight);
@@ -63,20 +57,20 @@ const ChatInput = observer(() => {
}; };
const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => { const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && !e.shiftKey) { if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault(); e.preventDefault();
chatStore.sendMessage(); chatStore.sendMessage();
} }
}; };
const inputMaxWidth = useBreakpointValue( const inputMaxWidth = useBreakpointValue(
{ base: "50rem", lg: "50rem", md: "80%", sm: "100vw" }, { base: '50rem', lg: '50rem', md: '80%', sm: '100vw' },
{ ssr: true }, { ssr: true },
); );
const inputMinWidth = useBreakpointValue({ lg: "40rem" }, { ssr: true }); const inputMinWidth = useBreakpointValue({ lg: '40rem' }, { ssr: true });
useEffect(() => { useEffect(() => {
setInputWidth("100%"); setInputWidth('100%');
}, [inputMaxWidth, inputMinWidth]); }, [inputMaxWidth, inputMinWidth]);
return ( return (
@@ -105,12 +99,12 @@ const ChatInput = observer(() => {
size="sm" size="sm"
variant="ghost" variant="ghost"
colorScheme="blue" colorScheme="blue"
onClick={(_) => { onClick={_ => {
userOptionsStore.toggleFollowMode(); userOptionsStore.toggleFollowMode();
}} }}
isDisabled={!chatStore.isLoading} isDisabled={!chatStore.isLoading}
> >
{shouldFollow ? "Disable Follow Mode" : "Enable Follow Mode"} {shouldFollow ? 'Disable Follow Mode' : 'Enable Follow Mode'}
</Button> </Button>
</Box> </Box>
)} )}
@@ -123,7 +117,7 @@ const ChatInput = observer(() => {
gap={2} gap={2}
alignItems="center" alignItems="center"
style={{ style={{
transition: "border-radius 0.2s ease", transition: 'border-radius 0.2s ease',
}} }}
> >
<GridItem> <GridItem>

View File

@@ -1,9 +1,9 @@
import React from "react"; import { Button } from '@chakra-ui/react';
import { Button } from "@chakra-ui/react"; import { motion } from 'framer-motion';
import clientChatStore from "../../../stores/ClientChatStore"; import { CirclePause, Send } from 'lucide-react';
import { CirclePause, Send } from "lucide-react"; import React from 'react';
import { motion } from "framer-motion"; import clientChatStore from '../../../stores/ClientChatStore';
interface SendButtonProps { interface SendButtonProps {
isLoading: boolean; isLoading: boolean;
@@ -13,25 +13,20 @@ interface SendButtonProps {
} }
const SendButton: React.FC<SendButtonProps> = ({ onClick }) => { const SendButton: React.FC<SendButtonProps> = ({ onClick }) => {
const isDisabled = const isDisabled = clientChatStore.input.trim().length === 0 && !clientChatStore.isLoading;
clientChatStore.input.trim().length === 0 && !clientChatStore.isLoading;
return ( return (
<Button <Button
onClick={(e) => onClick={e =>
clientChatStore.isLoading clientChatStore.isLoading ? clientChatStore.stopIncomingMessage() : onClick(e)
? clientChatStore.stopIncomingMessage()
: onClick(e)
} }
bg="transparent" bg="transparent"
color={ color={clientChatStore.input.trim().length <= 1 ? 'brand.700' : 'text.primary'}
clientChatStore.input.trim().length <= 1 ? "brand.700" : "text.primary"
}
borderRadius="full" borderRadius="full"
p={2} p={2}
isDisabled={isDisabled} isDisabled={isDisabled}
_hover={{ bg: !isDisabled ? "rgba(255, 255, 255, 0.2)" : "inherit" }} _hover={{ bg: !isDisabled ? 'rgba(255, 255, 255, 0.2)' : 'inherit' }}
_active={{ bg: !isDisabled ? "rgba(255, 255, 255, 0.3)" : "inherit" }} _active={{ bg: !isDisabled ? 'rgba(255, 255, 255, 0.3)' : 'inherit' }}
_focus={{ boxShadow: "none" }} _focus={{ boxShadow: 'none' }}
> >
{clientChatStore.isLoading ? <MySpinner /> : <Send size={20} />} {clientChatStore.isLoading ? <MySpinner /> : <Send size={20} />}
</Button> </Button>
@@ -45,10 +40,10 @@ const MySpinner = ({ onClick }) => (
exit={{ opacity: 0, scale: 0.9 }} exit={{ opacity: 0, scale: 0.9 }}
transition={{ transition={{
duration: 0.4, duration: 0.4,
ease: "easeInOut", ease: 'easeInOut',
}} }}
> >
<CirclePause color={"#F0F0F0"} size={24} onClick={onClick} /> <CirclePause color={'#F0F0F0'} size={24} onClick={onClick} />
</motion.div> </motion.div>
); );

View File

@@ -1,7 +1,7 @@
import React, {useEffect, useRef, useState} from "react"; import { Box, chakra, InputGroup } from '@chakra-ui/react';
import {observer} from "mobx-react-lite"; import { observer } from 'mobx-react-lite';
import {Box, chakra, InputGroup,} from "@chakra-ui/react"; import React, { useEffect, useRef, useState } from 'react';
import AutoResize from "react-textarea-autosize"; import AutoResize from 'react-textarea-autosize';
const AutoResizeTextArea = chakra(AutoResize); const AutoResizeTextArea = chakra(AutoResize);
@@ -15,10 +15,7 @@ interface InputTextAreaProps {
const InputTextArea: React.FC<InputTextAreaProps> = observer( const InputTextArea: React.FC<InputTextAreaProps> = observer(
({ inputRef, value, onChange, onKeyDown, isLoading }) => { ({ inputRef, value, onChange, onKeyDown, isLoading }) => {
const [heightConstraint, setHeightConstraint] = useState<number | undefined>(10);
const [heightConstraint, setHeightConstraint] = useState<
number | undefined
>(10);
useEffect(() => { useEffect(() => {
if (value.length > 10) { if (value.length > 10) {
@@ -34,7 +31,6 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
display="flex" display="flex"
flexDirection="column" flexDirection="column"
> >
{/* Input Area */} {/* Input Area */}
<InputGroup position="relative"> <InputGroup position="relative">
<AutoResizeTextArea <AutoResizeTextArea
@@ -43,7 +39,7 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
value={value} value={value}
height={heightConstraint} height={heightConstraint}
autoFocus autoFocus
onChange={(e) => onChange(e.target.value)} onChange={e => onChange(e.target.value)}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
p={2} p={2}
pr="8px" pr="8px"
@@ -53,19 +49,19 @@ const InputTextArea: React.FC<InputTextAreaProps> = observer(
borderRadius="20px" borderRadius="20px"
border="none" border="none"
placeholder="Free my mind..." placeholder="Free my mind..."
_placeholder={{ color: "gray.400" }} _placeholder={{ color: 'gray.400' }}
_focus={{ _focus={{
outline: "none", outline: 'none',
}} }}
disabled={isLoading} disabled={isLoading}
minRows={1} minRows={1}
maxRows={12} maxRows={12}
style={{ style={{
touchAction: "none", touchAction: 'none',
resize: "none", resize: 'none',
overflowY: "auto", overflowY: 'auto',
width: "100%", width: '100%',
transition: "height 0.2s ease-in-out", transition: 'height 0.2s ease-in-out',
}} }}
/> />
</InputGroup> </InputGroup>

View File

@@ -1,9 +1,10 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react'; import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react'; import React from 'react';
import ChatInput from '../ChatInput'; import { describe, it, expect, vi, beforeEach } from 'vitest';
import userOptionsStore from '../../../../stores/UserOptionsStore';
import chatStore from '../../../../stores/ClientChatStore'; import chatStore from '../../../../stores/ClientChatStore';
import userOptionsStore from '../../../../stores/UserOptionsStore';
import ChatInput from '../ChatInput';
// Mock browser APIs // Mock browser APIs
class MockResizeObserver { class MockResizeObserver {
@@ -85,7 +86,7 @@ vi.mock('./ChatInputTextArea', () => ({
aria-label="Chat input" aria-label="Chat input"
ref={inputRef} ref={inputRef}
value={value} value={value}
onChange={(e) => onChange(e.target.value)} onChange={e => onChange(e.target.value)}
onKeyDown={onKeyDown} onKeyDown={onKeyDown}
disabled={isLoading} disabled={isLoading}
/> />

View File

@@ -8,16 +8,16 @@ const SUPPORTED_MODELS_GROUPS = {
groq: [ groq: [
// "mixtral-8x7b-32768", // "mixtral-8x7b-32768",
// "deepseek-r1-distill-llama-70b", // "deepseek-r1-distill-llama-70b",
"meta-llama/llama-4-scout-17b-16e-instruct", 'meta-llama/llama-4-scout-17b-16e-instruct',
"gemma2-9b-it", 'gemma2-9b-it',
"mistral-saba-24b", 'mistral-saba-24b',
// "qwen-2.5-32b", // "qwen-2.5-32b",
"llama-3.3-70b-versatile", 'llama-3.3-70b-versatile',
// "llama-3.3-70b-versatile" // "llama-3.3-70b-versatile"
// "llama-3.1-70b-versatile", // "llama-3.1-70b-versatile",
// "llama-3.3-70b-versatile" // "llama-3.3-70b-versatile"
], ],
cerebras: ["llama-3.3-70b"], cerebras: ['llama-3.3-70b'],
claude: [ claude: [
// "claude-3-5-sonnet-20241022", // "claude-3-5-sonnet-20241022",
// "claude-3-opus-20240229" // "claude-3-opus-20240229"
@@ -44,16 +44,16 @@ const SUPPORTED_MODELS_GROUPS = {
// "grok-beta" // "grok-beta"
], ],
cloudflareAI: [ cloudflareAI: [
"llama-3.2-3b-instruct", // max_tokens 'llama-3.2-3b-instruct', // max_tokens
"llama-3-8b-instruct", // max_tokens 'llama-3-8b-instruct', // max_tokens
"llama-3.1-8b-instruct-fast", // max_tokens 'llama-3.1-8b-instruct-fast', // max_tokens
"deepseek-math-7b-instruct", 'deepseek-math-7b-instruct',
"deepseek-coder-6.7b-instruct-awq", 'deepseek-coder-6.7b-instruct-awq',
"hermes-2-pro-mistral-7b", 'hermes-2-pro-mistral-7b',
"openhermes-2.5-mistral-7b-awq", 'openhermes-2.5-mistral-7b-awq',
"mistral-7b-instruct-v0.2", 'mistral-7b-instruct-v0.2',
"neural-chat-7b-v3-1-awq", 'neural-chat-7b-v3-1-awq',
"openchat-3.5-0106", 'openchat-3.5-0106',
// "gemma-7b-it", // "gemma-7b-it",
], ],
}; };
@@ -66,10 +66,10 @@ export type ModelFamily = keyof typeof SUPPORTED_MODELS_GROUPS;
function getModelFamily(model: string): ModelFamily | undefined { function getModelFamily(model: string): ModelFamily | undefined {
return Object.keys(SUPPORTED_MODELS_GROUPS) return Object.keys(SUPPORTED_MODELS_GROUPS)
.filter((family) => { .filter(family => {
return SUPPORTED_MODELS_GROUPS[ return SUPPORTED_MODELS_GROUPS[family as keyof typeof SUPPORTED_MODELS_GROUPS].includes(
family as keyof typeof SUPPORTED_MODELS_GROUPS model.trim(),
].includes(model.trim()); );
}) })
.at(0) as ModelFamily | undefined; .at(0) as ModelFamily | undefined;
} }

View File

@@ -1,30 +1,30 @@
import DOMPurify from "isomorphic-dompurify"; import DOMPurify from 'isomorphic-dompurify';
function domPurify(dirty: string) { function domPurify(dirty: string) {
return DOMPurify.sanitize(dirty, { return DOMPurify.sanitize(dirty, {
USE_PROFILES: { html: true }, USE_PROFILES: { html: true },
ALLOWED_TAGS: [ ALLOWED_TAGS: [
"b", 'b',
"i", 'i',
"u", 'u',
"a", 'a',
"p", 'p',
"span", 'span',
"div", 'div',
"table", 'table',
"thead", 'thead',
"tbody", 'tbody',
"tr", 'tr',
"td", 'td',
"th", 'th',
"ul", 'ul',
"ol", 'ol',
"li", 'li',
"code", 'code',
"pre", 'pre',
], ],
ALLOWED_ATTR: ["href", "src", "alt", "title", "class", "style"], ALLOWED_ATTR: ['href', 'src', 'alt', 'title', 'class', 'style'],
FORBID_TAGS: ["script", "iframe"], FORBID_TAGS: ['script', 'iframe'],
KEEP_CONTENT: true, KEEP_CONTENT: true,
SAFE_FOR_TEMPLATES: true, SAFE_FOR_TEMPLATES: true,
}); });

View File

@@ -1,18 +1,17 @@
// Function to generate a Markdown representation of the current conversation // Function to generate a Markdown representation of the current conversation
import { type IMessage } from "../../../stores/ClientChatStore"; import { type Instance } from 'mobx-state-tree';
import { type Instance } from "mobx-state-tree";
export function formatConversationMarkdown( import { type IMessage } from '../../../stores/ClientChatStore';
messages: Instance<typeof IMessage>[],
): string { export function formatConversationMarkdown(messages: Instance<typeof IMessage>[]): string {
return messages return messages
.map((message) => { .map(message => {
if (message.role === "user") { if (message.role === 'user') {
return `**You**: ${message.content}`; return `**You**: ${message.content}`;
} else if (message.role === "assistant") { } else if (message.role === 'assistant') {
return `**Geoff's AI**: ${message.content}`; return `**Geoff's AI**: ${message.content}`;
} }
return ""; return '';
}) })
.join("\n\n"); .join('\n\n');
} }

View File

@@ -1,6 +1,6 @@
import React from "react"; import React from 'react';
import MessageMarkdownRenderer from "./MessageMarkdownRenderer"; import MessageMarkdownRenderer from './MessageMarkdownRenderer';
const ChatMessageContent = ({ content }) => { const ChatMessageContent = ({ content }) => {
return <MessageMarkdownRenderer markdown={content} />; return <MessageMarkdownRenderer markdown={content} />;

View File

@@ -1,9 +1,11 @@
import React from "react"; import { Box, Grid, GridItem } from '@chakra-ui/react';
import {Box, Grid, GridItem} from "@chakra-ui/react"; import { observer } from 'mobx-react-lite';
import MessageBubble from "./MessageBubble"; import React from 'react';
import {observer} from "mobx-react-lite";
import chatStore from "../../../stores/ClientChatStore"; import chatStore from '../../../stores/ClientChatStore';
import {useIsMobile} from "../../contexts/MobileContext"; import { useIsMobile } from '../../contexts/MobileContext';
import MessageBubble from './MessageBubble';
interface ChatMessagesProps { interface ChatMessagesProps {
scrollRef: React.RefObject<HTMLDivElement>; scrollRef: React.RefObject<HTMLDivElement>;
@@ -13,11 +15,7 @@ const ChatMessages: React.FC<ChatMessagesProps> = observer(({ scrollRef }) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<Box <Box pt={isMobile ? 24 : undefined} overflowY={'scroll'} overflowX={'hidden'}>
pt={isMobile ? 24 : undefined}
overflowY={"scroll"}
overflowX={"hidden"}
>
<Grid <Grid
fontFamily="Arial, sans-serif" fontFamily="Arial, sans-serif"
templateColumns="1fr" templateColumns="1fr"

View File

@@ -1,19 +1,19 @@
import React, { useEffect, useRef, useState } from "react"; import { Box, Flex, Text } from '@chakra-ui/react';
import { Box, Flex, Text } from "@chakra-ui/react"; import { observer } from 'mobx-react-lite';
import MessageRenderer from "./ChatMessageContent"; import React, { useEffect, useRef, useState } from 'react';
import { observer } from "mobx-react-lite";
import MessageEditor from "./MessageEditorComponent";
import UserMessageTools from "./UserMessageTools";
import clientChatStore from "../../../stores/ClientChatStore";
import UserOptionsStore from "../../../stores/UserOptionsStore";
import MotionBox from "./MotionBox";
import clientChatStore from '../../../stores/ClientChatStore';
import UserOptionsStore from '../../../stores/UserOptionsStore';
import MessageRenderer from './ChatMessageContent';
import MessageEditor from './MessageEditorComponent';
import MotionBox from './MotionBox';
import UserMessageTools from './UserMessageTools';
const LoadingDots = () => { const LoadingDots = () => {
return ( return (
<Flex> <Flex>
{[0, 1, 2].map((i) => ( {[0, 1, 2].map(i => (
<MotionBox <MotionBox
key={i} key={i}
width="8px" width="8px"
@@ -34,10 +34,10 @@ const LoadingDots = () => {
))} ))}
</Flex> </Flex>
); );
} };
function renderMessage(msg: any) { function renderMessage(msg: any) {
if (msg.role === "user") { if (msg.role === 'user') {
return ( return (
<Text as="p" fontSize="sm" lineHeight="short" color="text.primary"> <Text as="p" fontSize="sm" lineHeight="short" color="text.primary">
{msg.content} {msg.content}
@@ -50,8 +50,8 @@ function renderMessage(msg: any) {
const MessageBubble = observer(({ msg, scrollRef }) => { const MessageBubble = observer(({ msg, scrollRef }) => {
const [isEditing, setIsEditing] = useState(false); const [isEditing, setIsEditing] = useState(false);
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const isUser = msg.role === "user"; const isUser = msg.role === 'user';
const senderName = isUser ? "You" : "Geoff's AI"; const senderName = isUser ? 'You' : "Geoff's AI";
const isLoading = !msg.content || !(msg.content.trim().length > 0); const isLoading = !msg.content || !(msg.content.trim().length > 0);
const messageRef = useRef(); const messageRef = useRef();
@@ -64,10 +64,15 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
}; };
useEffect(() => { useEffect(() => {
if (clientChatStore.items.length > 0 && clientChatStore.isLoading && UserOptionsStore.followModeEnabled) { // Refine condition if (
clientChatStore.items.length > 0 &&
clientChatStore.isLoading &&
UserOptionsStore.followModeEnabled
) {
// Refine condition
scrollRef.current?.scrollTo({ scrollRef.current?.scrollTo({
top: scrollRef.current.scrollHeight, top: scrollRef.current.scrollHeight,
behavior: "auto", behavior: 'auto',
}); });
} }
}); });
@@ -75,7 +80,7 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
return ( return (
<Flex <Flex
flexDirection="column" flexDirection="column"
alignItems={isUser ? "flex-end" : "flex-start"} alignItems={isUser ? 'flex-end' : 'flex-start'}
role="listitem" role="listitem"
flex={0} flex={0}
aria-label={`Message from ${senderName}`} aria-label={`Message from ${senderName}`}
@@ -85,19 +90,19 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
<Text <Text
fontSize="xs" fontSize="xs"
color="text.tertiary" color="text.tertiary"
textAlign={isUser ? "right" : "left"} textAlign={isUser ? 'right' : 'left'}
alignSelf={isUser ? "flex-end" : "flex-start"} alignSelf={isUser ? 'flex-end' : 'flex-start'}
mb={1} mb={1}
> >
{senderName} {senderName}
</Text> </Text>
<MotionBox <MotionBox
minW={{ base: "99%", sm: "99%", lg: isUser ? "55%" : "60%" }} minW={{ base: '99%', sm: '99%', lg: isUser ? '55%' : '60%' }}
maxW={{ base: "99%", sm: "99%", lg: isUser ? "65%" : "65%" }} maxW={{ base: '99%', sm: '99%', lg: isUser ? '65%' : '65%' }}
p={3} p={3}
borderRadius="1.5em" borderRadius="1.5em"
bg={isUser ? "#0A84FF" : "#3A3A3C"} bg={isUser ? '#0A84FF' : '#3A3A3C'}
color="text.primary" color="text.primary"
textAlign="left" textAlign="left"
boxShadow="0 2px 4px rgba(0, 0, 0, 0.1)" boxShadow="0 2px 4px rgba(0, 0, 0, 0.1)"
@@ -115,10 +120,10 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
whiteSpace="pre-wrap" whiteSpace="pre-wrap"
ref={messageRef} ref={messageRef}
sx={{ sx={{
"pre, code": { 'pre, code': {
maxWidth: "100%", maxWidth: '100%',
whiteSpace: "pre-wrap", whiteSpace: 'pre-wrap',
overflowX: "auto", overflowX: 'auto',
}, },
}} }}
> >
@@ -139,9 +144,7 @@ const MessageBubble = observer(({ msg, scrollRef }) => {
justifyContent="center" justifyContent="center"
alignItems="center" alignItems="center"
> >
{isHovered && !isEditing && ( {isHovered && !isEditing && <UserMessageTools message={msg} onEdit={handleEdit} />}
<UserMessageTools message={msg} onEdit={handleEdit} />
)}
</Box> </Box>
)} )}
</Flex> </Flex>

View File

@@ -1,10 +1,11 @@
import React, {type KeyboardEvent, useEffect } from "react"; import { Box, Flex, IconButton, Textarea } from '@chakra-ui/react';
import { Box, Flex, IconButton, Textarea } from "@chakra-ui/react"; import { Check, X } from 'lucide-react';
import { Check, X } from "lucide-react"; import { observer } from 'mobx-react-lite';
import { observer } from "mobx-react-lite"; import { type Instance } from 'mobx-state-tree';
import { type Instance } from "mobx-state-tree"; import React, { type KeyboardEvent, useEffect } from 'react';
import Message from "../../../models/Message";
import messageEditorStore from "../../../stores/MessageEditorStore"; import Message from '../../../models/Message';
import messageEditorStore from '../../../stores/MessageEditorStore';
interface MessageEditorProps { interface MessageEditorProps {
message: Instance<typeof Message>; message: Instance<typeof Message>;
@@ -30,15 +31,13 @@ const MessageEditor = observer(({ message, onCancel }: MessageEditorProps) => {
onCancel(); onCancel();
}; };
const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => { const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { if (e.key === 'Enter' && (e.metaKey || e.ctrlKey)) {
e.preventDefault(); e.preventDefault();
handleSave(); handleSave();
} }
if (e.key === "Escape") { if (e.key === 'Escape') {
e.preventDefault(); e.preventDefault();
handleCancel(); handleCancel();
} }
@@ -48,14 +47,14 @@ const MessageEditor = observer(({ message, onCancel }: MessageEditorProps) => {
<Box width="100%"> <Box width="100%">
<Textarea <Textarea
value={messageEditorStore.editedContent} value={messageEditorStore.editedContent}
onChange={(e) => messageEditorStore.setEditedContent(e.target.value)} onChange={e => messageEditorStore.setEditedContent(e.target.value)}
onKeyDown={handleKeyDown} onKeyDown={handleKeyDown}
minHeight="100px" minHeight="100px"
bg="transparent" bg="transparent"
border="1px solid" border="1px solid"
borderColor="whiteAlpha.300" borderColor="whiteAlpha.300"
_hover={{ borderColor: "whiteAlpha.400" }} _hover={{ borderColor: 'whiteAlpha.400' }}
_focus={{ borderColor: "brand.100", boxShadow: "none" }} _focus={{ borderColor: 'brand.100', boxShadow: 'none' }}
resize="vertical" resize="vertical"
color="text.primary" color="text.primary"
/> />
@@ -66,7 +65,7 @@ const MessageEditor = observer(({ message, onCancel }: MessageEditorProps) => {
onClick={handleCancel} onClick={handleCancel}
size="sm" size="sm"
variant="ghost" variant="ghost"
color={"accent.danger"} color={'accent.danger'}
/> />
<IconButton <IconButton
aria-label="Save edit" aria-label="Save edit"
@@ -74,7 +73,7 @@ const MessageEditor = observer(({ message, onCancel }: MessageEditorProps) => {
onClick={handleSave} onClick={handleSave}
size="sm" size="sm"
variant="ghost" variant="ghost"
color={"accent.confirm"} color={'accent.confirm'}
/> />
</Flex> </Flex>
</Box> </Box>

View File

@@ -1,5 +1,3 @@
import React from "react";
import { import {
Box, Box,
Code, Code,
@@ -17,13 +15,15 @@ import {
Thead, Thead,
Tr, Tr,
useColorModeValue, useColorModeValue,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import { marked } from "marked"; import katex from 'katex';
import CodeBlock from "../../code/CodeBlock"; import { marked } from 'marked';
import ImageWithFallback from "../../markdown/ImageWithFallback"; import markedKatex from 'marked-katex-extension';
import markedKatex from "marked-katex-extension"; import React from 'react';
import katex from "katex";
import domPurify from "../lib/domPurify"; import CodeBlock from '../../code/CodeBlock';
import ImageWithFallback from '../../markdown/ImageWithFallback';
import domPurify from '../lib/domPurify';
try { try {
if (localStorage) { if (localStorage) {
@@ -34,11 +34,13 @@ try {
throwOnError: false, throwOnError: false,
strict: true, strict: true,
colorIsTextColor: true, colorIsTextColor: true,
errorColor: "red", errorColor: 'red',
}), }),
); );
} }
} catch (_) {} } catch (_) {
// Silently ignore errors in marked setup - fallback to default behavior
}
const MemoizedCodeBlock = React.memo(CodeBlock); const MemoizedCodeBlock = React.memo(CodeBlock);
@@ -49,32 +51,29 @@ const MemoizedCodeBlock = React.memo(CodeBlock);
const getHeadingProps = (depth: number) => { const getHeadingProps = (depth: number) => {
switch (depth) { switch (depth) {
case 1: case 1:
return { as: "h1", size: "xl", mt: 4, mb: 2 }; return { as: 'h1', size: 'xl', mt: 4, mb: 2 };
case 2: case 2:
return { as: "h2", size: "lg", mt: 3, mb: 2 }; return { as: 'h2', size: 'lg', mt: 3, mb: 2 };
case 3: case 3:
return { as: "h3", size: "md", mt: 2, mb: 1 }; return { as: 'h3', size: 'md', mt: 2, mb: 1 };
case 4: case 4:
return { as: "h4", size: "sm", mt: 2, mb: 1 }; return { as: 'h4', size: 'sm', mt: 2, mb: 1 };
case 5: case 5:
return { as: "h5", size: "sm", mt: 2, mb: 1 }; return { as: 'h5', size: 'sm', mt: 2, mb: 1 };
case 6: case 6:
return { as: "h6", size: "xs", mt: 2, mb: 1 }; return { as: 'h6', size: 'xs', mt: 2, mb: 1 };
default: default:
return { as: `h${depth}`, size: "md", mt: 2, mb: 1 }; return { as: `h${depth}`, size: 'md', mt: 2, mb: 1 };
} }
}; };
interface TableToken extends marked.Tokens.Table { interface TableToken extends marked.Tokens.Table {
align: Array<"center" | "left" | "right" | null>; align: Array<'center' | 'left' | 'right' | null>;
header: (string | marked.Tokens.TableCell)[]; header: (string | marked.Tokens.TableCell)[];
rows: (string | marked.Tokens.TableCell)[][]; rows: (string | marked.Tokens.TableCell)[][];
} }
const CustomHeading: React.FC<{ text: string; depth: number }> = ({ const CustomHeading: React.FC<{ text: string; depth: number }> = ({ text, depth }) => {
text,
depth,
}) => {
const headingProps = getHeadingProps(depth); const headingProps = getHeadingProps(depth);
return ( return (
<Heading {...headingProps} wordBreak="break-word" maxWidth="100%"> <Heading {...headingProps} wordBreak="break-word" maxWidth="100%">
@@ -83,9 +82,7 @@ const CustomHeading: React.FC<{ text: string; depth: number }> = ({
); );
}; };
const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ children }) => {
children,
}) => {
return ( return (
<Text <Text
as="p" as="p"
@@ -100,9 +97,7 @@ const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({
); );
}; };
const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ children }) => {
children,
}) => {
return ( return (
<Box <Box
as="blockquote" as="blockquote"
@@ -120,16 +115,9 @@ const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({
); );
}; };
const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ code, language }) => {
code,
language,
}) => {
return ( return (
<MemoizedCodeBlock <MemoizedCodeBlock language={language} code={code} onRenderComplete={() => Promise.resolve()} />
language={language}
code={code}
onRenderComplete={() => Promise.resolve()}
/>
); );
}; };
@@ -141,10 +129,10 @@ const CustomList: React.FC<{
children: React.ReactNode; children: React.ReactNode;
}> = ({ ordered, start, children }) => { }> = ({ ordered, start, children }) => {
const commonStyles = { const commonStyles = {
fontSize: "sm", fontSize: 'sm',
wordBreak: "break-word" as const, wordBreak: 'break-word' as const,
maxWidth: "100%" as const, maxWidth: '100%' as const,
stylePosition: "outside" as const, stylePosition: 'outside' as const,
mb: 2, mb: 2,
pl: 4, pl: 4,
}; };
@@ -166,16 +154,13 @@ const CustomListItem: React.FC<{
return <ListItem mb={1}>{children}</ListItem>; return <ListItem mb={1}>{children}</ListItem>;
}; };
const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ math, displayMode }) => {
math,
displayMode,
}) => {
const renderedMath = katex.renderToString(math, { displayMode }); const renderedMath = katex.renderToString(math, { displayMode });
return ( return (
<Box <Box
as="span" as="span"
display={displayMode ? "block" : "inline"} display={displayMode ? 'block' : 'inline'}
p={displayMode ? 4 : 1} p={displayMode ? 4 : 1}
my={displayMode ? 4 : 0} my={displayMode ? 4 : 0}
borderRadius="md" borderRadius="md"
@@ -188,23 +173,17 @@ const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({
const CustomTable: React.FC<{ const CustomTable: React.FC<{
header: React.ReactNode[]; header: React.ReactNode[];
align: Array<"center" | "left" | "right" | null>; align: Array<'center' | 'left' | 'right' | null>;
rows: React.ReactNode[][]; rows: React.ReactNode[][];
}> = ({ header, align, rows }) => { }> = ({ header, align, rows }) => {
return ( return (
<Table <Table variant="simple" size="sm" my={4} borderRadius="md" overflow="hidden">
variant="simple"
size="sm"
my={4}
borderRadius="md"
overflow="hidden"
>
<Thead bg="background.secondary"> <Thead bg="background.secondary">
<Tr> <Tr>
{header.map((cell, i) => ( {header.map((cell, i) => (
<Th <Th
key={i} key={i}
textAlign={align[i] || "left"} textAlign={align[i] || 'left'}
fontWeight="bold" fontWeight="bold"
p={2} p={2}
minW={16} minW={16}
@@ -219,12 +198,7 @@ const CustomTable: React.FC<{
{rows.map((row, rIndex) => ( {rows.map((row, rIndex) => (
<Tr key={rIndex}> <Tr key={rIndex}>
{row.map((cell, cIndex) => ( {row.map((cell, cIndex) => (
<Td <Td key={cIndex} textAlign={align[cIndex] || 'left'} p={2} wordBreak="break-word">
key={cIndex}
textAlign={align[cIndex] || "left"}
p={2}
wordBreak="break-word"
>
{cell} {cell}
</Td> </Td>
))} ))}
@@ -241,13 +215,7 @@ const CustomHtmlBlock: React.FC<{ content: string }> = ({ content }) => {
const CustomText: React.FC<{ text: React.ReactNode }> = ({ text }) => { const CustomText: React.FC<{ text: React.ReactNode }> = ({ text }) => {
return ( return (
<Text <Text fontSize="sm" lineHeight="short" wordBreak="break-word" maxWidth="100%" as="span">
fontSize="sm"
lineHeight="short"
wordBreak="break-word"
maxWidth="100%"
as="span"
>
{text} {text}
</Text> </Text>
); );
@@ -262,13 +230,7 @@ const CustomStrong: React.FC<CustomStrongProps> = ({ children }) => {
const CustomEm: React.FC<{ children: React.ReactNode }> = ({ children }) => { const CustomEm: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return ( return (
<Text <Text as="em" fontStyle="italic" lineHeight="short" wordBreak="break-word" display="inline">
as="em"
fontStyle="italic"
lineHeight="short"
wordBreak="break-word"
display="inline"
>
{children} {children}
</Text> </Text>
); );
@@ -289,7 +251,7 @@ const CustomDel: React.FC<{ text: string }> = ({ text }) => {
}; };
const CustomCodeSpan: React.FC<{ code: string }> = ({ code }) => { const CustomCodeSpan: React.FC<{ code: string }> = ({ code }) => {
const bg = useColorModeValue("gray.100", "gray.800"); const bg = useColorModeValue('gray.100', 'gray.800');
return ( return (
<Code <Code
fontSize="sm" fontSize="sm"
@@ -312,13 +274,13 @@ const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({
return ( return (
<Box <Box
as="span" as="span"
display={displayMode ? "block" : "inline"} display={displayMode ? 'block' : 'inline'}
p={displayMode ? 4 : 1} p={displayMode ? 4 : 1}
my={displayMode ? 4 : 0} my={displayMode ? 4 : 0}
borderRadius="md" borderRadius="md"
overflow="auto" overflow="auto"
maxWidth="100%" maxWidth="100%"
className={`math ${displayMode ? "math-display" : "math-inline"}`} className={`math ${displayMode ? 'math-display' : 'math-inline'}`}
> >
{math} {math}
</Box> </Box>
@@ -336,8 +298,8 @@ const CustomLink: React.FC<{
title={title} title={title}
isExternal isExternal
sx={{ sx={{
"& span": { '& span': {
color: "text.link", color: 'text.link',
}, },
}} }}
maxWidth="100%" maxWidth="100%"
@@ -379,46 +341,34 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
tokens.forEach((token, i) => { tokens.forEach((token, i) => {
switch (token.type) { switch (token.type) {
case "heading": case 'heading':
output.push( output.push(<CustomHeading key={i} text={token.text} depth={token.depth} />);
<CustomHeading key={i} text={token.text} depth={token.depth} />,
);
break; break;
case "paragraph": { case 'paragraph': {
const parsedContent = token.tokens const parsedContent = token.tokens ? parseTokens(token.tokens) : token.text;
? parseTokens(token.tokens)
: token.text;
if (blockquoteContent.length > 0) { if (blockquoteContent.length > 0) {
blockquoteContent.push( blockquoteContent.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
);
} else { } else {
output.push( output.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
);
} }
break; break;
} }
case "br": case 'br':
output.push(<br key={i} />); output.push(<br key={i} />);
break; break;
case "escape": { case 'escape': {
break; break;
} }
case "blockquote_start": case 'blockquote_start':
blockquoteContent = []; blockquoteContent = [];
break; break;
case "blockquote_end": case 'blockquote_end':
output.push( output.push(<CustomBlockquote key={i}>{parseTokens(blockquoteContent)}</CustomBlockquote>);
<CustomBlockquote key={i}>
{parseTokens(blockquoteContent)}
</CustomBlockquote>,
);
blockquoteContent = []; blockquoteContent = [];
break; break;
case "blockquote": { case 'blockquote': {
output.push( output.push(
<CustomBlockquote key={i}> <CustomBlockquote key={i}>
{token.tokens ? parseTokens(token.tokens) : null} {token.tokens ? parseTokens(token.tokens) : null}
@@ -426,44 +376,30 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
} }
case "math": case 'math':
output.push( output.push(<CustomMath key={i} math={(token as any).value} displayMode={true} />);
<CustomMath key={i} math={(token as any).value} displayMode={true} />,
);
break; break;
case "inlineMath": case 'inlineMath':
output.push( output.push(<CustomMath key={i} math={(token as any).value} displayMode={false} />);
<CustomMath
key={i}
math={(token as any).value}
displayMode={false}
/>,
);
break; break;
case "inlineKatex": case 'inlineKatex':
case "blockKatex": { case 'blockKatex': {
const katexToken = token as any; const katexToken = token as any;
output.push( output.push(
<CustomKatex <CustomKatex key={i} math={katexToken.text} displayMode={katexToken.displayMode} />,
key={i}
math={katexToken.text}
displayMode={katexToken.displayMode}
/>,
); );
break; break;
} }
case "code": case 'code':
output.push( output.push(<CustomCodeBlock key={i} code={token.text} language={token.lang} />);
<CustomCodeBlock key={i} code={token.text} language={token.lang} />,
);
break; break;
case "hr": case 'hr':
output.push(<CustomHr key={i} />); output.push(<CustomHr key={i} />);
break; break;
case "list": { case 'list': {
const { ordered, start, items } = token; const { ordered, start, items } = token;
const listItems = items.map((listItem, idx) => { const listItems = items.map((listItem, idx) => {
const nestedContent = parseTokens(listItem.tokens); const nestedContent = parseTokens(listItem.tokens);
@@ -477,53 +413,43 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
} }
case "table": { case 'table': {
const tableToken = token as TableToken; const tableToken = token as TableToken;
output.push( output.push(
<CustomTable <CustomTable
key={i} key={i}
header={tableToken.header.map((cell) => header={tableToken.header.map(cell =>
typeof cell === "string" ? cell : parseTokens(cell.tokens || []), typeof cell === 'string' ? cell : parseTokens(cell.tokens || []),
)} )}
align={tableToken.align} align={tableToken.align}
rows={tableToken.rows.map((row) => rows={tableToken.rows.map(row =>
row.map((cell) => row.map(cell => (typeof cell === 'string' ? cell : parseTokens(cell.tokens || []))),
typeof cell === "string"
? cell
: parseTokens(cell.tokens || []),
),
)} )}
/>, />,
); );
break; break;
} }
case "html": case 'html':
output.push(<CustomHtmlBlock key={i} content={token.text} />); output.push(<CustomHtmlBlock key={i} content={token.text} />);
break; break;
case "def": case 'def':
case "space": case 'space':
break; break;
case "strong": case 'strong':
output.push( output.push(<CustomStrong key={i}>{parseTokens(token.tokens || [])}</CustomStrong>);
<CustomStrong key={i}>
{parseTokens(token.tokens || [])}
</CustomStrong>,
);
break; break;
case "em": case 'em':
output.push( output.push(
<CustomEm key={i}> <CustomEm key={i}>{token.tokens ? parseTokens(token.tokens) : token.text}</CustomEm>,
{token.tokens ? parseTokens(token.tokens) : token.text}
</CustomEm>,
); );
break; break;
case "codespan": case 'codespan':
output.push(<CustomCodeSpan key={i} code={token.text} />); output.push(<CustomCodeSpan key={i} code={token.text} />);
break; break;
case "link": case 'link':
output.push( output.push(
<CustomLink key={i} href={token.href} title={token.title}> <CustomLink key={i} href={token.href} title={token.title}>
{token.tokens ? parseTokens(token.tokens) : token.text} {token.tokens ? parseTokens(token.tokens) : token.text}
@@ -531,33 +457,24 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
case "image": case 'image':
output.push( output.push(
<CustomImage <CustomImage key={i} href={token.href} title={token.title} text={token.text} />,
key={i}
href={token.href}
title={token.title}
text={token.text}
/>,
); );
break; break;
case "text": { case 'text': {
const parsedContent = token.tokens const parsedContent = token.tokens ? parseTokens(token.tokens) : token.text;
? parseTokens(token.tokens)
: token.text;
if (blockquoteContent.length > 0) { if (blockquoteContent.length > 0) {
blockquoteContent.push( blockquoteContent.push(<React.Fragment key={i}>{parsedContent}</React.Fragment>);
<React.Fragment key={i}>{parsedContent}</React.Fragment>,
);
} else { } else {
output.push(<CustomText key={i} text={parsedContent} />); output.push(<CustomText key={i} text={parsedContent} />);
} }
break; break;
} }
default: default:
console.warn("Unhandled token type:", token.type, token); console.warn('Unhandled token type:', token.type, token);
} }
}); });

View File

@@ -1,13 +1,12 @@
import React from "react"; import React from 'react';
import {renderMessageMarkdown} from "./MessageMarkdown";
import { renderMessageMarkdown } from './MessageMarkdown';
interface CustomMarkdownRendererProps { interface CustomMarkdownRendererProps {
markdown: string; markdown: string;
} }
const MessageMarkdownRenderer: React.FC<CustomMarkdownRendererProps> = ({ const MessageMarkdownRenderer: React.FC<CustomMarkdownRendererProps> = ({ markdown }) => {
markdown,
}) => {
return <div>{renderMessageMarkdown(markdown)}</div>; return <div>{renderMessageMarkdown(markdown)}</div>;
}; };

View File

@@ -1,4 +1,4 @@
import {motion} from "framer-motion"; import { Box } from '@chakra-ui/react';
import {Box} from "@chakra-ui/react"; import { motion } from 'framer-motion';
export default motion(Box); export default motion(Box);

View File

@@ -1,6 +1,6 @@
import { observer } from "mobx-react-lite"; import { IconButton } from '@chakra-ui/react';
import { IconButton } from "@chakra-ui/react"; import { Edit2Icon } from 'lucide-react';
import { Edit2Icon } from "lucide-react"; import { observer } from 'mobx-react-lite';
const UserMessageTools = observer(({ disabled = false, message, onEdit }) => ( const UserMessageTools = observer(({ disabled = false, message, onEdit }) => (
<IconButton <IconButton
@@ -8,26 +8,26 @@ const UserMessageTools = observer(({ disabled = false, message, onEdit }) => (
color="text.primary" color="text.primary"
aria-label="Edit message" aria-label="Edit message"
title="Edit message" title="Edit message"
icon={<Edit2Icon size={"1em"} />} icon={<Edit2Icon size={'1em'} />}
onClick={() => onEdit(message)} onClick={() => onEdit(message)}
_active={{ _active={{
bg: "transparent", bg: 'transparent',
svg: { svg: {
stroke: "brand.100", stroke: 'brand.100',
transition: "stroke 0.3s ease-in-out", transition: 'stroke 0.3s ease-in-out',
}, },
}} }}
_hover={{ _hover={{
bg: "transparent", bg: 'transparent',
svg: { svg: {
stroke: "accent.secondary", stroke: 'accent.secondary',
transition: "stroke 0.3s ease-in-out", transition: 'stroke 0.3s ease-in-out',
}, },
}} }}
variant="ghost" variant="ghost"
size="sm" size="sm"
isDisabled={disabled} isDisabled={disabled}
_focus={{ boxShadow: "none" }} _focus={{ boxShadow: 'none' }}
/> />
)); ));

View File

@@ -1,8 +1,9 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react'; import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import React from 'react'; import React from 'react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import messageEditorStore from '../../../../stores/MessageEditorStore';
import MessageBubble from '../MessageBubble'; import MessageBubble from '../MessageBubble';
import messageEditorStore from "../../../../stores/MessageEditorStore";
// Mock browser APIs // Mock browser APIs
class MockResizeObserver { class MockResizeObserver {
@@ -18,7 +19,7 @@ global.ResizeObserver = MockResizeObserver;
vi.mock('../../../../models/Message', () => ({ vi.mock('../../../../models/Message', () => ({
default: { default: {
// This is needed for the Instance<typeof Message> type // This is needed for the Instance<typeof Message> type
} },
})); }));
// Mock the stores // Mock the stores
@@ -26,15 +27,15 @@ vi.mock('../../../../stores/ClientChatStore', () => ({
default: { default: {
items: [], items: [],
isLoading: false, isLoading: false,
editMessage: vi.fn().mockReturnValue(true) editMessage: vi.fn().mockReturnValue(true),
} },
})); }));
vi.mock('../../../../stores/UserOptionsStore', () => ({ vi.mock('../../../../stores/UserOptionsStore', () => ({
default: { default: {
followModeEnabled: false, followModeEnabled: false,
setFollowModeEnabled: vi.fn() setFollowModeEnabled: vi.fn(),
} },
})); }));
// Mock the MessageEditorStore // Mock the MessageEditorStore
@@ -48,13 +49,13 @@ vi.mock('../../../../stores/MessageEditorStore', () => ({
// Use the mocked messageEditorStore from the import // Use the mocked messageEditorStore from the import
messageEditorStore.onCancel(); messageEditorStore.onCancel();
return Promise.resolve(); return Promise.resolve();
}) }),
} },
})); }));
// Mock the MessageRenderer component // Mock the MessageRenderer component
vi.mock('../ChatMessageContent', () => ({ vi.mock('../ChatMessageContent', () => ({
default: ({ content }) => <div data-testid="message-content">{content}</div> default: ({ content }) => <div data-testid="message-content">{content}</div>,
})); }));
// Mock the UserMessageTools component // Mock the UserMessageTools component
@@ -63,30 +64,30 @@ vi.mock('../UserMessageTools', () => ({
<button data-testid="edit-button" onClick={() => onEdit(message)}> <button data-testid="edit-button" onClick={() => onEdit(message)}>
Edit Edit
</button> </button>
) ),
})); }));
vi.mock("../MotionBox", async (importOriginal) => { vi.mock('../MotionBox', async importOriginal => {
const actual = await importOriginal() const actual = await importOriginal();
return { default: { return {
default: {
...actual.default, ...actual.default,
div: (props: any) => React.createElement('div', props, props.children), div: (props: any) => React.createElement('div', props, props.children),
motion: (props: any) => React.createElement('div', props, props.children), motion: (props: any) => React.createElement('div', props, props.children),
},
} };
}
}); });
describe('MessageBubble', () => { describe('MessageBubble', () => {
const mockScrollRef = { current: { scrollTo: vi.fn() } }; const mockScrollRef = { current: { scrollTo: vi.fn() } };
const mockUserMessage = { const mockUserMessage = {
role: 'user', role: 'user',
content: 'Test message' content: 'Test message',
}; };
const mockAssistantMessage = { const mockAssistantMessage = {
role: 'assistant', role: 'assistant',
content: 'Assistant response' content: 'Assistant response',
}; };
beforeEach(() => { beforeEach(() => {

View File

@@ -1,18 +1,18 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent } from '@testing-library/react'; import { render, screen, fireEvent } from '@testing-library/react';
import React from 'react'; import React from 'react';
import MessageEditor from '../MessageEditorComponent'; import { describe, it, expect, vi, beforeEach } from 'vitest';
// Import the mocked stores // Import the mocked stores
import clientChatStore from '../../../../stores/ClientChatStore'; import clientChatStore from '../../../../stores/ClientChatStore';
import messageEditorStore from '../../../../stores/MessageEditorStore'; import messageEditorStore from '../../../../stores/MessageEditorStore';
import MessageEditor from '../MessageEditorComponent';
// Mock the Message model // Mock the Message model
vi.mock('../../../../models/Message', () => { vi.mock('../../../../models/Message', () => {
return { return {
default: { default: {
// This is needed for the Instance<typeof Message> type // This is needed for the Instance<typeof Message> type
} },
}; };
}); });
@@ -20,8 +20,8 @@ vi.mock('../../../../models/Message', () => {
globalThis.fetch = vi.fn(() => globalThis.fetch = vi.fn(() =>
Promise.resolve({ Promise.resolve({
ok: true, ok: true,
json: () => Promise.resolve({}) json: () => Promise.resolve({}),
}) }),
); );
// Mock the ClientChatStore // Mock the ClientChatStore
@@ -31,14 +31,14 @@ vi.mock('../../../../stores/ClientChatStore', () => {
removeAfter: vi.fn(), removeAfter: vi.fn(),
sendMessage: vi.fn(), sendMessage: vi.fn(),
setIsLoading: vi.fn(), setIsLoading: vi.fn(),
editMessage: vi.fn().mockReturnValue(true) editMessage: vi.fn().mockReturnValue(true),
}; };
// Add the mockUserMessage to the items array // Add the mockUserMessage to the items array
mockStore.items.indexOf = vi.fn().mockReturnValue(0); mockStore.items.indexOf = vi.fn().mockReturnValue(0);
return { return {
default: mockStore default: mockStore,
}; };
}); });
@@ -48,16 +48,16 @@ vi.mock('../../../../stores/MessageEditorStore', () => {
editedContent: 'Test message', // Set initial value to match the test expectation editedContent: 'Test message', // Set initial value to match the test expectation
message: null, message: null,
setEditedContent: vi.fn(), setEditedContent: vi.fn(),
setMessage: vi.fn((message) => { setMessage: vi.fn(message => {
mockStore.message = message; mockStore.message = message;
mockStore.editedContent = message.content; mockStore.editedContent = message.content;
}), }),
onCancel: vi.fn(), onCancel: vi.fn(),
handleSave: vi.fn() handleSave: vi.fn(),
}; };
return { return {
default: mockStore default: mockStore,
}; };
}); });
@@ -66,7 +66,7 @@ describe('MessageEditor', () => {
const mockUserMessage = { const mockUserMessage = {
content: 'Test message', content: 'Test message',
role: 'user', role: 'user',
setContent: vi.fn() setContent: vi.fn(),
}; };
const mockOnCancel = vi.fn(); const mockOnCancel = vi.fn();

View File

@@ -1,5 +1,6 @@
import React, { useState, useEffect, useCallback } from "react"; import React, { useState, useEffect, useCallback } from 'react';
import { buildCodeHighlighter } from "./CodeHighlighter";
import { buildCodeHighlighter } from './CodeHighlighter';
interface CodeBlockProps { interface CodeBlockProps {
language: string; language: string;
@@ -9,23 +10,19 @@ interface CodeBlockProps {
const highlighter = buildCodeHighlighter(); const highlighter = buildCodeHighlighter();
const CodeBlock: React.FC<CodeBlockProps> = ({ const CodeBlock: React.FC<CodeBlockProps> = ({ language, code, onRenderComplete }) => {
language, const [html, setHtml] = useState<string>('');
code,
onRenderComplete,
}) => {
const [html, setHtml] = useState<string>("");
const [loading, setLoading] = useState<boolean>(true); const [loading, setLoading] = useState<boolean>(true);
const highlightCode = useCallback(async () => { const highlightCode = useCallback(async () => {
try { try {
const highlighted = (await highlighter).codeToHtml(code, { const highlighted = (await highlighter).codeToHtml(code, {
lang: language, lang: language,
theme: "github-dark", theme: 'github-dark',
}); });
setHtml(highlighted); setHtml(highlighted);
} catch (error) { } catch (error) {
console.error("Error highlighting code:", error); console.error('Error highlighting code:', error);
setHtml(`<pre>${code}</pre>`); setHtml(`<pre>${code}</pre>`);
} finally { } finally {
setLoading(false); setLoading(false);
@@ -41,9 +38,9 @@ const CodeBlock: React.FC<CodeBlockProps> = ({
return ( return (
<div <div
style={{ style={{
backgroundColor: "#24292e", backgroundColor: '#24292e',
padding: "10px", padding: '10px',
borderRadius: "1.5em", borderRadius: '1.5em',
}} }}
> >
Loading code... Loading code...
@@ -55,12 +52,12 @@ const CodeBlock: React.FC<CodeBlockProps> = ({
<div <div
dangerouslySetInnerHTML={{ __html: html }} dangerouslySetInnerHTML={{ __html: html }}
style={{ style={{
transition: "none", transition: 'none',
padding: 20, padding: 20,
backgroundColor: "#24292e", backgroundColor: '#24292e',
overflowX: "auto", overflowX: 'auto',
borderRadius: ".37em", borderRadius: '.37em',
fontSize: ".75rem", fontSize: '.75rem',
}} }}
/> />
); );

View File

@@ -1,5 +1,6 @@
import { createHighlighterCore } from "shiki"; import { createHighlighterCore } from 'shiki';
/* eslint-disable import/no-unresolved */
export async function buildCodeHighlighter() { export async function buildCodeHighlighter() {
const [ const [
githubDark, githubDark,
@@ -23,26 +24,26 @@ export async function buildCodeHighlighter() {
zig, zig,
wasm, wasm,
] = await Promise.all([ ] = await Promise.all([
import("shiki/themes/github-dark.mjs"), import('shiki/themes/github-dark.mjs'),
import("shiki/langs/html.mjs"), import('shiki/langs/html.mjs'),
import("shiki/langs/javascript.mjs"), import('shiki/langs/javascript.mjs'),
import("shiki/langs/jsx.mjs"), import('shiki/langs/jsx.mjs'),
import("shiki/langs/typescript.mjs"), import('shiki/langs/typescript.mjs'),
import("shiki/langs/tsx.mjs"), import('shiki/langs/tsx.mjs'),
import("shiki/langs/go.mjs"), import('shiki/langs/go.mjs'),
import("shiki/langs/rust.mjs"), import('shiki/langs/rust.mjs'),
import("shiki/langs/python.mjs"), import('shiki/langs/python.mjs'),
import("shiki/langs/java.mjs"), import('shiki/langs/java.mjs'),
import("shiki/langs/kotlin.mjs"), import('shiki/langs/kotlin.mjs'),
import("shiki/langs/shell.mjs"), import('shiki/langs/shell.mjs'),
import("shiki/langs/sql.mjs"), import('shiki/langs/sql.mjs'),
import("shiki/langs/yaml.mjs"), import('shiki/langs/yaml.mjs'),
import("shiki/langs/toml.mjs"), import('shiki/langs/toml.mjs'),
import("shiki/langs/markdown.mjs"), import('shiki/langs/markdown.mjs'),
import("shiki/langs/json.mjs"), import('shiki/langs/json.mjs'),
import("shiki/langs/xml.mjs"), import('shiki/langs/xml.mjs'),
import("shiki/langs/zig.mjs"), import('shiki/langs/zig.mjs'),
import("shiki/wasm"), import('shiki/wasm'),
]); ]);
// Create the highlighter instance with the loaded themes and languages // Create the highlighter instance with the loaded themes and languages

View File

@@ -1,4 +1,3 @@
import React from "react";
import { import {
Alert, Alert,
AlertIcon, AlertIcon,
@@ -9,40 +8,41 @@ import {
Link, Link,
List, List,
ListItem, ListItem,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import { MarkdownEditor } from "./MarkdownEditor"; import React, { Fragment, useState } from 'react';
import { Fragment, useState } from "react";
import { MarkdownEditor } from './MarkdownEditor';
function ConnectComponent() { function ConnectComponent() {
const [formData, setFormData] = useState({ const [formData, setFormData] = useState({
markdown: "", markdown: '',
email: "", email: '',
firstname: "", firstname: '',
lastname: "", lastname: '',
}); });
const [isSubmitted, setIsSubmitted] = useState(false); const [isSubmitted, setIsSubmitted] = useState(false);
const [isError, setIsError] = useState(false); const [isError, setIsError] = useState(false);
const [validationError, setValidationError] = useState(""); const [validationError, setValidationError] = useState('');
const handleChange = (field: string) => (value: string) => { const handleChange = (field: string) => (value: string) => {
setFormData((prev) => ({ ...prev, [field]: value })); setFormData(prev => ({ ...prev, [field]: value }));
setIsSubmitted(false); setIsSubmitted(false);
setValidationError(""); setValidationError('');
}; };
const handleSubmitButton = async () => { const handleSubmitButton = async () => {
setValidationError(""); setValidationError('');
if (!formData.email || !formData.firstname || !formData.markdown) { if (!formData.email || !formData.firstname || !formData.markdown) {
setValidationError("Please fill in all required fields."); setValidationError('Please fill in all required fields.');
return; return;
} }
try { try {
const response = await fetch("/api/contact", { const response = await fetch('/api/contact', {
method: "POST", method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
body: JSON.stringify(formData), body: JSON.stringify(formData),
}); });
@@ -51,10 +51,10 @@ function ConnectComponent() {
setIsSubmitted(true); setIsSubmitted(true);
setIsError(false); setIsError(false);
setFormData({ setFormData({
markdown: "", markdown: '',
email: "", email: '',
firstname: "", firstname: '',
lastname: "", lastname: '',
}); });
} else { } else {
setIsError(true); setIsError(true);
@@ -68,7 +68,7 @@ function ConnectComponent() {
<Fragment> <Fragment>
<List color="text.primary" mb={4}> <List color="text.primary" mb={4}>
<ListItem> <ListItem>
Email:{" "} Email:{' '}
<Link href="mailto:geoff@seemueller.io" color="teal.500"> <Link href="mailto:geoff@seemueller.io" color="teal.500">
geoff@seemueller.io geoff@seemueller.io
</Link> </Link>
@@ -79,14 +79,14 @@ function ConnectComponent() {
<Input <Input
placeholder="First name *" placeholder="First name *"
value={formData.firstname} value={formData.firstname}
onChange={(e) => handleChange("firstname")(e.target.value)} onChange={e => handleChange('firstname')(e.target.value)}
color="text.primary" color="text.primary"
borderColor="text.primary" borderColor="text.primary"
/> />
<Input <Input
placeholder="Last name *" placeholder="Last name *"
value={formData.lastname} value={formData.lastname}
onChange={(e) => handleChange("lastname")(e.target.value)} onChange={e => handleChange('lastname')(e.target.value)}
color="text.primary" color="text.primary"
borderColor="text.primary" borderColor="text.primary"
// bg="text.primary" // bg="text.primary"
@@ -95,13 +95,13 @@ function ConnectComponent() {
<Input <Input
placeholder="Email *" placeholder="Email *"
value={formData.email} value={formData.email}
onChange={(e) => handleChange("email")(e.target.value)} onChange={e => handleChange('email')(e.target.value)}
mb={4} mb={4}
borderColor="text.primary" borderColor="text.primary"
color="text.primary" color="text.primary"
/> />
<MarkdownEditor <MarkdownEditor
onChange={handleChange("markdown")} onChange={handleChange('markdown')}
markdown={formData.markdown} markdown={formData.markdown}
placeholder="Your Message..." placeholder="Your Message..."
/> />
@@ -116,47 +116,32 @@ function ConnectComponent() {
mb={4} mb={4}
float="right" float="right"
_hover={{ _hover={{
bg: "", bg: '',
transform: "scale(1.05)", transform: 'scale(1.05)',
}} }}
_active={{ _active={{
bg: "gray.800", bg: 'gray.800',
transform: "scale(1)", transform: 'scale(1)',
}} }}
> >
SEND SEND
</Button> </Button>
<Box mt={12}> <Box mt={12}>
{isSubmitted && ( {isSubmitted && (
<Alert <Alert status="success" borderRadius="md" color="text.primary" bg="green.500">
status="success"
borderRadius="md"
color="text.primary"
bg="green.500"
>
<AlertIcon /> <AlertIcon />
Message sent successfully! Message sent successfully!
</Alert> </Alert>
)} )}
{isError && ( {isError && (
<Alert <Alert status="error" borderRadius="md" color="text.primary" bg="red.500">
status="error"
borderRadius="md"
color="text.primary"
bg="red.500"
>
<AlertIcon /> <AlertIcon />
There was an error sending your message. Please try again. There was an error sending your message. Please try again.
</Alert> </Alert>
)} )}
{validationError && ( {validationError && (
<Alert <Alert status="warning" borderRadius="md" color="background.primary" bg="yellow.500">
status="warning"
borderRadius="md"
color="background.primary"
bg="yellow.500"
>
<AlertIcon /> <AlertIcon />
{validationError} {validationError}
</Alert> </Alert>

View File

@@ -1,5 +1,5 @@
import React from "react"; import { Box, Textarea } from '@chakra-ui/react';
import { Box, Textarea } from "@chakra-ui/react"; import React from 'react';
export const MarkdownEditor = (props: { export const MarkdownEditor = (props: {
placeholder: string; placeholder: string;
@@ -11,7 +11,7 @@ export const MarkdownEditor = (props: {
<Textarea <Textarea
value={props.markdown} value={props.markdown}
placeholder={props.placeholder} placeholder={props.placeholder}
onChange={(e) => props.onChange(e.target.value)} onChange={e => props.onChange(e.target.value)}
width="100%" width="100%"
minHeight="150px" minHeight="150px"
height="100%" height="100%"

View File

@@ -1,13 +1,9 @@
import { import { ChakraProvider, cookieStorageManagerSSR, localStorageManager } from '@chakra-ui/react';
ChakraProvider,
cookieStorageManagerSSR,
localStorageManager,
} from "@chakra-ui/react";
export function Chakra({ cookies, children, theme }) { export function Chakra({ cookies, children, theme }) {
const colorModeManager = const colorModeManager =
typeof cookies === "string" typeof cookies === 'string'
? cookieStorageManagerSSR("color_state", cookies) ? cookieStorageManagerSSR('color_state', cookies)
: localStorageManager; : localStorageManager;
return ( return (

View File

@@ -1,5 +1,5 @@
import React, { createContext, useContext, useState, useEffect } from "react"; import { useMediaQuery } from '@chakra-ui/react';
import { useMediaQuery } from "@chakra-ui/react"; import React, { createContext, useContext, useState, useEffect } from 'react';
// Create the context to provide mobile state // Create the context to provide mobile state
const MobileContext = createContext(false); const MobileContext = createContext(false);
@@ -7,12 +7,11 @@ const MobileContext = createContext(false);
// Create a provider component to wrap your app // Create a provider component to wrap your app
export const MobileProvider = ({ children }: { children: React.ReactNode }) => { export const MobileProvider = ({ children }: { children: React.ReactNode }) => {
const [isMobile, setIsMobile] = useState(false); const [isMobile, setIsMobile] = useState(false);
const [isFallbackMobile] = useMediaQuery("(max-width: 768px)"); const [isFallbackMobile] = useMediaQuery('(max-width: 768px)');
useEffect(() => { useEffect(() => {
const userAgent = navigator.userAgent || navigator.vendor || window.opera; const userAgent = navigator.userAgent || navigator.vendor || window.opera;
const mobile = const mobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
userAgent.toLowerCase(), userAgent.toLowerCase(),
); );
setIsMobile(mobile); setIsMobile(mobile);
@@ -21,11 +20,7 @@ export const MobileProvider = ({ children }: { children: React.ReactNode }) => {
// Provide the combined mobile state globally // Provide the combined mobile state globally
const mobileState = isMobile || isFallbackMobile; const mobileState = isMobile || isFallbackMobile;
return ( return <MobileContext.Provider value={mobileState}>{children}</MobileContext.Provider>;
<MobileContext.Provider value={mobileState}>
{children}
</MobileContext.Provider>
);
}; };
// Custom hook to use the mobile context in any component // Custom hook to use the mobile context in any component

View File

@@ -1,5 +1,5 @@
import React from "react"; import { Badge, Box, Flex, Heading, Image, Text } from '@chakra-ui/react';
import { Badge, Box, Flex, Heading, Image, Text } from "@chakra-ui/react"; import React from 'react';
function DemoCard({ icon, title, description, imageUrl, badge, onClick }) { function DemoCard({ icon, title, description, imageUrl, badge, onClick }) {
return ( return (
@@ -9,15 +9,15 @@ function DemoCard({ icon, title, description, imageUrl, badge, onClick }) {
overflowY="hidden" overflowY="hidden"
boxShadow="md" boxShadow="md"
transition="transform 0.2s" transition="transform 0.2s"
_hover={{ transform: "scale(1.05)", cursor: "pointer" }} _hover={{ transform: 'scale(1.05)', cursor: 'pointer' }}
color="text.primary" color="text.primary"
onClick={onClick} onClick={onClick}
display="flex" display="flex"
flexDirection="column" flexDirection="column"
minW={"12rem"} minW={'12rem'}
maxW={"18rem"} maxW={'18rem'}
minH={"35rem"} minH={'35rem'}
maxH={"20rem"} maxH={'20rem'}
> >
{imageUrl && ( {imageUrl && (
<Image <Image
@@ -42,7 +42,7 @@ function DemoCard({ icon, title, description, imageUrl, badge, onClick }) {
</Flex> </Flex>
{badge && ( {badge && (
<Box p={2}> <Box p={2}>
<Badge colorScheme={"teal"}>{badge}</Badge> <Badge colorScheme={'teal'}>{badge}</Badge>
</Box> </Box>
)} )}
</Box> </Box>

View File

@@ -1,16 +1,12 @@
import React from "react"; import { SimpleGrid } from '@chakra-ui/react';
import { SimpleGrid } from "@chakra-ui/react"; import { Rocket, Shield } from 'lucide-react';
import { Rocket, Shield } from "lucide-react"; import React from 'react';
import DemoCard from "./DemoCard";
import DemoCard from './DemoCard';
function DemoComponent() { function DemoComponent() {
return ( return (
<SimpleGrid <SimpleGrid columns={{ base: 1, sm: 1, lg: 2 }} spacing={'7%'} minH={'min-content'} h={'100vh'}>
columns={{ base: 1, sm: 1, lg: 2 }}
spacing={"7%"}
minH={"min-content"}
h={"100vh"}
>
<DemoCard <DemoCard
icon={<Rocket size={24} color="teal" />} icon={<Rocket size={24} color="teal" />}
title="toak" title="toak"
@@ -18,7 +14,7 @@ function DemoComponent() {
imageUrl="/code-tokenizer-md.jpg" imageUrl="/code-tokenizer-md.jpg"
badge="npm" badge="npm"
onClick={() => { onClick={() => {
window.open("https://github.com/seemueller-io/toak"); window.open('https://github.com/seemueller-io/toak');
}} }}
/> />
<DemoCard <DemoCard
@@ -28,7 +24,7 @@ function DemoComponent() {
imageUrl="/rehoboam.png" imageUrl="/rehoboam.png"
badge="APP" badge="APP"
onClick={() => { onClick={() => {
window.open("https://rehoboam.seemueller.io"); window.open('https://rehoboam.seemueller.io');
}} }}
/> />
</SimpleGrid> </SimpleGrid>

View File

@@ -1,4 +1,3 @@
import React from "react";
import { import {
Box, Box,
Button, Button,
@@ -14,9 +13,11 @@ import {
Textarea, Textarea,
useToast, useToast,
VStack, VStack,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import { observer } from "mobx-react-lite"; import { observer } from 'mobx-react-lite';
import feedbackState from "../../stores/ClientFeedbackStore"; import React from 'react';
import feedbackState from '../../stores/ClientFeedbackStore';
const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => { const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => {
const toast = useToast(); const toast = useToast();
@@ -26,9 +27,9 @@ const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => {
if (success) { if (success) {
toast({ toast({
title: "Feedback Submitted", title: 'Feedback Submitted',
description: "Thank you for your feedback!", description: 'Thank you for your feedback!',
status: "success", status: 'success',
duration: 3000, duration: 3000,
isClosable: true, isClosable: true,
}); });
@@ -40,9 +41,9 @@ const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => {
} }
toast({ toast({
title: "Submission Failed", title: 'Submission Failed',
description: feedbackState.error, description: feedbackState.error,
status: "error", status: 'error',
duration: 3000, duration: 3000,
isClosable: true, isClosable: true,
}); });
@@ -78,7 +79,7 @@ const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => {
<Textarea <Textarea
placeholder="Type your feedback here..." placeholder="Type your feedback here..."
value={feedbackState.input} value={feedbackState.input}
onChange={(e) => feedbackState.setInput(e.target.value)} onChange={e => feedbackState.setInput(e.target.value)}
bg="gray.700" bg="gray.700"
color="white" color="white"
minHeight="120px" minHeight="120px"
@@ -89,7 +90,7 @@ const FeedbackModal = observer(({ isOpen, onClose, zIndex }) => {
bottom="2" bottom="2"
right="2" right="2"
fontSize="xs" fontSize="xs"
color={charactersRemaining < 50 ? "orange.300" : "gray.400"} color={charactersRemaining < 50 ? 'orange.300' : 'gray.400'}
> >
{charactersRemaining} characters remaining {charactersRemaining} characters remaining
</Text> </Text>

View File

@@ -1,14 +1,14 @@
import React from "react"; import { Box } from '@chakra-ui/react';
import { Box } from "@chakra-ui/react"; import React from 'react';
const TealDogecoinIcon = (props) => ( const TealDogecoinIcon = props => (
<Box <Box
as="svg" as="svg"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24" viewBox="0 0 24 24"
stroke={"currentColor"} stroke={'currentColor'}
fill="currentColor" fill="currentColor"
boxSize={props.boxSize || "1em"} boxSize={props.boxSize || '1em'}
{...props} {...props}
> >
<path <path

View File

@@ -1,17 +1,13 @@
import React from "react"; import { Box, VStack } from '@chakra-ui/react';
import { Box, VStack } from "@chakra-ui/react"; import React from 'react';
import {renderMarkdown} from "../markdown/MarkdownComponent";
import { renderMarkdown } from '../markdown/MarkdownComponent';
function LegalDoc({ text }) { function LegalDoc({ text }) {
return ( return (
<Box maxWidth="800px" margin="0 auto"> <Box maxWidth="800px" margin="0 auto">
<VStack spacing={6} align="stretch"> <VStack spacing={6} align="stretch">
<Box <Box color="text.primary" wordBreak="break-word" whiteSpace="pre-wrap" spacing={4}>
color="text.primary"
wordBreak="break-word"
whiteSpace="pre-wrap"
spacing={4}
>
{renderMarkdown(text)} {renderMarkdown(text)}
</Box> </Box>
</VStack> </VStack>

View File

@@ -1,21 +1,16 @@
import React, { useState, useEffect } from "react"; import { Image, Box, Spinner, Text, Flex } from '@chakra-ui/react';
import { Image, Box, Spinner, Text, Flex } from "@chakra-ui/react"; import { keyframes } from '@emotion/react';
import { keyframes } from "@emotion/react"; import React, { useState, useEffect } from 'react';
const shimmer = keyframes` const shimmer = keyframes`
0% { background-position: -100% 0; } 0% { background-position: -100% 0; }
100% { background-position: 100% 0; } 100% { background-position: 100% 0; }
`; `;
const ImageWithFallback = ({ const ImageWithFallback = ({ alt, src, fallbackSrc = '/fallback.png', ...props }) => {
alt,
src,
fallbackSrc = "/fallback.png",
...props
}) => {
const [isLoading, setIsLoading] = useState(true); const [isLoading, setIsLoading] = useState(true);
const [scrollPosition, setScrollPosition] = useState(0); const [scrollPosition, setScrollPosition] = useState(0);
const isSlowLoadingSource = src.includes("text2image.seemueller.io"); const isSlowLoadingSource = src.includes('text2image.seemueller.io');
const handleImageLoad = () => setIsLoading(false); const handleImageLoad = () => setIsLoading(false);
const handleImageError = () => { const handleImageError = () => {
@@ -33,24 +28,17 @@ const ImageWithFallback = ({
setScrollPosition(scrolled); setScrollPosition(scrolled);
}; };
window.addEventListener("scroll", handleScroll); window.addEventListener('scroll', handleScroll);
return () => { return () => {
window.removeEventListener("scroll", handleScroll); window.removeEventListener('scroll', handleScroll);
}; };
}, []); }, []);
const parallaxOffset = scrollPosition * 0.2; const parallaxOffset = scrollPosition * 0.2;
return ( return (
<Box <Box position="relative" w="full" maxW="full" borderRadius="md" my={2} overflow="hidden">
position="relative"
w="full"
maxW="full"
borderRadius="md"
my={2}
overflow="hidden"
>
{isLoading && isSlowLoadingSource && ( {isLoading && isSlowLoadingSource && (
<Flex <Flex
align="center" align="center"
@@ -76,7 +64,7 @@ const ImageWithFallback = ({
fallbackSrc={fallbackSrc} fallbackSrc={fallbackSrc}
onLoad={handleImageLoad} onLoad={handleImageLoad}
onError={handleImageError} onError={handleImageError}
display={isLoading ? "none" : "block"} display={isLoading ? 'none' : 'block'}
transform={`translateY(${parallaxOffset}px)`} transform={`translateY(${parallaxOffset}px)`}
transition="transform 0.1s ease-out" transition="transform 0.1s ease-out"
{...props} {...props}

View File

@@ -1,5 +1,3 @@
import React from "react";
import { import {
Box, Box,
Code, Code,
@@ -17,13 +15,15 @@ import {
Thead, Thead,
Tr, Tr,
useColorModeValue, useColorModeValue,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import {marked} from "marked"; import katex from 'katex';
import { marked } from 'marked';
import markedKatex from 'marked-katex-extension';
import React from 'react';
import markedKatex from "marked-katex-extension"; import CodeBlock from '../code/CodeBlock';
import katex from "katex";
import CodeBlock from "../code/CodeBlock"; import ImageWithFallback from './ImageWithFallback';
import ImageWithFallback from "./ImageWithFallback";
try { try {
if (localStorage) { if (localStorage) {
@@ -34,11 +34,12 @@ try {
throwOnError: false, throwOnError: false,
strict: true, strict: true,
colorIsTextColor: true, colorIsTextColor: true,
errorColor: "red", errorColor: 'red',
}), }),
); );
} }
} catch (_) { } catch (_) {
// Silently ignore errors in marked setup - fallback to default behavior
} }
const MemoizedCodeBlock = React.memo(CodeBlock); const MemoizedCodeBlock = React.memo(CodeBlock);
@@ -46,64 +47,46 @@ const MemoizedCodeBlock = React.memo(CodeBlock);
const getHeadingProps = (depth: number) => { const getHeadingProps = (depth: number) => {
switch (depth) { switch (depth) {
case 1: case 1:
return {as: "h1", size: "xl", mt: 4, mb: 2}; return { as: 'h1', size: 'xl', mt: 4, mb: 2 };
case 2: case 2:
return {as: "h2", size: "lg", mt: 3, mb: 2}; return { as: 'h2', size: 'lg', mt: 3, mb: 2 };
case 3: case 3:
return {as: "h3", size: "md", mt: 2, mb: 1}; return { as: 'h3', size: 'md', mt: 2, mb: 1 };
case 4: case 4:
return {as: "h4", size: "sm", mt: 2, mb: 1}; return { as: 'h4', size: 'sm', mt: 2, mb: 1 };
case 5: case 5:
return {as: "h5", size: "sm", mt: 2, mb: 1}; return { as: 'h5', size: 'sm', mt: 2, mb: 1 };
case 6: case 6:
return {as: "h6", size: "xs", mt: 2, mb: 1}; return { as: 'h6', size: 'xs', mt: 2, mb: 1 };
default: default:
return {as: `h${depth}`, size: "md", mt: 2, mb: 1}; return { as: `h${depth}`, size: 'md', mt: 2, mb: 1 };
} }
}; };
interface TableToken extends marked.Tokens.Table { interface TableToken extends marked.Tokens.Table {
align: Array<"center" | "left" | "right" | null>; align: Array<'center' | 'left' | 'right' | null>;
header: (string | marked.Tokens.TableCell)[]; header: (string | marked.Tokens.TableCell)[];
rows: (string | marked.Tokens.TableCell)[][]; rows: (string | marked.Tokens.TableCell)[][];
} }
const CustomHeading: React.FC<{ text: string; depth: number }> = ({ const CustomHeading: React.FC<{ text: string; depth: number }> = ({ text, depth }) => {
text,
depth,
}) => {
const headingProps = getHeadingProps(depth); const headingProps = getHeadingProps(depth);
return ( return (
<Heading <Heading {...headingProps} wordBreak="break-word" maxWidth="100%" color="text.accent">
{...headingProps}
wordBreak="break-word"
maxWidth="100%"
color="text.accent"
>
{text} {text}
</Heading> </Heading>
); );
}; };
const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ children }) => {
children,
}) => {
return ( return (
<Text <Text as="p" fontSize="sm" lineHeight="short" wordBreak="break-word" maxWidth="100%">
as="p"
fontSize="sm"
lineHeight="short"
wordBreak="break-word"
maxWidth="100%"
>
{children} {children}
</Text> </Text>
); );
}; };
const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ children }) => {
children,
}) => {
return ( return (
<Box <Box
as="blockquote" as="blockquote"
@@ -121,16 +104,9 @@ const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({
); );
}; };
const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ code, language }) => {
code,
language,
}) => {
return ( return (
<MemoizedCodeBlock <MemoizedCodeBlock language={language} code={code} onRenderComplete={() => Promise.resolve()} />
language={language}
code={code}
onRenderComplete={() => Promise.resolve()}
/>
); );
}; };
@@ -142,10 +118,10 @@ const CustomList: React.FC<{
children: React.ReactNode; children: React.ReactNode;
}> = ({ ordered, start, children }) => { }> = ({ ordered, start, children }) => {
const commonStyles = { const commonStyles = {
fontSize: "sm", fontSize: 'sm',
wordBreak: "break-word" as const, wordBreak: 'break-word' as const,
maxWidth: "100%" as const, maxWidth: '100%' as const,
stylePosition: "outside" as const, stylePosition: 'outside' as const,
mb: 2, mb: 2,
pl: 4, pl: 4,
}; };
@@ -167,16 +143,13 @@ const CustomListItem: React.FC<{
return <ListItem mb={1}>{children}</ListItem>; return <ListItem mb={1}>{children}</ListItem>;
}; };
const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({ math, displayMode }) => {
math,
displayMode,
}) => {
const renderedMath = katex.renderToString(math, { displayMode }); const renderedMath = katex.renderToString(math, { displayMode });
return ( return (
<Box <Box
as="span" as="span"
display={displayMode ? "block" : "inline"} display={displayMode ? 'block' : 'inline'}
// bg={bg} // bg={bg}
p={displayMode ? 4 : 1} p={displayMode ? 4 : 1}
my={displayMode ? 4 : 0} my={displayMode ? 4 : 0}
@@ -190,23 +163,17 @@ const CustomKatex: React.FC<{ math: string; displayMode: boolean }> = ({
const CustomTable: React.FC<{ const CustomTable: React.FC<{
header: React.ReactNode[]; header: React.ReactNode[];
align: Array<"center" | "left" | "right" | null>; align: Array<'center' | 'left' | 'right' | null>;
rows: React.ReactNode[][]; rows: React.ReactNode[][];
}> = ({ header, align, rows }) => { }> = ({ header, align, rows }) => {
return ( return (
<Table <Table variant="simple" size="sm" my={4} borderRadius="md" overflow="hidden">
variant="simple"
size="sm"
my={4}
borderRadius="md"
overflow="hidden"
>
<Thead bg="background.secondary"> <Thead bg="background.secondary">
<Tr> <Tr>
{header.map((cell, i) => ( {header.map((cell, i) => (
<Th <Th
key={i} key={i}
textAlign={align[i] || "left"} textAlign={align[i] || 'left'}
fontWeight="bold" fontWeight="bold"
p={2} p={2}
minW={16} minW={16}
@@ -221,12 +188,7 @@ const CustomTable: React.FC<{
{rows.map((row, rIndex) => ( {rows.map((row, rIndex) => (
<Tr key={rIndex}> <Tr key={rIndex}>
{row.map((cell, cIndex) => ( {row.map((cell, cIndex) => (
<Td <Td key={cIndex} textAlign={align[cIndex] || 'left'} p={2} wordBreak="break-word">
key={cIndex}
textAlign={align[cIndex] || "left"}
p={2}
wordBreak="break-word"
>
{cell} {cell}
</Td> </Td>
))} ))}
@@ -266,13 +228,7 @@ const CustomStrong: React.FC<CustomStrongProps> = ({children}) => {
const CustomEm: React.FC<{ children: React.ReactNode }> = ({ children }) => { const CustomEm: React.FC<{ children: React.ReactNode }> = ({ children }) => {
return ( return (
<Text <Text as="em" fontStyle="italic" lineHeight="short" wordBreak="break-word" display="inline">
as="em"
fontStyle="italic"
lineHeight="short"
wordBreak="break-word"
display="inline"
>
{children} {children}
</Text> </Text>
); );
@@ -293,7 +249,7 @@ const CustomDel: React.FC<{ text: string }> = ({text}) => {
}; };
const CustomCodeSpan: React.FC<{ code: string }> = ({ code }) => { const CustomCodeSpan: React.FC<{ code: string }> = ({ code }) => {
const bg = useColorModeValue("gray.100", "gray.800"); const bg = useColorModeValue('gray.100', 'gray.800');
return ( return (
<Code <Code
fontSize="sm" fontSize="sm"
@@ -316,13 +272,13 @@ const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({
return ( return (
<Box <Box
as="span" as="span"
display={displayMode ? "block" : "inline"} display={displayMode ? 'block' : 'inline'}
p={displayMode ? 4 : 1} p={displayMode ? 4 : 1}
my={displayMode ? 4 : 0} my={displayMode ? 4 : 0}
borderRadius="md" borderRadius="md"
overflow="auto" overflow="auto"
maxWidth="100%" maxWidth="100%"
className={`math ${displayMode ? "math-display" : "math-inline"}`} className={`math ${displayMode ? 'math-display' : 'math-inline'}`}
> >
{math} {math}
</Box> </Box>
@@ -340,8 +296,8 @@ const CustomLink: React.FC<{
title={title} title={title}
isExternal isExternal
sx={{ sx={{
"& span": { '& span': {
color: "text.link", color: 'text.link',
}, },
}} }}
maxWidth="100%" maxWidth="100%"
@@ -378,46 +334,34 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
tokens.forEach((token, i) => { tokens.forEach((token, i) => {
switch (token.type) { switch (token.type) {
case "heading": case 'heading':
output.push( output.push(<CustomHeading key={i} text={token.text} depth={token.depth} />);
<CustomHeading key={i} text={token.text} depth={token.depth}/>,
);
break; break;
case "paragraph": { case 'paragraph': {
const parsedContent = token.tokens const parsedContent = token.tokens ? parseTokens(token.tokens) : token.text;
? parseTokens(token.tokens)
: token.text;
if (blockquoteContent.length > 0) { if (blockquoteContent.length > 0) {
blockquoteContent.push( blockquoteContent.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
);
} else { } else {
output.push( output.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
);
} }
break; break;
} }
case "br": case 'br':
output.push(<br key={i} />); output.push(<br key={i} />);
break; break;
case "escape": { case 'escape': {
break; break;
} }
case "blockquote_start": case 'blockquote_start':
blockquoteContent = []; blockquoteContent = [];
break; break;
case "blockquote_end": case 'blockquote_end':
output.push( output.push(<CustomBlockquote key={i}>{parseTokens(blockquoteContent)}</CustomBlockquote>);
<CustomBlockquote key={i}>
{parseTokens(blockquoteContent)}
</CustomBlockquote>,
);
blockquoteContent = []; blockquoteContent = [];
break; break;
case "blockquote": { case 'blockquote': {
output.push( output.push(
<CustomBlockquote key={i}> <CustomBlockquote key={i}>
{token.tokens ? parseTokens(token.tokens) : null} {token.tokens ? parseTokens(token.tokens) : null}
@@ -425,43 +369,29 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
} }
case "math": case 'math':
output.push( output.push(<CustomMath key={i} math={(token as any).value} displayMode={true} />);
<CustomMath key={i} math={(token as any).value} displayMode={true}/>,
);
break; break;
case "inlineMath": case 'inlineMath':
output.push( output.push(<CustomMath key={i} math={(token as any).value} displayMode={false} />);
<CustomMath
key={i}
math={(token as any).value}
displayMode={false}
/>,
);
break; break;
case "inlineKatex": case 'inlineKatex':
case "blockKatex": { case 'blockKatex': {
const katexToken = token as any; const katexToken = token as any;
output.push( output.push(
<CustomKatex <CustomKatex key={i} math={katexToken.text} displayMode={katexToken.displayMode} />,
key={i}
math={katexToken.text}
displayMode={katexToken.displayMode}
/>,
); );
break; break;
} }
case "code": case 'code':
output.push( output.push(<CustomCodeBlock key={i} code={token.text} language={token.lang} />);
<CustomCodeBlock key={i} code={token.text} language={token.lang}/>,
);
break; break;
case "hr": case 'hr':
output.push(<CustomHr key={i} />); output.push(<CustomHr key={i} />);
break; break;
case "list": { case 'list': {
const { ordered, start, items } = token; const { ordered, start, items } = token;
const listItems = items.map((listItem, idx) => { const listItems = items.map((listItem, idx) => {
const nestedContent = parseTokens(listItem.tokens); const nestedContent = parseTokens(listItem.tokens);
@@ -475,53 +405,43 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
} }
case "table": { case 'table': {
const tableToken = token as TableToken; const tableToken = token as TableToken;
output.push( output.push(
<CustomTable <CustomTable
key={i} key={i}
header={tableToken.header.map((cell) => header={tableToken.header.map(cell =>
typeof cell === "string" ? cell : parseTokens(cell.tokens || []), typeof cell === 'string' ? cell : parseTokens(cell.tokens || []),
)} )}
align={tableToken.align} align={tableToken.align}
rows={tableToken.rows.map((row) => rows={tableToken.rows.map(row =>
row.map((cell) => row.map(cell => (typeof cell === 'string' ? cell : parseTokens(cell.tokens || []))),
typeof cell === "string"
? cell
: parseTokens(cell.tokens || []),
),
)} )}
/>, />,
); );
break; break;
} }
case "html": case 'html':
output.push(<CustomHtmlBlock key={i} content={token.text} />); output.push(<CustomHtmlBlock key={i} content={token.text} />);
break; break;
case "def": case 'def':
case "space": case 'space':
break; break;
case "strong": case 'strong':
output.push( output.push(<CustomStrong key={i}>{parseTokens(token.tokens || [])}</CustomStrong>);
<CustomStrong key={i}>
{parseTokens(token.tokens || [])}
</CustomStrong>,
);
break; break;
case "em": case 'em':
output.push( output.push(
<CustomEm key={i}> <CustomEm key={i}>{token.tokens ? parseTokens(token.tokens) : token.text}</CustomEm>,
{token.tokens ? parseTokens(token.tokens) : token.text}
</CustomEm>,
); );
break; break;
case "codespan": case 'codespan':
output.push(<CustomCodeSpan key={i} code={token.text} />); output.push(<CustomCodeSpan key={i} code={token.text} />);
break; break;
case "link": case 'link':
output.push( output.push(
<CustomLink key={i} href={token.href} title={token.title}> <CustomLink key={i} href={token.href} title={token.title}>
{token.tokens ? parseTokens(token.tokens) : token.text} {token.tokens ? parseTokens(token.tokens) : token.text}
@@ -529,26 +449,17 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
); );
break; break;
case "image": case 'image':
output.push( output.push(
<CustomImage <CustomImage key={i} href={token.href} title={token.title} text={token.text} />,
key={i}
href={token.href}
title={token.title}
text={token.text}
/>,
); );
break; break;
case "text": { case 'text': {
const parsedContent = token.tokens const parsedContent = token.tokens ? parseTokens(token.tokens) : token.text;
? parseTokens(token.tokens)
: token.text;
if (blockquoteContent.length > 0) { if (blockquoteContent.length > 0) {
blockquoteContent.push( blockquoteContent.push(<React.Fragment key={i}>{parsedContent}</React.Fragment>);
<React.Fragment key={i}>{parsedContent}</React.Fragment>,
);
} else { } else {
output.push(<CustomText key={i} text={parsedContent} />); output.push(<CustomText key={i} text={parsedContent} />);
} }
@@ -556,7 +467,7 @@ function parseTokens(tokens: marked.Token[]): JSX.Element[] {
} }
default: default:
console.warn("Unhandled token type:", token.type, token); console.warn('Unhandled token type:', token.type, token);
} }
}); });

View File

@@ -1,7 +1,8 @@
import React from "react"; import { IconButton } from '@chakra-ui/react';
import { IconButton } from "@chakra-ui/react"; import { Github } from 'lucide-react';
import { Github } from "lucide-react"; import React from 'react';
import { toolbarButtonZIndex } from "./Toolbar";
import { toolbarButtonZIndex } from './Toolbar';
export default function GithubButton() { export default function GithubButton() {
return ( return (
@@ -16,10 +17,10 @@ export default function GithubButton() {
stroke="text.accent" stroke="text.accent"
color="text.accent" color="text.accent"
_hover={{ _hover={{
bg: "transparent", bg: 'transparent',
svg: { svg: {
stroke: "accent.secondary", stroke: 'accent.secondary',
transition: "stroke 0.3s ease-in-out", transition: 'stroke 0.3s ease-in-out',
}, },
}} }}
title="GitHub" title="GitHub"

View File

@@ -1,8 +1,9 @@
import React from "react"; import { IconButton, useDisclosure } from '@chakra-ui/react';
import { IconButton, useDisclosure } from "@chakra-ui/react"; import { LucideHeart } from 'lucide-react';
import { LucideHeart } from "lucide-react"; import React from 'react';
import { toolbarButtonZIndex } from "./Toolbar";
import SupportThisSiteModal from "./SupportThisSiteModal"; import SupportThisSiteModal from './SupportThisSiteModal';
import { toolbarButtonZIndex } from './Toolbar';
export default function SupportThisSiteButton() { export default function SupportThisSiteButton() {
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
@@ -18,10 +19,10 @@ export default function SupportThisSiteButton() {
stroke="text.accent" stroke="text.accent"
bg="transparent" bg="transparent"
_hover={{ _hover={{
bg: "transparent", bg: 'transparent',
svg: { svg: {
stroke: "accent.danger", stroke: 'accent.danger',
transition: "stroke 0.3s ease-in-out", transition: 'stroke 0.3s ease-in-out',
}, },
}} }}
title="Support" title="Support"
@@ -29,9 +30,9 @@ export default function SupportThisSiteButton() {
zIndex={toolbarButtonZIndex} zIndex={toolbarButtonZIndex}
sx={{ sx={{
svg: { svg: {
stroke: "text.accent", stroke: 'text.accent',
strokeWidth: "2px", strokeWidth: '2px',
transition: "stroke 0.2s ease-in-out", transition: 'stroke 0.2s ease-in-out',
}, },
}} }}
/> />

View File

@@ -1,4 +1,3 @@
import React from "react";
import { import {
Box, Box,
Button, Button,
@@ -19,26 +18,26 @@ import {
useClipboard, useClipboard,
useToast, useToast,
VStack, VStack,
} from "@chakra-ui/react"; } from '@chakra-ui/react';
import { QRCodeCanvas } from "qrcode.react"; import { observer } from 'mobx-react-lite';
import { FaBitcoin, FaEthereum } from "react-icons/fa"; import { QRCodeCanvas } from 'qrcode.react';
import { observer } from "mobx-react-lite"; import React from 'react';
import clientTransactionStore from "../../stores/ClientTransactionStore"; import { FaBitcoin, FaEthereum } from 'react-icons/fa';
import DogecoinIcon from "../icons/DogecoinIcon";
import clientTransactionStore from '../../stores/ClientTransactionStore';
import DogecoinIcon from '../icons/DogecoinIcon';
const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => { const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
const { hasCopied, onCopy } = useClipboard( const { hasCopied, onCopy } = useClipboard(clientTransactionStore.depositAddress || '');
clientTransactionStore.depositAddress || "",
);
const toast = useToast(); const toast = useToast();
const handleCopy = () => { const handleCopy = () => {
if (clientTransactionStore.depositAddress) { if (clientTransactionStore.depositAddress) {
onCopy(); onCopy();
toast({ toast({
title: "Address Copied!", title: 'Address Copied!',
description: "Thank you for your support!", description: 'Thank you for your support!',
status: "success", status: 'success',
duration: 3000, duration: 3000,
isClosable: true, isClosable: true,
}); });
@@ -49,17 +48,17 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
try { try {
await clientTransactionStore.prepareTransaction(); await clientTransactionStore.prepareTransaction();
toast({ toast({
title: "Success", title: 'Success',
description: `Use your wallet app (Coinbase, ...ect) to send the selected asset to the provided address.`, description: `Use your wallet app (Coinbase, ...ect) to send the selected asset to the provided address.`,
status: "success", status: 'success',
duration: 6000, duration: 6000,
isClosable: true, isClosable: true,
}); });
} catch (error) { } catch (error) {
toast({ toast({
title: "Transaction Failed", title: 'Transaction Failed',
description: "There was an issue preparing your transaction.", description: 'There was an issue preparing your transaction.',
status: "error", status: 'error',
duration: 3000, duration: 3000,
isClosable: true, isClosable: true,
}); });
@@ -68,31 +67,22 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
const donationMethods = [ const donationMethods = [
{ {
name: "Ethereum", name: 'Ethereum',
icon: FaEthereum, icon: FaEthereum,
}, },
{ {
name: "Bitcoin", name: 'Bitcoin',
icon: FaBitcoin, icon: FaBitcoin,
}, },
{ {
name: "Dogecoin", name: 'Dogecoin',
icon: DogecoinIcon, icon: DogecoinIcon,
}, },
]; ];
return ( return (
<Modal <Modal isOpen={isOpen} onClose={onClose} size="md" motionPreset="slideInBottom" zIndex={zIndex}>
isOpen={isOpen} <ModalOverlay bg="bg.primary" backdropFilter="blur(10px) hue-rotate(90deg)" />
onClose={onClose}
size="md"
motionPreset="slideInBottom"
zIndex={zIndex}
>
<ModalOverlay
bg='bg.primary'
backdropFilter='blur(10px) hue-rotate(90deg)'
/>
<ModalContent bg="bg.primary" color="text.primary"> <ModalContent bg="bg.primary" color="text.primary">
<ModalHeader textAlign="center" mb={2}> <ModalHeader textAlign="center" mb={2}>
Support Support
@@ -109,38 +99,38 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
// colorScheme="teal" // colorScheme="teal"
isFitted isFitted
> >
<TabList mb={2} w={"20%"}> <TabList mb={2} w={'20%'}>
{donationMethods.map((method) => ( {donationMethods.map(method => (
<Tab <Tab
p={4} p={4}
key={method.name} key={method.name}
color={"text.primary"} color={'text.primary'}
bg={clientTransactionStore.selectedMethod=== method.name ? "bg.primary": "bg.secondary"} bg={
clientTransactionStore.selectedMethod === method.name
? 'bg.primary'
: 'bg.secondary'
}
onClick={() => { onClick={() => {
clientTransactionStore.setSelectedMethod(method.name); clientTransactionStore.setSelectedMethod(method.name);
}} }}
> >
<Box p={1} w={"fit-content"} > <Box p={1} w={'fit-content'}>
<method.icon />{" "} <method.icon />{' '}
</Box> </Box>
{method.name} {method.name}
</Tab> </Tab>
))} ))}
</TabList> </TabList>
<TabPanels> <TabPanels>
{donationMethods.map((method) => ( {donationMethods.map(method => (
<TabPanel key={method.name}> <TabPanel key={method.name}>
{!clientTransactionStore.userConfirmed ? ( {!clientTransactionStore.userConfirmed ? (
<VStack spacing={4}> <VStack spacing={4}>
<Text>Enter your information:</Text> <Text>Enter your information:</Text>
<Input <Input
placeholder="Your name" placeholder="Your name"
value={ value={clientTransactionStore.donerId as string | undefined}
clientTransactionStore.donerId as string | undefined onChange={e => clientTransactionStore.setDonerId(e.target.value)}
}
onChange={(e) =>
clientTransactionStore.setDonerId(e.target.value)
}
type="text" type="text"
bg="bg.secondary" bg="bg.secondary"
color="text.primary" color="text.primary"
@@ -149,12 +139,8 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
<Text>Enter the amount you wish to donate:</Text> <Text>Enter the amount you wish to donate:</Text>
<Input <Input
placeholder="Enter amount" placeholder="Enter amount"
value={ value={clientTransactionStore.amount as number | undefined}
clientTransactionStore.amount as number | undefined onChange={e => clientTransactionStore.setAmount(e.target.value)}
}
onChange={(e) =>
clientTransactionStore.setAmount(e.target.value)
}
type="number" type="number"
bg="bg.secondary" bg="bg.secondary"
// color="white" // color="white"
@@ -170,17 +156,9 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
</VStack> </VStack>
) : ( ) : (
<> <>
<Box <Box bg="white" p={2} borderRadius="lg" mb={4} w={'min-content'}>
bg="white"
p={2}
borderRadius="lg"
mb={4}
w={"min-content"}
>
<QRCodeCanvas <QRCodeCanvas
value={ value={clientTransactionStore.depositAddress as string}
clientTransactionStore.depositAddress as string
}
size={180} size={180}
/> />
</Box> </Box>
@@ -204,7 +182,7 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
// colorScheme="teal" // colorScheme="teal"
mb={4} mb={4}
> >
{hasCopied ? "Address Copied!" : "Copy Address"} {hasCopied ? 'Address Copied!' : 'Copy Address'}
</Button> </Button>
<Text fontSize="md" fontWeight="bold"> <Text fontSize="md" fontWeight="bold">
Transaction ID: {clientTransactionStore.txId} Transaction ID: {clientTransactionStore.txId}

View File

@@ -1,8 +1,10 @@
import React from "react"; import { Flex } from '@chakra-ui/react';
import { Flex } from "@chakra-ui/react"; import React from 'react';
import SupportThisSiteButton from "./SupportThisSiteButton";
import GithubButton from "./GithubButton"; import BuiltWithButton from '../BuiltWithButton';
import BuiltWithButton from "../BuiltWithButton";
import GithubButton from './GithubButton';
import SupportThisSiteButton from './SupportThisSiteButton';
const toolbarButtonZIndex = 901; const toolbarButtonZIndex = 901;
@@ -11,8 +13,8 @@ export { toolbarButtonZIndex };
function ToolBar({ isMobile }) { function ToolBar({ isMobile }) {
return ( return (
<Flex <Flex
direction={isMobile ? "row" : "column"} direction={isMobile ? 'row' : 'column'}
alignItems={isMobile ? "flex-start" : "flex-end"} alignItems={isMobile ? 'flex-start' : 'flex-end'}
pb={4} pb={4}
> >
<SupportThisSiteButton /> <SupportThisSiteButton />

View File

@@ -1,15 +1,14 @@
import { useEffect, useState } from "react"; import { useMediaQuery } from '@chakra-ui/react';
import { useMediaQuery } from "@chakra-ui/react"; import { useEffect, useState } from 'react';
// Only use this when it is necessary to style responsively outside a MobileProvider. // Only use this when it is necessary to style responsively outside a MobileProvider.
export function useIsMobile() { export function useIsMobile() {
const [isMobile, setIsMobile] = useState(false); const [isMobile, setIsMobile] = useState(false);
const [isFallbackMobile] = useMediaQuery("(max-width: 768px)"); const [isFallbackMobile] = useMediaQuery('(max-width: 768px)');
useEffect(() => { useEffect(() => {
const userAgent = navigator.userAgent || navigator.vendor || window.opera; const userAgent = navigator.userAgent || navigator.vendor || window.opera;
const mobile = const mobile = /android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
/android|webos|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(
userAgent.toLowerCase(), userAgent.toLowerCase(),
); );
setIsMobile(mobile); setIsMobile(mobile);

View File

@@ -1,5 +1,6 @@
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook } from '@testing-library/react'; import { renderHook } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import usePageLoaded from '../usePageLoaded'; import usePageLoaded from '../usePageLoaded';
describe('usePageLoaded', () => { describe('usePageLoaded', () => {
@@ -16,7 +17,7 @@ describe('usePageLoaded', () => {
// Mock document.readyState to be "complete" // Mock document.readyState to be "complete"
Object.defineProperty(document, 'readyState', { Object.defineProperty(document, 'readyState', {
configurable: true, configurable: true,
get: () => 'complete' get: () => 'complete',
}); });
const { result } = renderHook(() => usePageLoaded(callback)); const { result } = renderHook(() => usePageLoaded(callback));
@@ -35,7 +36,7 @@ describe('usePageLoaded', () => {
// Mock document.readyState to be "loading" // Mock document.readyState to be "loading"
Object.defineProperty(document, 'readyState', { Object.defineProperty(document, 'readyState', {
configurable: true, configurable: true,
get: () => 'loading' get: () => 'loading',
}); });
const { result } = renderHook(() => usePageLoaded(callback)); const { result } = renderHook(() => usePageLoaded(callback));
@@ -54,7 +55,7 @@ describe('usePageLoaded', () => {
// Mock document.readyState to be "loading" // Mock document.readyState to be "loading"
Object.defineProperty(document, 'readyState', { Object.defineProperty(document, 'readyState', {
configurable: true, configurable: true,
get: () => 'loading' get: () => 'loading',
}); });
const { unmount } = renderHook(() => usePageLoaded(callback)); const { unmount } = renderHook(() => usePageLoaded(callback));
@@ -70,16 +71,19 @@ describe('usePageLoaded', () => {
// Mock document.readyState to be "loading" // Mock document.readyState to be "loading"
Object.defineProperty(document, 'readyState', { Object.defineProperty(document, 'readyState', {
configurable: true, configurable: true,
get: () => 'loading' get: () => 'loading',
}); });
// Capture the event handler // Capture the event handler
let loadHandler: Function; let loadHandler: () => void;
vi.stubGlobal('addEventListener', vi.fn((event, handler) => { vi.stubGlobal(
'addEventListener',
vi.fn((event, handler) => {
if (event === 'load') { if (event === 'load') {
loadHandler = handler; loadHandler = handler;
} }
})); }),
);
const { result } = renderHook(() => usePageLoaded(callback)); const { result } = renderHook(() => usePageLoaded(callback));

View File

@@ -1,17 +1,18 @@
import { useState, useEffect } from "react"; import { useState, useEffect } from 'react';
import { useIsMobile } from "../components/contexts/MobileContext";
import { useIsMobile } from '../components/contexts/MobileContext';
export const useMaxWidth = () => { export const useMaxWidth = () => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const [maxWidth, setMaxWidth] = useState("600px"); const [maxWidth, setMaxWidth] = useState('600px');
const calculateMaxWidth = () => { const calculateMaxWidth = () => {
if (isMobile) { if (isMobile) {
setMaxWidth("800px"); setMaxWidth('800px');
} else if (window.innerWidth < 1024) { } else if (window.innerWidth < 1024) {
setMaxWidth("500px"); setMaxWidth('500px');
} else { } else {
setMaxWidth("800px"); setMaxWidth('800px');
} }
}; };
@@ -22,10 +23,10 @@ export const useMaxWidth = () => {
calculateMaxWidth(); calculateMaxWidth();
}; };
window.addEventListener("resize", handleResize); window.addEventListener('resize', handleResize);
return () => { return () => {
window.removeEventListener("resize", handleResize); window.removeEventListener('resize', handleResize);
}; };
}, [isMobile]); }, [isMobile]);

View File

@@ -1,4 +1,4 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from 'react';
const usePageLoaded = (callback: () => void) => { const usePageLoaded = (callback: () => void) => {
const [isLoaded, setIsLoaded] = useState(false); const [isLoaded, setIsLoaded] = useState(false);
@@ -9,15 +9,15 @@ const usePageLoaded = (callback: () => void) => {
callback(); callback();
}; };
if (document.readyState === "complete") { if (document.readyState === 'complete') {
// Page is already fully loaded // Page is already fully loaded
handlePageLoad(); handlePageLoad();
} else { } else {
// Wait for the page to load // Wait for the page to load
window.addEventListener("load", handlePageLoad); window.addEventListener('load', handlePageLoad);
} }
return () => window.removeEventListener("load", handlePageLoad); return () => window.removeEventListener('load', handlePageLoad);
}, [callback]); }, [callback]);
return isLoaded; return isLoaded;

View File

@@ -1,6 +1,7 @@
import { Flex } from "@chakra-ui/react"; import { Flex } from '@chakra-ui/react';
import React from "react"; import React from 'react';
import { useIsMobile } from "../components/contexts/MobileContext";
import { useIsMobile } from '../components/contexts/MobileContext';
function Content({ children }) { function Content({ children }) {
const isMobile = useIsMobile(); const isMobile = useIsMobile();

View File

@@ -1,8 +1,9 @@
import React from "react"; import { Box, Heading, Text } from '@chakra-ui/react';
import { Box, Heading, Text } from "@chakra-ui/react"; import React from 'react';
import { usePageContext } from "../renderer/usePageContext";
import Routes from "../renderer/routes"; import { useIsMobile } from '../components/contexts/MobileContext';
import { useIsMobile } from "../components/contexts/MobileContext"; import Routes from '../renderer/routes';
import { usePageContext } from '../renderer/usePageContext';
export default function Hero() { export default function Hero() {
const pageContext = usePageContext(); const pageContext = usePageContext();
@@ -12,12 +13,12 @@ export default function Hero() {
<Box p={2}> <Box p={2}>
<Box> <Box>
<Heading <Heading
textAlign={isMobile ? "left" : "right"} textAlign={isMobile ? 'left' : 'right'}
minWidth="90px" minWidth="90px"
maxWidth={"220px"} maxWidth={'220px'}
color="text.accent" color="text.accent"
as="h3" as="h3"
letterSpacing={"tight"} letterSpacing={'tight'}
size="lg" size="lg"
> >
{Routes[normalizePath(pageContext.urlPathname)]?.heroLabel} {Routes[normalizePath(pageContext.urlPathname)]?.heroLabel}
@@ -28,9 +29,9 @@ export default function Hero() {
isTruncated isTruncated
maxWidth="100%" maxWidth="100%"
whiteSpace="nowrap" whiteSpace="nowrap"
letterSpacing={"tight"} letterSpacing={'tight'}
color="text.accent" color="text.accent"
textAlign={isMobile ? "left" : "right"} textAlign={isMobile ? 'left' : 'right'}
overflow="hidden" overflow="hidden"
> >
{new Date().toLocaleDateString()} {new Date().toLocaleDateString()}
@@ -39,9 +40,9 @@ export default function Hero() {
); );
} }
const normalizePath = (path) => { const normalizePath = path => {
if (!path) return "/"; if (!path) return '/';
if (path.length > 1 && path.endsWith("/")) { if (path.length > 1 && path.endsWith('/')) {
path = path.slice(0, -1); path = path.slice(0, -1);
} }
return path.toLowerCase(); return path.toLowerCase();

View File

@@ -1,16 +1,18 @@
import React, { useEffect, useState } from "react"; import { observer } from 'mobx-react-lite';
import { PageContextProvider } from "../renderer/usePageContext"; import React, { useEffect, useState } from 'react';
import { MobileProvider } from "../components/contexts/MobileContext";
import LayoutComponent from "./LayoutComponent"; import { Chakra } from '../components/contexts/ChakraContext';
import userOptionsStore from "../stores/UserOptionsStore"; import { MobileProvider } from '../components/contexts/MobileContext';
import { observer } from "mobx-react-lite"; import { PageContextProvider } from '../renderer/usePageContext';
import { Chakra } from "../components/contexts/ChakraContext"; import userOptionsStore from '../stores/UserOptionsStore';
import { getTheme } from "./theme/color-themes";
import LayoutComponent from './LayoutComponent';
import { getTheme } from './theme/color-themes';
export { Layout }; export { Layout };
const Layout = observer(({ pageContext, children }) => { const Layout = observer(({ pageContext, children }) => {
const [activeTheme, setActiveTheme] = useState<string>("darknight"); const [activeTheme, setActiveTheme] = useState<string>('darknight');
useEffect(() => { useEffect(() => {
if (userOptionsStore.theme !== activeTheme) { if (userOptionsStore.theme !== activeTheme) {
@@ -22,21 +24,23 @@ const Layout = observer(({ pageContext, children }) => {
if (pageContext?.headersOriginal) { if (pageContext?.headersOriginal) {
const headers = new Headers(pageContext.headersOriginal); const headers = new Headers(pageContext.headersOriginal);
const cookies = headers.get("cookie"); const cookies = headers.get('cookie');
const userPreferencesCookie = cookies const userPreferencesCookie = cookies
?.split("; ") ?.split('; ')
.find((row) => row.startsWith("user_preferences=")) .find(row => row.startsWith('user_preferences='))
?.split("=")[1]; ?.split('=')[1];
try { try {
const { theme: receivedTheme } = JSON.parse( const { theme: receivedTheme } = JSON.parse(atob(userPreferencesCookie ?? '{}'));
atob(userPreferencesCookie ?? "{}"),
);
setActiveTheme(receivedTheme); setActiveTheme(receivedTheme);
} catch (e) {} } catch (e) {
// Ignore parsing errors for user preferences cookie
}
}
} catch (e) {
// Ignore errors when accessing headers or cookies
} }
} catch (e) {}
return ( return (
<React.StrictMode> <React.StrictMode>

View File

@@ -1,10 +1,12 @@
import React from "react"; import { Grid, GridItem } from '@chakra-ui/react';
import { Grid, GridItem } from "@chakra-ui/react"; import React from 'react';
import Navigation from "./Navigation";
import Routes from "../renderer/routes"; import { useIsMobile } from '../components/contexts/MobileContext';
import Hero from "./Hero"; import Routes from '../renderer/routes';
import Content from "./Content";
import { useIsMobile } from "../components/contexts/MobileContext"; import Content from './Content';
import Hero from './Hero';
import Navigation from './Navigation';
export default function LayoutComponent({ children }) { export default function LayoutComponent({ children }) {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
@@ -17,17 +19,17 @@ export default function LayoutComponent({ children }) {
"main"` "main"`
: `"nav main"` : `"nav main"`
} }
gridTemplateRows={isMobile ? "auto 1fr" : "1fr"} gridTemplateRows={isMobile ? 'auto 1fr' : '1fr'}
gridTemplateColumns={isMobile ? "1fr" : "auto 1fr"} gridTemplateColumns={isMobile ? '1fr' : 'auto 1fr'}
minHeight="100vh" minHeight="100vh"
gap="1" gap="1"
> >
<GridItem area={"nav"} hidden={false}> <GridItem area={'nav'} hidden={false}>
<Navigation routeRegistry={Routes}> <Navigation routeRegistry={Routes}>
<Hero /> <Hero />
</Navigation> </Navigation>
</GridItem> </GridItem>
<GridItem area={"main"}> <GridItem area={'main'}>
<Content>{children}</Content> <Content>{children}</Content>
</GridItem> </GridItem>
</Grid> </Grid>

View File

@@ -1,16 +1,16 @@
import { Box } from "@chakra-ui/react"; import { Box } from '@chakra-ui/react';
import React from "react"; import React from 'react';
function NavItem({ path, children, color, onClick, as, cursor }) { function NavItem({ path, children, color, onClick, as, cursor }) {
return ( return (
<Box <Box
as={as ?? "a"} as={as ?? 'a'}
href={path} href={path}
mb={2} mb={2}
cursor={cursor} cursor={cursor}
// ml={5} // ml={5}
mr={2} mr={2}
color={color ?? "text.accent"} color={color ?? 'text.accent'}
letterSpacing="normal" letterSpacing="normal"
display="block" display="block"
position="relative" position="relative"
@@ -18,20 +18,20 @@ function NavItem({ path, children, color, onClick, as, cursor }) {
onClick={onClick} onClick={onClick}
_after={{ _after={{
content: '""', content: '""',
position: "absolute", position: 'absolute',
width: "100%", width: '100%',
height: "2px", height: '2px',
bottom: "0", bottom: '0',
left: "0", left: '0',
bg: "accent.secondary", bg: 'accent.secondary',
transform: "scaleX(0)", transform: 'scaleX(0)',
transformOrigin: "right", transformOrigin: 'right',
transition: "transform 0.3s ease-in-out", transition: 'transform 0.3s ease-in-out',
}} }}
_hover={{ _hover={{
color: "tertiary.tertiary", color: 'tertiary.tertiary',
_after: { _after: {
transform: "scaleX(1)", transform: 'scaleX(1)',
}, },
}} }}
> >

View File

@@ -1,40 +1,36 @@
import React, { useEffect } from "react"; import { Box, Collapse, Grid, GridItem, useBreakpointValue } from '@chakra-ui/react';
import { observer } from "mobx-react-lite"; import { MenuIcon } from 'lucide-react';
import { import { observer } from 'mobx-react-lite';
Box, import React, { useEffect } from 'react';
Collapse,
Grid, import { useIsMobile } from '../components/contexts/MobileContext';
GridItem, import { usePageContext } from '../renderer/usePageContext';
useBreakpointValue, import menuState from '../stores/AppMenuStore';
} from "@chakra-ui/react"; import userOptionsStore from '../stores/UserOptionsStore';
import { MenuIcon } from "lucide-react";
import Sidebar from "./Sidebar"; import NavItem from './NavItem';
import NavItem from "./NavItem"; import Sidebar from './Sidebar';
import menuState from "../stores/AppMenuStore"; import { getTheme } from './theme/color-themes';
import { usePageContext } from "../renderer/usePageContext";
import { useIsMobile } from "../components/contexts/MobileContext";
import { getTheme } from "./theme/color-themes";
import userOptionsStore from "../stores/UserOptionsStore";
const Navigation = observer(({ children, routeRegistry }) => { const Navigation = observer(({ children, routeRegistry }) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const pageContext = usePageContext(); const pageContext = usePageContext();
const currentPath = pageContext.urlPathname || "/"; const currentPath = pageContext.urlPathname || '/';
const getTopValue = () => { const getTopValue = () => {
if (!isMobile) return undefined; if (!isMobile) return undefined;
if (currentPath === "/") return 12; if (currentPath === '/') return 12;
return 0; return 0;
}; };
const variant = useBreakpointValue( const variant = useBreakpointValue(
{ {
base: "outline", base: 'outline',
md: "solid", md: 'solid',
}, },
{ {
fallback: "md", fallback: 'md',
}, },
); );
@@ -50,7 +46,7 @@ const Navigation = observer(({ children, routeRegistry }) => {
top={0} top={0}
left={0} left={0}
zIndex={1100} zIndex={1100}
width={isMobile ? "20%" : "100%"} width={isMobile ? '20%' : '100%'}
hidden={!isMobile} hidden={!isMobile}
> >
<Grid templateColumns="auto 1fr" alignItems="center"> <Grid templateColumns="auto 1fr" alignItems="center">
@@ -85,10 +81,10 @@ const Navigation = observer(({ children, routeRegistry }) => {
as="nav" as="nav"
templateColumns="1fr" templateColumns="1fr"
width="100%" width="100%"
h={isMobile ? "100vh" : "100vh"} h={isMobile ? '100vh' : '100vh'}
top={getTopValue()} top={getTopValue()}
position={"relative"} position={'relative'}
bg={"transparent"} bg={'transparent'}
zIndex={1000} zIndex={1000}
gap={4} gap={4}
p={isMobile ? 4 : 0} p={isMobile ? 4 : 0}
@@ -97,8 +93,8 @@ const Navigation = observer(({ children, routeRegistry }) => {
<GridItem> <GridItem>
<Sidebar> <Sidebar>
{Object.keys(routeRegistry) {Object.keys(routeRegistry)
.filter((p) => !routeRegistry[p].hideNav) .filter(p => !routeRegistry[p].hideNav)
.map((path) => ( .map(path => (
<NavItem key={path} path={path}> <NavItem key={path} path={path}>
{routeRegistry[path].sidebarLabel} {routeRegistry[path].sidebarLabel}
</NavItem> </NavItem>
@@ -114,15 +110,11 @@ const Navigation = observer(({ children, routeRegistry }) => {
top="0" top="0"
left="0" left="0"
right="0" right="0"
height={menuState.isOpen ? "100vh" : "auto"} height={menuState.isOpen ? '100vh' : 'auto'}
pointerEvents="none" pointerEvents="none"
zIndex={900} zIndex={900}
> >
<Box <Box height="100%" transition="all 0.3s" opacity={menuState.isOpen ? 1 : 0} />
height="100%"
transition="all 0.3s"
opacity={menuState.isOpen ? 1 : 0}
/>
</Box> </Box>
)} )}
</Grid> </Grid>

View File

@@ -1,14 +1,16 @@
import React, { useState } from "react"; import { Box, Flex, VStack } from '@chakra-ui/react';
import { Box, Flex, VStack } from "@chakra-ui/react"; import React, { useState } from 'react';
import NavItem from "./NavItem";
import ToolBar from "../components/toolbar/Toolbar"; import { useIsMobile } from '../components/contexts/MobileContext';
import { useIsMobile } from "../components/contexts/MobileContext"; import FeedbackModal from '../components/feedback/FeedbackModal';
import FeedbackModal from "../components/feedback/FeedbackModal"; import { ThemeSelectionOptions } from '../components/ThemeSelection';
import { ThemeSelectionOptions } from "../components/ThemeSelection"; import ToolBar from '../components/toolbar/Toolbar';
import NavItem from './NavItem';
function LowerSidebarContainer({ children, isMobile, ...props }) { function LowerSidebarContainer({ children, isMobile, ...props }) {
const bottom = isMobile ? undefined : "6rem"; const bottom = isMobile ? undefined : '6rem';
const position = isMobile ? "relative" : "absolute"; const position = isMobile ? 'relative' : 'absolute';
return ( return (
<Box width="100%" m={0.99} position={position} bottom={bottom} {...props}> <Box width="100%" m={0.99} position={position} bottom={bottom} {...props}>
{children} {children}
@@ -23,7 +25,7 @@ function Sidebar({ children: navLinks }) {
<SidebarContainer isMobile={isMobile}> <SidebarContainer isMobile={isMobile}>
<VStack <VStack
spacing={6} spacing={6}
alignItems={isMobile ? "flex-start" : "flex-end"} alignItems={isMobile ? 'flex-start' : 'flex-end'}
letterSpacing="tighter" letterSpacing="tighter"
width="100%" width="100%"
height="100%" height="100%"
@@ -31,11 +33,11 @@ function Sidebar({ children: navLinks }) {
{navLinks} {navLinks}
<Box <Box
alignItems={isMobile ? "flex-start" : "flex-end"} alignItems={isMobile ? 'flex-start' : 'flex-end'}
bg="background.primary" bg="background.primary"
zIndex={1000} zIndex={1000}
width="100%" width="100%"
fontSize={"x-small"} fontSize={'x-small'}
> >
<LowerSidebarContainer isMobile={isMobile}> <LowerSidebarContainer isMobile={isMobile}>
<ToolBar isMobile={isMobile} /> <ToolBar isMobile={isMobile} />
@@ -58,12 +60,12 @@ function RegulatoryItems({ isMobile }) {
return ( return (
<> <>
<VStack alignItems={isMobile ? "flex-start" : "flex-end"} spacing={1}> <VStack alignItems={isMobile ? 'flex-start' : 'flex-end'} spacing={1}>
<NavItem <NavItem
color="text.tertiary" color="text.tertiary"
as={"span"} as={'span'}
path="" path=""
cursor={"pointer"} cursor={'pointer'}
onClick={openFeedbackModal} onClick={openFeedbackModal}
> >
Feedback Feedback
@@ -77,22 +79,14 @@ function RegulatoryItems({ isMobile }) {
</VStack> </VStack>
{/* Feedback Modal */} {/* Feedback Modal */}
<FeedbackModal <FeedbackModal isOpen={isFeedbackModalOpen} onClose={closeFeedbackModal} />
isOpen={isFeedbackModalOpen}
onClose={closeFeedbackModal}
/>
</> </>
); );
} }
function SidebarContainer({ children, isMobile }) { function SidebarContainer({ children, isMobile }) {
return ( return (
<Flex <Flex mt={isMobile ? 28 : undefined} position="relative" height="100vh" width="100%">
mt={isMobile ? 28 : undefined}
position="relative"
height="100vh"
width="100%"
>
{children} {children}
</Flex> </Flex>
); );

View File

@@ -1,25 +1,25 @@
import { extendTheme } from "@chakra-ui/react"; import { extendTheme } from '@chakra-ui/react';
const fonts = { const fonts = {
body: "monospace", body: 'monospace',
heading: "monospace", heading: 'monospace',
}; };
const styles = { const styles = {
global: { global: {
body: { body: {
fontFamily: fonts.body, fontFamily: fonts.body,
bg: "background.primary", bg: 'background.primary',
color: "text.primary", color: 'text.primary',
margin: 0, margin: 0,
overflow: "hidden", overflow: 'hidden',
}, },
html: { html: {
overflow: "hidden", overflow: 'hidden',
}, },
"::selection": { '::selection': {
backgroundColor: "accent.secondary", backgroundColor: 'accent.secondary',
color: "background.primary", color: 'background.primary',
}, },
}, },
}; };
@@ -27,69 +27,69 @@ const styles = {
const components = { const components = {
Button: { Button: {
baseStyle: { baseStyle: {
fontWeight: "bold", fontWeight: 'bold',
borderRadius: "md", // Slightly rounded corners borderRadius: 'md', // Slightly rounded corners
}, },
variants: { variants: {
solid: { solid: {
bg: "accent.primary", bg: 'accent.primary',
color: "background.primary", color: 'background.primary',
_hover: { _hover: {
bg: "accent.primary", bg: 'accent.primary',
color: "background.primary", color: 'background.primary',
}, },
}, },
outline: { outline: {
borderColor: "accent.primary", borderColor: 'accent.primary',
color: "text.primary", color: 'text.primary',
_hover: { _hover: {
bg: "accent.primary", bg: 'accent.primary',
color: "background.primary", color: 'background.primary',
}, },
}, },
ghost: { ghost: {
color: "text.primary", color: 'text.primary',
_hover: { _hover: {
bg: "background.secondary", bg: 'background.secondary',
}, },
}, },
}, },
}, },
Link: { Link: {
baseStyle: { baseStyle: {
color: "accent.secondary", color: 'accent.secondary',
_hover: { _hover: {
color: "accent.primary", color: 'accent.primary',
textDecoration: "none", textDecoration: 'none',
}, },
}, },
}, },
Heading: { Heading: {
baseStyle: { baseStyle: {
color: "text.primary", color: 'text.primary',
letterSpacing: "tight", letterSpacing: 'tight',
}, },
sizes: { sizes: {
"4xl": { fontSize: ["6xl", null, "7xl"], lineHeight: 1 }, '4xl': { fontSize: ['6xl', null, '7xl'], lineHeight: 1 },
"3xl": { fontSize: ["5xl", null, "6xl"], lineHeight: 1.2 }, '3xl': { fontSize: ['5xl', null, '6xl'], lineHeight: 1.2 },
"2xl": { fontSize: ["4xl", null, "5xl"] }, '2xl': { fontSize: ['4xl', null, '5xl'] },
xl: { fontSize: ["3xl", null, "4xl"] }, xl: { fontSize: ['3xl', null, '4xl'] },
lg: { fontSize: ["2xl", null, "3xl"] }, lg: { fontSize: ['2xl', null, '3xl'] },
md: { fontSize: "xl" }, md: { fontSize: 'xl' },
sm: { fontSize: "md" }, sm: { fontSize: 'md' },
xs: { fontSize: "sm" }, xs: { fontSize: 'sm' },
}, },
}, },
Text: { Text: {
baseStyle: { baseStyle: {
color: "text.primary", color: 'text.primary',
}, },
variants: { variants: {
secondary: { secondary: {
color: "text.secondary", color: 'text.secondary',
}, },
accent: { accent: {
color: "text.accent", color: 'text.accent',
}, },
}, },
}, },
@@ -97,21 +97,21 @@ const components = {
variants: { variants: {
filled: { filled: {
field: { field: {
bg: "background.secondary", bg: 'background.secondary',
_hover: { _hover: {
bg: "background.tertiary", bg: 'background.tertiary',
}, },
_focus: { _focus: {
bg: "background.tertiary", bg: 'background.tertiary',
borderColor: "accent.primary", borderColor: 'accent.primary',
}, },
}, },
}, },
}, },
}, },
CodeBlocks: { CodeBlocks: {
baseStyle: (props) => ({ baseStyle: props => ({
bg: "background.primary", bg: 'background.primary',
// color: 'text.primary', // color: 'text.primary',
}), }),
}, },
@@ -119,59 +119,59 @@ const components = {
const Base_theme = extendTheme({ const Base_theme = extendTheme({
config: { config: {
cssVarPrefix: "wgs", cssVarPrefix: 'wgs',
initialColorMode: "dark", initialColorMode: 'dark',
useSystemColorMode: false, useSystemColorMode: false,
}, },
fonts, fonts,
styles, styles,
components, components,
letterSpacings: { letterSpacings: {
tighter: "-0.05em", tighter: '-0.05em',
tight: "-0.025em", tight: '-0.025em',
normal: "0", normal: '0',
wide: "0.025em", wide: '0.025em',
wider: "0.05em", wider: '0.05em',
widest: "0.1em", widest: '0.1em',
}, },
space: { space: {
px: "1px", px: '1px',
0.5: "0.125rem", 0.5: '0.125rem',
1: "0.25rem", 1: '0.25rem',
1.5: "0.375rem", 1.5: '0.375rem',
2: "0.5rem", 2: '0.5rem',
2.5: "0.625rem", 2.5: '0.625rem',
3: "0.75rem", 3: '0.75rem',
3.5: "0.875rem", 3.5: '0.875rem',
4: "1rem", 4: '1rem',
5: "1.25rem", 5: '1.25rem',
6: "1.5rem", 6: '1.5rem',
7: "1.75rem", 7: '1.75rem',
8: "2rem", 8: '2rem',
9: "2.25rem", 9: '2.25rem',
10: "2.5rem", 10: '2.5rem',
12: "3rem", 12: '3rem',
14: "3.5rem", 14: '3.5rem',
16: "4rem", 16: '4rem',
18: "4.5rem", 18: '4.5rem',
20: "5rem", 20: '5rem',
22: "5.5rem", 22: '5.5rem',
24: "6rem", 24: '6rem',
28: "7rem", 28: '7rem',
32: "8rem", 32: '8rem',
34: "8.5rem", 34: '8.5rem',
36: "9rem", 36: '9rem',
38: "9.5rem", 38: '9.5rem',
40: "10rem", 40: '10rem',
44: "11rem", 44: '11rem',
48: "12rem", 48: '12rem',
52: "13rem", 52: '13rem',
56: "14rem", 56: '14rem',
60: "15rem", 60: '15rem',
64: "16rem", 64: '16rem',
72: "18rem", 72: '18rem',
80: "20rem", 80: '20rem',
96: "24rem", 96: '24rem',
}, },
}); });

View File

@@ -1,32 +1,32 @@
export default { export default {
brand: { brand: {
900: "#21252b", 900: '#21252b',
800: "#343a40", 800: '#343a40',
750: "#495057", 750: '#495057',
700: "#525c65", 700: '#525c65',
600: "#90ee90", 600: '#90ee90',
500: "#ffa07a", 500: '#ffa07a',
400: "#e0e0e0", 400: '#e0e0e0',
300: "#ff69b4", 300: '#ff69b4',
200: "#da70d6", 200: '#da70d6',
100: "#ffffff", 100: '#ffffff',
}, },
background: { background: {
primary: "#21252b", primary: '#21252b',
secondary: "#343a40", secondary: '#343a40',
tertiary: "#495057", tertiary: '#495057',
}, },
text: { text: {
primary: "#e0e0e0", primary: '#e0e0e0',
secondary: "#c0c0c0", secondary: '#c0c0c0',
tertiary: "#a9a9a9", tertiary: '#a9a9a9',
accent: "#87cefa", accent: '#87cefa',
link: "#87cefa", link: '#87cefa',
}, },
accent: { accent: {
primary: "#90ee90", primary: '#90ee90',
secondary: "#ffa07a", secondary: '#ffa07a',
danger: "#ff69b4", danger: '#ff69b4',
confirm: "#90ee90", confirm: '#90ee90',
}, },
}; };

View File

@@ -1,32 +1,32 @@
export default { export default {
brand: { brand: {
900: "#1E1E2E", 900: '#1E1E2E',
800: "#302D41", 800: '#302D41',
750: "#332E41", 750: '#332E41',
700: "#575268", 700: '#575268',
600: "#6E6C7E", 600: '#6E6C7E',
500: "#988BA2", 500: '#988BA2',
400: "#C3BAC6", 400: '#C3BAC6',
300: "#D9E0EE", 300: '#D9E0EE',
200: "#F5E0DC", 200: '#F5E0DC',
100: "#FAE3B0", 100: '#FAE3B0',
}, },
background: { background: {
primary: "#1E1E2E", primary: '#1E1E2E',
secondary: "#302D41", secondary: '#302D41',
tertiary: "#575268", tertiary: '#575268',
}, },
text: { text: {
primary: "#D9E0EE", primary: '#D9E0EE',
secondary: "#C3BAC6", secondary: '#C3BAC6',
tertiary: "#988BA2", tertiary: '#988BA2',
accent: "#F5E0DC", accent: '#F5E0DC',
link: "#96CDFB", link: '#96CDFB',
}, },
accent: { accent: {
primary: "#F5C2E7", primary: '#F5C2E7',
secondary: "#DDB6F2", secondary: '#DDB6F2',
danger: "#F28FAD", danger: '#F28FAD',
confirm: "#ABE9B3", confirm: '#ABE9B3',
}, },
}; };

View File

@@ -1,32 +1,32 @@
export default { export default {
brand: { brand: {
900: "#000000", 900: '#000000',
800: "#333333", 800: '#333333',
750: "#2B2B2B", 750: '#2B2B2B',
700: "#666666", 700: '#666666',
600: "#999999", 600: '#999999',
500: "#CCCCCC", 500: '#CCCCCC',
400: "#FFFFFF", 400: '#FFFFFF',
300: "#F0F0F0", 300: '#F0F0F0',
200: "#F8F9FA", 200: '#F8F9FA',
100: "#FFFFFF", 100: '#FFFFFF',
}, },
background: { background: {
primary: "#000000", primary: '#000000',
secondary: "#222222", secondary: '#222222',
tertiary: "#333333", tertiary: '#333333',
}, },
text: { text: {
primary: "#F0F0F0", primary: '#F0F0F0',
secondary: "#CCCCCC", secondary: '#CCCCCC',
tertiary: "#999999", tertiary: '#999999',
accent: "#FFFFFF", accent: '#FFFFFF',
link: "#0d9488", link: '#0d9488',
}, },
accent: { accent: {
primary: "#FFFFFF", primary: '#FFFFFF',
secondary: "#c0c0c0", secondary: '#c0c0c0',
danger: "#E53E3E", danger: '#E53E3E',
confirm: "#00D26A", confirm: '#00D26A',
}, },
}; };

View File

@@ -1,40 +1,40 @@
export default { export default {
brand: { brand: {
colors: { colors: {
900: "#2C2E43", 900: '#2C2E43',
800: "#3D4162", 800: '#3D4162',
750: "#4F5285", 750: '#4F5285',
700: "#6076AC", 700: '#6076AC',
600: "#7693D6", 600: '#7693D6',
500: "#8DAFF0", 500: '#8DAFF0',
400: "#A3C7FF", 400: '#A3C7FF',
300: "#B9E0FF", 300: '#B9E0FF',
200: "#CDF4FE", 200: '#CDF4FE',
100: "#E1FEFF", 100: '#E1FEFF',
}, },
}, },
background: { background: {
primary: "linear-gradient(360deg, #15171C 100%, #353A47 100%)", primary: 'linear-gradient(360deg, #15171C 100%, #353A47 100%)',
secondary: "#1B1F26", secondary: '#1B1F26',
tertiary: "#1E1E2E", tertiary: '#1E1E2E',
}, },
text: { text: {
primary: "#f8f8f8", primary: '#f8f8f8',
secondary: "#3D4162", secondary: '#3D4162',
tertiary: "#e5ebff", tertiary: '#e5ebff',
accent: "#e6e6e6", accent: '#e6e6e6',
link: "aquamarine", link: 'aquamarine',
}, },
accent: { accent: {
primary: "#127c91", primary: '#127c91',
secondary: "#39b4bf", secondary: '#39b4bf',
danger: "#E74C3C", danger: '#E74C3C',
confirm: "#27AE60", confirm: '#27AE60',
}, },
}; };

View File

@@ -1,35 +1,35 @@
export default { export default {
brand: { brand: {
900: "#15171C", 900: '#15171C',
800: "#1B1F26", 800: '#1B1F26',
750: "#222731", 750: '#222731',
700: "#353A47", 700: '#353A47',
600: "#535966", 600: '#535966',
500: "#747C88", 500: '#747C88',
400: "#A0A4AC", 400: '#A0A4AC',
300: "#C6CBDC", 300: '#C6CBDC',
200: "#E6E9F0", 200: '#E6E9F0',
100: "#F3F4F8", 100: '#F3F4F8',
}, },
background: { background: {
primary: "#15171C", primary: '#15171C',
secondary: "#1B1F26", secondary: '#1B1F26',
tertiary: "#353A47", tertiary: '#353A47',
}, },
text: { text: {
primary: "#ffffff", primary: '#ffffff',
secondary: "#A0A4AC", secondary: '#A0A4AC',
tertiary: "#747C88", tertiary: '#747C88',
accent: "#E6E9F0", accent: '#E6E9F0',
link: "#96CDFB", link: '#96CDFB',
}, },
accent: { accent: {
primary: "#0095ff", primary: '#0095ff',
secondary: "#00acff", secondary: '#00acff',
danger: "#EA4D4D", danger: '#EA4D4D',
confirm: "#10CE8D", confirm: '#10CE8D',
}, },
}; };

View File

@@ -1,16 +1,18 @@
import { extendTheme } from "@chakra-ui/react"; import { extendTheme } from '@chakra-ui/react';
import BaseTheme from "../base_theme";
import DarknightColors from "./Darknight"; import BaseTheme from '../base_theme';
import CapuchinColors from "./Capuchin";
import VsCodeColors from "./VsCode"; import CapuchinColors from './Capuchin';
import OneDark from "./OneDark"; import DarknightColors from './Darknight';
import OneDark from './OneDark';
import VsCodeColors from './VsCode';
export function getColorThemes() { export function getColorThemes() {
return [ return [
{ name: "darknight", colors: DarknightColors }, { name: 'darknight', colors: DarknightColors },
{ name: "onedark", colors: OneDark }, { name: 'onedark', colors: OneDark },
{ name: "capuchin", colors: CapuchinColors }, { name: 'capuchin', colors: CapuchinColors },
{ name: "vscode", colors: VsCodeColors }, { name: 'vscode', colors: VsCodeColors },
]; ];
} }
@@ -36,13 +38,13 @@ const onedark = extendTheme({
export function getTheme(theme: string) { export function getTheme(theme: string) {
switch (theme) { switch (theme) {
case "onedark": case 'onedark':
return onedark; return onedark;
case "darknight": case 'darknight':
return darknight; return darknight;
case "capuchin": case 'capuchin':
return capuchin; return capuchin;
case "vscode": case 'vscode':
return vsCode; return vsCode;
default: default:
return darknight; return darknight;

View File

@@ -1,7 +1,8 @@
import { types, flow } from "mobx-state-tree"; /* eslint-disable no-irregular-whitespace */
import { types, flow } from 'mobx-state-tree';
// Utility to pause execution inside a flow // Utility to pause execution inside a flow
const sleep = (ms: number) => new Promise<void>((res) => setTimeout(res, ms)); const sleep = (ms: number) => new Promise<void>(res => setTimeout(res, ms));
// Simple function to generate a unique ID // Simple function to generate a unique ID
export const generateId = () => { export const generateId = () => {
@@ -9,7 +10,7 @@ export const generateId = () => {
}; };
// Utility for efficient batched content updates // Utility for efficient batched content updates
let batchedContent = ""; let batchedContent = '';
let batchUpdateTimeout: NodeJS.Timeout | null = null; let batchUpdateTimeout: NodeJS.Timeout | null = null;
const BATCH_UPDATE_DELAY = 50; // ms const BATCH_UPDATE_DELAY = 50; // ms
@@ -26,24 +27,24 @@ export const batchContentUpdate = (message: any, content: string) => {
batchUpdateTimeout = setTimeout(() => { batchUpdateTimeout = setTimeout(() => {
if (message && batchedContent) { if (message && batchedContent) {
message.append(batchedContent); message.append(batchedContent);
batchedContent = ""; batchedContent = '';
} }
batchUpdateTimeout = null; batchUpdateTimeout = null;
}, BATCH_UPDATE_DELAY); }, BATCH_UPDATE_DELAY);
}; };
const Message = types const Message = types
.model("Message", { .model('Message', {
id: types.optional(types.identifier, generateId), id: types.optional(types.identifier, generateId),
content: types.string, content: types.string,
role: types.enumeration(["user", "assistant"]), role: types.enumeration(['user', 'assistant']),
}) })
// Runtimeonly flags that never persist or get serialized // Runtime-only flags that never persist or get serialized
.volatile(() => ({ .volatile(() => ({
/** Indicates that characters are still being streamed in */ /** Indicates that characters are still being streamed in */
isStreaming: false, isStreaming: false,
})) }))
.actions((self) => { .actions(self => {
// Basic mutators --------------------------------------------------------- // Basic mutators ---------------------------------------------------------
const setContent = (newContent: string) => { const setContent = (newContent: string) => {
self.content = newContent; self.content = newContent;
@@ -59,11 +60,7 @@ const Message = types
* @param chunkSize How many characters to reveal per tick (default 3). * @param chunkSize How many characters to reveal per tick (default 3).
* @param delay Delay (ms) between ticks (default 20ms). * @param delay Delay (ms) between ticks (default 20ms).
*/ */
const streamContent = flow(function* ( const streamContent = flow(function* (newContent: string, chunkSize = 3, delay = 20) {
newContent: string,
chunkSize = 3,
delay = 20
) {
self.isStreaming = true; self.isStreaming = true;
let pointer = 0; let pointer = 0;

View File

@@ -1,4 +1,4 @@
// runs before anything else // runs before anything else
import UserOptionsStore from "../stores/UserOptionsStore"; import UserOptionsStore from '../stores/UserOptionsStore';
UserOptionsStore.initialize(); UserOptionsStore.initialize();

View File

@@ -1,18 +1,19 @@
import Routes from "../renderer/routes"; import type { PageContextServer } from 'vike/types';
import Routes from '../renderer/routes';
export { data }; export { data };
export type Data = Awaited<ReturnType<typeof data>>; export type Data = Awaited<ReturnType<typeof data>>;
import type { PageContextServer } from "vike/types";
// sets the window title depending on the route // sets the window title depending on the route
const data = async (pageContext: PageContextServer) => { const data = async (pageContext: PageContextServer) => {
const getTitle = (path) => { const getTitle = path => {
return Routes[normalizePath(path)]?.heroLabel || ""; return Routes[normalizePath(path)]?.heroLabel || '';
}; };
const normalizePath = (path) => { const normalizePath = path => {
if (!path) return "/"; if (!path) return '/';
if (path.length > 1 && path.endsWith("/")) { if (path.length > 1 && path.endsWith('/')) {
path = path.slice(0, -1); path = path.slice(0, -1);
} }
return path.toLowerCase(); return path.toLowerCase();

View File

@@ -1,6 +1,7 @@
// client error catcher // client error catcher
import { usePageContext } from "../../renderer/usePageContext"; import { Center, Text } from '@chakra-ui/react';
import { Center, Text } from "@chakra-ui/react";
import { usePageContext } from '../../renderer/usePageContext';
export { Page }; export { Page };
@@ -11,18 +12,16 @@ function Page() {
const { abortReason, abortStatusCode } = pageContext; const { abortReason, abortStatusCode } = pageContext;
if (abortReason?.notAdmin) { if (abortReason?.notAdmin) {
msg = "You cannot access this page because you aren't an administrator."; msg = "You cannot access this page because you aren't an administrator.";
} else if (typeof abortReason === "string") { } else if (typeof abortReason === 'string') {
msg = abortReason; msg = abortReason;
} else if (abortStatusCode === 403) { } else if (abortStatusCode === 403) {
msg = msg = "You cannot access this page because you don't have enough privileges.";
"You cannot access this page because you don't have enough privileges.";
} else if (abortStatusCode === 401) { } else if (abortStatusCode === 401) {
msg = msg = "You cannot access this page because you aren't logged in. Please log in.";
"You cannot access this page because you aren't logged in. Please log in.";
} else { } else {
msg = pageContext.is404 msg = pageContext.is404
? "This page doesn't exist." ? "This page doesn't exist."
: "Something went wrong. Try again (later)."; : 'Something went wrong. Try again (later).';
} }
return ( return (
@@ -32,6 +31,7 @@ function Page() {
); );
} }
/* eslint-disable @typescript-eslint/no-namespace */
declare global { declare global {
namespace Vike { namespace Vike {
interface PageContext { interface PageContext {

View File

@@ -1,21 +1,16 @@
import React from "react"; import { Box, VStack } from '@chakra-ui/react';
import { Box, VStack } from "@chakra-ui/react"; import React, { Fragment } from 'react';
import ConnectComponent from "../../components/connect/ConnectComponent";
import { Fragment } from "react"; import ConnectComponent from '../../components/connect/ConnectComponent';
import { useIsMobile } from "../../components/contexts/MobileContext"; import { useIsMobile } from '../../components/contexts/MobileContext';
export default function ConnectPage() { export default function ConnectPage() {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<Fragment> <Fragment>
<VStack <VStack minH={'100%'} maxW={'40rem'} align="start" h={!isMobile ? '90vh' : '70vh'}>
minH={"100%"} <Box maxW={'710px'} p={2} overflowY={'auto'} mt={isMobile ? 24 : 0}>
maxW={"40rem"}
align="start"
h={!isMobile ? "90vh" : "70vh"}
>
<Box maxW={"710px"} p={2} overflowY={"auto"} mt={isMobile ? 24 : 0}>
<ConnectComponent /> <ConnectComponent />
</Box> </Box>
</VStack> </VStack>

View File

@@ -1,13 +1,14 @@
import React, { useEffect } from "react"; import { Stack } from '@chakra-ui/react';
import { Stack } from "@chakra-ui/react"; import React, { useEffect } from 'react';
import Chat from "../../components/chat/Chat";
import clientChatStore from "../../stores/ClientChatStore"; import Chat from '../../components/chat/Chat';
import clientChatStore from '../../stores/ClientChatStore';
// renders "/" // renders "/"
export default function IndexPage() { export default function IndexPage() {
useEffect(() => { useEffect(() => {
try { try {
const model = localStorage.getItem("recentModel"); const model = localStorage.getItem('recentModel');
clientChatStore.setModel(model as string); clientChatStore.setModel(model as string);
} catch (_) { } catch (_) {

View File

@@ -1,22 +1,24 @@
import React, { Fragment } from "react"; import { Box, VStack } from '@chakra-ui/react';
import { Box, VStack } from "@chakra-ui/react"; import React, { Fragment } from 'react';
import PrivacyPolicy from "../../components/legal/LegalDoc";
import privacy_policy from "./privacy_policy"; import { useIsMobile } from '../../components/contexts/MobileContext';
import { useIsMobile } from "../../components/contexts/MobileContext"; import PrivacyPolicy from '../../components/legal/LegalDoc';
import privacy_policy from './privacy_policy';
export default function Page() { export default function Page() {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<Fragment> <Fragment>
<VStack <VStack
width={"100%"} width={'100%'}
align={"center"} align={'center'}
height={!isMobile ? "100%" : "100%"} height={!isMobile ? '100%' : '100%'}
overflowX={"auto"} overflowX={'auto'}
> >
<Box <Box
overflowY={isMobile ? "scroll" : undefined} overflowY={isMobile ? 'scroll' : undefined}
maxH={!isMobile ? "70vh" : "89vh"} maxH={!isMobile ? '70vh' : '89vh'}
mt={isMobile ? 24 : undefined} mt={isMobile ? 24 : undefined}
> >
<PrivacyPolicy text={privacy_policy} /> <PrivacyPolicy text={privacy_policy} />

View File

@@ -1,4 +1,4 @@
const privacyPolicyUpdateDate = new Date().toISOString().split("T")[0]; const privacyPolicyUpdateDate = new Date().toISOString().split('T')[0];
export default ` export default `
### Privacy Policy ### Privacy Policy

View File

@@ -1,22 +1,24 @@
import React, { Fragment } from "react"; import { Box, VStack } from '@chakra-ui/react';
import { Box, VStack } from "@chakra-ui/react"; import React, { Fragment } from 'react';
import TermsOfService from "../../components/legal/LegalDoc";
import terms_of_service from "./terms_of_service"; import { useIsMobile } from '../../components/contexts/MobileContext';
import { useIsMobile } from "../../components/contexts/MobileContext"; import TermsOfService from '../../components/legal/LegalDoc';
import terms_of_service from './terms_of_service';
export default function Page() { export default function Page() {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
return ( return (
<Fragment> <Fragment>
<VStack <VStack
width={"100%"} width={'100%'}
align={"center"} align={'center'}
height={!isMobile ? "100%" : "100%"} height={!isMobile ? '100%' : '100%'}
overflowX={"auto"} overflowX={'auto'}
> >
<Box <Box
overflowY={isMobile ? "scroll" : undefined} overflowY={isMobile ? 'scroll' : undefined}
maxH={!isMobile ? "70vh" : "89vh"} maxH={!isMobile ? '70vh' : '89vh'}
mt={isMobile ? 24 : undefined} mt={isMobile ? 24 : undefined}
> >
<TermsOfService text={terms_of_service} /> <TermsOfService text={terms_of_service} />

View File

@@ -1,4 +1,4 @@
const tosUpdateDate = new Date().toISOString().split("T")[0]; const tosUpdateDate = new Date().toISOString().split('T')[0];
export default ` export default `
### Terms of Service ### Terms of Service

View File

@@ -1,6 +1,6 @@
import type { Config } from "vike/types"; import type { Config } from 'vike/types';
// https://vike.dev/config // https://vike.dev/config
export default { export default {
passToClient: ["pageProps", "urlPathname"], passToClient: ['pageProps', 'urlPathname'],
} satisfies Config; } satisfies Config;

View File

@@ -1,14 +1,15 @@
export { onRenderClient }; export { onRenderClient };
import React from "react"; import React from 'react';
import { hydrateRoot } from "react-dom/client"; import { hydrateRoot } from 'react-dom/client';
import { Layout } from "../layout/Layout";
import { Layout } from '../layout/Layout';
// See https://vike.dev/onRenderClient for usage details // See https://vike.dev/onRenderClient for usage details
async function onRenderClient(pageContext) { async function onRenderClient(pageContext) {
const { Page, pageProps } = pageContext; const { Page, pageProps } = pageContext;
hydrateRoot( hydrateRoot(
document.getElementById("page-view"), document.getElementById('page-view'),
<Layout pageContext={pageContext}> <Layout pageContext={pageContext}>
<Page {...pageProps} /> <Page {...pageProps} />
</Layout>, </Layout>,

View File

@@ -1,15 +1,14 @@
import React from "react"; import React from 'react';
import { renderToStream } from 'react-streaming/server';
import { escapeInject } from 'vike/server';
import type { OnRenderHtmlAsync } from 'vike/types';
import { Layout } from '../layout/Layout';
export { onRenderHtml }; export { onRenderHtml };
import { renderToStream } from "react-streaming/server";
import { escapeInject } from "vike/server";
import { Layout } from "../layout/Layout";
import type { OnRenderHtmlAsync } from "vike/types";
// See https://vike.dev/onRenderHtml for usage details // See https://vike.dev/onRenderHtml for usage details
const onRenderHtml: OnRenderHtmlAsync = async ( const onRenderHtml: OnRenderHtmlAsync = async (pageContext): ReturnType<OnRenderHtmlAsync> => {
pageContext,
): ReturnType<OnRenderHtmlAsync> => {
const { Page, pageProps } = pageContext; const { Page, pageProps } = pageContext;
const page = ( const page = (
@@ -20,9 +19,9 @@ const onRenderHtml: OnRenderHtmlAsync = async (
let ua; let ua;
try { try {
ua = pageContext.headers["user-agent"]; ua = pageContext.headers['user-agent'];
} catch (e) { } catch (e) {
ua = ""; ua = '';
} }
const res = escapeInject`<!DOCTYPE html> const res = escapeInject`<!DOCTYPE html>

View File

@@ -1,14 +1,14 @@
export default { export default {
"/": { sidebarLabel: "Home", heroLabel: "gsio" }, '/': { sidebarLabel: 'Home', heroLabel: 'gsio' },
"/connect": { sidebarLabel: "Connect", heroLabel: "connect" }, '/connect': { sidebarLabel: 'Connect', heroLabel: 'connect' },
"/privacy-policy": { '/privacy-policy': {
sidebarLabel: "", sidebarLabel: '',
heroLabel: "privacy policy", heroLabel: 'privacy policy',
hideNav: true, hideNav: true,
}, },
"/terms-of-service": { '/terms-of-service': {
sidebarLabel: "", sidebarLabel: '',
heroLabel: "terms of service", heroLabel: 'terms of service',
hideNav: true, hideNav: true,
}, },
}; };

View File

@@ -4,12 +4,13 @@ type Page = (pageProps: PageProps) => React.ReactElement;
type PageProps = Record<string, unknown>; type PageProps = Record<string, unknown>;
declare global { declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
namespace Vike { namespace Vike {
interface PageContext { interface PageContext {
Page: Page; Page: Page;
pageProps?: PageProps; pageProps?: PageProps;
fetch?: typeof fetch; fetch?: typeof fetch;
env: import("@open-gsio/env"); env: import('@open-gsio/env');
} }
} }
} }

View File

@@ -1,5 +1,5 @@
import { useContext, createContext, type ReactNode } from "react"; import { useContext, createContext, type ReactNode } from 'react';
import type { PageContext } from "vike/types"; import type { PageContext } from 'vike/types';
export { PageContextProvider }; export { PageContextProvider };
export { usePageContext }; export { usePageContext };

View File

@@ -1,43 +1,40 @@
export const resumeData = { export const resumeData = {
professionalSummary: professionalSummary:
"Software engineer and DoD veteran with 10+ years of diverse experiences. " + 'Software engineer and DoD veteran with 10+ years of diverse experiences. ' +
"Expertise in cloud technologies, DevOps practices, and full-stack development. " + 'Expertise in cloud technologies, DevOps practices, and full-stack development. ' +
"Solid track record of leading high-stakes projects and teams in both military and civilian sectors.", 'Solid track record of leading high-stakes projects and teams in both military and civilian sectors.',
skills: [ skills: [
"AI: Retrieval Augmented Generation, Meta, Mistral, OpenAI, Anthropic", 'AI: Retrieval Augmented Generation, Meta, Mistral, OpenAI, Anthropic',
"Cloud: Cloudflare, Google GKE, Amazon AWS Lambda, PCF/TAS, TrueNAS", 'Cloud: Cloudflare, Google GKE, Amazon AWS Lambda, PCF/TAS, TrueNAS',
"DEVOPS: Pulumi, Helm, Docker", 'DEVOPS: Pulumi, Helm, Docker',
"CI/CD: Github Actions, Gitlab CI", 'CI/CD: Github Actions, Gitlab CI',
"Languages: Typescript, Javascript, Rust, Python, Java, Go", 'Languages: Typescript, Javascript, Rust, Python, Java, Go',
"Databases: Durable Objects, Postgres, MySQL, Snowflake, Elasticsearch", 'Databases: Durable Objects, Postgres, MySQL, Snowflake, Elasticsearch',
"Other: Isolate Compute, WASM Toolchains, Microservice Architectures, GraphQL", 'Other: Isolate Compute, WASM Toolchains, Microservice Architectures, GraphQL',
], ],
experience: [ experience: [
{ {
title: "Senior Software Engineer", title: 'Senior Software Engineer',
company: "Orbis Operations LLC", company: 'Orbis Operations LLC',
timeline: "Mar 2022 - Aug 2024", timeline: 'Mar 2022 - Aug 2024',
description: description: 'Architected and delivered AI products with a focus in national security.',
"Architected and delivered AI products with a focus in national security.",
}, },
{ {
title: "Software Engineer", title: 'Software Engineer',
company: "JSOC", company: 'JSOC',
timeline: "Jan 2020 - Mar 2022", timeline: 'Jan 2020 - Mar 2022',
description: description: 'Spearheaded development of mission-critical data analytics systems.',
"Spearheaded development of mission-critical data analytics systems.",
}, },
{ {
title: "U.S. Army Ranger", title: 'U.S. Army Ranger',
company: "1st Battalion, 75th Ranger Regiment", company: '1st Battalion, 75th Ranger Regiment',
timeline: "Jul 2014 - Sep 2018", timeline: 'Jul 2014 - Sep 2018',
description: description: 'Conducted technical, high-risk operations in diverse environments.',
"Conducted technical, high-risk operations in diverse environments.",
}, },
], ],
education: [ education: [
"Ranger Assessment and Selection Program, U.S. Army", 'Ranger Assessment and Selection Program, U.S. Army',
"Basic Leaders Course, U.S. Army", 'Basic Leaders Course, U.S. Army',
"(In progress) BAS Computer Science", '(In progress) BAS Computer Science',
], ],
}; };

View File

@@ -4,34 +4,34 @@ Working with my partners, I offer a comprehensive skill set to address demanding
If you're facing difficult technical challenges and need reliable, efficient solutions, let's discuss how I can help.`, If you're facing difficult technical challenges and need reliable, efficient solutions, let's discuss how I can help.`,
offerings: [ offerings: [
{ {
title: "AI Integration and Development Services", title: 'AI Integration and Development Services',
description: description:
"Leverage advanced AI technologies like Retrieval Augmented Generation to develop custom AI solutions. Expertise with platforms such as OpenAI, Meta, Mistral, and Anthropic ensures state-of-the-art AI integration tailored to your business needs.", 'Leverage advanced AI technologies like Retrieval Augmented Generation to develop custom AI solutions. Expertise with platforms such as OpenAI, Meta, Mistral, and Anthropic ensures state-of-the-art AI integration tailored to your business needs.',
}, },
{ {
title: "Cloud Infrastructure and DevOps Consulting", title: 'Cloud Infrastructure and DevOps Consulting',
description: description:
"Provide comprehensive cloud solutions using platforms like Google GKE, AWS Lambda, and Cloudflare. Implement DevOps best practices with tools like Pulumi, Helm, and Docker to streamline your development pipeline and enhance scalability.", 'Provide comprehensive cloud solutions using platforms like Google GKE, AWS Lambda, and Cloudflare. Implement DevOps best practices with tools like Pulumi, Helm, and Docker to streamline your development pipeline and enhance scalability.',
}, },
{ {
title: "Full-Stack Development Services", title: 'Full-Stack Development Services',
description: description:
"Offer full-stack development expertise across multiple languages including TypeScript, Rust, Python, Java, and Go. Build robust, high-performance applications that meet your specific requirements.", 'Offer full-stack development expertise across multiple languages including TypeScript, Rust, Python, Java, and Go. Build robust, high-performance applications that meet your specific requirements.',
}, },
{ {
title: "Data Analytics and Visualization Solutions", title: 'Data Analytics and Visualization Solutions',
description: description:
"Develop mission-critical data analytics systems to unlock valuable insights. Utilize databases like PostgreSQL, MySQL, Snowflake, and Elasticsearch for efficient data management and retrieval.", 'Develop mission-critical data analytics systems to unlock valuable insights. Utilize databases like PostgreSQL, MySQL, Snowflake, and Elasticsearch for efficient data management and retrieval.',
}, },
{ {
title: "Real-Time Communication Systems", title: 'Real-Time Communication Systems',
description: description:
"Design and implement robust real-time communication systems, drawing from experience in developing solutions for special operations forces. Ensure secure, reliable, and efficient communication channels for your organization.", 'Design and implement robust real-time communication systems, drawing from experience in developing solutions for special operations forces. Ensure secure, reliable, and efficient communication channels for your organization.',
}, },
{ {
title: "Technical Leadership and Project Management", title: 'Technical Leadership and Project Management',
description: description:
"Provide leadership in high-stakes projects, guiding teams through complex technical challenges. Combine military discipline with technical expertise to deliver projects on time and within scope.", 'Provide leadership in high-stakes projects, guiding teams through complex technical challenges. Combine military discipline with technical expertise to deliver projects on time and within scope.',
}, },
], ],
}; };

View File

@@ -1,10 +1,10 @@
import { types } from "mobx-state-tree"; import { types } from 'mobx-state-tree';
const AppMenuStateModel = types const AppMenuStateModel = types
.model("AppMenuState", { .model('AppMenuState', {
isOpen: types.optional(types.boolean, false), isOpen: types.optional(types.boolean, false),
}) })
.actions((self) => ({ .actions(self => ({
openMenu() { openMenu() {
self.isOpen = true; self.isOpen = true;
}, },

View File

@@ -1,15 +1,16 @@
// --------------------------- // ---------------------------
// stores/ClientChatStore.ts (root) // stores/ClientChatStore.ts (root)
// --------------------------- // ---------------------------
import { types, type Instance } from "mobx-state-tree"; import { types, type Instance } from 'mobx-state-tree';
import { MessagesStore } from "./MessagesStore";
import { UIStore } from "./UIStore"; import { MessagesStore } from './MessagesStore';
import { ModelStore } from "./ModelStore"; import { ModelStore } from './ModelStore';
import { StreamStore } from "./StreamStore"; import { StreamStore } from './StreamStore';
import { UIStore } from './UIStore';
export const ClientChatStore = types export const ClientChatStore = types
.compose(MessagesStore, UIStore, ModelStore, StreamStore) .compose(MessagesStore, UIStore, ModelStore, StreamStore)
.named("ClientChatStore"); .named('ClientChatStore');
const clientChatStore = ClientChatStore.create(); const clientChatStore = ClientChatStore.create();

View File

@@ -1,44 +1,44 @@
import { types, flow } from "mobx-state-tree"; import { types, flow } from 'mobx-state-tree';
const ClientFeedbackStore = types const ClientFeedbackStore = types
.model("ClientFeedbackStore", { .model('ClientFeedbackStore', {
input: types.optional(types.string, ""), input: types.optional(types.string, ''),
isLoading: types.optional(types.boolean, false), isLoading: types.optional(types.boolean, false),
isSubmitted: types.optional(types.boolean, false), isSubmitted: types.optional(types.boolean, false),
error: types.optional(types.string, ""), error: types.optional(types.string, ''),
}) })
.actions((self) => { .actions(self => {
const setError = (error) => { const setError = error => {
self.error = error; self.error = error;
}; };
const setInput = (value) => { const setInput = value => {
self.input = value; self.input = value;
if (self.error) { if (self.error) {
setError(""); setError('');
} }
}; };
const reset = () => { const reset = () => {
self.input = ""; self.input = '';
self.isLoading = false; self.isLoading = false;
self.isSubmitted = false; self.isSubmitted = false;
self.error = ""; self.error = '';
}; };
const validateInput = () => { const validateInput = () => {
if (!self.input.trim()) { if (!self.input.trim()) {
setError("Feedback cannot be empty."); setError('Feedback cannot be empty.');
return false; return false;
} }
if (self.input.length > 500) { if (self.input.length > 500) {
setError("Feedback cannot exceed 500 characters."); setError('Feedback cannot exceed 500 characters.');
return false; return false;
} }
setError(""); setError('');
return true; return true;
}; };
@@ -50,10 +50,10 @@ const ClientFeedbackStore = types
self.isLoading = true; self.isLoading = true;
try { try {
const response = yield fetch("/api/feedback", { const response = yield fetch('/api/feedback', {
method: "POST", method: 'POST',
headers: { headers: {
"Content-Type": "application/json", 'Content-Type': 'application/json',
}, },
body: JSON.stringify({ feedback: self.input }), body: JSON.stringify({ feedback: self.input }),
}); });
@@ -63,13 +63,11 @@ const ClientFeedbackStore = types
} }
self.isSubmitted = true; self.isSubmitted = true;
self.input = ""; self.input = '';
return true; return true;
} catch (error) { } catch (error) {
console.error(error); console.error(error);
setError( setError(error.message || 'An error occurred while submitting feedback.');
error.message || "An error occurred while submitting feedback.",
);
return false; return false;
} finally { } finally {
self.isLoading = false; self.isLoading = false;

View File

@@ -1,15 +1,15 @@
import { types, flow } from "mobx-state-tree"; import { types, flow } from 'mobx-state-tree';
const ClientTransactionStore = types const ClientTransactionStore = types
.model("ClientTransactionStore", { .model('ClientTransactionStore', {
selectedMethod: types.string, selectedMethod: types.string,
depositAddress: types.maybeNull(types.string), depositAddress: types.maybeNull(types.string),
amount: types.optional(types.string, ""), amount: types.optional(types.string, ''),
donerId: types.optional(types.string, ""), donerId: types.optional(types.string, ''),
userConfirmed: types.optional(types.boolean, false), userConfirmed: types.optional(types.boolean, false),
txId: types.optional(types.string, ""), txId: types.optional(types.string, ''),
}) })
.actions((self) => ({ .actions(self => ({
setSelectedMethod(method: string) { setSelectedMethod(method: string) {
self.selectedMethod = method; self.selectedMethod = method;
self.userConfirmed = false; self.userConfirmed = false;
@@ -30,47 +30,45 @@ const ClientTransactionStore = types
self.depositAddress = address; self.depositAddress = address;
}, },
resetTransaction() { resetTransaction() {
self.txId = ""; self.txId = '';
self.depositAddress = null; self.depositAddress = null;
self.userConfirmed = false; self.userConfirmed = false;
}, },
prepareTransaction: flow(function* () { prepareTransaction: flow(function* () {
if (!self.amount || !self.donerId || parseInt(self.amount) <= 0) { if (!self.amount || !self.donerId || parseInt(self.amount) <= 0) {
throw new Error("Invalid donation data"); throw new Error('Invalid donation data');
} }
const currency = self.selectedMethod.toLowerCase(); const currency = self.selectedMethod.toLowerCase();
try { try {
const response = yield fetch("/api/tx", { const response = yield fetch('/api/tx', {
method: "POST", method: 'POST',
body: ["PREPARE_TX", self.donerId, currency, self.amount] body: ['PREPARE_TX', self.donerId, currency, self.amount].join(',').trim(),
.join(",")
.trim(),
}); });
if (!response.ok) throw new Error("Failed to prepare transaction"); if (!response.ok) throw new Error('Failed to prepare transaction');
const txData = yield response.json(); const txData = yield response.json();
let finalDepositAddress = txData.depositAddress; let finalDepositAddress = txData.depositAddress;
if (currency === "ethereum") { if (currency === 'ethereum') {
finalDepositAddress = "0x" + finalDepositAddress; finalDepositAddress = '0x' + finalDepositAddress;
} }
self.setTransactionId(txData.txKey); self.setTransactionId(txData.txKey);
self.setDepositAddress(finalDepositAddress); self.setDepositAddress(finalDepositAddress);
self.confirmUser(); self.confirmUser();
} catch (error) { } catch (error) {
console.error("Transaction preparation failed:", error); console.error('Transaction preparation failed:', error);
throw error; throw error;
} }
}), }),
})); }));
export default ClientTransactionStore.create({ export default ClientTransactionStore.create({
selectedMethod: "Ethereum", selectedMethod: 'Ethereum',
depositAddress: null, depositAddress: null,
amount: "", amount: '',
donerId: "", donerId: '',
userConfirmed: false, userConfirmed: false,
txId: "", txId: '',
}); });

View File

@@ -1,38 +1,40 @@
import {types, type Instance} from "mobx-state-tree"; import { types, type Instance } from 'mobx-state-tree';
import clientChatStore from "./ClientChatStore";
import UserOptionsStore from "./UserOptionsStore"; import Message, { batchContentUpdate } from '../models/Message';
import Message, { batchContentUpdate } from "../models/Message";
import {MessagesStore} from "./MessagesStore"; import clientChatStore from './ClientChatStore';
import { MessagesStore } from './MessagesStore';
import UserOptionsStore from './UserOptionsStore';
export const MessageEditorStore = types export const MessageEditorStore = types
.compose( .compose(
MessagesStore, MessagesStore,
types.model("MessageEditorStore", { types.model('MessageEditorStore', {
editedContent: types.optional(types.string, ""), editedContent: types.optional(types.string, ''),
messageId: types.optional(types.string, "") messageId: types.optional(types.string, ''),
}) }),
) )
.views((self) => ({ .views(self => ({
getMessage() { getMessage() {
// Find the message in clientChatStore by ID // Find the message in clientChatStore by ID
if (!self.messageId) return null; if (!self.messageId) return null;
const message = clientChatStore.items.find(item => item.id === self.messageId); const message = clientChatStore.items.find(item => item.id === self.messageId);
return message || null; return message || null;
} },
})) }))
.actions((self) => ({ .actions(self => ({
setEditedContent(content: string) { setEditedContent(content: string) {
self.editedContent = content; self.editedContent = content;
}, },
setMessage(message: Instance<typeof Message>) { setMessage(message: Instance<typeof Message>) {
// Handle messages that might not have an id property (for testing) // Handle messages that might not have an id property (for testing)
self.messageId = message.id || ""; self.messageId = message.id || '';
self.editedContent = message.content; self.editedContent = message.content;
}, },
onCancel() { onCancel() {
self.messageId = ""; self.messageId = '';
self.editedContent = ""; self.editedContent = '';
}, },
handleSave: async () => { handleSave: async () => {
// Get the message using the ID // Get the message using the ID
@@ -63,28 +65,28 @@ export const MessageEditorStore = types
try { try {
// Add a small delay before adding the assistant message (for better UX) // Add a small delay before adding the assistant message (for better UX)
await new Promise((r) => setTimeout(r, 500)); await new Promise(r => setTimeout(r, 500));
// Add an empty assistant message to clientChatStore's items // Add an empty assistant message to clientChatStore's items
clientChatStore.add(Message.create({content: "", role: "assistant"})); clientChatStore.add(Message.create({ content: '', role: 'assistant' }));
// Use clientChatStore for the API call since it has the model property // Use clientChatStore for the API call since it has the model property
const payload = { messages: clientChatStore.items.slice(), model: clientChatStore.model }; const payload = { messages: clientChatStore.items.slice(), model: clientChatStore.model };
// Make API call // Make API call
const response = await fetch("/api/chat", { const response = await fetch('/api/chat', {
method: "POST", method: 'POST',
headers: {"Content-Type": "application/json"}, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload), body: JSON.stringify(payload),
}); });
if (response.status === 429) { if (response.status === 429) {
clientChatStore.appendLast("\n\nError: Too many requests • please slow down."); clientChatStore.appendLast('\n\nError: Too many requests • please slow down.');
clientChatStore.setIsLoading(false); clientChatStore.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
return; return;
} }
if (response.status > 200) { if (response.status > 200) {
clientChatStore.appendLast("\n\nError: Something went wrong."); clientChatStore.appendLast('\n\nError: Something went wrong.');
clientChatStore.setIsLoading(false); clientChatStore.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
return; return;
@@ -96,13 +98,13 @@ export const MessageEditorStore = types
const eventSource = new EventSource(streamUrl); const eventSource = new EventSource(streamUrl);
// Set up event handlers using a more efficient approach // Set up event handlers using a more efficient approach
const handleMessage = (event) => { const handleMessage = event => {
try { try {
const parsed = JSON.parse(event.data); const parsed = JSON.parse(event.data);
if (parsed.type === "error") { if (parsed.type === 'error') {
// Append error message instead of replacing content // Append error message instead of replacing content
clientChatStore.appendLast("\n\nError: " + parsed.error); clientChatStore.appendLast('\n\nError: ' + parsed.error);
clientChatStore.setIsLoading(false); clientChatStore.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
eventSource.close(); eventSource.close();
@@ -112,9 +114,9 @@ export const MessageEditorStore = types
// Get the last message to use its streamContent method // Get the last message to use its streamContent method
const lastMessage = clientChatStore.items[clientChatStore.items.length - 1]; const lastMessage = clientChatStore.items[clientChatStore.items.length - 1];
if (parsed.type === "chat" && parsed.data.choices[0]?.finish_reason === "stop") { if (parsed.type === 'chat' && parsed.data.choices[0]?.finish_reason === 'stop') {
// For the final chunk, append it and close the connection // For the final chunk, append it and close the connection
const content = parsed.data.choices[0]?.delta?.content ?? ""; const content = parsed.data.choices[0]?.delta?.content ?? '';
if (content) { if (content) {
// Use appendLast for the final chunk to ensure it's added immediately // Use appendLast for the final chunk to ensure it's added immediately
clientChatStore.appendLast(content); clientChatStore.appendLast(content);
@@ -125,21 +127,21 @@ export const MessageEditorStore = types
return; return;
} }
if (parsed.type === "chat") { if (parsed.type === 'chat') {
// For regular chunks, use the batched content update for a smoother effect // For regular chunks, use the batched content update for a smoother effect
const content = parsed.data.choices[0]?.delta?.content ?? ""; const content = parsed.data.choices[0]?.delta?.content ?? '';
if (content && lastMessage) { if (content && lastMessage) {
// Use the batching utility for more efficient updates // Use the batching utility for more efficient updates
batchContentUpdate(lastMessage, content); batchContentUpdate(lastMessage, content);
} }
} }
} catch (err) { } catch (err) {
console.error("stream parse error", err); console.error('stream parse error', err);
} }
}; };
const handleError = () => { const handleError = () => {
clientChatStore.appendLast("\n\nError: Connection lost."); clientChatStore.appendLast('\n\nError: Connection lost.');
clientChatStore.setIsLoading(false); clientChatStore.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
eventSource.close(); eventSource.close();
@@ -148,13 +150,13 @@ export const MessageEditorStore = types
eventSource.onmessage = handleMessage; eventSource.onmessage = handleMessage;
eventSource.onerror = handleError; eventSource.onerror = handleError;
} catch (err) { } catch (err) {
console.error("sendMessage", err); console.error('sendMessage', err);
clientChatStore.appendLast("\n\nError: Sorry • network error."); clientChatStore.appendLast('\n\nError: Sorry • network error.');
clientChatStore.setIsLoading(false); clientChatStore.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
} }
} catch (err) { } catch (err) {
console.error("Error in handleSave:", err); console.error('Error in handleSave:', err);
// If any error occurs, just cancel the edit // If any error occurs, just cancel the edit
self.onCancel(); self.onCancel();
return; return;
@@ -162,7 +164,7 @@ export const MessageEditorStore = types
// Always clean up at the end // Always clean up at the end
self.onCancel(); self.onCancel();
} },
})); }));
const messageEditorStore = MessageEditorStore.create(); const messageEditorStore = MessageEditorStore.create();

View File

@@ -1,14 +1,15 @@
// --------------------------- // ---------------------------
// stores/MessagesStore.ts // stores/MessagesStore.ts
// --------------------------- // ---------------------------
import { type Instance, types } from "mobx-state-tree"; import { type Instance, types } from 'mobx-state-tree';
import Message from "../models/Message";
import Message from '../models/Message';
export const MessagesStore = types export const MessagesStore = types
.model("MessagesStore", { .model('MessagesStore', {
items: types.optional(types.array(Message), []), items: types.optional(types.array(Message), []),
}) })
.actions((self) => ({ .actions(self => ({
add(message: Instance<typeof Message>) { add(message: Instance<typeof Message>) {
self.items.push(message); self.items.push(message);
}, },

View File

@@ -1,24 +1,22 @@
// --------------------------- // ---------------------------
// stores/ModelStore.ts // stores/ModelStore.ts
// --------------------------- // ---------------------------
import { type Instance, types } from "mobx-state-tree"; import { type Instance, types } from 'mobx-state-tree';
export const ModelStore = types export const ModelStore = types
.model("ModelStore", { .model('ModelStore', {
model: types.optional( model: types.optional(types.string, 'meta-llama/llama-4-scout-17b-16e-instruct'),
types.string, imageModel: types.optional(types.string, 'black-forest-labs/flux-1.1-pro'),
"meta-llama/llama-4-scout-17b-16e-instruct",
),
imageModel: types.optional(types.string, "black-forest-labs/flux-1.1-pro"),
supportedModels: types.optional(types.array(types.string), []), supportedModels: types.optional(types.array(types.string), []),
}) })
.actions((self) => ({ .actions(self => ({
setModel(value: string) { setModel(value: string) {
self.model = value; self.model = value;
try { try {
localStorage.setItem("recentModel", value); localStorage.setItem('recentModel', value);
} catch (_) {} } catch (_) {
// Silently ignore localStorage errors (e.g., in environments where it's not available)
}
}, },
setImageModel(value: string) { setImageModel(value: string) {
self.imageModel = value; self.imageModel = value;

View File

@@ -1,5 +1,5 @@
import type {IMessagesStore} from "./MessagesStore.ts"; import type { IMessagesStore } from './MessagesStore.ts';
import type {IUIStore} from "./UIStore.ts"; import type { IModelStore } from './ModelStore.ts';
import type {IModelStore} from "./ModelStore.ts"; import type { IUIStore } from './UIStore.ts';
export type RootDeps = IMessagesStore & IUIStore & IModelStore; export type RootDeps = IMessagesStore & IUIStore & IModelStore;

View File

@@ -1,16 +1,19 @@
import {flow, getParent, type Instance, types} from "mobx-state-tree"; import { flow, getParent, type Instance, types } from 'mobx-state-tree';
import UserOptionsStore from "./UserOptionsStore";
import Message, { batchContentUpdate } from "../models/Message"; import Message, { batchContentUpdate } from '../models/Message';
import type {RootDeps} from "./RootDeps.ts";
import type { RootDeps } from './RootDeps.ts';
import UserOptionsStore from './UserOptionsStore';
export const StreamStore = types export const StreamStore = types
.model("StreamStore", { .model('StreamStore', {
streamId: types.optional(types.string, ""), streamId: types.optional(types.string, ''),
}) })
.volatile(() => ({ .volatile(() => ({
eventSource: undefined as unknown as EventSource, eventSource: undefined as unknown as EventSource,
})) }))
.actions((self: any) => { // ← annotate `self` so it isnt implicitly `any` .actions((self: any) => {
// ← annotate `self` so it isnt implicitly `any`
let root: RootDeps; let root: RootDeps;
try { try {
root = getParent<RootDeps>(self); root = getParent<RootDeps>(self);
@@ -26,7 +29,7 @@ export const StreamStore = types
try { try {
self.eventSource.close(); self.eventSource.close();
} catch (e) { } catch (e) {
console.error("error closing event source", e); console.error('error closing event source', e);
} finally { } finally {
setEventSource(null); setEventSource(null);
} }
@@ -42,31 +45,31 @@ export const StreamStore = types
const userMessage = Message.create({ const userMessage = Message.create({
content: root.input, content: root.input,
role: "user" as const, role: 'user' as const,
}); });
root.add(userMessage); root.add(userMessage);
root.setInput(""); root.setInput('');
try { try {
const payload = { messages: root.items.slice(), model: root.model }; const payload = { messages: root.items.slice(), model: root.model };
yield new Promise((r) => setTimeout(r, 500)); yield new Promise(r => setTimeout(r, 500));
root.add(Message.create({ content: "", role: "assistant" })); root.add(Message.create({ content: '', role: 'assistant' }));
const response: Response = yield fetch("/api/chat", { const response: Response = yield fetch('/api/chat', {
method: "POST", method: 'POST',
headers: { "Content-Type": "application/json" }, headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(payload), body: JSON.stringify(payload),
}); });
if (response.status === 429) { if (response.status === 429) {
root.appendLast("\n\nError: Too many requests • please slow down."); root.appendLast('\n\nError: Too many requests • please slow down.');
cleanup(); cleanup();
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
return; return;
} }
if (response.status > 200) { if (response.status > 200) {
root.appendLast("\n\nError: Something went wrong."); root.appendLast('\n\nError: Something went wrong.');
cleanup(); cleanup();
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
return; return;
@@ -80,9 +83,9 @@ export const StreamStore = types
try { try {
const parsed = JSON.parse(event.data); const parsed = JSON.parse(event.data);
if (parsed.type === "error") { if (parsed.type === 'error') {
// Append error message instead of replacing content // Append error message instead of replacing content
root.appendLast("\n\nError: " + parsed.error); root.appendLast('\n\nError: ' + parsed.error);
root.setIsLoading(false); root.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
cleanup(); cleanup();
@@ -92,12 +95,9 @@ export const StreamStore = types
// Get the last message // Get the last message
const lastMessage = root.items[root.items.length - 1]; const lastMessage = root.items[root.items.length - 1];
if ( if (parsed.type === 'chat' && parsed.data.choices[0]?.finish_reason === 'stop') {
parsed.type === "chat" &&
parsed.data.choices[0]?.finish_reason === "stop"
) {
// For the final chunk, append it and close the connection // For the final chunk, append it and close the connection
const content = parsed.data.choices[0]?.delta?.content ?? ""; const content = parsed.data.choices[0]?.delta?.content ?? '';
if (content) { if (content) {
// Use appendLast for the final chunk to ensure it's added immediately // Use appendLast for the final chunk to ensure it's added immediately
root.appendLast(content); root.appendLast(content);
@@ -108,21 +108,21 @@ export const StreamStore = types
return; return;
} }
if (parsed.type === "chat") { if (parsed.type === 'chat') {
// For regular chunks, use the batched content update for a smoother effect // For regular chunks, use the batched content update for a smoother effect
const content = parsed.data.choices[0]?.delta?.content ?? ""; const content = parsed.data.choices[0]?.delta?.content ?? '';
if (content && lastMessage) { if (content && lastMessage) {
// Use the batching utility for more efficient updates // Use the batching utility for more efficient updates
batchContentUpdate(lastMessage, content); batchContentUpdate(lastMessage, content);
} }
} }
} catch (err) { } catch (err) {
console.error("stream parse error", err); console.error('stream parse error', err);
} }
}; };
const handleError = () => { const handleError = () => {
root.appendLast("\n\nError: Connection lost."); root.appendLast('\n\nError: Connection lost.');
root.setIsLoading(false); root.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
cleanup(); cleanup();
@@ -131,8 +131,8 @@ export const StreamStore = types
self.eventSource.onmessage = handleMessage; self.eventSource.onmessage = handleMessage;
self.eventSource.onerror = handleError; self.eventSource.onerror = handleError;
} catch (err) { } catch (err) {
console.error("sendMessage", err); console.error('sendMessage', err);
root.appendLast("\n\nError: Sorry • network error."); root.appendLast('\n\nError: Sorry • network error.');
root.setIsLoading(false); root.setIsLoading(false);
UserOptionsStore.setFollowModeEnabled(false); UserOptionsStore.setFollowModeEnabled(false);
cleanup(); cleanup();

View File

@@ -1,15 +1,14 @@
// --------------------------- // ---------------------------
// stores/UIStore.ts // stores/UIStore.ts
// --------------------------- // ---------------------------
import { type Instance, types } from "mobx-state-tree"; import { type Instance, types } from 'mobx-state-tree';
export const UIStore = types export const UIStore = types
.model("UIStore", { .model('UIStore', {
input: types.optional(types.string, ""), input: types.optional(types.string, ''),
isLoading: types.optional(types.boolean, false), isLoading: types.optional(types.boolean, false),
}) })
.actions((self) => ({ .actions(self => ({
setInput(value: string) { setInput(value: string) {
self.input = value; self.input = value;
}, },

Some files were not shown because too many files have changed in this diff Show More