From 8b39b2c9332b5c06859bd7bea88eef90c336d10d Mon Sep 17 00:00:00 2001 From: ashum9 Date: Thu, 16 Jul 2026 16:38:08 +0530 Subject: [PATCH 1/8] setup base react vite and tailwind configuration --- mofa-frontend/.gitignore | 5 + mofa-frontend/README.md | 37 + mofa-frontend/eslint.config.js | 27 + mofa-frontend/index.html | 15 + mofa-frontend/package-lock.json | 3217 ++++++++++++++++++++++++++++ mofa-frontend/package.json | 43 + mofa-frontend/postcss.config.mjs | 5 + mofa-frontend/public/favicon.svg | 15 + mofa-frontend/public/mofa-logo.png | Bin 0 -> 103807 bytes mofa-frontend/tsconfig.json | 25 + mofa-frontend/vite.config.ts | 17 + 11 files changed, 3406 insertions(+) create mode 100644 mofa-frontend/.gitignore create mode 100644 mofa-frontend/README.md create mode 100644 mofa-frontend/eslint.config.js create mode 100644 mofa-frontend/index.html create mode 100644 mofa-frontend/package-lock.json create mode 100644 mofa-frontend/package.json create mode 100644 mofa-frontend/postcss.config.mjs create mode 100644 mofa-frontend/public/favicon.svg create mode 100644 mofa-frontend/public/mofa-logo.png create mode 100644 mofa-frontend/tsconfig.json create mode 100644 mofa-frontend/vite.config.ts diff --git a/mofa-frontend/.gitignore b/mofa-frontend/.gitignore new file mode 100644 index 0000000..fd7d79d --- /dev/null +++ b/mofa-frontend/.gitignore @@ -0,0 +1,5 @@ +node_modules/ +dist/ +.env +.DS_Store +*.log diff --git a/mofa-frontend/README.md b/mofa-frontend/README.md new file mode 100644 index 0000000..d2bdace --- /dev/null +++ b/mofa-frontend/README.md @@ -0,0 +1,37 @@ +# MoFA FM + +MoFA FM is a local AI podcast studio. It turns any article into a high-quality podcast script and synthesizes it into natural-sounding audio — running entirely on your machine. No cloud, no API keys, full privacy. + +## Features + +- **Offline-First**: Operates seamlessly against a local inference engine. +- **Visual Intelligence**: Real-time observability into the model's inner workings via the Theater view and Engine Monitor. +- **Design Excellence**: Highly polished interface with considered motion, sound design, and typography. +- **Robust Pipeline**: Hardened against intermittent network failures with intelligent retries. +- **Accessibility**: Full keyboard and screen reader support, honoring reduced-motion preferences. + +## Quick Start + +\`\`\`bash +npm install +npm run dev +\`\`\` + +## Architecture + +- **React + Vite**: Fast, modern frontend build. +- **Tailwind CSS**: Utility-first styling tied to a strict design token system. +- **Framer Motion**: Smooth, intentional animations and state transitions. + +### Mock vs. Real Engine + +MoFA FM is designed to run against the **MoFA Core Engine** (at `127.0.0.1:8420`). +However, for development and demonstration without the heavy backend, the app can run against a simulated local mock engine. + +To use the mock engine, create a `.env` file or set the environment variable: +\`\`\`env +VITE_USE_MOCK=true +VITE_ENGINE_URL=http://localhost:8420 +\`\`\` + +If `VITE_USE_MOCK=false`, the application will make real HTTP and SSE connections to your local Engine. diff --git a/mofa-frontend/eslint.config.js b/mofa-frontend/eslint.config.js new file mode 100644 index 0000000..bdcc475 --- /dev/null +++ b/mofa-frontend/eslint.config.js @@ -0,0 +1,27 @@ +import js from '@eslint/js'; +import globals from 'globals'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config({ + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }] + }, +}); diff --git a/mofa-frontend/index.html b/mofa-frontend/index.html new file mode 100644 index 0000000..916e967 --- /dev/null +++ b/mofa-frontend/index.html @@ -0,0 +1,15 @@ + + + + + + + + MoFA Engine + + + +
+ + + diff --git a/mofa-frontend/package-lock.json b/mofa-frontend/package-lock.json new file mode 100644 index 0000000..fe26f84 --- /dev/null +++ b/mofa-frontend/package-lock.json @@ -0,0 +1,3217 @@ +{ + "name": "applet", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "applet", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@tanstack/react-query": "^5.101.2", + "clsx": "^2.1.1", + "framer-motion": "^12.42.2", + "lucide-react": "^1.23.0", + "react": "^19.2.7", + "react-dom": "^19.2.7", + "tailwind-merge": "^3.6.0", + "wavesurfer.js": "^7.12.10" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@typescript-eslint/eslint-plugin": "^8.63.0", + "@typescript-eslint/parser": "^8.63.0", + "@vitejs/plugin-react": "^6.0.3", + "eslint": "^10.6.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.3", + "globals": "^17.7.0", + "postcss": "^8.5.16", + "tailwindcss": "^4.3.2", + "typescript": "^6.0.3", + "typescript-eslint": "^8.63.0", + "vite": "^8.1.4" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", + "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", + "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", + "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", + "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@emnapi/core": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.11.1.tgz", + "integrity": "sha512-RSvbQmHzdKzNsLYa/wHrbc3KN4sYLKAdPZxqiM2HATqv/SBk2/ENSHpvXGaLOMcsAyz0poEGqkmmKYG3OWiJEQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.2", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.11.1.tgz", + "integrity": "sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.2.tgz", + "integrity": "sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.6.0.tgz", + "integrity": "sha512-ii6Bw9jJ2zi2cWA2Z+9/QZ/+3DX6kwaV5Q986D/CdP3Lap3w/pgQZ373FV7byY/i7L4IRH/G43I5dz1ClsCbpA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.2.tgz", + "integrity": "sha512-+CNAzxglkrpNf/kKywqQfk74QjtceuOE7Qm+AF8miRvPF/wmmK5+OJOgVh3AVTT3RP2mH3+FOaxlE5v72owk0A==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/types": "^0.15.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.6.tgz", + "integrity": "sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.139.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.139.0.tgz", + "integrity": "sha512-r9gHphtCs+1M7J0pw6Sn/hh/Wpa/iQrOOkrNAlVLF/gHq+/CJmHIWKKUUhdWjcD6CIa8idarspCsASiXCXvFUw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.1.5.tgz", + "integrity": "sha512-lZg8fqIv2v7FF237bwMgzGZEJvGL79/s5knJ/i6FmsGF4XXlzccZ4jb+TrFIxtSSxFtIpdsgrPZeMk1I9AFcyQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.1.5.tgz", + "integrity": "sha512-51Bnx9pNiMRKSUNtBfySkNJ9vMU9Hh3I1ozDd6gyPPYzaXCfnptUcEZxXGYFn+ul2dtcMUiqGR1Yai2K10uoTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.1.5.tgz", + "integrity": "sha512-Tm+gbfC0aHu1tBA/JvKQh32S0K6YgCHkiAF4/W6xX0K0RmNuc94VeK419dJoE65R5aRxmo+noZQSWrAMF6yb6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.1.5.tgz", + "integrity": "sha512-JMzDKCCXq93YccG5gz3hvOs1oXRKAf0XYpfOS88e+wZrC8Iugj6j68867vrYZkvpDDpKn/KoKORThmchMpF6TA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.1.5.tgz", + "integrity": "sha512-uML21j2K5TfPGutKxub+M+nLjZIrWjXQ5Grx4lCe/nimTj9B4L63zHpjXLl4y0L3mcm2htEQIb06oCG/szerNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.1.5.tgz", + "integrity": "sha512-navSiuTMogvnQoZoM/v+l3ZWo50/NTwSHSzheABx/RCnmUPaKwq9qSo4Br2OYRs21+Fz8uFqITZM3H4opOB0/Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.1.5.tgz", + "integrity": "sha512-lAryqH7IteztmCXQXk0etKj4wBQ7Gx5S6LjKhsgp9zb8I5bsuvU/2llH1hDQcjsFeqIsovMVN339/8pUDDBXxA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.1.5.tgz", + "integrity": "sha512-fsK/sNBnxzBlL4O1JNrZakVQxPspqpED5dLtNsZS9oOKmtSpdNIzxH2kkol5HYTWJN47sE20ztMJPxfZ89qGOg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.1.5.tgz", + "integrity": "sha512-gLYb4BIadlfTOYT5gO503n8zQjXflgzpD0FcyKh0Mzx3rqCZKnHoJWV9xe1KXUJ5lx2JfcSHr/mhzS0PC/McAA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.1.5.tgz", + "integrity": "sha512-FjcpEKUyJygHgs1o50VYNvkt5+7Le/VEdYt0AkRpkL33MnyQfwr8l5mXwMmfmTbyMPr5vJLC+8/Gd9gXnwU1QQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.1.5.tgz", + "integrity": "sha512-Me+PfPI2TMeOQk0gYWfLQZtTktrmzbr8cDboqX83XKc7UrgAi55gF+2dUkWdxd19n55Essp2yeca+O9N5rBxHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.1.5.tgz", + "integrity": "sha512-yc5WrLzXks6zCQfn9Oxr8pORKyl/pF+QjHmW/Qx3qu0oyrrNC+y2JLTU1E2rcWYAmzlnqngWXHQjy51VzW70Vw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-wasm32-wasi": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.1.5.tgz", + "integrity": "sha512-VbQGPX2b4r48TAMIM2cjgluIM1HYutm4pcTEJsle7iEP7sB1dFqtPLBVbdLAZCxy1txCcPxf4QFf4v8uvltPqA==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.11.1", + "@emnapi/runtime": "1.11.1", + "@napi-rs/wasm-runtime": "^1.1.6" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.1.5.tgz", + "integrity": "sha512-gHv82k63z4qpV5+Q1y/12KrK0ltWBukVDI8nZcbT7Tt/ZlOIVwppazneq0F93oDxTo3IgAMEDIoQh3E2n6mVsw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.1.5.tgz", + "integrity": "sha512-tTZuDBPw85tEN5PQi1pnEBzDy0Z49HtScLAbD5t6hyeU92A95pRWaSMw1GZZi/RwgSgUIl0xrSlXIT/9QzvYSA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.2.tgz", + "integrity": "sha512-yWP/sqEcBLaD8JuA6zNwxoYKr75qxTioYwlRwekj5Jr/I5GXnoJfjetH/psLUIv74cYTH2lBUEzBkinthoYcBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "5.21.6", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.2" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.2.tgz", + "integrity": "sha512-z8ZgnzX8gdNoWLBLqBPoh/sjnxkwvf9ZuWjnO0l0yIzbLa5/9S+eC5QxGZKRobVHIC3/1BoMWjHblqWjcgFgag==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-arm64": "4.3.2", + "@tailwindcss/oxide-darwin-x64": "4.3.2", + "@tailwindcss/oxide-freebsd-x64": "4.3.2", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.3.2", + "@tailwindcss/oxide-linux-arm64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-arm64-musl": "4.3.2", + "@tailwindcss/oxide-linux-x64-gnu": "4.3.2", + "@tailwindcss/oxide-linux-x64-musl": "4.3.2", + "@tailwindcss/oxide-wasm32-wasi": "4.3.2", + "@tailwindcss/oxide-win32-arm64-msvc": "4.3.2", + "@tailwindcss/oxide-win32-x64-msvc": "4.3.2" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.2.tgz", + "integrity": "sha512-WHxqIuHpvZ5VtdX6GTl1Ik/Vp2YuN42Et+0CdeaVd/frQ9jAvGmvR8vLT+jk3e8/Q3x8kECB9+R17pgpp2BulA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.2.tgz", + "integrity": "sha512-GZypeUY/IDJW3877KeM+O67vbXr3MBnbtEL4aYhNErv/JWZhye2vGSWWG9tB6iiqR2MqRNkY8IOUy4NdSZV26w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.2.tgz", + "integrity": "sha512-UIIzmefR6KO1sDU7MzRqAxC8iBpft/VhkGjTjnhoS6k7Z3rQ9wEgA1ODSiyH/tcSYssulNm4Ci3hOeK1jH7ccQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.2.tgz", + "integrity": "sha512-GN+uAmcI6DNspnCDwtOAZrTz6oukJnp337qZvxqCGLd3BHBzJpO0ZbTLRvJNdztOeAmTzewewGIMPb0tk2R4WA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.2.tgz", + "integrity": "sha512-4ABn7qSbdHRwTiDiuWNegCyb5+2FJ4vKIKc3DmKrvAFw7MU1Lm11dIkTPwUaFdTzc7IsOpDbqBrlh0x6y36U/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.2.tgz", + "integrity": "sha512-wDgEIGwoM8w8pufh9LVt1PahDgNdKXrLC2qfAnV3vAmococ9RWbxeAw4pxPttd/TsJfwjyLf90Dg1y9y8I6Emw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.2.tgz", + "integrity": "sha512-J5Nuk0uZQIiMTJj3LEx4sAA9tMFUoXQZFv1J6An+QGYe53HKRJuFDi0rpq/tuouCZeAbOBY3kQ6g8qeD4TUjtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.2.tgz", + "integrity": "sha512-kqCZpSKOBEJO4mz7OqWoofBZeXTAwaVGPj0ErAj7CojmhKpWVWVOnrt9dE8odoIraZq4oj3ausM37kXi+Tow8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.2.tgz", + "integrity": "sha512-cixpqbh2toJDmkuCRI68nXA8ZxNmdK9Y+9v5h3MC3ZQKy/0BO8AWzlkWyRM7JAFSGBlfig4YVTPsK6MVgqz1uw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.2.tgz", + "integrity": "sha512-4ec2Z/LOmRsAgU23CS4xeJfcJlmRg94A/XrbGRCF1gyU/zdDfRLYDVsS+ynSZCmGNxQ1jQriQOKMQeQxBA3Isw==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.2.tgz", + "integrity": "sha512-Zyr/M0+XcYZu3bZrUytc7TXvrk0ftWfl8gN2MwekNDzhqhKRUucMPSeOzM0o0wH5AWOU49BsKRrfKxI2atCPMQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.2.tgz", + "integrity": "sha512-QI9BO7KlNZsp2GuO0jwAAj5jCDABOKXRkCk2XuKTSaNEFSdfzqswYVTtCHBNKHLsqyjFyFkqlDiwkNbTYSssMQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.2.tgz", + "integrity": "sha512-rjVWYCa7Ngbi5AarT6k8TkxUG3Wl1QKzHdIZVsjZSzf36Jmo2IKZt/NHRAwly8oDkbBOH0YTu+CHuf9jPxMc+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.2", + "@tailwindcss/oxide": "4.3.2", + "postcss": "^8.5.15", + "tailwindcss": "4.3.2" + } + }, + "node_modules/@tanstack/query-core": { + "version": "5.101.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.2.tgz", + "integrity": "sha512-hH5MLoJhF7KaIGd7q3xTXGXvslI+GYlM1Z/35aSHHWaCJWB7XvTSHYuV3eM7tw+aE0mT/xMro4M4Q9rCGHT0lw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.101.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.2.tgz", + "integrity": "sha512-seDkr6kzGzX1okaaTtZPtgA688CDPlXUz1C6xSg0ESqn04Vuc8tlrYms1s3de+znBqhPVxFRfpAfUf+6XvfPWg==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.101.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.3.tgz", + "integrity": "sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.17", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.17.tgz", + "integrity": "sha512-MXfmqaVPEVgkBT/aY0aGCkRWWtByiYQXo3xdQ8r5RzuFrPiRn8Gar2tQdXSUQ2GKV3bkXckek89V8wQBY2Q/Aw==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.63.0.tgz", + "integrity": "sha512-rvwSgqT+DHpWdzfSzPatRLm02a0GlESt++9iy3hLCDY4BgkaLcl8LBi9Yh7XGFBpwcBE/K3024QuXWTpbz4FfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.63.0", + "@typescript-eslint/type-utils": "8.63.0", + "@typescript-eslint/utils": "8.63.0", + "@typescript-eslint/visitor-keys": "8.63.0", + "ignore": "^7.0.5", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.63.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.63.0.tgz", + "integrity": "sha512-gwh4gvvlaVDKKxyfxMG+Gnu1u9X0OQBwyGLkbwB65dIzBKnxeRiJlNFqlI3zwVhNXJIs6qV7mlFCn/BIajlVig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.63.0", + "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/typescript-estree": "8.63.0", + "@typescript-eslint/visitor-keys": "8.63.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.63.0.tgz", + "integrity": "sha512-e5dh0/UI0ok53AlZ5wRkXCB32z/f2jUZqPR/ygAw5WYaSw8j9EoJWlS7wQjr/dmOaqWjnPIn2m+HhVPCMWGZVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.63.0", + "@typescript-eslint/types": "^8.63.0", + "debug": "^4.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.63.0.tgz", + "integrity": "sha512-uUyfMWCnDSN8bCpcrY8nGP2BLkQ9Xn0GsipcONcpIDWhwhO4ZSyHvyS14U3X75mzxWxL3I2UZIrenTzdzcJO8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/visitor-keys": "8.63.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.63.0.tgz", + "integrity": "sha512-sUAbkulqBAsncKnbRP3+7CtQFRKicexnj7ZwNC6ddCR7EmrXvjvdCYMJbUIqMd6lwoEriZjwLo08aS5tSjVMHg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.63.0.tgz", + "integrity": "sha512-Nzzh/OGxVCOjObjaj1CQF2RUasyYy2Jfuh+zZ3PjLzG2fYRriAiZLib9UKtO+CpQAS3YHiAS+ckZDclwqI1TPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/typescript-estree": "8.63.0", + "@typescript-eslint/utils": "8.63.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.63.0.tgz", + "integrity": "sha512-xyLtl9DUBBFrcJS4x2pIqGLH68/tC2uOa4Z7pUteW09D3bXnnXUom4dyPikzWgB7llmIc1zoeI3aoUdC4rPK/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.63.0.tgz", + "integrity": "sha512-ygBkU+B7ex5UI/gKhaqexWev79uISfIv7XQCRNYO/jmD8rGLPyWLAb3KMRT6nd8Gt9bmUBi9+iX6tBdYfOY81Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.63.0", + "@typescript-eslint/tsconfig-utils": "8.63.0", + "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/visitor-keys": "8.63.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.63.0.tgz", + "integrity": "sha512-fUKaeAvrTuQg/Tgt3nliAUSZHJM6DlCcfyEmxCvlX8kieWSStBX+5O5Fnidtc3i2JrH+9c/GL4RY2iasd/GPTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.63.0", + "@typescript-eslint/types": "8.63.0", + "@typescript-eslint/typescript-estree": "8.63.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.63.0.tgz", + "integrity": "sha512-UexrHGnGTpbuQHct2ExOc2ZcFbGUS9FOesCxxqdBGcpI1BxYu/LZ6U8Aq6/72XtF/qRBk9nhuGHFJIXXMhPMdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.63.0", + "eslint-visitor-keys": "^5.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.0.3.tgz", + "integrity": "sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + } + } + }, + "node_modules/acorn": { + "version": "8.17.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.17.0.tgz", + "integrity": "sha512-xRQbDb9BnwDafYNn6Vwl839DYVjqXYb1XVGtWAZ1kcDc6iwAL4hg3B1dZlRiuENFeO2H53gFG3in621AdERVAg==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.42", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.42.tgz", + "integrity": "sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "5.0.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.7.tgz", + "integrity": "sha512-7oFy703dxfY3/NLxC1fh2SUCQ0H9rmAY+5EpDVfXjUTTs+HEwR2nYaqLv+GWcTsumwxPfiz6CzCNkwXwBUwqCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "18 || 20 || >=22" + } + }, + "node_modules/browserslist": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.5.tgz", + "integrity": "sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.10.42", + "caniuse-lite": "^1.0.30001800", + "electron-to-chromium": "^1.5.387", + "node-releases": "^2.0.50", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001803", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001803.tgz", + "integrity": "sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.389", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.389.tgz", + "integrity": "sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==", + "dev": true, + "license": "ISC" + }, + "node_modules/enhanced-resolve": { + "version": "5.21.6", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.6.tgz", + "integrity": "sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.6.0.tgz", + "integrity": "sha512-6lVbcqSodALYo+4ELD0heG6lFiFxnLMuLkiMi2qV8LMp54N8tE8FT1GMH+ev4Ti00nFjNze2+Su6DsV5OQW3Dg==", + "dev": true, + "license": "MIT", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.6.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.2", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "minimatch": "^10.2.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.3.tgz", + "integrity": "sha512-5EMmLCV98Pi4o/f/3DP/v/tNqLHMIc9I8LKClNDWhZ9JTho89/kQcitCXQBMG7sAfVRK0Ie3T2EDOzp1YXYiVA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": "^9 || ^10" + } + }, + "node_modules/eslint-scope": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/espree": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.16.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^5.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/framer-motion": { + "version": "12.42.2", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.42.2.tgz", + "integrity": "sha512-5XY9luDiu0oHfHBjpDthFMh0ES+122w6p/papSJBweMkO8Sn+PW2QaEgRblQBpWFnuvZS5qvarpt/hO2pjGmnw==", + "license": "MIT", + "dependencies": { + "motion-dom": "^12.42.2", + "motion-utils": "^12.39.0", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "@emotion/is-prop-valid": "*", + "react": "^18.0.0 || ^19.0.0", + "react-dom": "^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@emotion/is-prop-valid": { + "optional": true + }, + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "17.7.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.7.0.tgz", + "integrity": "sha512-Czmyns5dUsq4seFBR/Kdydhmo8y9kC79hiSkPn0YcGtNnYWnrgt0vjrSjx9tspoDGWm2CMarffRuLjM4xUz8xg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", + "dev": true, + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.32.0", + "lightningcss-darwin-arm64": "1.32.0", + "lightningcss-darwin-x64": "1.32.0", + "lightningcss-freebsd-x64": "1.32.0", + "lightningcss-linux-arm-gnueabihf": "1.32.0", + "lightningcss-linux-arm64-gnu": "1.32.0", + "lightningcss-linux-arm64-musl": "1.32.0", + "lightningcss-linux-x64-gnu": "1.32.0", + "lightningcss-linux-x64-musl": "1.32.0", + "lightningcss-win32-arm64-msvc": "1.32.0", + "lightningcss-win32-x64-msvc": "1.32.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "1.23.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.23.0.tgz", + "integrity": "sha512-38BpJcD0JhFosxHApP/BYsBetLpQFRoTRzEzstM/XCc3jsAG7wqaY1lgVwxiUe3xqYE+lNxo2PkCmYwXWrwwIw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/minimatch": { + "version": "10.2.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.5.tgz", + "integrity": "sha512-MULkVLfKGYDFYejP07QOurDLLQpcjk7Fw+7jXS2R2czRQzR56yHRveU5NDJEOviH+hETZKSkIk5c+T23GjFUMg==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.5" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/motion-dom": { + "version": "12.42.2", + "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.42.2.tgz", + "integrity": "sha512-5gIMWLp/PycBtJRJWRgjxke5n8dlvkSn2DrYW+tr3XcqAZY1xZh6BJyooJXCM8wdfM7wfMjkBJNLge1CKPUIRA==", + "license": "MIT", + "dependencies": { + "motion-utils": "^12.39.0" + } + }, + "node_modules/motion-utils": { + "version": "12.39.0", + "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.39.0.tgz", + "integrity": "sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==", + "license": "MIT" + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.15", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.15.tgz", + "integrity": "sha512-y7Wygv/7mEOvxTuEQDB8StXdMRBWf1kR/tlhAzBRUFkB2jfcLOAxO/SHmOO2zgz1pVgK29/kyupn059/bCHdjA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.51", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.51.tgz", + "integrity": "sha512-wRNIrw4DmVLKQlbgOMdkMx27Wrpzes2hh5Jtbi2bjPd+4wJstWIqP5A+lscnqbm0xxmT5Bpg8Lec5ItEBwx6BQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.16", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.16.tgz", + "integrity": "sha512-vuwillviilfKZsg0VGj5R/YwwcHx4SLsIOI/7K6mQkWx+l5cUHTjj5g0AasTBcyXsbfTgrwsUNmVUb5xVwyPwg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.12", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.7.tgz", + "integrity": "sha512-HNe9WslTbXmFK8o8cmwgAeJFSBvt1bPdHCVKtaaV+WlAN36mpT4hcRpwbf3fY56ar2oIXzsBpOAiIRHAdY0OlQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.7", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", + "integrity": "sha512-t0BRVXvbiE/o20Hfw669rLbMCDWtYZLvmJigy2f0MxsXF+71pxhR3xOkspmsO8h3ZlNzyibAmtCa3l4lYKk6gQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.7" + } + }, + "node_modules/rolldown": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.1.5.tgz", + "integrity": "sha512-t9z29cJjXf/vxQ8dyhCSpt6H6aSwHTk8cT5I3iy6SMXuFpk5mB6PL6XfC8PCwrPTx93udwKUm9HRteAlTGBLiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.139.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm64": "1.1.5", + "@rolldown/binding-darwin-arm64": "1.1.5", + "@rolldown/binding-darwin-x64": "1.1.5", + "@rolldown/binding-freebsd-x64": "1.1.5", + "@rolldown/binding-linux-arm-gnueabihf": "1.1.5", + "@rolldown/binding-linux-arm64-gnu": "1.1.5", + "@rolldown/binding-linux-arm64-musl": "1.1.5", + "@rolldown/binding-linux-ppc64-gnu": "1.1.5", + "@rolldown/binding-linux-s390x-gnu": "1.1.5", + "@rolldown/binding-linux-x64-gnu": "1.1.5", + "@rolldown/binding-linux-x64-musl": "1.1.5", + "@rolldown/binding-openharmony-arm64": "1.1.5", + "@rolldown/binding-wasm32-wasi": "1.1.5", + "@rolldown/binding-win32-arm64-msvc": "1.1.5", + "@rolldown/binding-win32-x64-msvc": "1.1.5" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.2.tgz", + "integrity": "sha512-WtctNNSH8A9jlMIqxzuYumOHU5uGZyRv0Q5svQl+oEPy5w84YpBxdb7MdqyiSPQge5jTJ6zFQLq0PFygdccSBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/ts-api-utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-6.0.3.tgz", + "integrity": "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.63.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.63.0.tgz", + "integrity": "sha512-xgwXyzG4sK9ALkBxbyGkTMMOS+imnW65iPhxCQMK83KhxyoDNW7l+IDqEf9vMdoUidHpOoS967RCq4eMiTexwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.63.0", + "@typescript-eslint/parser": "8.63.0", + "@typescript-eslint/typescript-estree": "8.63.0", + "@typescript-eslint/utils": "8.63.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "8.1.4", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.1.4.tgz", + "integrity": "sha512-bTT9PsdWO+MQMNG9ZXIP/qM9wGh37DFxTV/sPq9cFpHr3w4jkgef032PkAL9jAqhk3Nz8NQw3O8n6/xFkqO4QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.32.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.16", + "rolldown": "~1.1.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.3.0", + "esbuild": "^0.27.0 || ^0.28.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/wavesurfer.js": { + "version": "7.12.10", + "resolved": "https://registry.npmjs.org/wavesurfer.js/-/wavesurfer.js-7.12.10.tgz", + "integrity": "sha512-M3AC5biFmvfy7Oxe8FN6I88H0z1c8Vuz81N6Oq2CY4kOumNDb6U1/0qg4pomjP619vJqdWADlgUcpOKvfGifng==", + "license": "BSD-3-Clause" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.4.3.tgz", + "integrity": "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/mofa-frontend/package.json b/mofa-frontend/package.json new file mode 100644 index 0000000..560804b --- /dev/null +++ b/mofa-frontend/package.json @@ -0,0 +1,43 @@ +{ + "name": "applet", + "version": "1.0.0", + "type": "module", + "description": "", + "main": "index.js", + "scripts": { + "dev": "vite --port 3000 --host 0.0.0.0", + "build": "tsc && vite build", + "lint": "eslint ." + }, + "keywords": [], + "author": "", + "license": "ISC", + "dependencies": { + "@tanstack/react-query": "^5.101.2", + "clsx": "^2.1.1", + "framer-motion": "^12.42.2", + "lucide-react": "^1.23.0", + "react": "^19.2.7", + "react-dom": "^19.2.7", + "tailwind-merge": "^3.6.0", + "wavesurfer.js": "^7.12.10" + }, + "devDependencies": { + "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.2", + "@types/react": "^19.2.17", + "@types/react-dom": "^19.2.3", + "@typescript-eslint/eslint-plugin": "^8.63.0", + "@typescript-eslint/parser": "^8.63.0", + "@vitejs/plugin-react": "^6.0.3", + "eslint": "^10.6.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.3", + "globals": "^17.7.0", + "postcss": "^8.5.16", + "tailwindcss": "^4.3.2", + "typescript": "^6.0.3", + "typescript-eslint": "^8.63.0", + "vite": "^8.1.4" + } +} diff --git a/mofa-frontend/postcss.config.mjs b/mofa-frontend/postcss.config.mjs new file mode 100644 index 0000000..ef6af3e --- /dev/null +++ b/mofa-frontend/postcss.config.mjs @@ -0,0 +1,5 @@ +export default { + plugins: { + '@tailwindcss/postcss': {}, + } +} diff --git a/mofa-frontend/public/favicon.svg b/mofa-frontend/public/favicon.svg new file mode 100644 index 0000000..95eaf7b --- /dev/null +++ b/mofa-frontend/public/favicon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/mofa-frontend/public/mofa-logo.png b/mofa-frontend/public/mofa-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..8eeb2cb5685ee74beb84a9dfbfe9573bab9324c7 GIT binary patch literal 103807 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 JQbQN)e*t9Ir@#OJ literal 0 HcmV?d00001 diff --git a/mofa-frontend/tsconfig.json b/mofa-frontend/tsconfig.json new file mode 100644 index 0000000..fae33a3 --- /dev/null +++ b/mofa-frontend/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "ignoreDeprecations": "6.0", + "baseUrl": ".", + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["src"] +} diff --git a/mofa-frontend/vite.config.ts b/mofa-frontend/vite.config.ts new file mode 100644 index 0000000..3994565 --- /dev/null +++ b/mofa-frontend/vite.config.ts @@ -0,0 +1,17 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; +import path from 'path'; + +export default defineConfig({ + plugins: [react()], + resolve: { + alias: { + '@': path.resolve(__dirname, './src'), + }, + }, + server: { + hmr: process.env.DISABLE_HMR !== 'true', + host: '0.0.0.0', + port: 3000, + }, +}); From d28d617cde3707fca839aaa6612d0abae0f43e15 Mon Sep 17 00:00:00 2001 From: ashum9 Date: Thu, 16 Jul 2026 16:38:08 +0530 Subject: [PATCH 2/8] add shared ui components and styling utilities --- mofa-frontend/src/index.css | 36 ++++++++++++++++++ mofa-frontend/src/lib/audio.ts | 23 ++++++++++++ mofa-frontend/src/lib/motion.ts | 26 +++++++++++++ mofa-frontend/src/lib/utils.ts | 11 ++++++ mofa-frontend/src/shared/Badge.tsx | 41 +++++++++++++++++++++ mofa-frontend/src/shared/Button.tsx | 31 ++++++++++++++++ mofa-frontend/src/shared/Card.tsx | 24 ++++++++++++ mofa-frontend/src/shared/Skeleton.tsx | 12 ++++++ mofa-frontend/src/shared/StatusDot.tsx | 51 ++++++++++++++++++++++++++ mofa-frontend/src/vite-env.d.ts | 1 + 10 files changed, 256 insertions(+) create mode 100644 mofa-frontend/src/index.css create mode 100644 mofa-frontend/src/lib/audio.ts create mode 100644 mofa-frontend/src/lib/motion.ts create mode 100644 mofa-frontend/src/lib/utils.ts create mode 100644 mofa-frontend/src/shared/Badge.tsx create mode 100644 mofa-frontend/src/shared/Button.tsx create mode 100644 mofa-frontend/src/shared/Card.tsx create mode 100644 mofa-frontend/src/shared/Skeleton.tsx create mode 100644 mofa-frontend/src/shared/StatusDot.tsx create mode 100644 mofa-frontend/src/vite-env.d.ts diff --git a/mofa-frontend/src/index.css b/mofa-frontend/src/index.css new file mode 100644 index 0000000..bc14f65 --- /dev/null +++ b/mofa-frontend/src/index.css @@ -0,0 +1,36 @@ +@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap'); +@import "tailwindcss"; + +@theme { + --color-background-primary: #ffffff; + --color-background-secondary: #f4f4f5; + + --color-text-primary: #09090b; + --color-text-secondary: #52525b; + --color-text-dim: #a1a1aa; + + --color-accent-blue: #2563eb; + --color-accent-cyan: #0891b2; + --color-accent-green: #059669; + --color-accent-yellow: #d97706; + --color-accent-red: #dc2626; + --color-accent-purple: #7c3aed; + + --radius-card: 10px; + --radius-small: 6px; + + --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif; + --font-mono: "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + +@layer base { + body { + @apply bg-background-primary text-text-primary font-sans antialiased; + margin: 0; + } + + *:focus-visible { + @apply outline-none ring-2 ring-accent-cyan ring-offset-2 ring-offset-background-primary; + } +} + diff --git a/mofa-frontend/src/lib/audio.ts b/mofa-frontend/src/lib/audio.ts new file mode 100644 index 0000000..ff3af24 --- /dev/null +++ b/mofa-frontend/src/lib/audio.ts @@ -0,0 +1,23 @@ +export function playChime() { + try { + const ctx = new (window.AudioContext || (window as any).webkitAudioContext)(); + const osc = ctx.createOscillator(); + const gainNode = ctx.createGain(); + + osc.type = 'sine'; + osc.frequency.setValueAtTime(523.25, ctx.currentTime); // C5 + osc.frequency.exponentialRampToValueAtTime(1046.50, ctx.currentTime + 0.1); // C6 + + gainNode.gain.setValueAtTime(0, ctx.currentTime); + gainNode.gain.linearRampToValueAtTime(0.3, ctx.currentTime + 0.05); + gainNode.gain.exponentialRampToValueAtTime(0.001, ctx.currentTime + 1.5); + + osc.connect(gainNode); + gainNode.connect(ctx.destination); + + osc.start(); + osc.stop(ctx.currentTime + 1.5); + } catch { + // Ignore if audio context fails + } +} diff --git a/mofa-frontend/src/lib/motion.ts b/mofa-frontend/src/lib/motion.ts new file mode 100644 index 0000000..600eb1f --- /dev/null +++ b/mofa-frontend/src/lib/motion.ts @@ -0,0 +1,26 @@ +export const motionVariants: any = { + enter: { + initial: { opacity: 0 }, + animate: { opacity: 1, transition: { duration: 0.4, ease: [0.25, 0.1, 0.25, 1] } }, + exit: { opacity: 0, transition: { duration: 0.3, ease: 'easeIn' } } + }, + fade: { + initial: { opacity: 0 }, + animate: { opacity: 1, transition: { duration: 0.3, ease: [0.25, 0.1, 0.25, 1] } }, + exit: { opacity: 0, transition: { duration: 0.2, ease: 'easeIn' } } + }, + staggerContainer: { + animate: { + transition: { + staggerChildren: 0.04 + } + } + }, + staggerItem: { + initial: { opacity: 0 }, + animate: { opacity: 1, transition: { duration: 0.3, ease: 'easeOut' } } + }, + buttonTap: { + scale: 0.98 + } +}; diff --git a/mofa-frontend/src/lib/utils.ts b/mofa-frontend/src/lib/utils.ts new file mode 100644 index 0000000..ce9a19e --- /dev/null +++ b/mofa-frontend/src/lib/utils.ts @@ -0,0 +1,11 @@ +import { clsx, type ClassValue } from 'clsx'; +import { twMerge } from 'tailwind-merge'; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} + + +export function formatMs(ms: number) { + return `${(ms / 1000).toFixed(1)}s`; +} diff --git a/mofa-frontend/src/shared/Badge.tsx b/mofa-frontend/src/shared/Badge.tsx new file mode 100644 index 0000000..d24d38e --- /dev/null +++ b/mofa-frontend/src/shared/Badge.tsx @@ -0,0 +1,41 @@ +import React from 'react'; +import { cn } from '../lib/utils'; +import { Capability } from '../engine/types'; + +interface BadgeProps extends React.HTMLAttributes { + variant?: 'blue' | 'purple' | 'cyan' | 'yellow' | 'green' | 'default'; + capability?: Capability; +} + +export function Badge({ className, variant = 'default', capability, children, ...props }: BadgeProps) { + let finalVariant = variant; + + if (capability) { + switch (capability) { + case 'Chat': finalVariant = 'blue'; break; + case 'Tts': finalVariant = 'purple'; break; + case 'Asr': finalVariant = 'cyan'; break; + case 'ImageGen': finalVariant = 'yellow'; break; + case 'Embedding': finalVariant = 'green'; break; + default: finalVariant = 'default'; + } + } + + return ( + + {capability || children} + + ); +} diff --git a/mofa-frontend/src/shared/Button.tsx b/mofa-frontend/src/shared/Button.tsx new file mode 100644 index 0000000..9886349 --- /dev/null +++ b/mofa-frontend/src/shared/Button.tsx @@ -0,0 +1,31 @@ +import React from 'react'; +import { cn } from '../lib/utils'; +import { motion, HTMLMotionProps } from 'framer-motion'; +import { motionVariants } from '../lib/motion'; + +interface ButtonProps extends HTMLMotionProps<'button'> { + variant?: 'primary' | 'secondary' | 'ghost'; +} + +export const Button = React.forwardRef( + ({ className, variant = 'primary', ...props }, ref) => { + return ( + + {props.children as React.ReactNode} + + ); + } +); +Button.displayName = 'Button'; diff --git a/mofa-frontend/src/shared/Card.tsx b/mofa-frontend/src/shared/Card.tsx new file mode 100644 index 0000000..e2451bb --- /dev/null +++ b/mofa-frontend/src/shared/Card.tsx @@ -0,0 +1,24 @@ +import React from 'react'; +import { cn } from '../lib/utils'; +import { motion, HTMLMotionProps } from 'framer-motion'; + +interface CardProps extends HTMLMotionProps<'div'> { + interactive?: boolean; +} + +export const Card = React.forwardRef( + ({ className, interactive, ...props }, ref) => { + return ( + + ); + } +); +Card.displayName = 'Card'; diff --git a/mofa-frontend/src/shared/Skeleton.tsx b/mofa-frontend/src/shared/Skeleton.tsx new file mode 100644 index 0000000..c232444 --- /dev/null +++ b/mofa-frontend/src/shared/Skeleton.tsx @@ -0,0 +1,12 @@ +import { cn } from '../lib/utils'; + +type SkeletonProps = React.HTMLAttributes; + +export function Skeleton({ className, ...props }: SkeletonProps) { + return ( +

