mirror of
https://github.com/geoffsee/open-gsio.git
synced 2025-09-08 22:56:46 +00:00
adds eslint
This commit is contained in:

committed by
Geoff Seemueller

parent
9698fc6f3b
commit
02c3253343
41
.eslintignore
Normal file
41
.eslintignore
Normal 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
49
.eslintrc.cjs
Normal 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
47
.prettierignore
Normal 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
19
.prettierrc.cjs
Normal 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
331
bun.lock
@@ -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=="],
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
18
package.json
18
package.json
@@ -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"
|
|
||||||
}
|
}
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
// for future use
|
// for future use
|
||||||
export {}
|
export {};
|
||||||
|
@@ -1,17 +1,17 @@
|
|||||||
#!/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,
|
||||||
options: {},
|
options: {},
|
||||||
strict: true,
|
strict: true,
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@@ -1,17 +1,16 @@
|
|||||||
#!/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,
|
||||||
options: {},
|
options: {},
|
||||||
strict: true,
|
strict: true,
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
@@ -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;
|
||||||
|
@@ -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}
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
|
@@ -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>
|
||||||
|
@@ -1,37 +1,38 @@
|
|||||||
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', () => ({
|
||||||
getColorThemes: () => [
|
getColorThemes: () => [
|
||||||
{
|
{
|
||||||
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', () => {
|
||||||
@@ -42,20 +43,20 @@ describe('ThemeSelectionOptions', () => {
|
|||||||
it('renders theme options for desktop view', () => {
|
it('renders theme options for desktop view', () => {
|
||||||
// Mock useIsMobile to return false (desktop view)
|
// Mock useIsMobile to return false (desktop view)
|
||||||
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(false);
|
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(false);
|
||||||
|
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders theme options for mobile view', () => {
|
it('renders theme options for mobile view', () => {
|
||||||
// Mock useIsMobile to return true (mobile view)
|
// Mock useIsMobile to return true (mobile view)
|
||||||
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(true);
|
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(true);
|
||||||
|
|
||||||
render(<ThemeSelectionOptions />);
|
render(<ThemeSelectionOptions />);
|
||||||
|
|
||||||
// Should still render 2 theme buttons
|
// Should still render 2 theme buttons
|
||||||
const buttons = screen.getAllByRole('button');
|
const buttons = screen.getAllByRole('button');
|
||||||
expect(buttons).toHaveLength(2);
|
expect(buttons).toHaveLength(2);
|
||||||
@@ -63,16 +64,16 @@ describe('ThemeSelectionOptions', () => {
|
|||||||
|
|
||||||
it('calls selectTheme when a theme button is clicked', () => {
|
it('calls selectTheme when a theme button is clicked', () => {
|
||||||
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(false);
|
vi.spyOn(MobileContext, 'useIsMobile').mockReturnValue(false);
|
||||||
|
|
||||||
render(<ThemeSelectionOptions />);
|
render(<ThemeSelectionOptions />);
|
||||||
|
|
||||||
const buttons = screen.getAllByRole('button');
|
const buttons = screen.getAllByRole('button');
|
||||||
fireEvent.click(buttons[0]); // Click the first theme button (light)
|
fireEvent.click(buttons[0]); // Click the first theme button (light)
|
||||||
|
|
||||||
// Verify that selectTheme was called with the correct theme name
|
// Verify that selectTheme was called with the correct theme name
|
||||||
expect(userOptionsStore.selectTheme).toHaveBeenCalledWith('light');
|
expect(userOptionsStore.selectTheme).toHaveBeenCalledWith('light');
|
||||||
|
|
||||||
fireEvent.click(buttons[1]); // Click the second theme button (dark)
|
fireEvent.click(buttons[1]); // Click the second theme button (dark)
|
||||||
expect(userOptionsStore.selectTheme).toHaveBeenCalledWith('dark');
|
expect(userOptionsStore.selectTheme).toHaveBeenCalledWith('dark');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -1,22 +1,23 @@
|
|||||||
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', () => {
|
||||||
it('renders correctly when visible', () => {
|
it('renders correctly when visible', () => {
|
||||||
render(<WelcomeHomeMessage visible={true} />);
|
render(<WelcomeHomeMessage visible={true} />);
|
||||||
|
|
||||||
// Check if the rendered markdown content is in the document
|
// Check if the rendered markdown content is in the document
|
||||||
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
||||||
expect(screen.getByText(`Rendered: ${welcome_home_tip}`)).toBeInTheDocument();
|
expect(screen.getByText(`Rendered: ${welcome_home_tip}`)).toBeInTheDocument();
|
||||||
|
|
||||||
// Verify that renderMarkdown was called with the correct arguments
|
// Verify that renderMarkdown was called with the correct arguments
|
||||||
expect(renderMarkdown).toHaveBeenCalledWith(welcome_home_text);
|
expect(renderMarkdown).toHaveBeenCalledWith(welcome_home_text);
|
||||||
expect(renderMarkdown).toHaveBeenCalledWith(welcome_home_tip);
|
expect(renderMarkdown).toHaveBeenCalledWith(welcome_home_tip);
|
||||||
@@ -24,17 +25,17 @@ describe('WelcomeHomeMessage', () => {
|
|||||||
|
|
||||||
it('applies animation variants based on visible prop', () => {
|
it('applies animation variants based on visible prop', () => {
|
||||||
const { rerender } = render(<WelcomeHomeMessage visible={true} />);
|
const { rerender } = render(<WelcomeHomeMessage visible={true} />);
|
||||||
|
|
||||||
// When visible is true, the component should have the visible animation state
|
// When visible is true, the component should have the visible animation state
|
||||||
// Since we've mocked framer-motion, we can't directly test the animation state
|
// Since we've mocked framer-motion, we can't directly test the animation state
|
||||||
// But we can verify that the component renders the content
|
// But we can verify that the component renders the content
|
||||||
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
||||||
|
|
||||||
// Re-render with visible=false
|
// Re-render with visible=false
|
||||||
rerender(<WelcomeHomeMessage visible={false} />);
|
rerender(<WelcomeHomeMessage visible={false} />);
|
||||||
|
|
||||||
// Content should still be in the document even when not visible
|
// Content should still be in the document even when not visible
|
||||||
// (since we've mocked the animations)
|
// (since we've mocked the animations)
|
||||||
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
expect(screen.getByText(`Rendered: ${welcome_home_text}`)).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -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>
|
||||||
|
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -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>
|
||||||
))}
|
))}
|
||||||
|
@@ -1,197 +1,190 @@
|
|||||||
import React, {useCallback, useEffect, useRef, useState} from "react";
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Button,
|
Button,
|
||||||
Divider,
|
Divider,
|
||||||
Flex,
|
Flex,
|
||||||
IconButton,
|
IconButton,
|
||||||
Menu,
|
Menu,
|
||||||
MenuButton,
|
MenuButton,
|
||||||
MenuItem,
|
MenuItem,
|
||||||
MenuList,
|
MenuList,
|
||||||
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 { isOpen, onOpen, onClose, onToggle, getDisclosureProps, getButtonProps } = useDisclosure();
|
||||||
const {
|
|
||||||
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[]>([]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setControlledOpen(isOpen);
|
setControlledOpen(isOpen);
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch("/api/models").then(response => response.json()).then((models) => {
|
fetch('/api/models')
|
||||||
setSupportedModels(models);
|
.then(response => response.json())
|
||||||
}).catch((err) => {
|
.then(models => {
|
||||||
console.error("Could not fetch models: ", err);
|
setSupportedModels(models);
|
||||||
});
|
})
|
||||||
}, []);
|
.catch(err => {
|
||||||
|
console.error('Could not fetch models: ', err);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClose = useCallback(() => {
|
||||||
|
onClose();
|
||||||
|
}, [isOpen]);
|
||||||
|
|
||||||
const handleClose = useCallback(() => {
|
const handleCopyConversation = useCallback(() => {
|
||||||
onClose();
|
navigator.clipboard
|
||||||
}, [isOpen]);
|
.writeText(formatConversationMarkdown(clientChatStore.items))
|
||||||
|
.then(() => {
|
||||||
|
window.alert('Conversation copied to clipboard. \n\nPaste it somewhere safe!');
|
||||||
|
onClose();
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('Could not copy text to clipboard: ', err);
|
||||||
|
window.alert('Failed to copy conversation. Please try again.');
|
||||||
|
});
|
||||||
|
}, [onClose]);
|
||||||
|
|
||||||
const handleCopyConversation = useCallback(() => {
|
async function selectModelFn({ name, value }) {
|
||||||
navigator.clipboard
|
clientChatStore.setModel(value);
|
||||||
.writeText(formatConversationMarkdown(clientChatStore.items))
|
}
|
||||||
.then(() => {
|
|
||||||
window.alert(
|
|
||||||
"Conversation copied to clipboard. \n\nPaste it somewhere safe!",
|
|
||||||
);
|
|
||||||
onClose();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error("Could not copy text to clipboard: ", err);
|
|
||||||
window.alert("Failed to copy conversation. Please try again.");
|
|
||||||
});
|
|
||||||
}, [onClose]);
|
|
||||||
|
|
||||||
async function selectModelFn({name, value}) {
|
function isSelectedModelFn({ name, value }) {
|
||||||
clientChatStore.setModel(value);
|
return clientChatStore.model === value;
|
||||||
}
|
}
|
||||||
|
|
||||||
function isSelectedModelFn({name, value}) {
|
const menuRef = useRef();
|
||||||
return clientChatStore.model === value;
|
const [menuState, setMenuState] = useState();
|
||||||
}
|
|
||||||
|
|
||||||
const menuRef = useRef();
|
useOutsideClick({
|
||||||
const [menuState, setMenuState] = useState();
|
enabled: !isMobile && isOpen,
|
||||||
|
ref: menuRef,
|
||||||
useOutsideClick({
|
handler: () => {
|
||||||
enabled: !isMobile && isOpen,
|
handleClose();
|
||||||
ref: menuRef,
|
|
||||||
handler: () => {
|
|
||||||
handleClose();
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Menu
|
|
||||||
isOpen={controlledOpen}
|
|
||||||
onClose={onClose}
|
|
||||||
onOpen={onOpen}
|
|
||||||
autoSelect={false}
|
|
||||||
closeOnSelect={false}
|
|
||||||
closeOnBlur={isOpen && !isMobileUserAgent}
|
|
||||||
isLazy={true}
|
|
||||||
lazyBehavior={"unmount"}
|
|
||||||
>
|
|
||||||
{isMobile ? (
|
|
||||||
<MenuButton
|
|
||||||
as={IconButton}
|
|
||||||
bg="text.accent"
|
|
||||||
icon={<Settings size={20}/>}
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
aria-label="Settings"
|
|
||||||
_hover={{bg: "rgba(255, 255, 255, 0.2)"}}
|
|
||||||
_focus={{boxShadow: "none"}}
|
|
||||||
{...MsM_commonButtonStyles}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<MenuButton
|
|
||||||
as={Button}
|
|
||||||
rightIcon={<ChevronDown size={16}/>}
|
|
||||||
isDisabled={isDisabled}
|
|
||||||
variant="ghost"
|
|
||||||
display="flex"
|
|
||||||
justifyContent="space-between"
|
|
||||||
alignItems="center"
|
|
||||||
minW="auto"
|
|
||||||
{...MsM_commonButtonStyles}
|
|
||||||
>
|
|
||||||
<Text noOfLines={1} maxW="100px" fontSize="sm">
|
|
||||||
{clientChatStore.model}
|
|
||||||
</Text>
|
|
||||||
</MenuButton>
|
|
||||||
)}
|
|
||||||
<MenuList
|
|
||||||
bg="background.tertiary"
|
|
||||||
border="none"
|
|
||||||
borderRadius="md"
|
|
||||||
boxShadow="lg"
|
|
||||||
minW={"10rem"}
|
|
||||||
ref={menuRef}
|
|
||||||
>
|
|
||||||
<FlyoutSubMenu
|
|
||||||
title="Text Models"
|
|
||||||
flyoutMenuOptions={supportedModels.map((modelData) => ({
|
|
||||||
name: modelData.id.split('/').pop() || modelData.id,
|
|
||||||
value: modelData.id
|
|
||||||
}))}
|
|
||||||
onClose={onClose}
|
|
||||||
parentIsOpen={isOpen}
|
|
||||||
setMenuState={setMenuState}
|
|
||||||
handleSelect={selectModelFn}
|
|
||||||
isSelected={isSelectedModelFn}
|
|
||||||
/>
|
|
||||||
<Divider color="text.tertiary"/>
|
|
||||||
{/*Export conversation button*/}
|
|
||||||
<MenuItem
|
|
||||||
bg="background.tertiary"
|
|
||||||
color="text.primary"
|
|
||||||
onClick={handleCopyConversation}
|
|
||||||
_hover={{bg: "rgba(0, 0, 0, 0.05)"}}
|
|
||||||
_focus={{bg: "rgba(0, 0, 0, 0.1)"}}
|
|
||||||
>
|
|
||||||
<Flex align="center">
|
|
||||||
<Copy size="16px" style={{marginRight: "8px"}}/>
|
|
||||||
<Box>Export</Box>
|
|
||||||
</Flex>
|
|
||||||
</MenuItem>
|
|
||||||
{/*New conversation button*/}
|
|
||||||
<MenuItem
|
|
||||||
bg="background.tertiary"
|
|
||||||
color="text.primary"
|
|
||||||
onClick={() => {
|
|
||||||
clientChatStore.setActiveConversation("conversation:new");
|
|
||||||
onClose();
|
|
||||||
}}
|
|
||||||
_hover={{bg: "rgba(0, 0, 0, 0.05)"}}
|
|
||||||
_focus={{bg: "rgba(0, 0, 0, 0.1)"}}
|
|
||||||
>
|
|
||||||
<Flex align="center">
|
|
||||||
<RefreshCcw size="16px" style={{marginRight: "8px"}}/>
|
|
||||||
<Box>New</Box>
|
|
||||||
</Flex>
|
|
||||||
</MenuItem>
|
|
||||||
</MenuList>
|
|
||||||
</Menu>
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Menu
|
||||||
|
isOpen={controlledOpen}
|
||||||
|
onClose={onClose}
|
||||||
|
onOpen={onOpen}
|
||||||
|
autoSelect={false}
|
||||||
|
closeOnSelect={false}
|
||||||
|
closeOnBlur={isOpen && !isMobileUserAgent}
|
||||||
|
isLazy={true}
|
||||||
|
lazyBehavior={'unmount'}
|
||||||
|
>
|
||||||
|
{isMobile ? (
|
||||||
|
<MenuButton
|
||||||
|
as={IconButton}
|
||||||
|
bg="text.accent"
|
||||||
|
icon={<Settings size={20} />}
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
aria-label="Settings"
|
||||||
|
_hover={{ bg: 'rgba(255, 255, 255, 0.2)' }}
|
||||||
|
_focus={{ boxShadow: 'none' }}
|
||||||
|
{...MsM_commonButtonStyles}
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<MenuButton
|
||||||
|
as={Button}
|
||||||
|
rightIcon={<ChevronDown size={16} />}
|
||||||
|
isDisabled={isDisabled}
|
||||||
|
variant="ghost"
|
||||||
|
display="flex"
|
||||||
|
justifyContent="space-between"
|
||||||
|
alignItems="center"
|
||||||
|
minW="auto"
|
||||||
|
{...MsM_commonButtonStyles}
|
||||||
|
>
|
||||||
|
<Text noOfLines={1} maxW="100px" fontSize="sm">
|
||||||
|
{clientChatStore.model}
|
||||||
|
</Text>
|
||||||
|
</MenuButton>
|
||||||
|
)}
|
||||||
|
<MenuList
|
||||||
|
bg="background.tertiary"
|
||||||
|
border="none"
|
||||||
|
borderRadius="md"
|
||||||
|
boxShadow="lg"
|
||||||
|
minW={'10rem'}
|
||||||
|
ref={menuRef}
|
||||||
|
>
|
||||||
|
<FlyoutSubMenu
|
||||||
|
title="Text Models"
|
||||||
|
flyoutMenuOptions={supportedModels.map(modelData => ({
|
||||||
|
name: modelData.id.split('/').pop() || modelData.id,
|
||||||
|
value: modelData.id,
|
||||||
|
}))}
|
||||||
|
onClose={onClose}
|
||||||
|
parentIsOpen={isOpen}
|
||||||
|
setMenuState={setMenuState}
|
||||||
|
handleSelect={selectModelFn}
|
||||||
|
isSelected={isSelectedModelFn}
|
||||||
|
/>
|
||||||
|
<Divider color="text.tertiary" />
|
||||||
|
{/*Export conversation button*/}
|
||||||
|
<MenuItem
|
||||||
|
bg="background.tertiary"
|
||||||
|
color="text.primary"
|
||||||
|
onClick={handleCopyConversation}
|
||||||
|
_hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
|
||||||
|
_focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
|
||||||
|
>
|
||||||
|
<Flex align="center">
|
||||||
|
<Copy size="16px" style={{ marginRight: '8px' }} />
|
||||||
|
<Box>Export</Box>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
{/*New conversation button*/}
|
||||||
|
<MenuItem
|
||||||
|
bg="background.tertiary"
|
||||||
|
color="text.primary"
|
||||||
|
onClick={() => {
|
||||||
|
clientChatStore.setActiveConversation('conversation:new');
|
||||||
|
onClose();
|
||||||
|
}}
|
||||||
|
_hover={{ bg: 'rgba(0, 0, 0, 0.05)' }}
|
||||||
|
_focus={{ bg: 'rgba(0, 0, 0, 0.1)' }}
|
||||||
|
>
|
||||||
|
<Flex align="center">
|
||||||
|
<RefreshCcw size="16px" style={{ marginRight: '8px' }} />
|
||||||
|
<Box>New</Box>
|
||||||
|
</Flex>
|
||||||
|
</MenuItem>
|
||||||
|
</MenuList>
|
||||||
|
</Menu>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
export default InputMenu;
|
export default InputMenu;
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -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>
|
||||||
|
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
@@ -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,34 +44,34 @@ 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",
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
export type SupportedModel =
|
export type SupportedModel =
|
||||||
| keyof typeof SUPPORTED_MODELS_GROUPS
|
| keyof typeof SUPPORTED_MODELS_GROUPS
|
||||||
| (typeof SUPPORTED_MODELS_GROUPS)[keyof typeof SUPPORTED_MODELS_GROUPS][number];
|
| (typeof SUPPORTED_MODELS_GROUPS)[keyof typeof SUPPORTED_MODELS_GROUPS][number];
|
||||||
|
|
||||||
export type ModelFamily = keyof typeof SUPPORTED_MODELS_GROUPS;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
const SUPPORTED_MODELS = [
|
const SUPPORTED_MODELS = [
|
||||||
|
@@ -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,
|
||||||
});
|
});
|
||||||
|
@@ -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');
|
||||||
}
|
}
|
||||||
|
@@ -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} />;
|
||||||
|
@@ -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"
|
||||||
|
@@ -1,43 +1,43 @@
|
|||||||
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"
|
||||||
height="8px"
|
height="8px"
|
||||||
borderRadius="50%"
|
borderRadius="50%"
|
||||||
backgroundColor="text.primary"
|
backgroundColor="text.primary"
|
||||||
margin="0 4px"
|
margin="0 4px"
|
||||||
animate={{
|
animate={{
|
||||||
scale: [1, 1.2, 1],
|
scale: [1, 1.2, 1],
|
||||||
opacity: [0.5, 1, 0.5],
|
opacity: [0.5, 1, 0.5],
|
||||||
}}
|
}}
|
||||||
transition={{
|
transition={{
|
||||||
duration: 1,
|
duration: 1,
|
||||||
repeat: Infinity,
|
repeat: Infinity,
|
||||||
delay: i * 0.2,
|
delay: i * 0.2,
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</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>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -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>;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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);
|
||||||
|
@@ -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' }}
|
||||||
/>
|
/>
|
||||||
));
|
));
|
||||||
|
|
||||||
|
@@ -1,14 +1,15 @@
|
|||||||
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 {
|
||||||
observe() {}
|
observe() {}
|
||||||
unobserve() {}
|
unobserve() {}
|
||||||
disconnect() {}
|
disconnect() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add ResizeObserver to the global object
|
// Add ResizeObserver to the global object
|
||||||
@@ -16,140 +17,140 @@ global.ResizeObserver = MockResizeObserver;
|
|||||||
|
|
||||||
// Mock the Message model
|
// Mock the Message model
|
||||||
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
|
||||||
vi.mock('../../../../stores/ClientChatStore', () => ({
|
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
|
||||||
vi.mock('../../../../stores/MessageEditorStore', () => ({
|
vi.mock('../../../../stores/MessageEditorStore', () => ({
|
||||||
default: {
|
default: {
|
||||||
editedContent: 'Test message',
|
editedContent: 'Test message',
|
||||||
setEditedContent: vi.fn(),
|
setEditedContent: vi.fn(),
|
||||||
setMessage: vi.fn(),
|
setMessage: vi.fn(),
|
||||||
onCancel: vi.fn(),
|
onCancel: vi.fn(),
|
||||||
handleSave: vi.fn().mockImplementation(function() {
|
handleSave: vi.fn().mockImplementation(function () {
|
||||||
// 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
|
||||||
vi.mock('../UserMessageTools', () => ({
|
vi.mock('../UserMessageTools', () => ({
|
||||||
default: ({ message, onEdit }) => (
|
default: ({ message, onEdit }) => (
|
||||||
<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 {
|
||||||
...actual.default,
|
default: {
|
||||||
div: (props: any) => React.createElement('div', props, props.children),
|
...actual.default,
|
||||||
motion: (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),
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
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(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render user message correctly', () => {
|
||||||
|
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
||||||
|
|
||||||
|
expect(screen.getByText('You')).toBeInTheDocument();
|
||||||
|
expect(screen.getByText('Test message')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render assistant message correctly', () => {
|
||||||
|
render(<MessageBubble msg={mockAssistantMessage} scrollRef={mockScrollRef} />);
|
||||||
|
|
||||||
|
expect(screen.getByText("Geoff's AI")).toBeInTheDocument();
|
||||||
|
expect(screen.getByTestId('message-content')).toHaveTextContent('Assistant response');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show edit button on hover for user messages', async () => {
|
||||||
|
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
||||||
|
|
||||||
|
// Simulate hover
|
||||||
|
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
||||||
|
|
||||||
|
expect(screen.getByTestId('edit-button')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show editor when edit button is clicked', () => {
|
||||||
|
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
||||||
|
|
||||||
|
// Simulate hover and click edit
|
||||||
|
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
||||||
|
fireEvent.click(screen.getByTestId('edit-button'));
|
||||||
|
|
||||||
|
// Check if the textarea is rendered (part of MessageEditor)
|
||||||
|
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should hide editor after message is edited and saved', async () => {
|
||||||
|
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
||||||
|
|
||||||
|
// Show the editor
|
||||||
|
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
||||||
|
fireEvent.click(screen.getByTestId('edit-button'));
|
||||||
|
|
||||||
|
// Verify editor is shown
|
||||||
|
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
||||||
|
|
||||||
|
// Find and click the save button
|
||||||
|
const saveButton = screen.getByLabelText('Save edit');
|
||||||
|
fireEvent.click(saveButton);
|
||||||
|
|
||||||
|
// Wait for the editor to disappear
|
||||||
|
await waitFor(() => {
|
||||||
|
// Check that the editor is no longer visible
|
||||||
|
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
|
||||||
|
// And the message content is visible again
|
||||||
|
expect(screen.getByText('Test message')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render user message correctly', () => {
|
// Verify that handleSave was called
|
||||||
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
expect(messageEditorStore.handleSave).toHaveBeenCalled();
|
||||||
|
});
|
||||||
expect(screen.getByText('You')).toBeInTheDocument();
|
|
||||||
expect(screen.getByText('Test message')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should render assistant message correctly', () => {
|
|
||||||
render(<MessageBubble msg={mockAssistantMessage} scrollRef={mockScrollRef} />);
|
|
||||||
|
|
||||||
expect(screen.getByText("Geoff's AI")).toBeInTheDocument();
|
|
||||||
expect(screen.getByTestId('message-content')).toHaveTextContent('Assistant response');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show edit button on hover for user messages', async () => {
|
|
||||||
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
|
||||||
|
|
||||||
// Simulate hover
|
|
||||||
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
|
||||||
|
|
||||||
expect(screen.getByTestId('edit-button')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should show editor when edit button is clicked', () => {
|
|
||||||
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
|
||||||
|
|
||||||
// Simulate hover and click edit
|
|
||||||
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
|
||||||
fireEvent.click(screen.getByTestId('edit-button'));
|
|
||||||
|
|
||||||
// Check if the textarea is rendered (part of MessageEditor)
|
|
||||||
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should hide editor after message is edited and saved', async () => {
|
|
||||||
render(<MessageBubble msg={mockUserMessage} scrollRef={mockScrollRef} />);
|
|
||||||
|
|
||||||
// Show the editor
|
|
||||||
fireEvent.mouseEnter(screen.getByRole('listitem'));
|
|
||||||
fireEvent.click(screen.getByTestId('edit-button'));
|
|
||||||
|
|
||||||
// Verify editor is shown
|
|
||||||
expect(screen.getByRole('textbox')).toBeInTheDocument();
|
|
||||||
|
|
||||||
// Find and click the save button
|
|
||||||
const saveButton = screen.getByLabelText('Save edit');
|
|
||||||
fireEvent.click(saveButton);
|
|
||||||
|
|
||||||
// Wait for the editor to disappear
|
|
||||||
await waitFor(() => {
|
|
||||||
// Check that the editor is no longer visible
|
|
||||||
expect(screen.queryByRole('textbox')).not.toBeInTheDocument();
|
|
||||||
// And the message content is visible again
|
|
||||||
expect(screen.getByText('Test message')).toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Verify that handleSave was called
|
|
||||||
expect(messageEditorStore.handleSave).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
@@ -1,27 +1,27 @@
|
|||||||
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
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
// Mock fetch globally
|
// Mock fetch globally
|
||||||
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,25 +48,25 @@ 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,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('MessageEditor', () => {
|
describe('MessageEditor', () => {
|
||||||
// Create a message object with a setContent method
|
// Create a message object with a setContent method
|
||||||
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();
|
||||||
|
|
||||||
@@ -93,7 +93,7 @@ describe('MessageEditor', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('should call handleSave when save button is clicked', () => {
|
it('should call handleSave when save button is clicked', () => {
|
||||||
render(<MessageEditor message={mockUserMessage} onCancel={mockOnCancel}/>);
|
render(<MessageEditor message={mockUserMessage} onCancel={mockOnCancel} />);
|
||||||
|
|
||||||
const saveButton = screen.getByLabelText('Save edit');
|
const saveButton = screen.getByLabelText('Save edit');
|
||||||
fireEvent.click(saveButton);
|
fireEvent.click(saveButton);
|
||||||
|
@@ -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',
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@@ -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
|
||||||
|
@@ -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>
|
||||||
|
@@ -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%"
|
||||||
|
@@ -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 (
|
||||||
|
@@ -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,25 +7,20 @@ 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);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// 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
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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
|
||||||
|
@@ -1,18 +1,14 @@
|
|||||||
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"
|
{renderMarkdown(text)}
|
||||||
wordBreak="break-word"
|
|
||||||
whiteSpace="pre-wrap"
|
|
||||||
spacing={4}
|
|
||||||
>
|
|
||||||
{renderMarkdown(text)}
|
|
||||||
</Box>
|
</Box>
|
||||||
</VStack>
|
</VStack>
|
||||||
</Box>
|
</Box>
|
||||||
|
@@ -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}
|
||||||
|
@@ -1,576 +1,487 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Box,
|
Box,
|
||||||
Code,
|
Code,
|
||||||
Divider,
|
Divider,
|
||||||
Heading,
|
Heading,
|
||||||
Link,
|
Link,
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
OrderedList,
|
OrderedList,
|
||||||
Table,
|
Table,
|
||||||
Tbody,
|
Tbody,
|
||||||
Td,
|
Td,
|
||||||
Text,
|
Text,
|
||||||
Th,
|
Th,
|
||||||
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) {
|
||||||
marked.use(
|
marked.use(
|
||||||
markedKatex({
|
markedKatex({
|
||||||
nonStandard: false,
|
nonStandard: false,
|
||||||
displayMode: true,
|
displayMode: true,
|
||||||
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);
|
||||||
|
|
||||||
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,
|
const headingProps = getHeadingProps(depth);
|
||||||
depth,
|
return (
|
||||||
}) => {
|
<Heading {...headingProps} wordBreak="break-word" maxWidth="100%" color="text.accent">
|
||||||
const headingProps = getHeadingProps(depth);
|
{text}
|
||||||
return (
|
</Heading>
|
||||||
<Heading
|
);
|
||||||
{...headingProps}
|
|
||||||
wordBreak="break-word"
|
|
||||||
maxWidth="100%"
|
|
||||||
color="text.accent"
|
|
||||||
>
|
|
||||||
{text}
|
|
||||||
</Heading>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({
|
const CustomParagraph: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
children,
|
return (
|
||||||
}) => {
|
<Text as="p" fontSize="sm" lineHeight="short" wordBreak="break-word" maxWidth="100%">
|
||||||
return (
|
{children}
|
||||||
<Text
|
</Text>
|
||||||
as="p"
|
);
|
||||||
fontSize="sm"
|
|
||||||
lineHeight="short"
|
|
||||||
wordBreak="break-word"
|
|
||||||
maxWidth="100%"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({
|
const CustomBlockquote: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
||||||
children,
|
return (
|
||||||
}) => {
|
<Box
|
||||||
return (
|
as="blockquote"
|
||||||
<Box
|
borderLeft="4px solid"
|
||||||
as="blockquote"
|
borderColor="gray.200"
|
||||||
borderLeft="4px solid"
|
fontStyle="italic"
|
||||||
borderColor="gray.200"
|
color="gray.600"
|
||||||
fontStyle="italic"
|
pl={4}
|
||||||
color="gray.600"
|
maxWidth="100%"
|
||||||
pl={4}
|
wordBreak="break-word"
|
||||||
maxWidth="100%"
|
mb={2}
|
||||||
wordBreak="break-word"
|
>
|
||||||
mb={2}
|
{children}
|
||||||
>
|
</Box>
|
||||||
{children}
|
);
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({
|
const CustomCodeBlock: React.FC<{ code: string; language?: string }> = ({ code, language }) => {
|
||||||
code,
|
return (
|
||||||
language,
|
<MemoizedCodeBlock language={language} code={code} onRenderComplete={() => Promise.resolve()} />
|
||||||
}) => {
|
);
|
||||||
return (
|
|
||||||
<MemoizedCodeBlock
|
|
||||||
language={language}
|
|
||||||
code={code}
|
|
||||||
onRenderComplete={() => Promise.resolve()}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomHr: React.FC = () => <Divider my={4}/>;
|
const CustomHr: React.FC = () => <Divider my={4} />;
|
||||||
|
|
||||||
const CustomList: React.FC<{
|
const CustomList: React.FC<{
|
||||||
ordered?: boolean;
|
ordered?: boolean;
|
||||||
start?: number;
|
start?: number;
|
||||||
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,
|
||||||
};
|
};
|
||||||
|
|
||||||
return ordered ? (
|
return ordered ? (
|
||||||
<OrderedList start={start} {...commonStyles}>
|
<OrderedList start={start} {...commonStyles}>
|
||||||
{children}
|
{children}
|
||||||
</OrderedList>
|
</OrderedList>
|
||||||
) : (
|
) : (
|
||||||
<List styleType="disc" {...commonStyles}>
|
<List styleType="disc" {...commonStyles}>
|
||||||
{children}
|
{children}
|
||||||
</List>
|
</List>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomListItem: React.FC<{
|
const CustomListItem: React.FC<{
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}> = ({children}) => {
|
}> = ({ children }) => {
|
||||||
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,
|
const renderedMath = katex.renderToString(math, { displayMode });
|
||||||
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}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
overflow="auto"
|
overflow="auto"
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
dangerouslySetInnerHTML={{__html: renderedMath}}
|
dangerouslySetInnerHTML={{ __html: renderedMath }}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
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"
|
<Thead bg="background.secondary">
|
||||||
size="sm"
|
<Tr>
|
||||||
my={4}
|
{header.map((cell, i) => (
|
||||||
borderRadius="md"
|
<Th
|
||||||
overflow="hidden"
|
key={i}
|
||||||
>
|
textAlign={align[i] || 'left'}
|
||||||
<Thead bg="background.secondary">
|
fontWeight="bold"
|
||||||
<Tr>
|
p={2}
|
||||||
{header.map((cell, i) => (
|
minW={16}
|
||||||
<Th
|
wordBreak="break-word"
|
||||||
key={i}
|
>
|
||||||
textAlign={align[i] || "left"}
|
{cell}
|
||||||
fontWeight="bold"
|
</Th>
|
||||||
p={2}
|
))}
|
||||||
minW={16}
|
</Tr>
|
||||||
wordBreak="break-word"
|
</Thead>
|
||||||
>
|
<Tbody>
|
||||||
{cell}
|
{rows.map((row, rIndex) => (
|
||||||
</Th>
|
<Tr key={rIndex}>
|
||||||
))}
|
{row.map((cell, cIndex) => (
|
||||||
</Tr>
|
<Td key={cIndex} textAlign={align[cIndex] || 'left'} p={2} wordBreak="break-word">
|
||||||
</Thead>
|
{cell}
|
||||||
<Tbody>
|
</Td>
|
||||||
{rows.map((row, rIndex) => (
|
))}
|
||||||
<Tr key={rIndex}>
|
</Tr>
|
||||||
{row.map((cell, cIndex) => (
|
))}
|
||||||
<Td
|
</Tbody>
|
||||||
key={cIndex}
|
</Table>
|
||||||
textAlign={align[cIndex] || "left"}
|
);
|
||||||
p={2}
|
|
||||||
wordBreak="break-word"
|
|
||||||
>
|
|
||||||
{cell}
|
|
||||||
</Td>
|
|
||||||
))}
|
|
||||||
</Tr>
|
|
||||||
))}
|
|
||||||
</Tbody>
|
|
||||||
</Table>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomHtmlBlock: React.FC<{ content: string }> = ({content}) => {
|
const CustomHtmlBlock: React.FC<{ content: string }> = ({ content }) => {
|
||||||
return <Box as="span" display="inline" dangerouslySetInnerHTML={{__html: content}} mb={2}/>;
|
return <Box as="span" display="inline" dangerouslySetInnerHTML={{ __html: content }} mb={2} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomText: React.FC<{ text: React.ReactNode }> = ({text}) => {
|
const CustomText: React.FC<{ text: React.ReactNode }> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
lineHeight="short"
|
lineHeight="short"
|
||||||
color="text.accent"
|
color="text.accent"
|
||||||
wordBreak="break-word"
|
wordBreak="break-word"
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
as="span"
|
as="span"
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
interface CustomStrongProps {
|
interface CustomStrongProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CustomStrong: React.FC<CustomStrongProps> = ({children}) => {
|
const CustomStrong: React.FC<CustomStrongProps> = ({ children }) => {
|
||||||
return <Text as="strong">{children}</Text>;
|
return <Text as="strong">{children}</Text>;
|
||||||
};
|
};
|
||||||
|
|
||||||
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"
|
{children}
|
||||||
fontStyle="italic"
|
</Text>
|
||||||
lineHeight="short"
|
);
|
||||||
wordBreak="break-word"
|
|
||||||
display="inline"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</Text>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomDel: React.FC<{ text: string }> = ({text}) => {
|
const CustomDel: React.FC<{ text: string }> = ({ text }) => {
|
||||||
return (
|
return (
|
||||||
<Text
|
<Text
|
||||||
as="del"
|
as="del"
|
||||||
textDecoration="line-through"
|
textDecoration="line-through"
|
||||||
lineHeight="short"
|
lineHeight="short"
|
||||||
wordBreak="break-word"
|
wordBreak="break-word"
|
||||||
display="inline"
|
display="inline"
|
||||||
>
|
>
|
||||||
{text}
|
{text}
|
||||||
</Text>
|
</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"
|
||||||
bg={bg}
|
bg={bg}
|
||||||
overflowX="clip"
|
overflowX="clip"
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
wordBreak="break-word"
|
wordBreak="break-word"
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
p={0.5}
|
p={0.5}
|
||||||
>
|
>
|
||||||
{code}
|
{code}
|
||||||
</Code>
|
</Code>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({
|
const CustomMath: React.FC<{ math: string; displayMode?: boolean }> = ({
|
||||||
math,
|
math,
|
||||||
displayMode = false,
|
displayMode = false,
|
||||||
}) => {
|
}) => {
|
||||||
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>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomLink: React.FC<{
|
const CustomLink: React.FC<{
|
||||||
href: string;
|
href: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}> = ({href, title, children, ...props}) => {
|
}> = ({ href, title, children, ...props }) => {
|
||||||
return (
|
return (
|
||||||
<Link
|
<Link
|
||||||
href={href}
|
href={href}
|
||||||
title={title}
|
title={title}
|
||||||
isExternal
|
isExternal
|
||||||
sx={{
|
sx={{
|
||||||
"& span": {
|
'& span': {
|
||||||
color: "text.link",
|
color: 'text.link',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
color="teal.500"
|
color="teal.500"
|
||||||
wordBreak="break-word"
|
wordBreak="break-word"
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
{children}
|
||||||
</Link>
|
</Link>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const CustomImage: React.FC<{ href: string; text: string; title?: string }> = ({
|
const CustomImage: React.FC<{ href: string; text: string; title?: string }> = ({
|
||||||
href,
|
href,
|
||||||
text,
|
text,
|
||||||
title,
|
title,
|
||||||
}) => {
|
}) => {
|
||||||
return (
|
return (
|
||||||
<ImageWithFallback
|
<ImageWithFallback
|
||||||
src={href}
|
src={href}
|
||||||
alt={text}
|
alt={text}
|
||||||
title={title}
|
title={title}
|
||||||
maxW="100%"
|
maxW="100%"
|
||||||
width="auto"
|
width="auto"
|
||||||
height="auto"
|
height="auto"
|
||||||
my={2}
|
my={2}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
function parseTokens(tokens: marked.Token[]): JSX.Element[] {
|
function parseTokens(tokens: marked.Token[]): JSX.Element[] {
|
||||||
const output: JSX.Element[] = [];
|
const output: JSX.Element[] = [];
|
||||||
let blockquoteContent: JSX.Element[] = [];
|
let blockquoteContent: 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)
|
if (blockquoteContent.length > 0) {
|
||||||
: token.text;
|
blockquoteContent.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
|
||||||
if (blockquoteContent.length > 0) {
|
} else {
|
||||||
blockquoteContent.push(
|
output.push(<CustomParagraph key={i}>{parsedContent}</CustomParagraph>);
|
||||||
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
output.push(
|
|
||||||
<CustomParagraph key={i}>{parsedContent}</CustomParagraph>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "br":
|
|
||||||
output.push(<br key={i}/>);
|
|
||||||
break;
|
|
||||||
case "escape": {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "blockquote_start":
|
|
||||||
blockquoteContent = [];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "blockquote_end":
|
|
||||||
output.push(
|
|
||||||
<CustomBlockquote key={i}>
|
|
||||||
{parseTokens(blockquoteContent)}
|
|
||||||
</CustomBlockquote>,
|
|
||||||
);
|
|
||||||
blockquoteContent = [];
|
|
||||||
break;
|
|
||||||
case "blockquote": {
|
|
||||||
output.push(
|
|
||||||
<CustomBlockquote key={i}>
|
|
||||||
{token.tokens ? parseTokens(token.tokens) : null}
|
|
||||||
</CustomBlockquote>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "math":
|
|
||||||
output.push(
|
|
||||||
<CustomMath key={i} math={(token as any).value} displayMode={true}/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "inlineMath":
|
|
||||||
output.push(
|
|
||||||
<CustomMath
|
|
||||||
key={i}
|
|
||||||
math={(token as any).value}
|
|
||||||
displayMode={false}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "inlineKatex":
|
|
||||||
case "blockKatex": {
|
|
||||||
const katexToken = token as any;
|
|
||||||
output.push(
|
|
||||||
<CustomKatex
|
|
||||||
key={i}
|
|
||||||
math={katexToken.text}
|
|
||||||
displayMode={katexToken.displayMode}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "code":
|
|
||||||
output.push(
|
|
||||||
<CustomCodeBlock key={i} code={token.text} language={token.lang}/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "hr":
|
|
||||||
output.push(<CustomHr key={i}/>);
|
|
||||||
break;
|
|
||||||
case "list": {
|
|
||||||
const {ordered, start, items} = token;
|
|
||||||
const listItems = items.map((listItem, idx) => {
|
|
||||||
const nestedContent = parseTokens(listItem.tokens);
|
|
||||||
return <CustomListItem key={idx}>{nestedContent}</CustomListItem>;
|
|
||||||
});
|
|
||||||
|
|
||||||
output.push(
|
|
||||||
<CustomList key={i} ordered={ordered} start={start}>
|
|
||||||
{listItems}
|
|
||||||
</CustomList>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "table": {
|
|
||||||
const tableToken = token as TableToken;
|
|
||||||
|
|
||||||
output.push(
|
|
||||||
<CustomTable
|
|
||||||
key={i}
|
|
||||||
header={tableToken.header.map((cell) =>
|
|
||||||
typeof cell === "string" ? cell : parseTokens(cell.tokens || []),
|
|
||||||
)}
|
|
||||||
align={tableToken.align}
|
|
||||||
rows={tableToken.rows.map((row) =>
|
|
||||||
row.map((cell) =>
|
|
||||||
typeof cell === "string"
|
|
||||||
? cell
|
|
||||||
: parseTokens(cell.tokens || []),
|
|
||||||
),
|
|
||||||
)}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case "html":
|
|
||||||
output.push(<CustomHtmlBlock key={i} content={token.text}/>);
|
|
||||||
break;
|
|
||||||
case "def":
|
|
||||||
case "space":
|
|
||||||
break;
|
|
||||||
case "strong":
|
|
||||||
output.push(
|
|
||||||
<CustomStrong key={i}>
|
|
||||||
{parseTokens(token.tokens || [])}
|
|
||||||
</CustomStrong>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
case "em":
|
|
||||||
output.push(
|
|
||||||
<CustomEm key={i}>
|
|
||||||
{token.tokens ? parseTokens(token.tokens) : token.text}
|
|
||||||
</CustomEm>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "codespan":
|
|
||||||
output.push(<CustomCodeSpan key={i} code={token.text}/>);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "link":
|
|
||||||
output.push(
|
|
||||||
<CustomLink key={i} href={token.href} title={token.title}>
|
|
||||||
{token.tokens ? parseTokens(token.tokens) : token.text}
|
|
||||||
</CustomLink>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "image":
|
|
||||||
output.push(
|
|
||||||
<CustomImage
|
|
||||||
key={i}
|
|
||||||
href={token.href}
|
|
||||||
title={token.title}
|
|
||||||
text={token.text}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case "text": {
|
|
||||||
const parsedContent = token.tokens
|
|
||||||
? parseTokens(token.tokens)
|
|
||||||
: token.text;
|
|
||||||
|
|
||||||
if (blockquoteContent.length > 0) {
|
|
||||||
blockquoteContent.push(
|
|
||||||
<React.Fragment key={i}>{parsedContent}</React.Fragment>,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
output.push(<CustomText key={i} text={parsedContent}/>);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
console.warn("Unhandled token type:", token.type, token);
|
|
||||||
}
|
}
|
||||||
});
|
break;
|
||||||
|
}
|
||||||
|
case 'br':
|
||||||
|
output.push(<br key={i} />);
|
||||||
|
break;
|
||||||
|
case 'escape': {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'blockquote_start':
|
||||||
|
blockquoteContent = [];
|
||||||
|
break;
|
||||||
|
|
||||||
return output;
|
case 'blockquote_end':
|
||||||
|
output.push(<CustomBlockquote key={i}>{parseTokens(blockquoteContent)}</CustomBlockquote>);
|
||||||
|
blockquoteContent = [];
|
||||||
|
break;
|
||||||
|
case 'blockquote': {
|
||||||
|
output.push(
|
||||||
|
<CustomBlockquote key={i}>
|
||||||
|
{token.tokens ? parseTokens(token.tokens) : null}
|
||||||
|
</CustomBlockquote>,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'math':
|
||||||
|
output.push(<CustomMath key={i} math={(token as any).value} displayMode={true} />);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'inlineMath':
|
||||||
|
output.push(<CustomMath key={i} math={(token as any).value} displayMode={false} />);
|
||||||
|
break;
|
||||||
|
case 'inlineKatex':
|
||||||
|
case 'blockKatex': {
|
||||||
|
const katexToken = token as any;
|
||||||
|
output.push(
|
||||||
|
<CustomKatex key={i} math={katexToken.text} displayMode={katexToken.displayMode} />,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'code':
|
||||||
|
output.push(<CustomCodeBlock key={i} code={token.text} language={token.lang} />);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'hr':
|
||||||
|
output.push(<CustomHr key={i} />);
|
||||||
|
break;
|
||||||
|
case 'list': {
|
||||||
|
const { ordered, start, items } = token;
|
||||||
|
const listItems = items.map((listItem, idx) => {
|
||||||
|
const nestedContent = parseTokens(listItem.tokens);
|
||||||
|
return <CustomListItem key={idx}>{nestedContent}</CustomListItem>;
|
||||||
|
});
|
||||||
|
|
||||||
|
output.push(
|
||||||
|
<CustomList key={i} ordered={ordered} start={start}>
|
||||||
|
{listItems}
|
||||||
|
</CustomList>,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'table': {
|
||||||
|
const tableToken = token as TableToken;
|
||||||
|
|
||||||
|
output.push(
|
||||||
|
<CustomTable
|
||||||
|
key={i}
|
||||||
|
header={tableToken.header.map(cell =>
|
||||||
|
typeof cell === 'string' ? cell : parseTokens(cell.tokens || []),
|
||||||
|
)}
|
||||||
|
align={tableToken.align}
|
||||||
|
rows={tableToken.rows.map(row =>
|
||||||
|
row.map(cell => (typeof cell === 'string' ? cell : parseTokens(cell.tokens || []))),
|
||||||
|
)}
|
||||||
|
/>,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'html':
|
||||||
|
output.push(<CustomHtmlBlock key={i} content={token.text} />);
|
||||||
|
break;
|
||||||
|
case 'def':
|
||||||
|
case 'space':
|
||||||
|
break;
|
||||||
|
case 'strong':
|
||||||
|
output.push(<CustomStrong key={i}>{parseTokens(token.tokens || [])}</CustomStrong>);
|
||||||
|
break;
|
||||||
|
case 'em':
|
||||||
|
output.push(
|
||||||
|
<CustomEm key={i}>{token.tokens ? parseTokens(token.tokens) : token.text}</CustomEm>,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'codespan':
|
||||||
|
output.push(<CustomCodeSpan key={i} code={token.text} />);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'link':
|
||||||
|
output.push(
|
||||||
|
<CustomLink key={i} href={token.href} title={token.title}>
|
||||||
|
{token.tokens ? parseTokens(token.tokens) : token.text}
|
||||||
|
</CustomLink>,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'image':
|
||||||
|
output.push(
|
||||||
|
<CustomImage key={i} href={token.href} title={token.title} text={token.text} />,
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'text': {
|
||||||
|
const parsedContent = token.tokens ? parseTokens(token.tokens) : token.text;
|
||||||
|
|
||||||
|
if (blockquoteContent.length > 0) {
|
||||||
|
blockquoteContent.push(<React.Fragment key={i}>{parsedContent}</React.Fragment>);
|
||||||
|
} else {
|
||||||
|
output.push(<CustomText key={i} text={parsedContent} />);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
console.warn('Unhandled token type:', token.type, token);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function renderMarkdown(markdown: string): JSX.Element[] {
|
export function renderMarkdown(markdown: string): JSX.Element[] {
|
||||||
marked.setOptions({
|
marked.setOptions({
|
||||||
breaks: true,
|
breaks: true,
|
||||||
gfm: true,
|
gfm: true,
|
||||||
silent: false,
|
silent: false,
|
||||||
async: true,
|
async: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
const tokens = marked.lexer(markdown);
|
const tokens = marked.lexer(markdown);
|
||||||
return parseTokens(tokens);
|
return parseTokens(tokens);
|
||||||
}
|
}
|
||||||
|
@@ -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"
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
|
@@ -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,32 +67,23 @@ 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}
|
<ModalContent bg="bg.primary" color="text.primary">
|
||||||
size="md"
|
|
||||||
motionPreset="slideInBottom"
|
|
||||||
zIndex={zIndex}
|
|
||||||
>
|
|
||||||
<ModalOverlay
|
|
||||||
bg='bg.primary'
|
|
||||||
backdropFilter='blur(10px) hue-rotate(90deg)'
|
|
||||||
/>
|
|
||||||
<ModalContent bg="bg.primary" color="text.primary" >
|
|
||||||
<ModalHeader textAlign="center" mb={2}>
|
<ModalHeader textAlign="center" mb={2}>
|
||||||
Support
|
Support
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
@@ -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}
|
||||||
@@ -218,7 +196,7 @@ const SupportThisSiteModal = observer(({ isOpen, onClose, zIndex }) => {
|
|||||||
</VStack>
|
</VStack>
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button variant="outline" mr={3} onClick={onClose} >
|
<Button variant="outline" mr={3} onClick={onClose}>
|
||||||
Close
|
Close
|
||||||
</Button>
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
|
@@ -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 />
|
||||||
|
@@ -1,17 +1,16 @@
|
|||||||
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);
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
|
@@ -1,10 +1,11 @@
|
|||||||
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', () => {
|
||||||
const callback = vi.fn();
|
const callback = vi.fn();
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
vi.clearAllMocks();
|
vi.clearAllMocks();
|
||||||
// Reset event listeners
|
// Reset event listeners
|
||||||
@@ -16,17 +17,17 @@ 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));
|
||||||
|
|
||||||
// The hook should return true
|
// The hook should return true
|
||||||
expect(result.current).toBe(true);
|
expect(result.current).toBe(true);
|
||||||
|
|
||||||
// Callback should be called immediately
|
// Callback should be called immediately
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
// No event listener should be added
|
// No event listener should be added
|
||||||
expect(window.addEventListener).not.toHaveBeenCalled();
|
expect(window.addEventListener).not.toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
@@ -35,17 +36,17 @@ 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));
|
||||||
|
|
||||||
// The hook should return false initially
|
// The hook should return false initially
|
||||||
expect(result.current).toBe(false);
|
expect(result.current).toBe(false);
|
||||||
|
|
||||||
// Callback should not be called yet
|
// Callback should not be called yet
|
||||||
expect(callback).not.toHaveBeenCalled();
|
expect(callback).not.toHaveBeenCalled();
|
||||||
|
|
||||||
// Event listener should be added
|
// Event listener should be added
|
||||||
expect(window.addEventListener).toHaveBeenCalledWith('load', expect.any(Function));
|
expect(window.addEventListener).toHaveBeenCalledWith('load', expect.any(Function));
|
||||||
});
|
});
|
||||||
@@ -54,14 +55,14 @@ 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));
|
||||||
|
|
||||||
// Unmount the hook
|
// Unmount the hook
|
||||||
unmount();
|
unmount();
|
||||||
|
|
||||||
// Event listener should be removed
|
// Event listener should be removed
|
||||||
expect(window.removeEventListener).toHaveBeenCalledWith('load', expect.any(Function));
|
expect(window.removeEventListener).toHaveBeenCalledWith('load', expect.any(Function));
|
||||||
});
|
});
|
||||||
@@ -70,30 +71,33 @@ 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(
|
||||||
if (event === 'load') {
|
'addEventListener',
|
||||||
loadHandler = handler;
|
vi.fn((event, handler) => {
|
||||||
}
|
if (event === 'load') {
|
||||||
}));
|
loadHandler = handler;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
const { result } = renderHook(() => usePageLoaded(callback));
|
const { result } = renderHook(() => usePageLoaded(callback));
|
||||||
|
|
||||||
// Initially, isLoaded should be false
|
// Initially, isLoaded should be false
|
||||||
expect(result.current).toBe(false);
|
expect(result.current).toBe(false);
|
||||||
|
|
||||||
// Simulate the load event
|
// Simulate the load event
|
||||||
loadHandler();
|
loadHandler();
|
||||||
|
|
||||||
// Now the callback should have been called
|
// Now the callback should have been called
|
||||||
expect(callback).toHaveBeenCalledTimes(1);
|
expect(callback).toHaveBeenCalledTimes(1);
|
||||||
|
|
||||||
// And isLoaded should be updated to true
|
// And isLoaded should be updated to true
|
||||||
// Note: We need to use rerender or waitFor in a real test to see this update
|
// Note: We need to use rerender or waitFor in a real test to see this update
|
||||||
// For simplicity, we're just testing the callback was called
|
// For simplicity, we're just testing the callback was called
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@@ -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]);
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
|
@@ -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) {}
|
} catch (e) {
|
||||||
|
// Ignore errors when accessing headers or cookies
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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)',
|
||||||
},
|
},
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
@@ -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>
|
||||||
|
@@ -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>
|
||||||
);
|
);
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
|
@@ -1,83 +1,80 @@
|
|||||||
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 = () => {
|
||||||
return Date.now().toString(36) + Math.random().toString(36).substring(2);
|
return Date.now().toString(36) + Math.random().toString(36).substring(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
// 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
|
||||||
|
|
||||||
export const batchContentUpdate = (message: any, content: string) => {
|
export const batchContentUpdate = (message: any, content: string) => {
|
||||||
if (!content) return;
|
if (!content) return;
|
||||||
|
|
||||||
// Add the content to the batch
|
// Add the content to the batch
|
||||||
batchedContent += content;
|
batchedContent += content;
|
||||||
|
|
||||||
// If we already have a timeout scheduled, do nothing
|
// If we already have a timeout scheduled, do nothing
|
||||||
if (batchUpdateTimeout) return;
|
if (batchUpdateTimeout) return;
|
||||||
|
|
||||||
// Schedule a timeout to apply the batched content
|
// Schedule a timeout to apply the batched content
|
||||||
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']),
|
||||||
})
|
})
|
||||||
// Runtime‑only 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
const append = (newContent: string) => {
|
const append = (newContent: string) => {
|
||||||
self.content += newContent;
|
self.content += newContent;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stream content into the message for a smooth “typing” effect.
|
* Stream content into the message for a smooth “typing” effect.
|
||||||
* @param newContent The full text to stream in.
|
* @param newContent The full text to stream in.
|
||||||
* @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 20 ms).
|
* @param delay Delay (ms) between ticks (default 20 ms).
|
||||||
*/
|
*/
|
||||||
const streamContent = flow(function* (
|
const streamContent = flow(function* (newContent: string, chunkSize = 3, delay = 20) {
|
||||||
newContent: string,
|
self.isStreaming = true;
|
||||||
chunkSize = 3,
|
let pointer = 0;
|
||||||
delay = 20
|
|
||||||
) {
|
|
||||||
self.isStreaming = true;
|
|
||||||
let pointer = 0;
|
|
||||||
|
|
||||||
// Reveal the content chunk‑by‑chunk
|
// Reveal the content chunk‑by‑chunk
|
||||||
while (pointer < newContent.length) {
|
while (pointer < newContent.length) {
|
||||||
append(newContent.slice(pointer, pointer + chunkSize));
|
append(newContent.slice(pointer, pointer + chunkSize));
|
||||||
pointer += chunkSize;
|
pointer += chunkSize;
|
||||||
yield sleep(delay);
|
yield sleep(delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.isStreaming = false; // finished
|
self.isStreaming = false; // finished
|
||||||
});
|
|
||||||
|
|
||||||
return { setContent, append, streamContent };
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
return { setContent, append, streamContent };
|
||||||
|
});
|
||||||
|
|
||||||
export default Message;
|
export default Message;
|
||||||
|
@@ -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();
|
||||||
|
@@ -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();
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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>
|
||||||
|
@@ -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 (_) {
|
||||||
|
@@ -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} />
|
||||||
|
@@ -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
|
||||||
|
@@ -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} />
|
||||||
|
@@ -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
|
||||||
|
@@ -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;
|
||||||
|
@@ -1,16 +1,17 @@
|
|||||||
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>,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -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>
|
||||||
@@ -43,7 +42,7 @@ window.ga_api = "/api/metrics";
|
|||||||
<script src="/cfga.min.js" async></script>
|
<script src="/cfga.min.js" async></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="page-view">${await renderToStream(page, {userAgent: ua})}</div>
|
<div id="page-view">${await renderToStream(page, { userAgent: ua })}</div>
|
||||||
</body>
|
</body>
|
||||||
</html>`;
|
</html>`;
|
||||||
|
|
||||||
|
@@ -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,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -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 };
|
||||||
|
@@ -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',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@@ -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.',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
@@ -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;
|
||||||
},
|
},
|
||||||
|
@@ -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();
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
@@ -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: '',
|
||||||
});
|
});
|
||||||
|
@@ -1,169 +1,171 @@
|
|||||||
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 => ({
|
||||||
|
setEditedContent(content: string) {
|
||||||
|
self.editedContent = content;
|
||||||
|
},
|
||||||
|
setMessage(message: Instance<typeof Message>) {
|
||||||
|
// Handle messages that might not have an id property (for testing)
|
||||||
|
self.messageId = message.id || '';
|
||||||
|
self.editedContent = message.content;
|
||||||
|
},
|
||||||
|
onCancel() {
|
||||||
|
self.messageId = '';
|
||||||
|
self.editedContent = '';
|
||||||
|
},
|
||||||
|
handleSave: async () => {
|
||||||
|
// Get the message using the ID
|
||||||
|
const message = self.getMessage();
|
||||||
|
|
||||||
|
// Check if message reference is still valid
|
||||||
|
if (!message) {
|
||||||
|
// Message reference is no longer valid, just cancel the edit
|
||||||
|
self.onCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the content we want to update
|
||||||
|
const contentToUpdate = self.editedContent;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Use the editMessage function from MessagesStore
|
||||||
|
const success = clientChatStore.editMessage(message, contentToUpdate);
|
||||||
|
if (!success) {
|
||||||
|
// Message not found in the items array, just cancel
|
||||||
|
self.onCancel();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}))
|
|
||||||
.actions((self) => ({
|
|
||||||
setEditedContent(content: string) {
|
|
||||||
self.editedContent = content;
|
|
||||||
},
|
|
||||||
setMessage(message: Instance<typeof Message>) {
|
|
||||||
// Handle messages that might not have an id property (for testing)
|
|
||||||
self.messageId = message.id || "";
|
|
||||||
self.editedContent = message.content;
|
|
||||||
},
|
|
||||||
onCancel() {
|
|
||||||
self.messageId = "";
|
|
||||||
self.editedContent = "";
|
|
||||||
},
|
|
||||||
handleSave: async () => {
|
|
||||||
// Get the message using the ID
|
|
||||||
const message = self.getMessage();
|
|
||||||
|
|
||||||
// Check if message reference is still valid
|
// Set follow mode and loading state
|
||||||
if (!message) {
|
UserOptionsStore.setFollowModeEnabled(true);
|
||||||
// Message reference is no longer valid, just cancel the edit
|
clientChatStore.setIsLoading(true);
|
||||||
self.onCancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Store the content we want to update
|
try {
|
||||||
const contentToUpdate = self.editedContent;
|
// Add a small delay before adding the assistant message (for better UX)
|
||||||
|
await new Promise(r => setTimeout(r, 500));
|
||||||
|
|
||||||
|
// Add an empty assistant message to clientChatStore's items
|
||||||
|
clientChatStore.add(Message.create({ content: '', role: 'assistant' }));
|
||||||
|
// Use clientChatStore for the API call since it has the model property
|
||||||
|
const payload = { messages: clientChatStore.items.slice(), model: clientChatStore.model };
|
||||||
|
|
||||||
|
// Make API call
|
||||||
|
const response = await fetch('/api/chat', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status === 429) {
|
||||||
|
clientChatStore.appendLast('\n\nError: Too many requests • please slow down.');
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (response.status > 200) {
|
||||||
|
clientChatStore.appendLast('\n\nError: Something went wrong.');
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { streamUrl } = await response.json();
|
||||||
|
|
||||||
|
// Use the StreamStore's functionality to handle the event source
|
||||||
|
const eventSource = new EventSource(streamUrl);
|
||||||
|
|
||||||
|
// Set up event handlers using a more efficient approach
|
||||||
|
const handleMessage = event => {
|
||||||
try {
|
try {
|
||||||
// Use the editMessage function from MessagesStore
|
const parsed = JSON.parse(event.data);
|
||||||
const success = clientChatStore.editMessage(message, contentToUpdate);
|
|
||||||
if (!success) {
|
|
||||||
// Message not found in the items array, just cancel
|
|
||||||
self.onCancel();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set follow mode and loading state
|
if (parsed.type === 'error') {
|
||||||
UserOptionsStore.setFollowModeEnabled(true);
|
// Append error message instead of replacing content
|
||||||
clientChatStore.setIsLoading(true);
|
clientChatStore.appendLast('\n\nError: ' + parsed.error);
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
try {
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
// Add a small delay before adding the assistant message (for better UX)
|
eventSource.close();
|
||||||
await new Promise((r) => setTimeout(r, 500));
|
|
||||||
|
|
||||||
// Add an empty assistant message to clientChatStore's items
|
|
||||||
clientChatStore.add(Message.create({content: "", role: "assistant"}));
|
|
||||||
// Use clientChatStore for the API call since it has the model property
|
|
||||||
const payload = {messages: clientChatStore.items.slice(), model: clientChatStore.model};
|
|
||||||
|
|
||||||
// Make API call
|
|
||||||
const response = await fetch("/api/chat", {
|
|
||||||
method: "POST",
|
|
||||||
headers: {"Content-Type": "application/json"},
|
|
||||||
body: JSON.stringify(payload),
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.status === 429) {
|
|
||||||
clientChatStore.appendLast("\n\nError: Too many requests • please slow down.");
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (response.status > 200) {
|
|
||||||
clientChatStore.appendLast("\n\nError: Something went wrong.");
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const {streamUrl} = await response.json();
|
|
||||||
|
|
||||||
// Use the StreamStore's functionality to handle the event source
|
|
||||||
const eventSource = new EventSource(streamUrl);
|
|
||||||
|
|
||||||
// Set up event handlers using a more efficient approach
|
|
||||||
const handleMessage = (event) => {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(event.data);
|
|
||||||
|
|
||||||
if (parsed.type === "error") {
|
|
||||||
// Append error message instead of replacing content
|
|
||||||
clientChatStore.appendLast("\n\nError: " + parsed.error);
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
eventSource.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last message to use its streamContent method
|
|
||||||
const lastMessage = clientChatStore.items[clientChatStore.items.length - 1];
|
|
||||||
|
|
||||||
if (parsed.type === "chat" && parsed.data.choices[0]?.finish_reason === "stop") {
|
|
||||||
// For the final chunk, append it and close the connection
|
|
||||||
const content = parsed.data.choices[0]?.delta?.content ?? "";
|
|
||||||
if (content) {
|
|
||||||
// Use appendLast for the final chunk to ensure it's added immediately
|
|
||||||
clientChatStore.appendLast(content);
|
|
||||||
}
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
eventSource.close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsed.type === "chat") {
|
|
||||||
// For regular chunks, use the batched content update for a smoother effect
|
|
||||||
const content = parsed.data.choices[0]?.delta?.content ?? "";
|
|
||||||
if (content && lastMessage) {
|
|
||||||
// Use the batching utility for more efficient updates
|
|
||||||
batchContentUpdate(lastMessage, content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("stream parse error", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = () => {
|
|
||||||
clientChatStore.appendLast("\n\nError: Connection lost.");
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
eventSource.close();
|
|
||||||
};
|
|
||||||
|
|
||||||
eventSource.onmessage = handleMessage;
|
|
||||||
eventSource.onerror = handleError;
|
|
||||||
} catch (err) {
|
|
||||||
console.error("sendMessage", err);
|
|
||||||
clientChatStore.appendLast("\n\nError: Sorry • network error.");
|
|
||||||
clientChatStore.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error in handleSave:", err);
|
|
||||||
// If any error occurs, just cancel the edit
|
|
||||||
self.onCancel();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always clean up at the end
|
// Get the last message to use its streamContent method
|
||||||
self.onCancel();
|
const lastMessage = clientChatStore.items[clientChatStore.items.length - 1];
|
||||||
|
|
||||||
|
if (parsed.type === 'chat' && parsed.data.choices[0]?.finish_reason === 'stop') {
|
||||||
|
// For the final chunk, append it and close the connection
|
||||||
|
const content = parsed.data.choices[0]?.delta?.content ?? '';
|
||||||
|
if (content) {
|
||||||
|
// Use appendLast for the final chunk to ensure it's added immediately
|
||||||
|
clientChatStore.appendLast(content);
|
||||||
|
}
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
eventSource.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.type === 'chat') {
|
||||||
|
// For regular chunks, use the batched content update for a smoother effect
|
||||||
|
const content = parsed.data.choices[0]?.delta?.content ?? '';
|
||||||
|
if (content && lastMessage) {
|
||||||
|
// Use the batching utility for more efficient updates
|
||||||
|
batchContentUpdate(lastMessage, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('stream parse error', err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleError = () => {
|
||||||
|
clientChatStore.appendLast('\n\nError: Connection lost.');
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
eventSource.close();
|
||||||
|
};
|
||||||
|
|
||||||
|
eventSource.onmessage = handleMessage;
|
||||||
|
eventSource.onerror = handleError;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('sendMessage', err);
|
||||||
|
clientChatStore.appendLast('\n\nError: Sorry • network error.');
|
||||||
|
clientChatStore.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
}
|
}
|
||||||
}));
|
} catch (err) {
|
||||||
|
console.error('Error in handleSave:', err);
|
||||||
|
// If any error occurs, just cancel the edit
|
||||||
|
self.onCancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always clean up at the end
|
||||||
|
self.onCancel();
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
const messageEditorStore = MessageEditorStore.create();
|
const messageEditorStore = MessageEditorStore.create();
|
||||||
|
|
||||||
|
@@ -1,51 +1,52 @@
|
|||||||
// ---------------------------
|
// ---------------------------
|
||||||
// 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);
|
||||||
},
|
},
|
||||||
updateLast(content: string) {
|
updateLast(content: string) {
|
||||||
if (self.items.length) {
|
if (self.items.length) {
|
||||||
self.items[self.items.length - 1].content = content;
|
self.items[self.items.length - 1].content = content;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
appendLast(content: string) {
|
appendLast(content: string) {
|
||||||
if (self.items.length) {
|
if (self.items.length) {
|
||||||
self.items[self.items.length - 1].content += content;
|
self.items[self.items.length - 1].content += content;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
removeAfter(index: number) {
|
removeAfter(index: number) {
|
||||||
if (index >= 0 && index < self.items.length) {
|
if (index >= 0 && index < self.items.length) {
|
||||||
self.items.splice(index + 1);
|
self.items.splice(index + 1);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reset() {
|
reset() {
|
||||||
self.items.clear();
|
self.items.clear();
|
||||||
},
|
},
|
||||||
editMessage(message: Instance<typeof Message>, newContent: string) {
|
editMessage(message: Instance<typeof Message>, newContent: string) {
|
||||||
// Find the index of the message in the items array
|
// Find the index of the message in the items array
|
||||||
const messageIndex = self.items.map(i => i.id).indexOf(message.id);
|
const messageIndex = self.items.map(i => i.id).indexOf(message.id);
|
||||||
if (messageIndex === -1) {
|
if (messageIndex === -1) {
|
||||||
// Message not found in the items array
|
// Message not found in the items array
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the message content
|
// Update the message content
|
||||||
message.setContent(newContent);
|
message.setContent(newContent);
|
||||||
|
|
||||||
// Remove all messages after the edited message
|
// Remove all messages after the edited message
|
||||||
self.removeAfter(messageIndex);
|
self.removeAfter(messageIndex);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface IMessagesStore extends Instance<typeof MessagesStore> {}
|
export interface IMessagesStore extends Instance<typeof MessagesStore> {}
|
||||||
|
@@ -1,35 +1,33 @@
|
|||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// 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",
|
supportedModels: types.optional(types.array(types.string), []),
|
||||||
),
|
})
|
||||||
imageModel: types.optional(types.string, "black-forest-labs/flux-1.1-pro"),
|
.actions(self => ({
|
||||||
supportedModels: types.optional(types.array(types.string), []),
|
setModel(value: string) {
|
||||||
})
|
self.model = value;
|
||||||
.actions((self) => ({
|
try {
|
||||||
setModel(value: string) {
|
localStorage.setItem('recentModel', value);
|
||||||
self.model = value;
|
} catch (_) {
|
||||||
try {
|
// Silently ignore localStorage errors (e.g., in environments where it's not available)
|
||||||
localStorage.setItem("recentModel", value);
|
}
|
||||||
} catch (_) {}
|
},
|
||||||
},
|
setImageModel(value: string) {
|
||||||
setImageModel(value: string) {
|
self.imageModel = value;
|
||||||
self.imageModel = value;
|
},
|
||||||
},
|
setSupportedModels(list: string[]) {
|
||||||
setSupportedModels(list: string[]) {
|
self.supportedModels = list;
|
||||||
self.supportedModels = list;
|
if (!list.includes(self.model)) {
|
||||||
if (!list.includes(self.model)) {
|
// fall back to last entry (arbitrary but predictable)
|
||||||
// fall back to last entry (arbitrary but predictable)
|
self.model = list[list.length - 1] ?? self.model;
|
||||||
self.model = list[list.length - 1] ?? self.model;
|
}
|
||||||
}
|
},
|
||||||
},
|
}));
|
||||||
}));
|
|
||||||
|
|
||||||
export interface IModelStore extends Instance<typeof ModelStore> {}
|
export interface IModelStore extends Instance<typeof ModelStore> {}
|
||||||
|
@@ -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;
|
||||||
|
@@ -1,155 +1,155 @@
|
|||||||
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 isn’t implicitly `any`
|
.actions((self: any) => {
|
||||||
let root: RootDeps;
|
// ← annotate `self` so it isn’t implicitly `any`
|
||||||
try {
|
let root: RootDeps;
|
||||||
root = getParent<RootDeps>(self);
|
try {
|
||||||
} catch {
|
root = getParent<RootDeps>(self);
|
||||||
root = self as any;
|
} catch {
|
||||||
}
|
root = self as any;
|
||||||
|
}
|
||||||
|
|
||||||
function setEventSource(source: EventSource | null) {
|
function setEventSource(source: EventSource | null) {
|
||||||
self.eventSource = source;
|
self.eventSource = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const sendMessage = flow(function* () {
|
const sendMessage = flow(function* () {
|
||||||
if (!root.input.trim() || root.isLoading) return;
|
if (!root.input.trim() || root.isLoading) return;
|
||||||
cleanup();
|
cleanup();
|
||||||
|
|
||||||
// ← **DO NOT** `yield` a synchronous action
|
// ← **DO NOT** `yield` a synchronous action
|
||||||
UserOptionsStore.setFollowModeEnabled(true);
|
UserOptionsStore.setFollowModeEnabled(true);
|
||||||
root.setIsLoading(true);
|
root.setIsLoading(true);
|
||||||
|
|
||||||
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) {
|
|
||||||
root.appendLast("\n\nError: Too many requests • please slow down.");
|
|
||||||
cleanup();
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (response.status > 200) {
|
|
||||||
root.appendLast("\n\nError: Something went wrong.");
|
|
||||||
cleanup();
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { streamUrl } = (yield response.json()) as { streamUrl: string };
|
|
||||||
|
|
||||||
setEventSource(new EventSource(streamUrl));
|
|
||||||
|
|
||||||
const handleMessage = (event: MessageEvent) => {
|
|
||||||
try {
|
|
||||||
const parsed = JSON.parse(event.data);
|
|
||||||
|
|
||||||
if (parsed.type === "error") {
|
|
||||||
// Append error message instead of replacing content
|
|
||||||
root.appendLast("\n\nError: " + parsed.error);
|
|
||||||
root.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get the last message
|
|
||||||
const lastMessage = root.items[root.items.length - 1];
|
|
||||||
|
|
||||||
if (
|
|
||||||
parsed.type === "chat" &&
|
|
||||||
parsed.data.choices[0]?.finish_reason === "stop"
|
|
||||||
) {
|
|
||||||
// For the final chunk, append it and close the connection
|
|
||||||
const content = parsed.data.choices[0]?.delta?.content ?? "";
|
|
||||||
if (content) {
|
|
||||||
// Use appendLast for the final chunk to ensure it's added immediately
|
|
||||||
root.appendLast(content);
|
|
||||||
}
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
root.setIsLoading(false);
|
|
||||||
cleanup();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parsed.type === "chat") {
|
|
||||||
// For regular chunks, use the batched content update for a smoother effect
|
|
||||||
const content = parsed.data.choices[0]?.delta?.content ?? "";
|
|
||||||
if (content && lastMessage) {
|
|
||||||
// Use the batching utility for more efficient updates
|
|
||||||
batchContentUpdate(lastMessage, content);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.error("stream parse error", err);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = () => {
|
|
||||||
root.appendLast("\n\nError: Connection lost.");
|
|
||||||
root.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
cleanup();
|
|
||||||
};
|
|
||||||
|
|
||||||
self.eventSource.onmessage = handleMessage;
|
|
||||||
self.eventSource.onerror = handleError;
|
|
||||||
} catch (err) {
|
|
||||||
console.error("sendMessage", err);
|
|
||||||
root.appendLast("\n\nError: Sorry • network error.");
|
|
||||||
root.setIsLoading(false);
|
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
|
||||||
cleanup();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const stopIncomingMessage = () => {
|
if (response.status === 429) {
|
||||||
cleanup();
|
root.appendLast('\n\nError: Too many requests • please slow down.');
|
||||||
root.setIsLoading(false);
|
cleanup();
|
||||||
UserOptionsStore.setFollowModeEnabled(false);
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (response.status > 200) {
|
||||||
|
root.appendLast('\n\nError: Something went wrong.');
|
||||||
|
cleanup();
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { streamUrl } = (yield response.json()) as { streamUrl: string };
|
||||||
|
|
||||||
|
setEventSource(new EventSource(streamUrl));
|
||||||
|
|
||||||
|
const handleMessage = (event: MessageEvent) => {
|
||||||
|
try {
|
||||||
|
const parsed = JSON.parse(event.data);
|
||||||
|
|
||||||
|
if (parsed.type === 'error') {
|
||||||
|
// Append error message instead of replacing content
|
||||||
|
root.appendLast('\n\nError: ' + parsed.error);
|
||||||
|
root.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
cleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the last message
|
||||||
|
const lastMessage = root.items[root.items.length - 1];
|
||||||
|
|
||||||
|
if (parsed.type === 'chat' && parsed.data.choices[0]?.finish_reason === 'stop') {
|
||||||
|
// For the final chunk, append it and close the connection
|
||||||
|
const content = parsed.data.choices[0]?.delta?.content ?? '';
|
||||||
|
if (content) {
|
||||||
|
// Use appendLast for the final chunk to ensure it's added immediately
|
||||||
|
root.appendLast(content);
|
||||||
|
}
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
root.setIsLoading(false);
|
||||||
|
cleanup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parsed.type === 'chat') {
|
||||||
|
// For regular chunks, use the batched content update for a smoother effect
|
||||||
|
const content = parsed.data.choices[0]?.delta?.content ?? '';
|
||||||
|
if (content && lastMessage) {
|
||||||
|
// Use the batching utility for more efficient updates
|
||||||
|
batchContentUpdate(lastMessage, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('stream parse error', err);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setStreamId = (id: string) => {
|
const handleError = () => {
|
||||||
self.streamId = id;
|
root.appendLast('\n\nError: Connection lost.');
|
||||||
|
root.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
cleanup();
|
||||||
};
|
};
|
||||||
|
|
||||||
return { sendMessage, stopIncomingMessage, cleanup, setEventSource, setStreamId };
|
self.eventSource.onmessage = handleMessage;
|
||||||
|
self.eventSource.onerror = handleError;
|
||||||
|
} catch (err) {
|
||||||
|
console.error('sendMessage', err);
|
||||||
|
root.appendLast('\n\nError: Sorry • network error.');
|
||||||
|
root.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const stopIncomingMessage = () => {
|
||||||
|
cleanup();
|
||||||
|
root.setIsLoading(false);
|
||||||
|
UserOptionsStore.setFollowModeEnabled(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
const setStreamId = (id: string) => {
|
||||||
|
self.streamId = id;
|
||||||
|
};
|
||||||
|
|
||||||
|
return { sendMessage, stopIncomingMessage, cleanup, setEventSource, setStreamId };
|
||||||
|
});
|
||||||
|
|
||||||
export interface IStreamStore extends Instance<typeof StreamStore> {}
|
export interface IStreamStore extends Instance<typeof StreamStore> {}
|
||||||
|
@@ -1,21 +1,20 @@
|
|||||||
|
|
||||||
// ---------------------------
|
// ---------------------------
|
||||||
// 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;
|
||||||
},
|
},
|
||||||
setIsLoading(value: boolean) {
|
setIsLoading(value: boolean) {
|
||||||
self.isLoading = value;
|
self.isLoading = value;
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
export interface IUIStore extends Instance<typeof UIStore> {}
|
export interface IUIStore extends Instance<typeof UIStore> {}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user