+ ); +} diff --git a/mofa-frontend/src/shared/StatusDot.tsx b/mofa-frontend/src/shared/StatusDot.tsx new file mode 100644 index 0000000..1c9452d --- /dev/null +++ b/mofa-frontend/src/shared/StatusDot.tsx @@ -0,0 +1,51 @@ +import React from 'react'; +import { cn } from '../lib/utils'; +import { motion } from 'framer-motion'; + +export type StatusType = 'Hot' | 'Healthy' | 'Closed' | 'Warming' | 'HalfOpen' | 'Busy' | 'Cold' | 'Unloaded' | 'Failed' | 'Open' | 'Unhealthy' | 'Connecting'; + +interface StatusDotProps { + status: StatusType; + className?: string; +} + +export function StatusDot({ status, className }: StatusDotProps) { + let colorClass = 'bg-text-dim'; + let animatePulse = false; + + switch (status) { + case 'Hot': + case 'Healthy': + case 'Closed': + colorClass = 'bg-accent-green shadow-[0_0_8px_rgba(16,185,129,0.6)]'; + break; + case 'Warming': + case 'HalfOpen': + case 'Connecting': + colorClass = 'bg-accent-yellow shadow-[0_0_8px_rgba(245,158,11,0.6)]'; + animatePulse = true; + break; + case 'Busy': + colorClass = 'bg-accent-blue shadow-[0_0_8px_rgba(59,130,246,0.6)]'; + animatePulse = true; + break; + case 'Cold': + case 'Unloaded': + break; + case 'Failed': + case 'Open': + case 'Unhealthy': + colorClass = 'bg-accent-red shadow-[0_0_8px_rgba(239,68,68,0.6)]'; + break; + default: + break; + } + + return ( + + ); +} diff --git a/mofa-frontend/src/vite-env.d.ts b/mofa-frontend/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/mofa-frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// From 5cfa985f3681e7a82dcf4ef3fbdb6ec757640956 Mon Sep 17 00:00:00 2001 From: ashum9 Date: Thu, 16 Jul 2026 16:38:08 +0530 Subject: [PATCH 3/8] implement rust engine sdk and sse connection hooks --- mofa-frontend/src/engine/client.ts | 115 ++++++++++++++++++ mofa-frontend/src/engine/index.ts | 43 +++++++ mofa-frontend/src/engine/types.ts | 96 +++++++++++++++ .../src/engine/useEngineConnection.ts | 28 +++++ mofa-frontend/src/engine/useEngineStatus.ts | 15 +++ 5 files changed, 297 insertions(+) create mode 100644 mofa-frontend/src/engine/client.ts create mode 100644 mofa-frontend/src/engine/index.ts create mode 100644 mofa-frontend/src/engine/types.ts create mode 100644 mofa-frontend/src/engine/useEngineConnection.ts create mode 100644 mofa-frontend/src/engine/useEngineStatus.ts diff --git a/mofa-frontend/src/engine/client.ts b/mofa-frontend/src/engine/client.ts new file mode 100644 index 0000000..eec03da --- /dev/null +++ b/mofa-frontend/src/engine/client.ts @@ -0,0 +1,115 @@ +import { + HealthResponse, + EngineStatus, + ModelCard, + InferenceRequest, + InferenceResponse, + EngineResult, + EngineEvent +} from './types'; +import { IEngineClient } from './index'; + +export class RealEngineClient implements IEngineClient { + private baseUrl: string; + + constructor(baseUrl: string) { + this.baseUrl = baseUrl.replace(/\/$/, ''); + } + + setBaseUrl(url: string) { + this.baseUrl = url.replace(/\/$/, ''); + } + + getBaseUrl() { + return this.baseUrl; + } + + private async request(path: string, options?: RequestInit): Promise> { + try { + const response = await fetch(`${this.baseUrl}${path}`, { + ...options, + headers: { + 'Content-Type': 'application/json', + ...(options?.headers || {}) + } + }); + + if (!response.ok) { + let detail = response.statusText; + let error = `HTTP ${response.status}`; + try { + const body = await response.json(); + if (body.error) error = body.error; + if (body.detail) detail = body.detail; + } catch { + // ignore parsing error if it's not JSON + } + return { success: false, type: 'http', error, detail }; + } + + const data = await response.json(); + return { success: true, data }; + } catch (e) { + return { success: false, type: 'network', error: 'Engine unreachable', detail: (e as Error).message }; + } + } + + async getHealth() { + return this.request('/health'); + } + + async getStatus() { + return this.request('/v1/status'); + } + + async getCapabilities() { + return this.request('/v1/capabilities'); + } + + async invoke(payload: InferenceRequest) { + return this.request('/v1/invoke', { + method: 'POST', + body: JSON.stringify(payload) + }); + } + + async refreshDiscovery() { + return this.request('/v1/discovery/refresh', { + method: 'POST' + }); + } + + subscribeEvents(handler: (e: EngineEvent) => void): () => void { + const eventSource = new EventSource(`${this.baseUrl}/v1/events`); + + eventSource.onmessage = (event) => { + try { + const raw = JSON.parse(event.data); + // Real engine uses serde tag="type" rename_all="snake_case" + // so type comes as "request_started", "model_status_changed", etc. + const snakeType: string = raw.type || ''; + // Convert snake_case to PascalCase: "request_started" → "RequestStarted" + const pascalType = snakeType.replace(/(^|_)([a-z])/g, (_: string, __: string, c: string) => c.toUpperCase()); + // Everything except 'type' goes into data + const { type: _, ...data } = raw; + handler({ type: pascalType as any, data, timestamp: Date.now() }); + } catch (e) { + console.error("Failed to parse SSE", e); + } + }; + + return () => { + eventSource.close(); + }; + } + + getAudioUrl(filename: string): string { + return `${this.baseUrl}/v1/files/${filename}`; + } + + async fetchAudio(filename: string): Promise { + const res = await fetch(this.getAudioUrl(filename)); + if (!res.ok) throw new Error(`Failed to fetch audio: ${res.statusText}`); + return res.blob(); + } +} diff --git a/mofa-frontend/src/engine/index.ts b/mofa-frontend/src/engine/index.ts new file mode 100644 index 0000000..c994705 --- /dev/null +++ b/mofa-frontend/src/engine/index.ts @@ -0,0 +1,43 @@ +import { HealthResponse, EngineStatus, ModelCard, InferenceRequest, InferenceResponse, EngineResult, EngineEvent } from './types'; +import { RealEngineClient } from './client'; +export interface IEngineClient { + getBaseUrl(): string; + setBaseUrl(url: string): void; + getHealth(): Promise>; + getStatus(): Promise>; + getCapabilities(): Promise>; + invoke(req: InferenceRequest): Promise>; + refreshDiscovery(): Promise>; + subscribeEvents(handler: (e: EngineEvent) => void): () => void; + getAudioUrl(filename: string): string; + fetchAudio(filename: string): Promise; +} + +export const defaultEngineUrl = import.meta.env.VITE_ENGINE_URL || 'http://127.0.0.1:8420'; + +export const getStoredEngineUrl = () => { + return localStorage.getItem('mofa_engine_url') || defaultEngineUrl; +}; + +import { useState, useEffect } from 'react'; + +type Listener = () => void; +const listeners = new Set(); + +export const setStoredEngineUrl = (url: string) => { + localStorage.setItem('mofa_engine_url', url); + engine.setBaseUrl(url); + listeners.forEach(l => l()); +}; + +export const useEngineUrl = () => { + const [url, setUrl] = useState(getStoredEngineUrl()); + useEffect(() => { + const listener = () => setUrl(getStoredEngineUrl()); + listeners.add(listener); + return () => { listeners.delete(listener); }; + }, []); + return url; +}; + +export const engine: IEngineClient = new RealEngineClient(getStoredEngineUrl()); diff --git a/mofa-frontend/src/engine/types.ts b/mofa-frontend/src/engine/types.ts new file mode 100644 index 0000000..dc2c09a --- /dev/null +++ b/mofa-frontend/src/engine/types.ts @@ -0,0 +1,96 @@ +export type Capability = 'Chat' | 'Tts' | 'Asr' | 'ImageGen' | 'VideoGen' | 'Vlm' | 'Embedding'; +export type ModelStatus = 'Cold' | 'Warming' | 'Hot' | 'Busy' | 'Failed'; +export type ModelResidency = 'Unknown' | 'Unloaded' | 'Loading' | 'Loaded' | 'Unloading' | 'Remote'; +export type ModelAvailability = 'Discovered' | 'Configured' | 'Unavailable'; +export type ExecutionState = 'Idle' | 'Active' | 'Overloaded'; +export type CostTier = 'Free' | 'Low' | 'Medium' | 'High'; +export type CircuitState = 'Closed' | 'Open' | 'HalfOpen'; +export type BackendHealth = 'Healthy' | 'Degraded' | 'Unhealthy'; +export type FallbackPolicy = 'capability_only' | 'disabled' | 'allow_named'; + +export interface HealthResponse { + status: string; + version: string; + uptime_secs: number; +} + +export interface ProviderHealth { + name: string; + healthy: boolean; + circuit_state: CircuitState; +} + +export interface Backend { + name: string; + kind: string; + health: BackendHealth; + circuit_state: CircuitState; + features: string[]; +} + +export interface EngineStatus { + total_models: number; + loaded_models: number; + providers: number; + memory_used_bytes: number; + memory_budget_bytes: number; + uptime_secs: number; + provider_health: ProviderHealth[]; + backends: Backend[]; +} + +export interface ModelCard { + id: string; + name: string; + provider: string; + capability: Capability; + capabilities: Capability[]; + status: ModelStatus; + availability: ModelAvailability; + residency: ModelResidency; + execution: ExecutionState; + cost_tier: CostTier; + context_window?: number; + memory_estimate_bytes?: number; +} + +export interface InferenceRequest { + capability: Capability; + model: string | null; + messages: Array<{ role: string; content: string }>; + hint_next?: string; + params: Record; + app_id: string; + session_id: string | null; + fallback_policy: FallbackPolicy; +} + +export interface InferenceResponse { + text: string; + file: string | null; + model_used: string; + provider: string; + duration_ms: number; + request_id: string; + tokens_used: number; + fallback_used: boolean; + routing_reason: string; + candidates_considered?: number; +} + +export interface EngineError { + error: string; + detail: string; +} + +export type EngineResult = + | { success: true; data: T } + | { success: false; type: 'network' | 'http'; error: string; detail?: string }; + +export type EngineEventType = 'RequestStarted' | 'RequestCompleted' | 'ModelStatusChanged' | 'ModelResidencyChanged' | 'MemoryChanged' | 'ProviderHealthChanged' | 'DiscoveryCompleted'; + +export interface EngineEvent { + type: EngineEventType; + data: any; + timestamp: number; +} diff --git a/mofa-frontend/src/engine/useEngineConnection.ts b/mofa-frontend/src/engine/useEngineConnection.ts new file mode 100644 index 0000000..305142a --- /dev/null +++ b/mofa-frontend/src/engine/useEngineConnection.ts @@ -0,0 +1,28 @@ +import { useQuery } from '@tanstack/react-query'; +import { engine, useEngineUrl } from './index'; + +export type ConnectionState = 'connecting' | 'connected' | 'disconnected'; + +export function useEngineConnection() { + const url = useEngineUrl(); + const { data, error, isFetching } = useQuery({ + queryKey: ['engine_health', url], + queryFn: () => engine.getHealth(), + refetchInterval: 3000, + retry: false, + }); + + let state: ConnectionState = 'connecting'; + if (data?.success) { + state = 'connected'; + } else if (data?.success === false || error) { + state = 'disconnected'; + } + + return { + state, + version: data?.success ? data.data.version : null, + uptime_secs: data?.success ? data.data.uptime_secs : null, + isFetching + }; +} diff --git a/mofa-frontend/src/engine/useEngineStatus.ts b/mofa-frontend/src/engine/useEngineStatus.ts new file mode 100644 index 0000000..3328fc9 --- /dev/null +++ b/mofa-frontend/src/engine/useEngineStatus.ts @@ -0,0 +1,15 @@ +import { useQuery } from '@tanstack/react-query'; +import { engine, useEngineUrl } from './index'; +import { useEngineConnection } from './useEngineConnection'; + +export function useEngineStatus() { + const { state } = useEngineConnection(); + const url = useEngineUrl(); + + return useQuery({ + queryKey: ['engine_status', url], + queryFn: () => engine.getStatus(), + refetchInterval: 2000, + enabled: state === 'connected', + }); +} From fbecebc210bff1b8fa550ef610a1883209a1ceaa Mon Sep 17 00:00:00 2001 From: ashum9 Date: Thu, 16 Jul 2026 16:38:08 +0530 Subject: [PATCH 4/8] build real time observability and metrics dashboard --- mofa-frontend/src/monitor/EventFeed.tsx | 131 ++++++++++++++ mofa-frontend/src/monitor/MemoryGauge.tsx | 80 +++++++++ mofa-frontend/src/monitor/ModelGrid.tsx | 82 +++++++++ mofa-frontend/src/monitor/MonitorSidebar.tsx | 58 ++++++ .../src/monitor/PreflightIndicator.tsx | 66 +++++++ mofa-frontend/src/monitor/ProviderHealth.tsx | 42 +++++ .../src/observability/MetricsStrip.tsx | 96 ++++++++++ .../src/observability/ObservabilityView.tsx | 170 ++++++++++++++++++ 8 files changed, 725 insertions(+) create mode 100644 mofa-frontend/src/monitor/EventFeed.tsx create mode 100644 mofa-frontend/src/monitor/MemoryGauge.tsx create mode 100644 mofa-frontend/src/monitor/ModelGrid.tsx create mode 100644 mofa-frontend/src/monitor/MonitorSidebar.tsx create mode 100644 mofa-frontend/src/monitor/PreflightIndicator.tsx create mode 100644 mofa-frontend/src/monitor/ProviderHealth.tsx create mode 100644 mofa-frontend/src/observability/MetricsStrip.tsx create mode 100644 mofa-frontend/src/observability/ObservabilityView.tsx diff --git a/mofa-frontend/src/monitor/EventFeed.tsx b/mofa-frontend/src/monitor/EventFeed.tsx new file mode 100644 index 0000000..785dea9 --- /dev/null +++ b/mofa-frontend/src/monitor/EventFeed.tsx @@ -0,0 +1,131 @@ +import React, { useEffect, useState } from 'react'; +import { engine } from '../engine'; +import { EngineEvent } from '../engine/types'; +import { Activity, CheckCircle2, Cpu, Loader, Box, RotateCw } from 'lucide-react'; +import { motion, AnimatePresence } from 'framer-motion'; + +export function EventFeed() { + const [events, setEvents] = useState<(EngineEvent & { _id: string })[]>([]); + + useEffect(() => { + let counter = 0; + const handleEvent = (evt: EngineEvent) => { + setEvents(prev => { + const newEvt = { ...evt, _id: `${evt.timestamp}-${counter++}` }; + const next = [newEvt, ...prev]; // Prepend for reverse chronological + if (next.length > 15) return next.slice(0, 15); + return next; + }); + }; + + const unsubscribe = engine.subscribeEvents(handleEvent); + return () => unsubscribe(); + }, []); + + return ( +
+
+ + {events.map((evt) => ( + + ))} + + {events.length === 0 && ( +
Waiting for engine events...
+ )} +
+
+
+
+ ); +} + +function EventCard({ evt }: { evt: EngineEvent }) { + const { icon, color, title, desc } = formatEvent(evt); + + return ( + +
+ {icon} +
+
+
+ {title} + + {new Date(evt.timestamp).toLocaleTimeString([], { hour12: false, hour: '2-digit', minute: '2-digit', second:'2-digit' })} + +
+
+ {desc} +
+
+
+ ); +} + +function formatEvent(evt: EngineEvent) { + switch (evt.type) { + case 'RequestStarted': + return { + icon: , + color: 'accent-blue', + title: 'Request Started', + desc: `${evt.data.capability || 'inference'} → ${evt.data.model_id}` + }; + case 'RequestCompleted': + return { + icon: , + color: evt.data.success ? 'accent-green' : 'accent-red', + title: evt.data.success ? 'Request Completed' : 'Request Failed', + desc: `${evt.data.request_id?.slice(0, 8)}… ${evt.data.duration_ms}ms` + }; + case 'ModelStatusChanged': + return { + icon: , + color: 'accent-yellow', + title: 'Model Status', + desc: `${evt.data.model_id}: ${evt.data.old} → ${evt.data.new}` + }; + case 'ModelResidencyChanged': + return { + icon: , + color: 'accent-cyan', + title: 'Model Residency', + desc: `${evt.data.model_id}: ${evt.data.old} → ${evt.data.new}` + }; + case 'MemoryChanged': + return { + icon: , + color: 'accent-purple', + title: 'Memory Changed', + desc: `${(evt.data.used_bytes / 1024 / 1024 / 1024).toFixed(2)} GB / ${(evt.data.total_bytes / 1024 / 1024 / 1024).toFixed(1)} GB` + }; + case 'ProviderHealthChanged': + return { + icon: , + color: 'accent-yellow', + title: 'Provider Health', + desc: `${evt.data.provider}: ${evt.data.health}` + }; + case 'DiscoveryCompleted': + return { + icon: , + color: evt.data.success ? 'accent-green' : 'accent-red', + title: 'Discovery', + desc: `${evt.data.provider}: ${evt.data.models} model(s)` + }; + default: + return { + icon: , + color: 'text-dim', + title: evt.type || 'Event', + desc: JSON.stringify(evt.data) + }; + } +} diff --git a/mofa-frontend/src/monitor/MemoryGauge.tsx b/mofa-frontend/src/monitor/MemoryGauge.tsx new file mode 100644 index 0000000..04320c2 --- /dev/null +++ b/mofa-frontend/src/monitor/MemoryGauge.tsx @@ -0,0 +1,80 @@ +import React, { useEffect, useState, useRef } from 'react'; +import { engine } from '../engine'; + +export function MemoryGauge() { + const [memory, setMemory] = useState(0); + const [maxMemory, setMaxMemory] = useState(16 * 1024 * 1024 * 1024); + const [delta, setDelta] = useState(null); + const deltaTimeout = useRef(null); + + useEffect(() => { + // Initial fetch + engine.getStatus().then(s => { + if (s.success) { + setMemory(s.data.memory_used_bytes || 0); + setMaxMemory(s.data.memory_budget_bytes || 16 * 1024 * 1024 * 1024); + } + }); + + const handleEvent = (evt: any) => { + if (evt.type === 'MemoryChanged') { + setMemory(prev => { + const newMem = evt.data.used_bytes; + const diff = newMem - prev; + if (Math.abs(diff) > 1024 * 1024) { // only show significant delta + setDelta(diff); + if (deltaTimeout.current) clearTimeout(deltaTimeout.current); + deltaTimeout.current = setTimeout(() => setDelta(null), 2000); + } + return newMem; + }); + } + }; + const unsubscribe = engine.subscribeEvents(handleEvent); + return () => { + unsubscribe(); + if (deltaTimeout.current) clearTimeout(deltaTimeout.current); + }; + }, []); + + const percentage = Math.min(100, Math.max(0, (memory / maxMemory) * 100)); + const memoryGb = (memory / 1024 / 1024 / 1024).toFixed(2); + const maxGb = (maxMemory / 1024 / 1024 / 1024).toFixed(1); + + let colorClass = 'bg-accent-green'; + let textColorClass = 'text-accent-green'; + if (percentage >= 90) { + colorClass = 'bg-accent-red'; + textColorClass = 'text-accent-red'; + } else if (percentage >= 80) { + colorClass = 'bg-accent-yellow'; + textColorClass = 'text-accent-yellow'; + } + + return ( +
+
+
+ {memoryGb} + / {maxGb} GB +
+
+ {percentage.toFixed(1)}% +
+
+
+
+
+
+ {delta !== null && ( + 0 ? 'text-accent-red' : 'text-accent-green'}`}> + {delta > 0 ? '+' : ''}{(delta / 1024 / 1024 / 1024).toFixed(2)} GB + + )} +
+
+ ); +} diff --git a/mofa-frontend/src/monitor/ModelGrid.tsx b/mofa-frontend/src/monitor/ModelGrid.tsx new file mode 100644 index 0000000..1598021 --- /dev/null +++ b/mofa-frontend/src/monitor/ModelGrid.tsx @@ -0,0 +1,82 @@ +import React, { useEffect, useState } from 'react'; +import { engine } from '../engine'; +import { ModelCard } from '../engine/types'; +import { StatusDot } from '../shared/StatusDot'; +import { Badge } from '../shared/Badge'; +import { Cpu } from 'lucide-react'; + +export function ModelGrid() { + const [models, setModels] = useState([]); + + useEffect(() => { + // Initial load + engine.getCapabilities().then(c => { + if (c.success) setModels(c.data); + }); + + const handleEvent = (evt: any) => { + if (evt.type === 'ModelStatusChanged' || evt.type === 'ModelResidencyChanged') { + engine.getCapabilities().then(c => { + if (c.success) setModels(c.data); + }); + } + }; + + const unsubscribe = engine.subscribeEvents(handleEvent); + return () => unsubscribe(); + }, []); + + const activeModels = models.filter(m => m.status !== 'Cold' || m.residency === 'Remote'); + + if (activeModels.length === 0) { + return ( +
+ + All models cold on disk +
+ ); + } + + return ( +
+ {activeModels.map(model => { + const memGb = model.memory_estimate_bytes ? (model.memory_estimate_bytes / 1024 / 1024 / 1024).toFixed(1) + 'GB' : '0GB'; + + return ( +
+
+ +
+
{model.id}
+
+ {model.provider} + {model.residency !== 'Remote' && ( + <> + · + {memGb} + + )} +
+
+
+
+ + {model.residency === 'Remote' ? 'REMOTE' : model.status.toUpperCase()} + +
+
+ ); + })} +
+ ); +} diff --git a/mofa-frontend/src/monitor/MonitorSidebar.tsx b/mofa-frontend/src/monitor/MonitorSidebar.tsx new file mode 100644 index 0000000..d1ca99d --- /dev/null +++ b/mofa-frontend/src/monitor/MonitorSidebar.tsx @@ -0,0 +1,58 @@ +import React from 'react'; +import { Activity, Shield, Box, Zap } from 'lucide-react'; +import { MemoryGauge } from './MemoryGauge'; +import { ModelGrid } from './ModelGrid'; +import { ProviderHealth } from './ProviderHealth'; +import { PreflightIndicator } from './PreflightIndicator'; + +export function MonitorSidebar() { + return ( + + ); +} diff --git a/mofa-frontend/src/monitor/PreflightIndicator.tsx b/mofa-frontend/src/monitor/PreflightIndicator.tsx new file mode 100644 index 0000000..86d299f --- /dev/null +++ b/mofa-frontend/src/monitor/PreflightIndicator.tsx @@ -0,0 +1,66 @@ +import React, { useEffect, useState } from 'react'; +import { engine } from '../engine'; +import { Zap, RotateCw, CheckCircle2 } from 'lucide-react'; + +export function PreflightIndicator() { + const [status, setStatus] = useState<{ type: 'idle' | 'warming' | 'evicting'; model?: string; loadedCount: number }>({ + type: 'idle', + loadedCount: 0 + }); + + useEffect(() => { + // Initial fetch to get loaded count + engine.getStatus().then(s => { + if (s.success) { + setStatus(prev => ({ ...prev, loadedCount: s.data.loaded_models })); + } + }); + + const handleEvent = (evt: any) => { + if (evt.type === 'ModelResidencyChanged') { + const { model, from, to, reason } = evt.data; + if (to === 'Loading') { + setStatus(prev => ({ ...prev, type: 'warming', model })); + } else if (to === 'Unloaded' && reason === 'eviction') { + setStatus(prev => ({ ...prev, type: 'evicting', model })); + } else if (to === 'Loaded' || to === 'Unloaded') { + // Re-fetch loaded count + engine.getStatus().then(s => { + if (s.success) { + setStatus({ type: 'idle', loadedCount: s.data.loaded_models }); + } + }); + } + } else if (evt.type === 'ModelStatusChanged') { + const { model, from, to } = evt.data; + if (to === 'Warming') { + setStatus(prev => ({ ...prev, type: 'warming', model })); + } + } + }; + + const unsubscribe = engine.subscribeEvents(handleEvent); + return () => unsubscribe(); + }, []); + + return ( +
+ {status.type === 'idle' ? ( +
+ + Idle · {status.loadedCount} Loaded +
+ ) : status.type === 'warming' ? ( +
+ + Pre-warming {status.model} +
+ ) : ( +
+ + Evicting {status.model} +
+ )} +
+ ); +} diff --git a/mofa-frontend/src/monitor/ProviderHealth.tsx b/mofa-frontend/src/monitor/ProviderHealth.tsx new file mode 100644 index 0000000..cf44eec --- /dev/null +++ b/mofa-frontend/src/monitor/ProviderHealth.tsx @@ -0,0 +1,42 @@ +import React from 'react'; +import { ShieldAlert, ShieldCheck } from 'lucide-react'; +import { useEngineStatus } from '../engine/useEngineStatus'; + +export function ProviderHealth() { + const { data: statusRes } = useEngineStatus(); + + const providers = (statusRes?.success ? statusRes.data.provider_health : null) || [ + { name: 'Ollama (Local)', healthy: true, circuit_state: 'closed' }, + { name: 'Kokoro (Local)', healthy: true, circuit_state: 'closed' } + ]; + + return ( +
+ {providers.map(p => { + const state = (p.circuit_state || '').toLowerCase(); + const isClosed = state === 'closed'; + const isHalfOpen = state === 'halfopen' || state === 'half_open'; + + return ( +
+
+ {isClosed ? ( + + ) : isHalfOpen ? ( + + ) : ( + + )} + {p.name} +
+
+ + {isClosed ? 'CLOSED' : isHalfOpen ? 'HALF_OPEN' : 'OPEN'} + +
+
+ ); + })} +
+ ); +} diff --git a/mofa-frontend/src/observability/MetricsStrip.tsx b/mofa-frontend/src/observability/MetricsStrip.tsx new file mode 100644 index 0000000..aef5b15 --- /dev/null +++ b/mofa-frontend/src/observability/MetricsStrip.tsx @@ -0,0 +1,96 @@ +import React, { useEffect, useState } from 'react'; +import { engine } from '../engine'; +import { EngineStatus } from '../engine/types'; +import { Card } from '../shared/Card'; +import { Activity, Clock, Cpu, HardDrive } from 'lucide-react'; + +export function MetricsStrip() { + const [status, setStatus] = useState(null); + const [requestCount, setRequestCount] = useState(0); + const [avgLatency, setAvgLatency] = useState(0); + + useEffect(() => { + // Initial fetch + engine.getStatus().then(res => { + if (res.success) setStatus(res.data); + }); + + const handleEvent = (evt: any) => { + if (evt.type === 'RequestStarted') { + setRequestCount(prev => prev + 1); + } else if (evt.type === 'RequestCompleted') { + if (evt.data && evt.data.duration_ms) { + setAvgLatency(prev => { + if (prev === 0) return evt.data.duration_ms; + return prev * 0.8 + evt.data.duration_ms * 0.2; + }); + } + } else if ( + evt.type === 'ModelStatusChanged' || + evt.type === 'ModelResidencyChanged' || + evt.type === 'MemoryChanged' + ) { + engine.getStatus().then(res => { + if (res.success) setStatus(res.data); + }); + } + }; + + const unsubscribe = engine.subscribeEvents(handleEvent); + return () => unsubscribe(); + }, []); + + const memoryPercent = status + ? ((status.memory_used_bytes / status.memory_budget_bytes) * 100).toFixed(1) + : 0; + + return ( +
+ +
+ +
+
+
Total Requests
+
{requestCount}
+
+
+ + +
+ +
+
+
Avg Latency
+
+ {avgLatency > 0 ? `${(avgLatency / 1000).toFixed(2)}s` : '--'} +
+
+
+ + +
+ +
+
+
Models Loaded
+
+ {status?.loaded_models ?? '--'} / {status?.total_models ?? '--'} +
+
+
+ + +
+ +
+
+
Memory Usage
+
+ {memoryPercent}% +
+
+
+
+ ); +} diff --git a/mofa-frontend/src/observability/ObservabilityView.tsx b/mofa-frontend/src/observability/ObservabilityView.tsx new file mode 100644 index 0000000..fd09348 --- /dev/null +++ b/mofa-frontend/src/observability/ObservabilityView.tsx @@ -0,0 +1,170 @@ +import React, { useEffect, useState } from 'react'; +import { motion } from 'framer-motion'; +import { Card } from '../shared/Card'; +import { Button } from '../shared/Button'; +import { MetricsStrip } from './MetricsStrip'; +import { Activity, LayoutDashboard, Cpu, Network, ExternalLink } from 'lucide-react'; + +const GRAFANA_URL = import.meta.env.VITE_GRAFANA_URL || 'http://localhost:3000'; + +type TabId = 'overview' | 'memory' | 'routing'; + +interface TabConfig { + id: TabId; + label: string; + icon: React.ReactNode; + dashboardPath: string; + description: string; +} + +const TABS: TabConfig[] = [ + { + id: 'overview', + label: 'Engine Overview', + icon: , + dashboardPath: '/d/engine-overview/mofa-engine-overview', + description: 'Request rate, error rate, P95 latency, TTFT, and tokens/sec.' + }, + { + id: 'memory', + label: 'Memory & Lifecycle', + icon: , + dashboardPath: '/d/engine-memory/mofa-memory-and-lifecycle', + description: 'Memory vs budget, model loads/unloads, eviction rate, and cold-load heatmap.' + }, + { + id: 'routing', + label: 'Preflight & Routing', + icon: , + dashboardPath: '/d/engine-routing/mofa-preflight-and-routing', + description: 'Fallback routing, circuit breakers, and capability matching.' + } +]; + +export function ObservabilityView() { + const [activeTab, setActiveTab] = useState('overview'); + const [grafanaAvailable, setGrafanaAvailable] = useState(null); + + useEffect(() => { + let mounted = true; + + // Lightweight check for Grafana availability using a known public static asset + const checkGrafana = () => { + const img = new Image(); + img.onload = () => { + if (mounted) setGrafanaAvailable(true); + }; + img.onerror = () => { + if (mounted) setGrafanaAvailable(false); + }; + // Prevent caching + img.src = `${GRAFANA_URL}/public/img/grafana_icon.svg?t=${Date.now()}`; + }; + + checkGrafana(); + + return () => { mounted = false; }; + }, []); + + const activeConfig = TABS.find(t => t.id === activeTab)!; + + return ( + +
+ {/* Header */} +
+
+

+ + Engine Observability +

+

+ Powered by Prometheus + Grafana +

+
+ {grafanaAvailable && ( + + )} +
+ + + + {/* Tab Navigation */} +
+ {TABS.map(tab => ( + + ))} +
+ +
+ {grafanaAvailable === null ? ( +
+
Checking observability stack...
+
+ ) : grafanaAvailable ? ( + +
+
{activeConfig.label}
+
{activeConfig.description}
+
+
+