commit d670921f7460d2f098eb3beff72d836be48634c7 Author: safavimohadeseh78 Date: Wed Sep 9 17:08:46 2026 +0330 Initialize the admin app with banner management for app sections. Co-authored-by: Cursor diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..3b510aa --- /dev/null +++ b/.editorconfig @@ -0,0 +1,8 @@ +[*.{js,jsx,mjs,cjs,ts,tsx,mts,cts,vue,css,scss,sass,less,styl}] +charset = utf-8 +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +end_of_line = lf +max_line_length = 100 diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..90c7404 --- /dev/null +++ b/.env.development @@ -0,0 +1,4 @@ +# Same-origin in dev (Vite proxies to the real API — avoids CORS) +VITE_API_BASE_URL=/server/api +# بدون سرور هم می‌شود وارد شد +VITE_USE_MOCK_AUTH=true diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..d3d8334 --- /dev/null +++ b/.env.example @@ -0,0 +1 @@ +VITE_API_BASE_URL=https://parche.montest.ir/server/api diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..6313b56 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..79977f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,44 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +.DS_Store +dist +dist-ssr +coverage +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +*.tsbuildinfo + +.eslintcache + +# Cypress +/cypress/videos/ +/cypress/screenshots/ + +# Vitest +__screenshots__/ + +# Vite +*.timestamp-*-*.mjs + +# env +.env +.env.local +.env.*.local diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..d5648b9 --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,10 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["eslint", "typescript", "unicorn", "oxc", "vue"], + "env": { + "browser": true + }, + "categories": { + "correctness": "error" + } +} diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..29a2402 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,6 @@ +{ + "$schema": "https://json.schemastore.org/prettierrc", + "semi": false, + "singleQuote": true, + "printWidth": 100 +} diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..3f84126 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,9 @@ +{ + "recommendations": [ + "Vue.volar", + "dbaeumer.vscode-eslint", + "EditorConfig.EditorConfig", + "oxc.oxc-vscode", + "esbenp.prettier-vscode" + ] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..583dd69 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# fabric-trade-admin + +This template should help get you started developing with Vue 3 in Vite. + +## Recommended IDE Setup + +[VS Code](https://code.visualstudio.com/) + [Vue (Official)](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur). + +## Recommended Browser Setup + +- Chromium-based browsers (Chrome, Edge, Brave, etc.): + - [Vue.js devtools](https://chromewebstore.google.com/detail/vuejs-devtools/nhdogjmejiglipccpnnnanhbledajbpd) + - [Turn on Custom Object Formatter in Chrome DevTools](http://bit.ly/object-formatters) +- Firefox: + - [Vue.js devtools](https://addons.mozilla.org/en-US/firefox/addon/vue-js-devtools/) + - [Turn on Custom Object Formatter in Firefox DevTools](https://fxdx.dev/firefox-devtools-custom-object-formatters/) + +## Type Support for `.vue` Imports in TS + +TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) to make the TypeScript language service aware of `.vue` types. + +## Customize configuration + +See [Vite Configuration Reference](https://vite.dev/config/). + +## Project Setup + +```sh +npm install +``` + +### Compile and Hot-Reload for Development + +```sh +npm run dev +``` + +### Type-Check, Compile and Minify for Production + +```sh +npm run build +``` + +### Lint with [ESLint](https://eslint.org/) + +```sh +npm run lint +``` diff --git a/deploy/nginx-admin.conf b/deploy/nginx-admin.conf new file mode 100644 index 0000000..748341e --- /dev/null +++ b/deploy/nginx-admin.conf @@ -0,0 +1,17 @@ +# Example: admin panel at https://parche.montech.ir/admin/ +# Place dist/ contents in the server path mapped to /admin/ + +location /admin/ { + alias /var/www/parche/admin/; + try_files $uri $uri/ /admin/index.html; +} + +location ~ ^/admin/assets/ { + alias /var/www/parche/admin/assets/; + expires 7d; + add_header Cache-Control "public, immutable"; + types { + application/javascript js; + text/css css; + } +} diff --git a/env.d.ts b/env.d.ts new file mode 100644 index 0000000..a1b07af --- /dev/null +++ b/env.d.ts @@ -0,0 +1,2 @@ +/// +/// diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000..89fdc89 --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,26 @@ +import { globalIgnores } from 'eslint/config' +import { defineConfigWithVueTs, vueTsConfigs } from '@vue/eslint-config-typescript' +import pluginVue from 'eslint-plugin-vue' +import pluginOxlint from 'eslint-plugin-oxlint' +import skipFormatting from 'eslint-config-prettier/flat' + +// To allow more languages other than `ts` in `.vue` files, uncomment the following lines: +// import { configureVueProject } from '@vue/eslint-config-typescript' +// configureVueProject({ scriptLangs: ['ts', 'tsx'] }) +// More info at https://github.com/vuejs/eslint-config-typescript/#advanced-setup + +export default defineConfigWithVueTs( + { + name: 'app/files-to-lint', + files: ['**/*.{vue,ts,mts,tsx}'], + }, + + globalIgnores(['**/dist/**', '**/dist-ssr/**', '**/coverage/**']), + + ...pluginVue.configs['flat/essential'], + vueTsConfigs.recommended, + + ...pluginOxlint.buildFromOxlintConfigFile('.oxlintrc.json'), + + skipFormatting, +) diff --git a/index.html b/index.html new file mode 100644 index 0000000..d810e40 --- /dev/null +++ b/index.html @@ -0,0 +1,13 @@ + + + + + + + پنل مدیریت | پارچه + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..da02afa --- /dev/null +++ b/package-lock.json @@ -0,0 +1,6297 @@ +{ + "name": "fabric-trade-admin", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fabric-trade-admin", + "version": "0.0.0", + "dependencies": { + "@unocss/vite": "^66.7.5", + "@vueuse/core": "^14.4.0", + "lodash-es": "^4.18.1", + "pinia": "^4.0.2", + "unocss": "^66.7.5", + "vue": "^3.5.40", + "vue-router": "^5.2.0" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.4", + "@types/lodash-es": "^4.17.12", + "@types/node": "^24.13.3", + "@vitejs/plugin-vue": "^6.0.8", + "@vitejs/plugin-vue-jsx": "^5.1.6", + "@vue/eslint-config-typescript": "^14.9.0", + "@vue/tsconfig": "^0.9.1", + "eslint": "^10.7.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-oxlint": "~1.73.0", + "eslint-plugin-vue": "~10.9.2", + "jiti": "^2.7.0", + "npm-run-all2": "^9.0.2", + "oxlint": "~1.74.0", + "prettier": "3.9.5", + "typescript": "~6.0.0", + "vite": "^8.1.5", + "vite-plugin-vue-devtools": "^8.1.5", + "vue-eslint-parser": "^10.4.1", + "vue-tsc": "^3.3.7" + }, + "engines": { + "node": "^22.18.0 || >=24.12.0" + } + }, + "node_modules/@antfu/install-pkg": { + "version": "1.1.0", + "resolved": "https://registry.npmmirror.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz", + "integrity": "sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ==", + "license": "MIT", + "dependencies": { + "package-manager-detector": "^1.3.0", + "tinyexec": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "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/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@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-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "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-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "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-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", + "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-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-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.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==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/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.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-proposal-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.7.tgz", + "integrity": "sha512-EtU0Hi3GvrTqD56xKmZvV/uCXK2ZbwVNPNLAquVItcAZpUhkXwWlo3Fmj0c2LxgSf2I8IDULeAepwNP1OefLXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-syntax-decorators": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-decorators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.29.7.tgz", + "integrity": "sha512-9MTTLbF39X6sqM92JPEsoI7++26hjZvzkxKZy64aMhWLH2mPkJ/Q3AV4QLmls3R14FpSpkOwQQfUh962JGQxxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.29.7.tgz", + "integrity": "sha512-TSu8+mHCoEaaCDEZ0I3+6mvTBYR4PCxQwf2z9/r5Tbztv6NaLR3B9thGTTxX2WGuGHJqRiAbKPeGTJ5XWXVg6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.29.7.tgz", + "integrity": "sha512-ngr+82Sh0xMz25TPCZi+nC2iTzjfCdWS2ONXTp/PtSCHCgaCNBpdMqgvJ2ccdLlClVZ7sisIgB914j/JFe+RZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.29.7.tgz", + "integrity": "sha512-jK52h8LaLc7JarhQV2ofeFMts4H7vnOXnqZNA6fYglBTZewRBE51KWt3BUltW1P+KoPsYkHoJeXePuz4zo2LMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-syntax-typescript": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.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.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "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": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-2.0.0-alpha.3.tgz", + "integrity": "sha512-AZypUeJ/yByuxyS7BlSNRDOMLMlROYtjYdIAuBmJssVz1UJDSeYxLrdizhXCFYhedC5bqd/ASy8EuNXbVVXp9g==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "2.0.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "2.0.0-alpha.3", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-2.0.0-alpha.3.tgz", + "integrity": "sha512-hFPAhMUjJD9BSyCANEISPOogeXC9Zo9ZQl7L6vKnaVsMkCtzznaW/naYypeyl0Gv5rYfWYsZbpixTMpjDJzQeA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-2.0.1.tgz", + "integrity": "sha512-9DsSk+o5NBX0CCJT8s0EROGSGxjR/tKu6aBTaVyq+SjAEQH4XcdcRxPBRzsBLizTTJ49MJjF+jgu3qnO9GLQcQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "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.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", + "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/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/@iconify/types": { + "version": "2.0.0", + "resolved": "https://registry.npmmirror.com/@iconify/types/-/types-2.0.0.tgz", + "integrity": "sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg==", + "license": "MIT" + }, + "node_modules/@iconify/utils": { + "version": "3.1.4", + "resolved": "https://registry.npmmirror.com/@iconify/utils/-/utils-3.1.4.tgz", + "integrity": "sha512-b1S7B1k9ohZ+iNTi2ATxbRYG9fTrJmUT0rc46bvVnNxqNRGW7dyo/vRREwyniI5IRN2RSJHDcm+s3BjWrSAjHw==", + "license": "MIT", + "dependencies": { + "@antfu/install-pkg": "^1.1.0", + "@iconify/types": "^2.0.0", + "import-meta-resolve": "^4.2.0" + } + }, + "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==", + "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==", + "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==", + "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==", + "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==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.2.2.tgz", + "integrity": "sha512-JfB4kuJQjaoHuCTseIINHtHWeJnvgEcxjwA5t/Y00ZgaOO1Crz3fjT/p8kT28zA/Caz7oiUMn3d6H2yOVCVwuw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tybys/wasm-util": "^0.10.3" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + }, + "peerDependencies": { + "@emnapi/core": "^1.7.1 || ^2.0.0-alpha.3", + "@emnapi/runtime": "^1.7.1 || ^2.0.0-alpha.3" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@oxc-parser/binding-android-arm-eabi": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-android-arm-eabi/-/binding-android-arm-eabi-0.131.0.tgz", + "integrity": "sha512-t2xicr9pfzkSRYx5aPqZqlLaayIwJTqgQ81Jor31Xep2nGyL2Aq3d0K5wOfeR7VevaSdxaS9dzSQP9xDwn8fDg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-android-arm64": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-android-arm64/-/binding-android-arm64-0.131.0.tgz", + "integrity": "sha512-nlGIod6gw75x1aEDgLS+srj+JRGY0HHm9MI9YgzE/B64l6d6+H3MSP9NOgp0+HTg8tp4vV9rVfgQGgd+TfVZcA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-arm64": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-darwin-arm64/-/binding-darwin-arm64-0.131.0.tgz", + "integrity": "sha512-jukuV6xe5RbQKFo7QD34NDCLDZp4PSOm8rmckhNdH/60ymG5zXbDzGBEyc+nTkuLQNama2aSGCt+CPfpjNTqyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-darwin-x64": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-darwin-x64/-/binding-darwin-x64-0.131.0.tgz", + "integrity": "sha512-g3JOo4khe9rslHm5WYaVDWb0HS/M1MLR3I9S8560MkKIcC96VQY00QjOlsuRyfSj/JDXj8i9T7ryPO2RidiXVg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-freebsd-x64": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-freebsd-x64/-/binding-freebsd-x64-0.131.0.tgz", + "integrity": "sha512-1hziITDTxjMePnX+dR9ocVT+EuZkQ8wm4FPAbmbEiKG+Phbo73J1ZnPAA6Y/aGsWF3McOFnQuZIktAFwalkfJQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-gnueabihf": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.131.0.tgz", + "integrity": "sha512-9uRxfXwyKG9+MwmGQBo2ncPNwZH5HTmCETFM2WiuDBNDCW4NC5ttSQkwCAMrTAWgwMzVBH1CP8pM0v7nebCWXQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm-musleabihf": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.131.0.tgz", + "integrity": "sha512-mgbLvzRShXOLBdWGInf08Af4q+pfj1xD8hSgLClDZ9of/BXkB6+LIhTH7fihiDUipqB3yoSkKBWaZ3Ejlf5Yag==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-gnu": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.131.0.tgz", + "integrity": "sha512-OPT8++4aN6j2GJ8+3IZHS/byXoZP4aSBn+FoG6rgBJ2fKwPKXWF3MqrFMNW7NKHM28FLY579xYLxJSfgobEqPA==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-arm64-musl": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.131.0.tgz", + "integrity": "sha512-vtPiwmfVTAXzaxDKsOXG+LwgRAA7WEnaeHzhS5z0GE89gAK18KSXnly7Z6saXXq6L3dVMyK44uoTI03zKxrpmw==", + "cpu": [ + "arm64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-ppc64-gnu": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.131.0.tgz", + "integrity": "sha512-8AW8L7w5cGHSdZPcyZX2yR0+GUODsT15rbRjfdD54rv6DMbtuEB19ysLOpKJlRGfH6UNYNpCHaU1uJWgTWf1/w==", + "cpu": [ + "ppc64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-gnu": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.131.0.tgz", + "integrity": "sha512-vvpjkjEOUsPcsYf8evE4MO3aGx9+3wodXEBOicGNnOwTuAik8eBONNkgSdhkGsAblQmfVHJyanRnpxglddTXIA==", + "cpu": [ + "riscv64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-riscv64-musl": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.131.0.tgz", + "integrity": "sha512-AqmcNC3fClXX+fxQ6VGEN1667xVFiRBkY0CZmDMSiaeFUsv1+UkBPYYi48IUKcA9/ivvoKNRzQl2I4//kT9F/w==", + "cpu": [ + "riscv64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-s390x-gnu": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.131.0.tgz", + "integrity": "sha512-7d3jOMKy7RSQCcDLIci+ySll2FgsOMl/GiRux4q2JNv0zg4EdhFISa9idvrdN/HEUIQQJNg6dmveUeJl2YErGA==", + "cpu": [ + "s390x" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-gnu": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.131.0.tgz", + "integrity": "sha512-JHK/h95qVqVQ+ITER837kcTdwBDFpFaNnOTYGCP0zdUSX/mLKC7tXOoyrTb6vG7iRPwGlcgBil3v2IjYw1FqJA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-linux-x64-musl": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-linux-x64-musl/-/binding-linux-x64-musl-0.131.0.tgz", + "integrity": "sha512-b2BO82O8azXAyf7EUgOPKu145nWypbNyk07HbU09fkzhm9lEA5oPvaN/M8Nlo7tOErVTa2WOgS4QbOnxAPXdDQ==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-openharmony-arm64": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-openharmony-arm64/-/binding-openharmony-arm64-0.131.0.tgz", + "integrity": "sha512-GHO9glZaX7LkX/OGfluEPf1yjg+ehiFbUdowbX6uNWOQhmwKWU4m4+nZ9FJkrHNKuxyI1KKertMdGjVKCApKWA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-wasm32-wasi/-/binding-wasm32-wasi-0.131.0.tgz", + "integrity": "sha512-3SkikPaEFoih1N83qLVEDLRLeY4nYsf6JT9SnWiMCQ5lGQdKup6bEuKCqkRiG9dD1IIaFeYz9RjlciPmYoFIWA==", + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "1.10.0", + "@emnapi/runtime": "1.10.0", + "@napi-rs/wasm-runtime": "^1.1.4" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmmirror.com/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@oxc-parser/binding-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmmirror.com/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@oxc-parser/binding-win32-arm64-msvc": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.131.0.tgz", + "integrity": "sha512-Os5bEhryeA2jkH+ZrnZyAC1EP5gs+X4YB1Fjqml7UPD5kU7ecsK1MPEVMfCrdt/GDNpDbavYXiOXOdyJ5b3OPw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-ia32-msvc": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.131.0.tgz", + "integrity": "sha512-m+jNz9EuF0NXoiptc6B9h5yompZQVW/a5MJeOu5zojfH5yWk82tvF2ccrHkfhgtrS9h9DD5l1Qv8dWlfY7Nz8g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-parser/binding-win32-x64-msvc": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-parser/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.131.0.tgz", + "integrity": "sha512-o14Hk8dAyiEUMFEWEgmAwFZvBt1RzAYLM3xeQ+5315JXgVYhoemivgYcbYVRbsFkS71ShMGlAFE0kPnr460rww==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxc-project/types": { + "version": "0.142.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.142.0.tgz", + "integrity": "sha512-7W+2q5AKQVU36fkaryontrHn3YDt1RyUYXatw9i5H8ocYe2sPKSFB6eS8WNPeRKiN1qAWWZUPm7gwFzJGrccqQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.74.0.tgz", + "integrity": "sha512-+gHd12muVI9ZLBaWLPkHt3Fj7jihFjgQ1MGtBaRL8vWrWrI0P7dLUty/cHrHS0oqPYIRgQUJsPu2CExQuMcwNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.74.0.tgz", + "integrity": "sha512-xjKdoMB+H+RCOByv/7l7nfIGW9mlOisqYdcyC75UqYuQecLpReAeEYUf2CNeDEI3KtmUgxpRw/+c63y4AeF/Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.74.0.tgz", + "integrity": "sha512-iUK7wvc6sejMKsC+Pt67mntoF5weFcyEunhZfLJceU6gL419mexz5wBkSx/EnkFBExMLNtOi9fnDSc5xfK0IzQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.74.0.tgz", + "integrity": "sha512-ggKc/tn5SJ1u2yG2izC6VKODfYKV8MQ2AicJlNzOjuyrC29udvOef6/JzK2r32xqCnBDLFouR1VCkjzEI0/N9Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.74.0.tgz", + "integrity": "sha512-u++dH/43jy9hTLbneaWlS0gla/Bp1JdwJ2zgevCl8nDFUh6qRCGMxcL0f0lb7By3A9p/LfFr+7cG4HU1hG856g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.74.0.tgz", + "integrity": "sha512-Sj1zmtFDVTPeIbIz4ZfcXAbFHqCmKCXdCUlAJzvTF7I20NTH1RDpoF2PhkqNODutJzVhJYmm3oz0GwgY+tvE2g==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.74.0.tgz", + "integrity": "sha512-//PKyQb/tQXcHArx2f7z+oVI/eMS2Jpv+edNuAtOrgIhWdGcpHxogveAxzmF2rpH1AIHp4Hq04RF/rgJdiICnQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.74.0.tgz", + "integrity": "sha512-/k1Me+aX2tjuH10K62mLS0y8cLkJBHX6Ce0xPK+eWeel4bSdEGZ8dv4+hYMzg0GrSmjwy4yAYsDPeEeKBft/2w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.74.0.tgz", + "integrity": "sha512-3tFSjBxc5D8/zvjEuLvOqcA8ZXKD0+6NuaVO/edeamNc49MoAsbfaC9s1UiwODwgF6slGaF8yJA2TPkukd77tg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.74.0.tgz", + "integrity": "sha512-9QggtPkSPXOCTu8Szis7auOK/sC7KdQaN+/TujP7YVVhzCAOhgdRfgv8uEz0r2tk5xdgus5rLYUrCDoZNtiRUw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.74.0.tgz", + "integrity": "sha512-VM5VPUJ4DJIWiK+AZn8FScUqMr6OFrCAYybMYjEEi7W13ParI64MByiXTkKMqZpBmvQ9zxl9Ebq2VUOiZRJYUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.74.0.tgz", + "integrity": "sha512-SaDY1gh9rOA592J54g+gu5hkOFFQBZsMmIYHs+NRHG+Uq0OxtuuCXMWQ3vu1830Eugv5uMXyjG+bv2Z9y4IXjw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.74.0.tgz", + "integrity": "sha512-ZATQeHZCyr6MbDveg0obD5sxLHFOghtOdC5jwVwYlvFWqtFOxctgFEG6Ef/64hYvZrWyhyCckB10AelqLopeDA==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.74.0.tgz", + "integrity": "sha512-+aIvJyrdeD7LwCQ2WYLMUWNmnbeDRSPb40aBYtPjD9+PTqUwgJnk+HK5yLfSMeqXrMrDhE9uTmtt2y50tvjhHw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.74.0.tgz", + "integrity": "sha512-XyktaR8lhK2qWiCK0Tk8oYD+/cgn+oHA6ddRnxSSXUKkkojkV78CmShZUxQF+yrBFs0SuW+JBOPG6hecyc/iZg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.74.0.tgz", + "integrity": "sha512-mzbjrPl4neaVUiJ1fUiEUxTGaSZBoiKtaoB6jmIpz9S+VOA2vDYmJpihQ82w6178V5jxziclTg8Cgj5yF6tTDg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.74.0.tgz", + "integrity": "sha512-vUAe9okpS2Oa5+lX67lqHMuNUvfkleRKwrUDJ/WJBsgmddvZ1mrsh2HVmuFDRzqFELhaJhFaCNOuR6a7L3rtIA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.74.0.tgz", + "integrity": "sha512-yyXXJyYYSXL4I8K8jAWjJs+J3fa9gH2JmEbo4f5adm+1tNC9itseicBNuwK7BDHvqQ5J534s+yDULu89vYL2ZQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.74.0.tgz", + "integrity": "sha512-VTC9IYTIMrVUk/i6Ms1ohzzDKZFkWn0KU2OBbPBzgmVZ2V30165T/zK4LztTr0Xgp9fZ1qQZ1rsZAu/rEmySlA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "license": "MIT" + }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/@quansync/fs/node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.1.tgz", + "integrity": "sha512-02hOeOSryYxVrOIphmLAsqnCJWxwlzFk+pEt/N/i6OgT3lShHO7xGCU5cpgchRDHboAEbSjzgGh+O/u1GswQmA==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.1.tgz", + "integrity": "sha512-fMsTOnN0OjFm3CyppWPitKnc8UlliVARUULW6cfU6AIqjdtgmSFWSk9vecHzZduv/yMWIHDlRhM1e8Iff9uAfA==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.1.tgz", + "integrity": "sha512-1wjKdz/XLGKHaTNHjQveQ/B23TKx4ItAqm1JbyVuvNPc4Ze0Fb48s49TAd/2zcplPl8okE/UbTgmlVfwT7eFeQ==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.1.tgz", + "integrity": "sha512-Fa0jHR07E7YBN4vOEsbVf2briYNsuOowfLJaXULZM0ldMlaCaj2LJgLMbMe4iacRyZmvR8efFhgR9wKuGclQUg==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.1.tgz", + "integrity": "sha512-pzkgu1SSHGgRRyRZ4fbmSgmajbVt+epaLP99NDjFft69v/ypfTi6swBMiVdh2EkQ0OSnHE1lZDM7DRGkyAzUpA==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.1.tgz", + "integrity": "sha512-QI5SEDY8cbiYWHx0VO4vIc3UlS6a32vXHjU8Qy/17adEmZIPuByJg13UEvo9c/UCiUkdcVWY83C+b+JrwnNyUg==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.1.tgz", + "integrity": "sha512-Sm41FyCeXqmYcERoYOCbGIL5hNfd8w9LQ7Y61Bev48HkcjaJqV/iiVOaiDxjVTRMS+QKrZmD8cfPt4uMVnvM+A==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.1.tgz", + "integrity": "sha512-2x+WhXTGl9yJYPbltW/BSEPTVz9OIWQyER4N+gJEDWkkn904eRcBzELqh/Hf7K0w/ubGbKNMv0ZC+94QK/IFEg==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.1.tgz", + "integrity": "sha512-eEjmQpuRQayHPWWnywaWHkFT3ToPbP3RYy42VVd/B9aBGDA+Ol25EIWHxKQST3IiWJjikCWUF7KtbfqwZrzVwQ==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.1.tgz", + "integrity": "sha512-/Orga1fZYkLc/56jBICcHrKchl8Z2UKdDSr3LG9ToWO1lQ6a4Livk9Xz+9WN91zsz5QR3XQz2NNoSDEvP6qadw==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.1.tgz", + "integrity": "sha512-xxBJRL+0q0Kce7orznGWLuylHDY65vuARXZRpX+hPdv+DqK2c3NlCsVA98tlWzWNEE7yPqA/1NQ5nnCrj49Y5A==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.1.tgz", + "integrity": "sha512-M6AdXIXw3s+/8XpKMzdGDEXGS1S7kwUsy+rcTIUIOx5Ge4nXKCtAFHFV9YKkXvGcC5WMoTjAteLzlsQROVI0Yw==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-wasm32-wasi/-/binding-wasm32-wasi-1.2.1.tgz", + "integrity": "sha512-/TX0SoRGojHzSAHpfVBbavRVSazg5U3h3Y3VXfcc0cdugq6kxdqw8LPGFiPr+/7gE/60zRcsOY2Vi9b9eT0jww==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "2.0.0-alpha.3", + "@emnapi/runtime": "2.0.0-alpha.3", + "@napi-rs/wasm-runtime": "^1.2.0" + }, + "engines": { + "node": "^20.19.0 || ^22.13.0 || >=23.5.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.1.tgz", + "integrity": "sha512-EvRrivJieyHG+AO9lleZWgq+g0+S7oV2C51yuqlcyU/R9net+sI4Pj0F+lUoP2bEr6TWX3SqFaaS0SzfLxSzkw==", + "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.2.1", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.1.tgz", + "integrity": "sha512-Z4eCmn5QJ/5+azF9knpLWKfVd9aidn0mAe9TpJgvBLId9Ax3t0+JVxBmT25Bv7NBbVW1TZyKjQjQReouMeH5UQ==", + "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/@tsconfig/node24": { + "version": "24.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node24/-/node24-24.0.4.tgz", + "integrity": "sha512-2A933l5P5oCbv6qSxHs7ckKwobs8BDAe9SJ/Xr2Hy+nDlwmLE1GhFh/g/vXGRZWgxBg9nX/5piDtHR9Dkw/XuA==", + "dev": true, + "license": "MIT" + }, + "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==", + "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==", + "license": "MIT" + }, + "node_modules/@types/jsesc": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@types/jsesc/-/jsesc-2.5.1.tgz", + "integrity": "sha512-9VN+6yxLOPLOav+7PwjZbxiID2bVaeq0ED4qSQmdQTdjnXJSaCVKTR58t15oqH1H5t8Ng2ZX1SabJVoN9Q34bw==", + "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/lodash": { + "version": "4.17.25", + "resolved": "https://registry.npmmirror.com/@types/lodash/-/lodash-4.17.25.tgz", + "integrity": "sha512-+K1NIO8I+F9/wNulfVvu23QYd0Pe9/OCqRrim4NoYIf1VoEDL90Ve4ClzpyqBLc7NpGGWRvYNCKZ1BE/Jpf8dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/lodash-es": { + "version": "4.17.12", + "resolved": "https://registry.npmmirror.com/@types/lodash-es/-/lodash-es-4.17.12.tgz", + "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/lodash": "*" + } + }, + "node_modules/@types/node": { + "version": "24.13.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz", + "integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/web-bluetooth": { + "version": "0.0.21", + "resolved": "https://registry.npmmirror.com/@types/web-bluetooth/-/web-bluetooth-0.0.21.tgz", + "integrity": "sha512-oIQLCGWtcFZy2JW77j9k8nHzAOpqMHLQejDA48XXMWH6tjCQHz5RCFz1bzsmROyL6PUm+LLnUiI4BCn221inxA==", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.65.0.tgz", + "integrity": "sha512-IEgob78X12rHpUmtcwFsXhZdVGJtwTVP8FiCLZkR6GlYVrl2PcuB+KhCE5BlVC/eQpQnu8WXRtkHZuPar+gCRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/type-utils": "8.65.0", + "@typescript-eslint/utils": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.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.65.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.6.tgz", + "integrity": "sha512-BAg6QkE8W+TuQLrrw0Ugr7HegXduRuuj8/ti2kSOc+jz1dmx8/WNcjr6XGnq5YpDWxFwwaavqD0+jIUOKelTsw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.65.0.tgz", + "integrity": "sha512-CZ4nMxWwgu1HEEFNkeaCptra9QCtkmKdgf3sWh1rl1trIhmxLilgTV4cwcbQ4wemnT4sWQN8CaKOmdYx+g2gMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.65.0.tgz", + "integrity": "sha512-SxnPhbTsGahizDgbu7oqFH/xVtzIqMd/s+WtnSxNxJZJpLbdT5IPdzg8EZxO3+PoKahXmwJLeNQOpKJb3/bi7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.65.0", + "@typescript-eslint/types": "^8.65.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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.65.0.tgz", + "integrity": "sha512-Esbl8OSYiVxBokYgWPf7VVWg/BE798wXhimnn9ML9Pt5qoDf8bfQlgjlKXR/k98+AcNzlLKYrpCcrcuZ9DZLgg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.65.0.tgz", + "integrity": "sha512-j6GzGqCiRdA7Qhur2VVmKZAkBLfnHFQfx4TaJGL9RMveZqCo48jSHHO0DTgizEnGhtWnqmbtCUSrqSkdiY/0Hg==", + "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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.65.0.tgz", + "integrity": "sha512-YjaZ7PRI5qY7ax2L3PbvX0rRyGtipAReCWs0mhhDBHjH/vl0g0BonaGXrKdKpMbIIsMIwDgbk/xzkBTyAltS5g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.65.0.tgz", + "integrity": "sha512-JSSwWNy+H0E/01jJEM+hrX6N0OFDzFzeIhHFSAS01tlVaevpG8cFyYRPhS5yjGOvBUx3sqQHVMjCL1CAZZMxBg==", + "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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.65.0.tgz", + "integrity": "sha512-JboAE2swaYt4tb1fHhHTABE2K+OLy09XfcTbhnk4Pw96f9dd2e9iYsJ28gBggHlo5z5x1rkyWvcPoTuNTd4oGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.65.0", + "@typescript-eslint/tsconfig-utils": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/visitor-keys": "8.65.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/typescript-estree/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/@typescript-eslint/utils": { + "version": "8.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.65.0.tgz", + "integrity": "sha512-gXiwIHsYreboxeJucHKPvgwl7dXt50mF8s1/c00cP/WoVTyWKFdtfhRWwZiXYFU5H2O8vVoSLNrexFZjYS/SGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.65.0", + "@typescript-eslint/types": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.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.65.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.65.0.tgz", + "integrity": "sha512-8C71BQkGjiMmXtop7pHVJu1l2NNShFdkCyD6a2ezzs5vU/L3LRtb69EtcteFwz0mYMPzIgOw0n6OV4VBUWZd7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.65.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/@unocss/cli": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/cli/-/cli-66.7.5.tgz", + "integrity": "sha512-fgWkECRn2LGVo9sEpmjk/KJ3NSKUDitaZCNrJcEYM93DG+ELriTHcL+VWBlF4rcZf9fdGlq1nKbbRHUZirFCHQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "@unocss/config": "66.7.5", + "@unocss/core": "66.7.5", + "@unocss/preset-wind3": "66.7.5", + "@unocss/preset-wind4": "66.7.5", + "@unocss/transformer-directives": "66.7.5", + "cac": "^7.0.0", + "chokidar": "^5.0.0", + "colorette": "^2.0.20", + "consola": "^3.4.2", + "magic-string": "^0.30.21", + "pathe": "^2.0.3", + "perfect-debounce": "^2.1.0", + "tinyglobby": "^0.2.17", + "unplugin-utils": "^0.3.1" + }, + "bin": { + "unocss": "bin/unocss.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/config": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/config/-/config-66.7.5.tgz", + "integrity": "sha512-dkPl9glhEahJ+Xoja5ZseKKnH+vZaeaKQzg8b0otcKcPPNrHQgu1nu3QgfeOjnXOGrjZIotHwUeVtt4ZA2Skgg==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "colorette": "^2.0.20", + "consola": "^3.4.2", + "unconfig": "^7.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/core": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/core/-/core-66.7.5.tgz", + "integrity": "sha512-UdJb8MiMywcau8QrWEVgUAz0kvoFHyR+sACwYCgmBh/BpKJGyR/zw/Ys3wvysbm0f+i/20VGBex/QQxYVlzdyQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/extractor-arbitrary-variants": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/extractor-arbitrary-variants/-/extractor-arbitrary-variants-66.7.5.tgz", + "integrity": "sha512-5zOkbnLIJc8E749qNjLXfPHl3FdHloop12h706/ojr6idK4ix0KLm43R//uLnphixCehdHJRuHnavnM4C/kQbA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/inspector": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/inspector/-/inspector-66.7.5.tgz", + "integrity": "sha512-WmTJMnj8bmRxvw/wGeShmL2eEHr2/L0BdGTXSxhfzwcO8y5XZEbBmVciLcM7pqaTXQ6JY4+KnITrDUf1urjZxQ==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/rule-utils": "66.7.5", + "colorette": "^2.0.20", + "gzip-size": "^6.0.0", + "sirv": "^3.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-attributify": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-attributify/-/preset-attributify-66.7.5.tgz", + "integrity": "sha512-1Oi1Cp81pqYJwG3h4+OlP5A0FKyaa07MFBXaXc4Yr3faiTbsI8SKj2TqnZCb+NQvBsEqslEd+jKXGZ3lKzCVOQ==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-icons": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-icons/-/preset-icons-66.7.5.tgz", + "integrity": "sha512-ZsxadWnGGtHdANTikuMnjkQaT1qwUFJHZBF4fzVsPMnUiiKGs8rzXukwM9w3Gi9ontM7nbG2FYi9clWETSlpFg==", + "license": "MIT", + "dependencies": { + "@iconify/utils": "^3.1.3", + "@unocss/core": "66.7.5", + "ofetch": "^1.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-mini": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-mini/-/preset-mini-66.7.5.tgz", + "integrity": "sha512-o37TSl4ecT0dKu+3/TYuTYht75h82SEwDNl476m9ve0KW4Pv1O2tT/9TWd7N5cutEpySr8/YtjMwtWBD+drxBg==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/extractor-arbitrary-variants": "66.7.5", + "@unocss/rule-utils": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-tagify": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-tagify/-/preset-tagify-66.7.5.tgz", + "integrity": "sha512-/8YB1tXVi+WmNKPhsCdtO1xnQKEkshSnWDp6AbvVP3f6qOF7adlMYpAt3kpWCoVUBsfOQ06ZQlnfricMjObyoQ==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-typography": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-typography/-/preset-typography-66.7.5.tgz", + "integrity": "sha512-2dxC8LT9KYa29UZT4muDFl7DbIXvKktTfeSMbUGMdZKbHcuMtKSP2U52wti1PL5I9duqp4v+8G33EeVutGTUaQ==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/rule-utils": "66.7.5" + } + }, + "node_modules/@unocss/preset-uno": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-uno/-/preset-uno-66.7.5.tgz", + "integrity": "sha512-zaUlYgNngbt50fZA/LbtsEnmPKojPqeiXCyUUiKQMv2uJQhncR32xhLZXVQ+TJD7hlfZ+6FAqlco1NIiAcub9w==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/preset-wind3": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-web-fonts": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-web-fonts/-/preset-web-fonts-66.7.5.tgz", + "integrity": "sha512-OLLTK7kswdSu51qxEm6O+AehecgCfS08Ivqo+280lKzFW7V1jXr5okeJ1ty+85oHCprJqzcD9iG1khxNRLomcA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "ofetch": "^1.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-wind": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-wind/-/preset-wind-66.7.5.tgz", + "integrity": "sha512-LVKgGr0A9Lc7F85xGXrrb71DDXMlHGA8bcj/Kht8BCsuRdBZadNbLlnv5qnSJiHYhi3/blzcgVoaeRor6L9yNA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/preset-wind3": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-wind3": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-wind3/-/preset-wind3-66.7.5.tgz", + "integrity": "sha512-atFe/7Qein+oMdyZs0hEo+3EjV99Av2LVxDbzpCungxIfbS3TnQt70EIuHXMPNCVWLYwrMV+/P1n9Ntb0E3mow==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/preset-mini": "66.7.5", + "@unocss/rule-utils": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/preset-wind4": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/preset-wind4/-/preset-wind4-66.7.5.tgz", + "integrity": "sha512-n3jIvQv8x1jXpmWfvNFBIqHNARki4mKZXfxAA31gekpXsRRTg16u1+yC1+PBBJgoEDFEnnmKnG7EZP88S8LVXA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/extractor-arbitrary-variants": "66.7.5", + "@unocss/rule-utils": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/rule-utils": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/rule-utils/-/rule-utils-66.7.5.tgz", + "integrity": "sha512-/AKHBRF6ZOexE3EDDv8ZEYh40P5e2Eha41IYUbE1wjigW7++ssmvimSTdufJzZvU5DGP++E3B3WEsFPprZMjAg==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/transformer-attributify-jsx": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/transformer-attributify-jsx/-/transformer-attributify-jsx-66.7.5.tgz", + "integrity": "sha512-r8qDwNSt0eGSwWws3xsuIHb3PZYR2embFdYoE67hD/xlYgLjX1uPy/HUlGCSSh4uLc4vVYjurr0Oq5xF/B8YiA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "oxc-parser": "^0.131.0", + "oxc-walker": "^0.7.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/transformer-compile-class": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/transformer-compile-class/-/transformer-compile-class-66.7.5.tgz", + "integrity": "sha512-KuECgsGF7tGe808vIvKViEjI0UCUgYgneJfK+/TWBkjC7s8dLVaUtJzzcP9/r6OfGlgyn/x1YTdRqTaCENa7Xg==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/transformer-directives": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/transformer-directives/-/transformer-directives-66.7.5.tgz", + "integrity": "sha512-VMJApXXOwlDubkW+cNMmOkfxLefFupJr+yU23gGYUB2NPsuVltc8H5CDM0gfVebpeL5CUW05evxzEAk2wsju+Q==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5", + "@unocss/rule-utils": "66.7.5", + "css-tree": "^3.2.1" + } + }, + "node_modules/@unocss/transformer-variant-group": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/transformer-variant-group/-/transformer-variant-group-66.7.5.tgz", + "integrity": "sha512-iDmP3mM8J+IxuQf5Uh33zsi528xnGxTpKRJ0c+LCrqBTTkR2tZr4aCzNmJ0g29Js2yEOsyNXRRc8BNTuvgn0AA==", + "license": "MIT", + "dependencies": { + "@unocss/core": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@unocss/vite": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/@unocss/vite/-/vite-66.7.5.tgz", + "integrity": "sha512-1z1TBCNJCR2WzjPtjzmCHr8rtzXHosMjLdsCNe6Mzsfwiw044gzzLVuiEZO9vIjkI50lvQ+gIOxOiVQG0hGAeA==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "@unocss/config": "66.7.5", + "@unocss/core": "66.7.5", + "@unocss/inspector": "66.7.5", + "chokidar": "^5.0.0", + "magic-string": "^0.30.21", + "pathe": "^2.0.3", + "tinyglobby": "^0.2.17", + "unplugin-utils": "^0.3.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0-0" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "6.0.8", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-6.0.8.tgz", + "integrity": "sha512-0ZjgOg7oO6farnNGup7yvoM/YXZV84OZxHAwtflItNa/6zzQyVb5LNxyea3FEKEX2XlagIKzrlH7wwxkKgtiew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vitejs/plugin-vue-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue-jsx/-/plugin-vue-jsx-5.1.6.tgz", + "integrity": "sha512-YXvi4as2clxt6DFw5+a0tTA97ntiQXm/raR8ofNj3aNwwdlVGTiG2gp7EvfZW17P50acL/9bP0ccF4XnqNmlgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-syntax-typescript": "^7.29.7", + "@babel/plugin-transform-typescript": "^7.29.7", + "@rolldown/pluginutils": "^1.0.1", + "@vue/babel-plugin-jsx": "^2.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "vue": "^3.0.0" + } + }, + "node_modules/@volar/language-core": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.28.tgz", + "integrity": "sha512-w4qhIJ8ZSitgLAkVay6AbcnC7gP3glYM3fYwKV3srj8m494E3xtrCv6E+bWviiK/8hs6e6t1ij1s2Endql7vzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/source-map": "2.4.28" + } + }, + "node_modules/@volar/source-map": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.28.tgz", + "integrity": "sha512-yX2BDBqJkRXfKw8my8VarTyjv48QwxdJtvRgUpNE5erCsgEUdI2DsLbpa+rOQVAJYshY99szEcRDmyHbF10ggQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@volar/typescript": { + "version": "2.4.28", + "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.28.tgz", + "integrity": "sha512-Ja6yvWrbis2QtN4ClAKreeUZPVYMARDYZl9LMEv1iQ1QdepB6wn0jTRxA9MftYmYa4DQ4k/DaSZpFPUfxl8giw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "path-browserify": "^1.0.1", + "vscode-uri": "^3.0.8" + } + }, + "node_modules/@vue-macros/common": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@vue-macros/common/-/common-3.1.4.tgz", + "integrity": "sha512-/5Fv+6DgIcM9ajY05ZmKBv+LMX1M9A0X+IUwDRVdt67ciw8OV9bvG2r34p3RiEadlsQybjhKPRKNXDC8Bp23cw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-sfc": "^3.5.22", + "ast-kit": "^2.1.2", + "local-pkg": "^1.1.2", + "magic-string-ast": "^1.0.2", + "unplugin-utils": "^0.3.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/vue-macros" + }, + "peerDependencies": { + "vue": "^2.7.0 || ^3.2.25" + }, + "peerDependenciesMeta": { + "vue": { + "optional": true + } + } + }, + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-2.0.1.tgz", + "integrity": "sha512-uZ66EaFbnnZSYqYEyplWvn46GhZ1KuYSThdT68p+am7MgBNbQ3hphTL9L+xSIsWkdktwhPYLwPgVWqo96jDdRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@vue/babel-plugin-jsx": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-2.0.1.tgz", + "integrity": "sha512-a8CaLQjD/s4PVdhrLD/zT574ZNPnZBOY+IhdtKWRB4HRZ0I2tXBi5ne7d9eCfaYwp5gU5+4KIyFTV1W1YL9xZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.4", + "@babel/types": "^7.28.4", + "@vue/babel-helper-vue-transform-on": "2.0.1", + "@vue/babel-plugin-resolve-type": "2.0.1", + "@vue/shared": "^3.5.22" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/@vue/babel-plugin-resolve-type": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-2.0.1.tgz", + "integrity": "sha512-ybwgIuRGRRBhOU37GImDoWQoz+TlSqap65qVI6iwg/J7FfLTLmMf97TS7xQH9I7Qtr/gp161kYVdhr1ZMraSYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.4", + "@vue/compiler-sfc": "^3.5.22" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.40.tgz", + "integrity": "sha512-39E8IgOhTbVDnoJFMKc2DvYnypcZwUqgUhQkccva/0m6FUwtIKSGV7n1hpVmYcFaoRAwf9pBcwnKlCEsN63ZEQ==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/shared": "3.5.40", + "entities": "^7.0.1", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.40.tgz", + "integrity": "sha512-pwkx4vqlqOspFstrcmzwkKLePVMD3PT65imRzLhanU2V1Fj4K13g6OXjanOyzw3aTAuRk84BOmY8f3rEHqPaVA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.40.tgz", + "integrity": "sha512-gIf497P4kpuALcvs5n3AEg1Vdn0pSY4XbjASIfHNYF1/MP3T2Mf2STERTubysBxCRxzJGJYtF/O7vwJrxFB3Vw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.7", + "@vue/compiler-core": "3.5.40", + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-ssr": "3.5.40", + "@vue/shared": "3.5.40", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.21", + "postcss": "^8.5.19", + "source-map-js": "^1.2.1" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.40.tgz", + "integrity": "sha512-rrE5xiXG663+vHCHa3J9p2z5OcBRjXmoqenprJxAFQxg5pSshzeBiCE6pu46axapRJ2Adk0YDA2BRZVjiHXnhg==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/devtools-api": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-8.2.1.tgz", + "integrity": "sha512-6u4vXBlIBAC1wMplIZgpyPn7uh/s4Bf6F5bMzvLv+EdJ0aHs/+4B7Ygv864EStQSjRbsRzTko/kUG1A1IejQ3A==", + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.2.1" + } + }, + "node_modules/@vue/devtools-core": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-8.2.1.tgz", + "integrity": "sha512-s/VfAY9oDTb/kFEWmy461jaFde2MIV1RO/gi1vwM+PAZBZ/Pc2Ndu3BNBdZUze8QDUuyYvElbEEGA83syjJfzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-kit": "^8.2.1", + "@vue/devtools-shared": "^8.2.1" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/@vue/devtools-kit": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-8.2.1.tgz", + "integrity": "sha512-FIGIuq3AWReEpbAHY/cRGeHDfI0qOb8OCQ3YjbEAX04uaxIDbGc9rhkbVcG7rnfHPXE3RsU5KrWOu9V/okd8AQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^8.2.1", + "birpc": "^2.6.1", + "hookable": "^5.5.3", + "perfect-debounce": "^2.0.0" + } + }, + "node_modules/@vue/devtools-shared": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-8.2.1.tgz", + "integrity": "sha512-Fkac7lUdGReh6pVOi3AYPRGe82LQqRmAfThW7RRligOAP0ZA/Z1z9XLHDM9dv34pV2HRc79DK8uKPeG2fLnA/g==", + "license": "MIT" + }, + "node_modules/@vue/eslint-config-typescript": { + "version": "14.9.0", + "resolved": "https://registry.npmjs.org/@vue/eslint-config-typescript/-/eslint-config-typescript-14.9.0.tgz", + "integrity": "sha512-E3j9hDlfVf10F30MRcLTPY2IIhWIx1nsvkVukk14kTcuA+oBVot9zsP1hzsO+PAMDxV3Fd9FimBJtUBNBL5KFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^8.60.0", + "fast-glob": "^3.3.3", + "typescript-eslint": "^8.60.0", + "vue-eslint-parser": "^10.4.0" + }, + "bin": { + "vue-eslint-config-typescript": "dist/bin.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^9.10.0 || ^10.0.0", + "eslint-plugin-vue": "^9.28.0 || ^10.0.0", + "typescript": ">=4.8.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@vue/language-core": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/@vue/language-core/-/language-core-3.3.9.tgz", + "integrity": "sha512-in/68oAa4BCtVY6n/nkuhLIkV8DHYd2UivedJ6cMZ6UYtlq9jaoaSNUBHYCVO44z3nKg7MdE5OBoHKt5SxeBKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/language-core": "2.4.28", + "@vue/compiler-dom": "^3.5.0", + "@vue/shared": "^3.5.0", + "alien-signals": "^3.2.1", + "muggle-string": "^0.4.1", + "path-browserify": "^1.0.1", + "picomatch": "^4.0.4" + } + }, + "node_modules/@vue/language-core/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/@vue/reactivity": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.5.40.tgz", + "integrity": "sha512-B7ot9UlUZOi1zbq61/LvE88ZLTV8IlajTdiZTAEiDQgrnIMIZoPr9kGw0Zw46ObW62O9+H/Be3kMbfb7kYPQZA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.5.40.tgz", + "integrity": "sha512-KAZLweuZ6uUJPK1PMSQPgBU5gCjgrrfjUhSglmU9NhH+Zjepa8cnwSydPWDWHDwOgY4g3VcZ+PljbiHlURNCbw==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.5.40.tgz", + "integrity": "sha512-ZfrX8ssZQds900L9pr8AuK05ddnMsR4MPMZr8cPN9GoqoPWcXLhjvvbIA2SMv+7a97sJ1vv9pj/zxK0Cq/eEFQ==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.5.40", + "@vue/runtime-core": "3.5.40", + "@vue/shared": "3.5.40", + "csstype": "^3.2.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.5.40.tgz", + "integrity": "sha512-XNJym9WpevhTVt1HuwOrCRJ5Q+9z4BjTMrDtjTrvx74SmUll8spNTw6whWJa9mEkO4PKn5TihI/bm/8ds2QVJw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/shared": "3.5.40" + } + }, + "node_modules/@vue/shared": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.40.tgz", + "integrity": "sha512-WxnBtruIqOoV3rA4jeKDWzrYI5h7Cp4+pjwDi8kWGHz+IslhiN+wguLVVhtv2l8VoU02rzDCVfDjgCl1lNpZVg==", + "license": "MIT" + }, + "node_modules/@vue/tsconfig": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@vue/tsconfig/-/tsconfig-0.9.1.tgz", + "integrity": "sha512-buvjm+9NzLCJL29KY1j1991YYJ5e6275OiK+G4jtmfIb+z4POywbdm0wXusT9adVWqe0xqg70TbI7+mRx4uU9w==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 5.8", + "vue": "^3.4.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + }, + "vue": { + "optional": true + } + } + }, + "node_modules/@vueuse/core": { + "version": "14.4.0", + "resolved": "https://registry.npmmirror.com/@vueuse/core/-/core-14.4.0.tgz", + "integrity": "sha512-X4WHz1HlCzCBoYXesUkifzzWBAcZgXG8Fi5iNPQg/epdzOB3gu8Fawj3hvuwYR1nGcXGnvxwYYcUC/71++svtQ==", + "license": "MIT", + "dependencies": { + "@types/web-bluetooth": "^0.0.21", + "@vueuse/metadata": "14.4.0", + "@vueuse/shared": "14.4.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/@vueuse/metadata": { + "version": "14.4.0", + "resolved": "https://registry.npmmirror.com/@vueuse/metadata/-/metadata-14.4.0.tgz", + "integrity": "sha512-swx/255R6JyHZFJhx845iz5CRWDZdCfvkZOpACWc5+c5WHcG24mv8gUT1WIdFQaHt6dq79rvILd9QnCWiyVm9g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/@vueuse/shared": { + "version": "14.4.0", + "resolved": "https://registry.npmmirror.com/@vueuse/shared/-/shared-14.4.0.tgz", + "integrity": "sha512-JRgY90Sz8DDtPMsaDflvPMp9xYk69JZAmbuDvAquUVXKr2gEjqtzGNTTthLfckH0BzBqvnu31gb4a8TGLRe79g==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vue": "^3.5.0" + } + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "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/alien-signals": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/alien-signals/-/alien-signals-3.2.1.tgz", + "integrity": "sha512-I8FjmltrfnDFoZedi5CG8DghVYNhzb/Ijluz7tCSJH0xpd0484Kowhbb1XDYOxfJpU1p5wnM2X54dA+IfGyD1g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ansi-styles": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-7.0.0.tgz", + "integrity": "sha512-kKvt3m4uwzqL0wlkPd09CmljPJGOZZ4D0fP65sqFSvPkMRKhNi+74MgIJ5QxE6SxqB4t4KyUFGg8+n5zjo6hew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansis": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.3.1.tgz", + "integrity": "sha512-BJ8/l4R5LRE7hW9WdSuGYrLSHi2ynxeFpDFbH0K/CgNeY/tyhk+vO6TYxXC5r5CpUhNVX310xzPsN/H9lCdfOA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + } + }, + "node_modules/ast-kit": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/ast-kit/-/ast-kit-2.2.0.tgz", + "integrity": "sha512-m1Q/RaVOnTp9JxPX+F+Zn7IcLYMzM8kZofDImfsKZd8MbR+ikdOzTeztStWqfrqIxZnYWryyI9ePm3NGjnZgGw==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "pathe": "^2.0.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/ast-walker-scope": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/ast-walker-scope/-/ast-walker-scope-0.9.0.tgz", + "integrity": "sha512-IJdzo2vLiElBxKzwS36VsCue/62d6IdWjnPB2v3nuPKeWGynp6FF/CYoLa5i/3jXH/z97ZDdsXz6abpgM6w07A==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.2", + "@babel/types": "^7.29.0", + "ast-kit": "^2.2.0" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "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.11.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.11.tgz", + "integrity": "sha512-/yImnXwyTvgMkhgekLHok/Rx5vO6E0BmStWlSqKWMVm2a2ITuZ1Tn+9bgLS+gZRdZmWtd8nxuhHpdmCUOWsTQQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/birpc": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-2.9.0.tgz", + "integrity": "sha512-KrayHS5pBi69Xi9JmvoqrIgYGDkD6mcSe/i6YKi3w5kekCLzrX4+nawcXqrj2tIp50Kw/mT/s3p+GVK0A0sKxw==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^4.0.2" + }, + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.7", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.7.tgz", + "integrity": "sha512-JxV13hNrFxqjOc8alRbq9dK1MM79NEXYpma2B2J4wAtpWS5zIEIKqWPGCl7N4o7Uc7B7itylh7SuDujATRyyTw==", + "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.44", + "caniuse-lite": "^1.0.30001806", + "electron-to-chromium": "^1.5.393", + "node-releases": "^2.0.51", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cac": { + "version": "7.0.0", + "resolved": "https://registry.npmmirror.com/cac/-/cac-7.0.0.tgz", + "integrity": "sha512-tixWYgm5ZoOD+3g6UTea91eow5z6AAHaho3g0V9CNSNb45gM8SmflpAc+GRd1InC4AqN/07Unrgp56Y94N9hJQ==", + "license": "MIT", + "engines": { + "node": ">=20.19.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001806", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001806.tgz", + "integrity": "sha512-72Cuvd95zbSYPKq6Fhg8eDJRlzgWDf7/mtoZv6Qe/DYNCEBdNxoA3+rZAU2ZhGCpZlns3EssFavaZomckT5Uuw==", + "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/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmmirror.com/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "license": "MIT" + }, + "node_modules/confbox": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.4.tgz", + "integrity": "sha512-ysOGlgTFbN2/Y6Cg3Iye8YKulHw+R2fNXHrgSmXISQdMnomY6eNDprVdW9R5xBguEqI954+S6709UyiO7B+6OQ==", + "license": "MIT" + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmmirror.com/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "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/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmmirror.com/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/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/default-browser": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.5.0.tgz", + "integrity": "sha512-H9LMLr5zwIbSxrmvikGuI/5KGhZ8E2zH3stkMgM5LpOWDutGM2JZaj460Udnf1a+946zc7YBgrqEWwbk7zHvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.7", + "resolved": "https://registry.npmmirror.com/defu/-/defu-6.1.7.tgz", + "integrity": "sha512-7z22QmUWiQ/2d0KkdYmANbRUVABpZ9SNYyH5vx6PZ+nE5bcC0l7uFvEfHlyld/HcGBFTL536ClDt3DEcSlEJAQ==", + "license": "MIT" + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmmirror.com/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "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/duplexer": { + "version": "0.1.2", + "resolved": "https://registry.npmmirror.com/duplexer/-/duplexer-0.1.2.tgz", + "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.399", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.399.tgz", + "integrity": "sha512-lEcqhErbHjXRvd41rnWLpzbyU/IXfIYo7QwaFWmxGeLiLyY2TBCdHnWY88vB+p3ubnihRypDm66panXl7TylLA==", + "dev": true, + "license": "ISC" + }, + "node_modules/entities": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz", + "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/error-stack-parser-es": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-1.0.5.tgz", + "integrity": "sha512-5qucVt2XcuGMcEGgWI7i+yZpmpByQ8J1lHhcL7PwqCwu9FPP3VUXzT4ltHe5i2z9dePwEHcDVOAfSnHsOlCXRA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "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.8.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.8.0.tgz", + "integrity": "sha512-nuKKvN+oIBO0koN7Tm7dlkmnkc21mtt0QJLwAKzjLq14y6lRTdVG36MZHJ8eQHwdJMwZbQNMlPOYedMq/oVJvQ==", + "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.7.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.5", + "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-config-prettier": { + "version": "10.1.8", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", + "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "funding": { + "url": "https://opencollective.com/eslint-config-prettier" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-oxlint": { + "version": "1.73.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-oxlint/-/eslint-plugin-oxlint-1.73.0.tgz", + "integrity": "sha512-2qsGYkwpas99+jLmB7F3W8Gv+7QkHIr67AMw10UTs/QAMCm2eO0Z8B8ROMvAgyKaWIitkcvH8DwLfTrHMeXzCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jsonc-parser": "^3.3.1" + }, + "peerDependencies": { + "oxlint": "~1.73.0" + } + }, + "node_modules/eslint-plugin-vue": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.9.2.tgz", + "integrity": "sha512-4g7ZP3pYcuqd7Zp0pzUKcos0W+RkjBz4EGdhJ92FcYk6v03Ti/GK5NwjgsjxHK+98eXDbHeK7VtX1az7/8doZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^7.1.0", + "semver": "^7.6.3", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0", + "@typescript-eslint/parser": "^7.0.0 || ^8.0.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "vue-eslint-parser": "^10.3.0" + }, + "peerDependenciesMeta": { + "@stylistic/eslint-plugin": { + "optional": true + }, + "@typescript-eslint/parser": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue/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/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/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/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/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/exsolve": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.1.1.tgz", + "integrity": "sha512-9U/jZUgjnSGyntRr6y5Muu1MJcwFl6kPu7k8qLF0IMNfLqvw0NZ4nnVDq0RVoZ0RvCyumib4Ez3KYrVfilrw+g==", + "license": "MIT" + }, + "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-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "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/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "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/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "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/gzip-size": { + "version": "6.0.0", + "resolved": "https://registry.npmmirror.com/gzip-size/-/gzip-size-6.0.0.tgz", + "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==", + "license": "MIT", + "dependencies": { + "duplexer": "^0.1.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "license": "MIT" + }, + "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/import-meta-resolve": { + "version": "4.2.0", + "resolved": "https://registry.npmmirror.com/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", + "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "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-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-wsl": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.1.tgz", + "integrity": "sha512-e6rvdUCiQCAuumZslxRJWR/Doq4VpPR82kqclvcS0efgt430SlGIk05vdCN58+VrzgtIcfNODjozVielycD4Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "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==", + "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-parse-even-better-errors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-6.0.0.tgz", + "integrity": "sha512-2/8adwnK1/+Fdjyts4r6wSpfANWw8zdNhU9U/Llk59c6O+DjSisPWPykwoL8gZmocP9Dy64S7oie2g+Mia123A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "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==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, + "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/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", + "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.33.0", + "lightningcss-darwin-arm64": "1.33.0", + "lightningcss-darwin-x64": "1.33.0", + "lightningcss-freebsd-x64": "1.33.0", + "lightningcss-linux-arm-gnueabihf": "1.33.0", + "lightningcss-linux-arm64-gnu": "1.33.0", + "lightningcss-linux-arm64-musl": "1.33.0", + "lightningcss-linux-x64-gnu": "1.33.0", + "lightningcss-linux-x64-musl": "1.33.0", + "lightningcss-win32-arm64-msvc": "1.33.0", + "lightningcss-win32-x64-msvc": "1.33.0" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "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.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "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/local-pkg": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-1.2.1.tgz", + "integrity": "sha512-++gUqRDEvcnN6Zhqrr+y/CkVEHhlrR96vZn3nZZPYzMcBUyBtTKzB9NadClFIsIVSsu+3i9tfk/erqy9kAmt7Q==", + "license": "MIT", + "dependencies": { + "mlly": "^1.7.4", + "pkg-types": "^2.3.0", + "quansync": "^0.2.11" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmmirror.com/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "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/magic-regexp": { + "version": "0.10.0", + "resolved": "https://registry.npmmirror.com/magic-regexp/-/magic-regexp-0.10.0.tgz", + "integrity": "sha512-Uly1Bu4lO1hwHUW0CQeSWuRtzCMNO00CmXtS8N6fyvB3B979GOEEeAkiTUDsmbYLAbvpUS/Kt5c4ibosAzVyVg==", + "license": "MIT", + "dependencies": { + "estree-walker": "^3.0.3", + "magic-string": "^0.30.12", + "mlly": "^1.7.2", + "regexp-tree": "^0.1.27", + "type-level-regexp": "~0.1.17", + "ufo": "^1.5.4", + "unplugin": "^2.0.0" + } + }, + "node_modules/magic-regexp/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmmirror.com/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/magic-regexp/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmmirror.com/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/magic-regexp/node_modules/unplugin": { + "version": "2.3.11", + "resolved": "https://registry.npmmirror.com/unplugin/-/unplugin-2.3.11.tgz", + "integrity": "sha512-5uKD0nqiYVzlmCRs01Fhs2BdkEgBS3SAVP6ndrBsuK42iC2+JHyxM05Rm9G8+5mkmRtzMZGY8Ct5+mliZxU/Ww==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "acorn": "^8.15.0", + "picomatch": "^4.0.3", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=18.12.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==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/magic-string-ast": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/magic-string-ast/-/magic-string-ast-1.0.3.tgz", + "integrity": "sha512-CvkkH1i81zl7mmb94DsRiFeG9V2fR2JeuK8yDgS8oiZSFa++wWLEgZ5ufEOyLHbvSbD1gTRKv9NdX69Rnvr9JA==", + "license": "MIT", + "dependencies": { + "magic-string": "^0.30.19" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmmirror.com/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", + "license": "CC0-1.0" + }, + "node_modules/memorystream": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", + "integrity": "sha512-S3UwM3yj5mtUSEfP41UZmt/0SCoVYUcU1rkXv+BQ5Ig8ndL4sPoJNBUJERafdPb5jjHJGuMgytgKvKIf58XNBw==", + "dev": true, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "brace-expansion": "^5.0.8" + }, + "engines": { + "node": "18 || 20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mlly": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.8.2.tgz", + "integrity": "sha512-d+ObxMQFmbt10sretNDytwt85VrbkhhUA/JBGm1MPaWJ65Cl4wOgLaB1NYvJSZ0Ef03MMEU/0xpPMXUIQ29UfA==", + "license": "MIT", + "dependencies": { + "acorn": "^8.16.0", + "pathe": "^2.0.3", + "pkg-types": "^1.3.1", + "ufo": "^1.6.3" + } + }, + "node_modules/mlly/node_modules/confbox": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.1.8.tgz", + "integrity": "sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w==", + "license": "MIT" + }, + "node_modules/mlly/node_modules/pkg-types": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.3.1.tgz", + "integrity": "sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ==", + "license": "MIT", + "dependencies": { + "confbox": "^0.1.8", + "mlly": "^1.7.4", + "pathe": "^2.0.1" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "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/muggle-string": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", + "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.16", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.16.tgz", + "integrity": "sha512-bzlKTyNJ7+LdGIIwy8ijFpIqEQIvafahV7eYykJ8Cvh42EdJeODoJ6gUJXpQJvej1BddH8OqTXZNE/KfbWAu8Q==", + "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-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmmirror.com/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "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/nostics": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/nostics/-/nostics-1.2.0.tgz", + "integrity": "sha512-FGqEfhQjrvo1lL8KFifdTQiNwwQHJxC1jtYE1Rc54qF/jxONUNL+kC9gS1krX8Q65PgrQ5fCqH/I4NhWBvdSqg==", + "license": "MIT" + }, + "node_modules/npm-normalize-package-bin": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/npm-normalize-package-bin/-/npm-normalize-package-bin-6.0.0.tgz", + "integrity": "sha512-tdt4aFn9QamlhdN3HV2D2ccpBwO5/fyjjbXUxYA6uBjyekMZcZvDq0aSj9t5Jo+tih6AYFnt/cuIRn9013e0Uw==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/npm-run-all2": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/npm-run-all2/-/npm-run-all2-9.0.3.tgz", + "integrity": "sha512-BQAEdU1PtYc48qYRdghW2BVTQT3VqWCoFQmO87NlM1h1PYwMCKQpUWaNyB20V26caNzFsXQDfyOdznLlHCih6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^7.0.0", + "cross-spawn": "^7.0.6", + "memorystream": "^0.3.1", + "picomatch": "^4.0.2", + "pidtree": "^1.0.0", + "read-package-json-fast": "^6.0.0", + "shell-quote": "^1.8.4", + "which": "^7.0.0" + }, + "bin": { + "npm-run-all": "bin/npm-run-all/index.js", + "npm-run-all2": "bin/npm-run-all/index.js", + "run-p": "bin/run-p/index.js", + "run-s": "bin/run-s/index.js" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0", + "npm": ">= 10" + } + }, + "node_modules/npm-run-all2/node_modules/isexe": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-4.0.0.tgz", + "integrity": "sha512-FFUtZMpoZ8RqHS3XeXEmHWLA4thH+ZxCv2lOiPIn1Xc7CxrqhWzNSDzD+/chS/zbYezmiwWLdQC09JdQKmthOw==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=20" + } + }, + "node_modules/npm-run-all2/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/npm-run-all2/node_modules/which": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-7.0.0.tgz", + "integrity": "sha512-RancgH2dmbLdHl6LRhEqvklWMgl/Hdnun0Y90KhBOLkMefg8Qa7/Zel8Sm+8HEcP6DEjzsWzpkuBQEZok58isA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^4.0.0" + }, + "bin": { + "node-which": "bin/which.js" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/obug": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.4.tgz", + "integrity": "sha512-4a+OsYv9UktOJKE+l1A4OufDgdRF9PifWj+tJnHURo/P+WOxpG4GzUFL9qCalmWauao6ogiG+QvnCovwPoyAWA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT", + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/ofetch": { + "version": "1.5.1", + "resolved": "https://registry.npmmirror.com/ofetch/-/ofetch-1.5.1.tgz", + "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", + "license": "MIT", + "dependencies": { + "destr": "^2.0.5", + "node-fetch-native": "^1.6.7", + "ufo": "^1.6.1" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/open": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.4.0", + "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", + "is-inside-container": "^1.0.0", + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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/oxc-parser": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/oxc-parser/-/oxc-parser-0.131.0.tgz", + "integrity": "sha512-SJ3/7ZPbgie8dr5Z9BI/M51zZbpXba+hRSG0MDzVwMW5CRQg2fjYE0jHGlLX4eeiibGgC/mzoDFKSDHwVZEHRQ==", + "license": "MIT", + "dependencies": { + "@oxc-project/types": "^0.131.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxc-parser/binding-android-arm-eabi": "0.131.0", + "@oxc-parser/binding-android-arm64": "0.131.0", + "@oxc-parser/binding-darwin-arm64": "0.131.0", + "@oxc-parser/binding-darwin-x64": "0.131.0", + "@oxc-parser/binding-freebsd-x64": "0.131.0", + "@oxc-parser/binding-linux-arm-gnueabihf": "0.131.0", + "@oxc-parser/binding-linux-arm-musleabihf": "0.131.0", + "@oxc-parser/binding-linux-arm64-gnu": "0.131.0", + "@oxc-parser/binding-linux-arm64-musl": "0.131.0", + "@oxc-parser/binding-linux-ppc64-gnu": "0.131.0", + "@oxc-parser/binding-linux-riscv64-gnu": "0.131.0", + "@oxc-parser/binding-linux-riscv64-musl": "0.131.0", + "@oxc-parser/binding-linux-s390x-gnu": "0.131.0", + "@oxc-parser/binding-linux-x64-gnu": "0.131.0", + "@oxc-parser/binding-linux-x64-musl": "0.131.0", + "@oxc-parser/binding-openharmony-arm64": "0.131.0", + "@oxc-parser/binding-wasm32-wasi": "0.131.0", + "@oxc-parser/binding-win32-arm64-msvc": "0.131.0", + "@oxc-parser/binding-win32-ia32-msvc": "0.131.0", + "@oxc-parser/binding-win32-x64-msvc": "0.131.0" + } + }, + "node_modules/oxc-parser/node_modules/@oxc-project/types": { + "version": "0.131.0", + "resolved": "https://registry.npmmirror.com/@oxc-project/types/-/types-0.131.0.tgz", + "integrity": "sha512-PgnWDfV0h+b16XNKbXU7Daib/BFSt/J2mEzfYIBu6JB/wNdlU+kVYXCkGA1A9fWkTbOgbjh4e6NhPeQOYvFhEA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/Boshen" + } + }, + "node_modules/oxc-walker": { + "version": "0.7.0", + "resolved": "https://registry.npmmirror.com/oxc-walker/-/oxc-walker-0.7.0.tgz", + "integrity": "sha512-54B4KUhrzbzc4sKvKwVYm7E2PgeROpGba0/2nlNZMqfDyca+yOor5IMb4WLGBatGDT0nkzYdYuzylg7n3YfB7A==", + "license": "MIT", + "dependencies": { + "magic-regexp": "^0.10.0" + }, + "peerDependencies": { + "oxc-parser": ">=0.98.0" + } + }, + "node_modules/oxlint": { + "version": "1.74.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.74.0.tgz", + "integrity": "sha512-odGl2s2x5IOJoj3A0v1k0PGBXVFBZeZ2+AK/+K2MJur7Ghi3bkyX5NuLUWHKqa4js1wjep3hJeuTQJOlr+4+dA==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.74.0", + "@oxlint/binding-android-arm64": "1.74.0", + "@oxlint/binding-darwin-arm64": "1.74.0", + "@oxlint/binding-darwin-x64": "1.74.0", + "@oxlint/binding-freebsd-x64": "1.74.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.74.0", + "@oxlint/binding-linux-arm-musleabihf": "1.74.0", + "@oxlint/binding-linux-arm64-gnu": "1.74.0", + "@oxlint/binding-linux-arm64-musl": "1.74.0", + "@oxlint/binding-linux-ppc64-gnu": "1.74.0", + "@oxlint/binding-linux-riscv64-gnu": "1.74.0", + "@oxlint/binding-linux-riscv64-musl": "1.74.0", + "@oxlint/binding-linux-s390x-gnu": "1.74.0", + "@oxlint/binding-linux-x64-gnu": "1.74.0", + "@oxlint/binding-linux-x64-musl": "1.74.0", + "@oxlint/binding-openharmony-arm64": "1.74.0", + "@oxlint/binding-win32-arm64-msvc": "1.74.0", + "@oxlint/binding-win32-ia32-msvc": "1.74.0", + "@oxlint/binding-win32-x64-msvc": "1.74.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=0.24.0", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-manager-detector": { + "version": "1.8.0", + "resolved": "https://registry.npmmirror.com/package-manager-detector/-/package-manager-detector-1.8.0.tgz", + "integrity": "sha512-yQA4H19AmPEoMUeavPMDIe1higySl/gH/yaQrkT/s07Qp+7pp2hYz30N3z2l5BkjVkF9Ow6o0wjJamm2y7Sn0A==", + "license": "MIT" + }, + "node_modules/path-browserify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", + "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "license": "MIT" + }, + "node_modules/perfect-debounce": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.1.0.tgz", + "integrity": "sha512-LjgdTytVFXeUgtHZr9WYViYSM/g8MkcTPYDlPa3cDqMirHjKiSZPYd6DoL7pK8AJQr+uWkQvCjHNdiMqsrJs+g==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-1.0.0.tgz", + "integrity": "sha512-avfAvjB9Dd0wdj3rjJX//yS+G79OO0KrS5pJHFJENjYGX6N4SMgEDBBI/yFy0lloOYSaC6XQxzpOAMPfSYFV/Q==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/pinia": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-4.0.2.tgz", + "integrity": "sha512-yKVVA7bSj5oRZFp/Ab9wLlmyb5gPUYEiIm4ryiWTe/xe7PtkRdMVOp1X1ggvq0c6Uj7Q0Du1HnV2mtAwM0Ks1g==", + "license": "MIT", + "dependencies": { + "nostics": "^1.1.4" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/devtools-api": "^8.1.5", + "typescript": ">=5.6.0", + "vue": "^3.5.11" + }, + "peerDependenciesMeta": { + "@vue/devtools-api": { + "optional": false + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pkg-types": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.1.tgz", + "integrity": "sha512-y+ichcgc2LrADuhLNAx8DFjVfgz91pRxfZdI3UDhxHvcVEZsenLO+7XaU5vOp0u/7V/wZ+plyuQxtrDlZJ+yeg==", + "license": "MIT", + "dependencies": { + "confbox": "^0.2.4", + "exsolve": "^1.0.8", + "pathe": "^2.0.3" + } + }, + "node_modules/postcss": { + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", + "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.16", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.4.tgz", + "integrity": "sha512-HeP7D2wyhkR+XaK6v4W8oRF62Dsz4flyuczALJp61GckGm42u1saSSJ/0auvcBqxs3jMRFEcPK34At/0JBKdOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.9.5", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.5.tgz", + "integrity": "sha512-/FVl766LpUfB5vXgCYOYa0MeV/441Ia99AeICQIQFTY/Nw0roZwULcXpku5i1/m5kt/baz+s4Zogspd839HSMg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "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/quansync": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-0.2.11.tgz", + "integrity": "sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/read-package-json-fast": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/read-package-json-fast/-/read-package-json-fast-6.0.0.tgz", + "integrity": "sha512-PNaGjoCnw9DBA2Kl8D+8po957z778q/HOPuY2u3Bkw/JO3eC8MDx7jn/PgMtSgpcBbs+6UOjDbwReGpXmRvs0g==", + "dev": true, + "license": "ISC", + "dependencies": { + "json-parse-even-better-errors": "^6.0.0", + "npm-normalize-package-bin": "^6.0.0" + }, + "engines": { + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" + } + }, + "node_modules/readdirp": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.0.0.tgz", + "integrity": "sha512-9u/XQ1pvrQtYyMpZe7DXKv2p5CNvyVwzUB6uhLAnQwHMSgKMBR62lc7AHljaeteeHXn11XTAaLLUVZYVZyuRBQ==", + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/regexp-tree": { + "version": "0.1.27", + "resolved": "https://registry.npmmirror.com/regexp-tree/-/regexp-tree-0.1.27.tgz", + "integrity": "sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA==", + "license": "MIT", + "bin": { + "regexp-tree": "bin/regexp-tree" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rolldown": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.1.tgz", + "integrity": "sha512-4FKJhg8d3OiyQOA6Q1Q0hoFFpW9/OoX+VsHzpECsdsIZoOArrAK90gl59YK/Z+gnDel45bgJZK03ozH/9bCqEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.142.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.2.1", + "@rolldown/binding-darwin-arm64": "1.2.1", + "@rolldown/binding-darwin-x64": "1.2.1", + "@rolldown/binding-freebsd-x64": "1.2.1", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.1", + "@rolldown/binding-linux-arm64-gnu": "1.2.1", + "@rolldown/binding-linux-arm64-musl": "1.2.1", + "@rolldown/binding-linux-ppc64-gnu": "1.2.1", + "@rolldown/binding-linux-s390x-gnu": "1.2.1", + "@rolldown/binding-linux-x64-gnu": "1.2.1", + "@rolldown/binding-linux-x64-musl": "1.2.1", + "@rolldown/binding-openharmony-arm64": "1.2.1", + "@rolldown/binding-wasm32-wasi": "1.2.1", + "@rolldown/binding-win32-arm64-msvc": "1.2.1", + "@rolldown/binding-win32-x64-msvc": "1.2.1" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scule": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/scule/-/scule-1.3.0.tgz", + "integrity": "sha512-6FtHJEvt+pVMIB9IBY+IcCJ6Z5f1iQnytgyfKMhDKgmzYG+TeH/wx1y3l27rshSbLiSanrR9ffZDrEsmjlQF2g==", + "license": "MIT" + }, + "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/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/shell-quote": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.10.0.tgz", + "integrity": "sha512-w1aiOKwKuRgtwAReIIj89puqg+I7GvX4IbLrvmhXbzQsj1+Zwi4VO3+fa6ZF91TWSjIxoEkKnMeHcLEODK5ZXA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tinyexec": { + "version": "1.3.0", + "resolved": "https://registry.npmmirror.com/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "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/tinyglobby/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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", + "optional": true + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-level-regexp": { + "version": "0.1.17", + "resolved": "https://registry.npmmirror.com/type-level-regexp/-/type-level-regexp-0.1.17.tgz", + "integrity": "sha512-wTk4DH3cxwk196uGLK/E9pE45aLfeKJacKmcEgEOA/q5dnPGNxXt0cfYdFxb57L+sEpf1oJH4Dnx/pnRcku9jg==", + "license": "MIT" + }, + "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.65.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.65.0.tgz", + "integrity": "sha512-/ggrHAwyjENDusvyxbuqxAC2dTnZg/Z8F+fgQtYIz+L6n/9HfSlEZcFGV/NsMNa6CkGk0xUjUAFwC0vHOflvIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.65.0", + "@typescript-eslint/parser": "8.65.0", + "@typescript-eslint/typescript-estree": "8.65.0", + "@typescript-eslint/utils": "8.65.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/ufo": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.4.tgz", + "integrity": "sha512-JFNbkD1Svwe0KvGi8GOeLcP4kAWQ609twvCdcHxq1oSL8svv39ZuSvajcD8B+5D0eL4+s1Is2D/O6KN3qcTeRA==", + "license": "MIT" + }, + "node_modules/unconfig": { + "version": "7.5.0", + "resolved": "https://registry.npmmirror.com/unconfig/-/unconfig-7.5.0.tgz", + "integrity": "sha512-oi8Qy2JV4D3UQ0PsopR28CzdQ3S/5A1zwsUwp/rosSbfhJ5z7b90bIyTwi/F7hCLD4SGcZVjDzd4XoUQcEanvA==", + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "defu": "^6.1.4", + "jiti": "^2.6.1", + "quansync": "^1.0.0", + "unconfig-core": "7.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig-core": { + "version": "7.5.0", + "resolved": "https://registry.npmmirror.com/unconfig-core/-/unconfig-core-7.5.0.tgz", + "integrity": "sha512-Su3FauozOGP44ZmKdHy2oE6LPjk51M/TRRjHv2HNCWiDvfvCoxC2lno6jevMA91MYAdCdwP05QnWdWpSbncX/w==", + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig-core/node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/unconfig/node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmmirror.com/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.18.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz", + "integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/unocss": { + "version": "66.7.5", + "resolved": "https://registry.npmmirror.com/unocss/-/unocss-66.7.5.tgz", + "integrity": "sha512-nAdmU8TwnQoiLnQjZ6Hm1GmHy9lTexKsAZNEJtZnxN9wyFRc1eLjQgmh9r7UEGxBQMQLD8OZOgmk5HpwObbh0Q==", + "license": "MIT", + "dependencies": { + "@unocss/cli": "66.7.5", + "@unocss/core": "66.7.5", + "@unocss/preset-attributify": "66.7.5", + "@unocss/preset-icons": "66.7.5", + "@unocss/preset-mini": "66.7.5", + "@unocss/preset-tagify": "66.7.5", + "@unocss/preset-typography": "66.7.5", + "@unocss/preset-uno": "66.7.5", + "@unocss/preset-web-fonts": "66.7.5", + "@unocss/preset-wind": "66.7.5", + "@unocss/preset-wind3": "66.7.5", + "@unocss/preset-wind4": "66.7.5", + "@unocss/transformer-attributify-jsx": "66.7.5", + "@unocss/transformer-compile-class": "66.7.5", + "@unocss/transformer-directives": "66.7.5", + "@unocss/transformer-variant-group": "66.7.5", + "@unocss/vite": "66.7.5" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@unocss/astro": "66.7.5", + "@unocss/postcss": "66.7.5", + "@unocss/webpack": "66.7.5" + }, + "peerDependenciesMeta": { + "@unocss/astro": { + "optional": true + }, + "@unocss/postcss": { + "optional": true + }, + "@unocss/webpack": { + "optional": true + } + } + }, + "node_modules/unplugin": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-3.3.0.tgz", + "integrity": "sha512-qa66K+crbfyE6JK10GjvbJeRrOsuC/JpbnHctfyp/i4oBTxWOzJfRZyDiOk1PtErMFRu8JhsU/wPvOdBNWe5Rg==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "picomatch": "^4.0.4", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@farmfe/core": "*", + "@rspack/core": "*", + "bun-types-no-globals": "*", + "esbuild": "*", + "rolldown": "*", + "rollup": "*", + "unloader": "*", + "vite": "*", + "webpack": "*" + }, + "peerDependenciesMeta": { + "@farmfe/core": { + "optional": true + }, + "@rspack/core": { + "optional": true + }, + "bun-types-no-globals": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "rolldown": { + "optional": true + }, + "rollup": { + "optional": true + }, + "unloader": { + "optional": true + }, + "vite": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "node_modules/unplugin-utils": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/unplugin-utils/-/unplugin-utils-0.3.2.tgz", + "integrity": "sha512-xVToRh2CTmLk2HnEG7ac4rl1MJTT3RFkpS8B++/SnB0kXvuaavD+n3m/vrzyWQOdJNSZQACnbz01pnppbwV5BA==", + "license": "MIT", + "dependencies": { + "pathe": "^2.0.3", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, + "node_modules/unplugin-utils/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/unplugin/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "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/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.0.tgz", + "integrity": "sha512-pn+CFpM0lwDeKwmOq1ZaBK/9sjorZcgqxki6MbY/jPEVd9vichIlmlD4HmQ5wdP5EgqQCFRaACBxMC7uEGc6lQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.23", + "rolldown": "~1.2.0", + "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.4.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/vite-dev-rpc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/vite-dev-rpc/-/vite-dev-rpc-2.0.0.tgz", + "integrity": "sha512-yKwbTwdHKSD2k/aGqyWpPHepo45OQc8lH3/6IfT4ZqeKE26ooKvi4WIEKzqWav8v+9Is8u1k8q54hvOmqASazA==", + "dev": true, + "license": "MIT", + "dependencies": { + "birpc": "^4.0.0", + "vite-hot-client": "^2.2.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.9.0 || ^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0 || ^6.0.1 || ^7.0.0-0 || ^8.0.0" + } + }, + "node_modules/vite-dev-rpc/node_modules/birpc": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-4.0.0.tgz", + "integrity": "sha512-LShSxJP0KTmd101b6DRyGBj57LZxSDYWKitQNW/mi8GRMvZb078Uf9+pveax1DrVL89vm7mWe+TovdI/UDOuPw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/vite-hot-client": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-2.2.0.tgz", + "integrity": "sha512-76Zs9zrHbH7M7wqeyooGQKdX+yg0pQ0xuQ1PbFp4z5a0Lzn2e5IPFoCswnmqZ4GiwqB4Jo3WcDAMO9jARTJl8w==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0 || ^7.0.0-0 || ^8.0.0" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "11.4.1", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-11.4.1.tgz", + "integrity": "sha512-ShOFe2PURXGvRS5OrgmOLZOCwDTD7dEBVt0tMpFPKb9AsvqXKCRGM8QgKrUbRbJYFXScHvDPpGRd28rYidC0tA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansis": "^4.3.0", + "error-stack-parser-es": "^1.0.5", + "obug": "^2.1.1", + "ohash": "^2.0.11", + "open": "^11.0.0", + "perfect-debounce": "^2.1.0", + "sirv": "^3.0.2", + "unplugin-utils": "^0.3.1", + "vite-dev-rpc": "^2.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0-0 || ^8.0.0-0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-8.2.1.tgz", + "integrity": "sha512-5JLxXWWCo5lJMw16/xVeNvJ8k2zLwZPf1vITLzya/2IePrCBeGe/p/iAokgXHZpEi39fcYtPXmO8SaKeXmqCAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^8.2.1", + "@vue/devtools-kit": "^8.2.1", + "@vue/devtools-shared": "^8.2.1", + "sirv": "^3.0.2", + "vite-plugin-inspect": "^11.3.3", + "vite-plugin-vue-inspector": "^6.0.0" + }, + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/vite-plugin-vue-inspector": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-6.0.0.tgz", + "integrity": "sha512-OpyITJLgZNibxlrik1EmRtvXHDjLRxNPsWkGFTERZs2LgMEdG4W0WoFt5GIgp3a3jRou+eJR8U1zOBk/XQgEbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" + }, + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/vite-plugin-vue-inspector/node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz", + "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vite-plugin-vue-inspector/node_modules/@vue/babel-plugin-jsx": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz", + "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-syntax-jsx": "^7.27.1", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.0", + "@babel/types": "^7.28.2", + "@vue/babel-helper-vue-transform-on": "1.5.0", + "@vue/babel-plugin-resolve-type": "1.5.0", + "@vue/shared": "^3.5.18" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + } + } + }, + "node_modules/vite-plugin-vue-inspector/node_modules/@vue/babel-plugin-resolve-type": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz", + "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/parser": "^7.28.0", + "@vue/compiler-sfc": "^3.5.18" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/vite/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/vscode-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", + "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/vue": { + "version": "3.5.40", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.5.40.tgz", + "integrity": "sha512-+8PJ4SJXdn/cHGImF4CKdxlWHIN5Dkt7DoufRREM6h6uVCx2m7QxgcEQmmzyOK8A9mcafg7sFbJFYsdFVubTig==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.40", + "@vue/compiler-sfc": "3.5.40", + "@vue/runtime-dom": "3.5.40", + "@vue/server-renderer": "3.5.40", + "@vue/shared": "3.5.40" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "10.4.1", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.1.tgz", + "integrity": "sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.4.0", + "eslint-scope": "^8.2.0 || ^9.0.0", + "eslint-visitor-keys": "^4.2.0 || ^5.0.0", + "espree": "^10.3.0 || ^11.0.0", + "esquery": "^1.6.0", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0" + } + }, + "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/vue-eslint-parser/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/vue-router": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-5.2.0.tgz", + "integrity": "sha512-QAC5i0LEb1GLG0LXDQmHu8L7FX12j0KwU/JTKmLQUJMrn04gQdKP6Du+p0QwpHb3iy71vBlqnHQ8WAfOSAWhqw==", + "license": "MIT", + "dependencies": { + "@babel/generator": "^8.0.0", + "@vue-macros/common": "^3.1.3", + "@vue/devtools-api": "^8.1.5", + "ast-walker-scope": "^0.9.0", + "chokidar": "^5.0.0", + "json5": "^2.2.3", + "local-pkg": "^1.2.1", + "magic-string": "^0.30.21", + "mlly": "^1.8.2", + "muggle-string": "^0.4.1", + "nostics": "^1.1.4", + "pathe": "^2.0.3", + "picomatch": "^4.0.5", + "scule": "^1.3.0", + "tinyglobby": "^0.2.17", + "unplugin": "^3.3.0", + "unplugin-utils": "^0.3.2", + "yaml": "^2.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@pinia/colada": ">=0.21.2", + "@vue/compiler-sfc": "^3.5.34 || ^4.0.0", + "pinia": "^3.0.4 || ^4.0.2", + "vite": "^7.3.0 || ^8.0.0", + "vue": "^3.5.34 || ^4.0.0" + }, + "peerDependenciesMeta": { + "@pinia/colada": { + "optional": true + }, + "@vue/compiler-sfc": { + "optional": true + }, + "pinia": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vue-router/node_modules/@babel/generator": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-8.0.0.tgz", + "integrity": "sha512-NT9NrVwJsbSV6Y2FSstWa71EETOnzrjkL5/wX3D2mYHtKM+qvqB1DvR4D0Setb/gDBsHzRICifwEWMO8CnTF6g==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^8.0.0", + "@babel/types": "^8.0.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "@types/jsesc": "^2.5.0", + "jsesc": "^3.0.2" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/vue-router/node_modules/@babel/helper-string-parser": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-8.0.0.tgz", + "integrity": "sha512-6mJgmFFFIIO82vvoLt9XtRC7/TkzXfts1t/SpRX4IHSzMgqoPYCWesVu1udUPUWioAE/2fcG6WuI8zrkE1gwrg==", + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/vue-router/node_modules/@babel/helper-validator-identifier": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-8.0.4.tgz", + "integrity": "sha512-4wFaiLd0bVo4cIoTXI3zKI038NIWE/cr3jvBjejOVYVxV/m8Ltav1USiGzG1fmS5J2RhgEOgXNNK46cRPnRsrg==", + "license": "MIT", + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/vue-router/node_modules/@babel/parser": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-8.0.4.tgz", + "integrity": "sha512-srpptsAkEbbNIC/q8nT7o+m6CQe8CJUTV/t7MYc9NnWlgYVtHOb7JH6SorxMhN0kuRJjVqXbKClG6xSbPtzz+g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^8.0.4" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/vue-router/node_modules/@babel/types": { + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-8.0.4.tgz", + "integrity": "sha512-eY+Yn3dCqTGmyiq2QRU66lA5FL8lqqqvecHt0fF3uHONIa7ToYsaCiWV8lOKqAs0Rb2SjixiKFROngnulPtt2g==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^8.0.0", + "@babel/helper-validator-identifier": "^8.0.4" + }, + "engines": { + "node": "^22.18.0 || >=24.11.0" + } + }, + "node_modules/vue-router/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vue-tsc": { + "version": "3.3.9", + "resolved": "https://registry.npmjs.org/vue-tsc/-/vue-tsc-3.3.9.tgz", + "integrity": "sha512-TS3Y1ux/IRoE8OCP2PpACAeOseuIs0UvWrcr7u+w3PmfY+SlCfEf8zjrBgnQksHUgLpthi5vHlffcQTQTdPBZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@volar/typescript": "2.4.28", + "@vue/language-core": "3.3.9" + }, + "bin": { + "vue-tsc": "bin/vue-tsc.js" + }, + "peerDependencies": { + "typescript": ">=5.0.0" + } + }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "license": "MIT" + }, + "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/wsl-utils": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.1.tgz", + "integrity": "sha512-g/eziiSUNBSsdDJtCLB8bdYEUMj4jR7AGeUo96p/3dTafgjHhpF4RiCFPiRILwjQoDXx5MqkBr4fwWtR3Ky4Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/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/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..1b7198a --- /dev/null +++ b/package.json @@ -0,0 +1,51 @@ +{ + "name": "fabric-trade-admin", + "version": "0.0.0", + "private": true, + "type": "module", + "scripts": { + "dev": "vite", + "build": "run-p type-check \"build-only {@}\" --", + "preview": "vite preview", + "build-only": "vite build", + "type-check": "vue-tsc --build", + "lint": "run-s \"lint:*\"", + "lint:oxlint": "oxlint . --fix", + "lint:eslint": "eslint . --fix --cache", + "format": "prettier --write --experimental-cli src/" + }, + "dependencies": { + "@unocss/vite": "^66.7.5", + "@vueuse/core": "^14.4.0", + "lodash-es": "^4.18.1", + "pinia": "^4.0.2", + "unocss": "^66.7.5", + "vue": "^3.5.40", + "vue-router": "^5.2.0" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.4", + "@types/lodash-es": "^4.17.12", + "@types/node": "^24.13.3", + "@vitejs/plugin-vue": "^6.0.8", + "@vitejs/plugin-vue-jsx": "^5.1.6", + "@vue/eslint-config-typescript": "^14.9.0", + "@vue/tsconfig": "^0.9.1", + "eslint": "^10.7.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-oxlint": "~1.73.0", + "eslint-plugin-vue": "~10.9.2", + "jiti": "^2.7.0", + "npm-run-all2": "^9.0.2", + "oxlint": "~1.74.0", + "prettier": "3.9.5", + "typescript": "~6.0.0", + "vite": "^8.1.5", + "vite-plugin-vue-devtools": "^8.1.5", + "vue-eslint-parser": "^10.4.1", + "vue-tsc": "^3.3.7" + }, + "engines": { + "node": "^22.18.0 || >=24.12.0" + } +} diff --git a/public/.htaccess b/public/.htaccess new file mode 100644 index 0000000..ec82b63 --- /dev/null +++ b/public/.htaccess @@ -0,0 +1,18 @@ + + RewriteEngine On + RewriteBase /admin/ + + # Serve existing files and directories + RewriteCond %{REQUEST_FILENAME} -f [OR] + RewriteCond %{REQUEST_FILENAME} -d + RewriteRule ^ - [L] + + # SPA fallback + RewriteRule ^ index.html [L] + + + + AddType application/javascript .js + AddType text/css .css + AddType application/wasm .wasm + diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000..df36fcf Binary files /dev/null and b/public/favicon.ico differ diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..73bb1a9 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum).woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum).woff2 new file mode 100644 index 0000000..c3dcbab Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum).woff2 differ diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Black.woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Black.woff2 new file mode 100644 index 0000000..fc008ef Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Black.woff2 differ diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Bold.woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Bold.woff2 new file mode 100644 index 0000000..69f7c66 Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Bold.woff2 differ diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Light.woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Light.woff2 new file mode 100644 index 0000000..40f5b09 Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Light.woff2 differ diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Medium.woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Medium.woff2 new file mode 100644 index 0000000..8273b0a Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_Medium.woff2 differ diff --git a/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_UltraLight.woff2 b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_UltraLight.woff2 new file mode 100644 index 0000000..8b77d17 Binary files /dev/null and b/src/assets/fonts/iranSans/woff2/IRANSansWeb(FaNum)_UltraLight.woff2 differ diff --git a/src/assets/styles/admin.css b/src/assets/styles/admin.css new file mode 100644 index 0000000..53398bd --- /dev/null +++ b/src/assets/styles/admin.css @@ -0,0 +1,702 @@ +.admin-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); +} + +.admin-page-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 16px; + margin-bottom: 20px; +} + +.admin-page-header__title { + margin: 0; + font-size: 1.25rem; + font-weight: 700; + color: var(--color-text); +} + +.admin-table-wrap { + overflow-x: auto; +} + +.admin-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +.admin-table th { + padding: 11px 16px; + text-align: center; + font-weight: 600; + font-size: 0.8125rem; + color: var(--color-text-muted); + background: var(--color-bg); + border-bottom: 1px solid var(--color-border); + white-space: nowrap; +} + +.admin-table td { + padding: 13px 16px; + text-align: center; + border-bottom: 1px solid var(--color-border-light); + vertical-align: middle; + color: var(--color-text); +} + +.admin-table tbody tr { + transition: background var(--transition-fast); +} + +.admin-table tbody tr:hover { + background: var(--color-border-light); +} + +.admin-table tbody tr.is-selected { + background: var(--color-primary-soft); +} + +.admin-table .col-numeric, +.admin-table td.numeric, +.admin-table th.numeric { + text-align: center; + font-variant-numeric: tabular-nums; +} + +.admin-table .col-status, +.admin-table td.status, +.admin-table th.status { + text-align: center; +} + +.admin-table .col-actions, +.admin-table td.actions, +.admin-table th.actions { + text-align: center; + white-space: nowrap; +} + +.admin-table tbody tr:last-child td { + border-bottom: none; +} + +.admin-table--compact td, +.admin-table--compact th { + padding: 10px 12px; +} + +.admin-btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: 6px; + min-height: var(--control-height); + padding: 0 20px; + border-radius: var(--radius-sm); + font-size: 0.875rem; + font-weight: 600; + border: 1px solid transparent; + transition: background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast); + white-space: nowrap; +} + +.admin-btn:focus-visible { + outline: none; + box-shadow: var(--focus-ring); +} + +.admin-btn:active:not(:disabled) { + transform: translateY(1px); +} + +.admin-btn--primary { + background: var(--btn-primary-bg); + color: #fff; + border-color: var(--btn-primary-bg); +} + +.admin-btn--primary:hover:not(:disabled) { + background: var(--btn-primary-hover); +} + +.admin-btn--danger { + background: var(--color-danger); + color: #fff; + border-color: var(--color-danger); +} + +.admin-btn--danger:hover:not(:disabled) { + background: #c82333; +} + +.admin-btn--success { + background: var(--color-success); + color: #fff; +} + +.admin-btn--success:hover { + background: var(--color-success-dark); +} + +.admin-btn--outline { + background: var(--color-surface); + color: var(--color-text); + border-color: var(--color-border); +} + +.admin-btn--outline:hover { + background: var(--color-border-light); +} + +.admin-btn--outline-success { + background: var(--color-surface); + color: var(--color-success); + border-color: var(--color-success); +} + +.admin-btn--outline-danger { + background: var(--color-surface); + color: var(--color-danger); + border-color: var(--color-danger); +} + +.admin-btn--outline-warning { + background: var(--color-surface); + color: var(--color-warning-dark); + border-color: var(--color-warning); +} + +.admin-btn--ghost { + background: transparent; + color: var(--color-primary); + border-color: transparent; + padding: 6px 12px; +} + +.admin-btn--ghost:hover { + background: var(--color-info-light); +} + +.admin-btn--sm { + min-height: var(--control-height-sm); + padding: 0 14px; + font-size: 0.8125rem; +} + +.admin-btn--xs { + min-height: 28px; + padding: 0 10px; + font-size: 0.75rem; +} + +.admin-btn__spinner { + width: 14px; + height: 14px; + border: 2px solid rgba(255, 255, 255, 0.35); + border-top-color: #fff; + border-radius: 50%; + animation: admin-spin 0.7s linear infinite; +} + +.admin-btn--outline .admin-btn__spinner { + border-color: rgba(var(--color-primary-rgb), 0.2); + border-top-color: var(--color-primary); +} + +@keyframes admin-spin { + to { + transform: rotate(360deg); + } +} + +.admin-btn:disabled { + opacity: 0.55; + cursor: not-allowed; + transform: none; +} + +.admin-badge { + display: inline-flex; + align-items: center; + min-height: 24px; + padding: 2px 10px; + border-radius: 6px; + font-size: 0.75rem; + font-weight: 600; + white-space: nowrap; + border: 1px solid transparent; +} + +.admin-badge--warning { + background: var(--color-warning-light); + color: var(--color-warning-dark); +} + +.admin-badge--purple { + background: var(--color-purple-light); + color: var(--color-purple); +} + +.admin-badge--success { + background: var(--color-success-light); + color: var(--color-success-dark); +} + +.admin-badge--danger { + background: var(--color-danger-light); + color: var(--color-danger); +} + +.admin-badge--info { + background: var(--color-info-light); + color: var(--color-info); +} + +.admin-badge--neutral { + background: var(--color-border-light); + color: var(--color-text-muted); +} + +.admin-badge--delivered { + background: var(--color-success-light); + color: var(--color-success-dark); +} + +.admin-tabs { + display: flex; + flex-wrap: wrap; + gap: 0; + border-bottom: 1px solid var(--color-border); + overflow: visible; +} + +.admin-tab { + padding: 12px 16px; + font-size: 0.875rem; + font-weight: 500; + color: var(--color-text-muted); + background: none; + border: none; + border-bottom: 2px solid transparent; + margin-bottom: -1px; + white-space: nowrap; + flex-shrink: 0; + transition: color var(--transition-fast), border-color var(--transition-fast); +} + +.admin-tab:focus-visible { + outline: none; + box-shadow: inset 0 -2px 0 var(--color-primary); +} + +.admin-tab:hover { + color: var(--color-text); +} + +.admin-tab.active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); + font-weight: 600; +} + +.admin-input { + width: 100%; + padding: 10px 14px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + font-size: 0.875rem; + background: var(--color-surface); + color: var(--color-text); +} + +.admin-input[type='number'], +.admin-input[type='tel'], +.admin-input[inputmode='numeric'], +.admin-input[inputmode='decimal'], +.admin-input[inputmode='tel'], +.admin-input[dir='ltr'] { + text-align: right; +} + +select.admin-input { + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24'%3E%3Cpath stroke='%236b7280' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.75' d='m7 10 5 5 5-5'/%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: left 12px center; + padding-inline: 14px 36px; + cursor: pointer; +} + +html.dark select.admin-input { + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='none' viewBox='0 0 24 24'%3E%3Cpath stroke='%94a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.75' d='m7 10 5 5 5-5'/%3E%3C/svg%3E"); +} + +.admin-input:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: var(--focus-ring); +} + +.admin-input--sm { + padding: 6px 10px; + font-size: 0.8125rem; + max-width: 120px; +} + +.admin-stat-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: 20px; + display: flex; + flex-direction: column; + gap: 8px; +} + +.admin-stat-card__label { + font-size: 0.8125rem; + color: var(--color-text-muted); + margin: 0; +} + +.admin-stat-card__value { + font-size: 1.75rem; + font-weight: 700; + margin: 0; + line-height: 1.2; +} + +.admin-stat-card__icon { + width: 40px; + height: 40px; + border-radius: var(--radius-sm); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 4px; +} + +.admin-stat-card__link { + font-size: 0.75rem; + color: var(--color-primary); + margin-top: auto; +} + +.admin-link { + color: var(--color-primary); + font-size: 0.8125rem; + font-weight: 500; +} + +.admin-link:hover { + text-decoration: underline; +} + +.admin-pagination { + display: flex; + align-items: center; + justify-content: space-between; + padding: 16px; + border-top: 1px solid var(--color-border-light); + font-size: 0.8125rem; + color: var(--color-text-muted); +} + +.admin-pagination__pages { + display: flex; + gap: 4px; +} + +.admin-pagination__page { + min-width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: var(--radius-sm); + border: 1px solid var(--color-border); + background: var(--color-surface); + font-size: 0.8125rem; +} + +.admin-pagination__page.active { + background: var(--color-primary); + color: #fff; + border-color: var(--color-primary); +} + +.admin-summary-grid { + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: 12px; + margin-bottom: 20px; +} + +.admin-summary-item { + background: var(--color-border-light); + border-radius: var(--radius-sm); + padding: 12px 16px; +} + +.admin-summary-item__label { + font-size: 0.75rem; + color: var(--color-text-muted); + margin: 0 0 4px; +} + +.admin-summary-item__value { + font-size: 0.9375rem; + font-weight: 600; + margin: 0; +} + +.admin-info-grid { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 12px; +} + +.admin-info-row { + display: flex; + align-items: center; + gap: 8px; + font-size: 0.8125rem; +} + +.admin-info-row__label { + color: var(--color-text-muted); +} + +.admin-info-row__value { + font-weight: 500; +} + +.admin-logo-par { + width: 40px; + height: 40px; + border-radius: var(--radius-sm); + background: var(--color-primary); + color: #fff; + display: flex; + align-items: center; + justify-content: center; + font-weight: 900; + font-size: 1.125rem; +} + +.admin-logo-fam { + width: 40px; + height: 40px; + border-radius: var(--radius-sm); + background: #f5f0e8; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + font-size: 0.5rem; + font-weight: 700; + color: var(--color-primary); + line-height: 1.2; +} + +.admin-logo-fam span:first-child { + font-size: 0.625rem; +} + +.admin-action-group { + display: flex; + gap: 8px; +} + +.admin-section-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: 20px; + margin-bottom: 16px; +} + +.admin-section-card__title { + margin: 0 0 16px; + font-size: 0.9375rem; + font-weight: 700; +} + +.admin-form-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 16px; + margin-top: 20px; +} + +.admin-form-field label { + display: block; + font-size: 0.8125rem; + color: var(--color-text-muted); + margin-bottom: 6px; +} + +.admin-form-field textarea { + width: 100%; + min-height: 80px; + padding: 10px 14px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + font-size: 0.875rem; + resize: vertical; +} + +.admin-footer-actions { + display: flex; + gap: 12px; + margin-top: 24px; + padding-top: 20px; + border-top: 1px solid var(--color-border-light); +} + +.admin-empty-placeholder { + padding: 48px 24px; + text-align: center; + color: var(--color-text-muted); + font-size: 0.9375rem; +} + +.admin-form { + display: flex; + flex-direction: column; + gap: 16px; +} + +.admin-form__error { + margin: 0; + padding: 10px 12px; + border-radius: var(--radius-sm); + background: var(--color-danger-light); + color: var(--color-danger); + font-size: 0.8125rem; +} + +.admin-form__field { + display: flex; + flex-direction: column; + gap: 6px; +} + +.admin-form__field label { + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-text); +} + +.admin-form__required { + color: var(--color-danger); +} + +.admin-form__textarea { + width: 100%; + padding: 10px 14px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + font-size: 0.875rem; + resize: vertical; + min-height: 80px; + font-family: inherit; +} + +.admin-form__textarea:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: var(--focus-ring); +} + +.admin-skeleton { + background: linear-gradient( + 90deg, + var(--color-border-light) 25%, + var(--color-border) 50%, + var(--color-border-light) 75% + ); + background-size: 200% 100%; + animation: admin-skeleton 1.2s ease-in-out infinite; + border-radius: var(--radius-sm); +} + +@keyframes admin-skeleton { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +@media (prefers-reduced-motion: reduce) { + .admin-skeleton { + animation: none; + } + + .admin-btn__spinner { + animation: none; + } +} + +.admin-form__row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; +} + +@media print { + @page { + margin: 12mm; + } + + html.printing-order-detail body > *:not(.admin-modal-backdrop) { + display: none !important; + } + + html.printing-order-detail .admin-modal-backdrop { + position: static !important; + inset: auto !important; + z-index: auto !important; + display: block !important; + padding: 0 !important; + background: transparent !important; + } + + html.printing-order-detail .admin-modal { + width: 100% !important; + max-height: none !important; + overflow: visible !important; + border-radius: 0 !important; + box-shadow: none !important; + background: #fff !important; + color: #111 !important; + } + + html.printing-order-detail .admin-modal__header { + border-bottom-color: #ddd !important; + padding: 0 0 12px !important; + } + + html.printing-order-detail .admin-modal__close, + html.printing-order-detail .admin-modal__footer, + html.printing-order-detail .no-print { + display: none !important; + } + + html.printing-order-detail .admin-modal__body { + overflow: visible !important; + max-height: none !important; + padding: 0 !important; + } + + html.printing-order-detail .admin-modal__title { + color: #111 !important; + } +} diff --git a/src/assets/styles/fonts.css b/src/assets/styles/fonts.css new file mode 100644 index 0000000..7493471 --- /dev/null +++ b/src/assets/styles/fonts.css @@ -0,0 +1,39 @@ +@font-face { + font-family: 'IRANSans'; + src: url('../fonts/iranSans/woff2/IRANSansWeb(FaNum).woff2') format('woff2'); + font-weight: 400; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'IRANSans'; + src: url('../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Light.woff2') format('woff2'); + font-weight: 300; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'IRANSans'; + src: url('../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Medium.woff2') format('woff2'); + font-weight: 500; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'IRANSans'; + src: url('../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Bold.woff2') format('woff2'); + font-weight: 700; + font-style: normal; + font-display: swap; +} + +@font-face { + font-family: 'IRANSans'; + src: url('../fonts/iranSans/woff2/IRANSansWeb(FaNum)_Black.woff2') format('woff2'); + font-weight: 900; + font-style: normal; + font-display: swap; +} diff --git a/src/assets/styles/main.css b/src/assets/styles/main.css new file mode 100644 index 0000000..29c59c3 --- /dev/null +++ b/src/assets/styles/main.css @@ -0,0 +1,195 @@ +@import './fonts.css'; + +:root { + /* Brand — هم‌تراز اپ کاربر (mockups / main.css) */ + --color-primary: #0a353c; + --color-primary-hover: #072a2f; + --color-primary-soft: #e8f4f1; + --color-primary-dark: #062428; + --color-primary-light: #e8f4f1; + --color-primary-rgb: 10, 53, 60; + --color-accent-navy: #1b223c; + --color-sidebar-bg: #0a353c; + --color-sidebar-active: #0e454e; + --color-sidebar-hover: #0e454e; + --color-success: #1b8a5a; + --color-success-light: #eaf8f1; + --color-success-dark: #0d7a4d; + --color-success-soft: #eaf8f1; + --color-warning: #e8a317; + --color-warning-light: #fff6e5; + --color-warning-dark: #d97706; + --color-danger: #dc3545; + --color-danger-light: #fee2e2; + --color-purple: #7c3aed; + --color-purple-light: #ede9fe; + --color-info: #3b6fa0; + --color-info-light: #eef3f7; + --color-bg: #f6f8f7; + --color-surface: #ffffff; + --color-elevated: #ffffff; + --color-border: #e5e9e8; + --color-border-light: #eef1f0; + --color-text: #121212; + --color-text-muted: #6b7280; + --color-text-secondary: #6b7280; + --admin-primary: var(--color-primary); + --admin-muted: var(--color-text-muted); + --admin-surface: var(--color-surface); + --admin-border: var(--color-border); + --admin-soft: var(--color-primary-soft); + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 16px; + --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.04); + --shadow-card: 0 1px 3px rgba(16, 24, 40, 0.06), 0 4px 16px rgba(16, 24, 40, 0.04); + --sidebar-width: 240px; + --header-height: 72px; + --font-family: 'IRANSans', 'Tahoma', sans-serif; + --btn-primary-bg: #0a353c; + --btn-primary-hover: #072a2f; + --admin-desktop-min: 1280px; + --control-height: 40px; + --control-height-sm: 32px; + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --transition-fast: 0.15s ease; + --transition-base: 0.18s ease; + --focus-ring: 0 0 0 3px rgba(10, 53, 60, 0.18); +} + +html.dark { + --color-primary: #5eb8ad; + --color-primary-hover: #7ad0c5; + --color-primary-soft: #14353a; + --color-primary-dark: #7ad0c5; + --color-primary-light: #14353a; + --color-primary-rgb: 94, 184, 173; + --color-accent-navy: #9bb0d0; + --color-sidebar-bg: #0b0f14; + --color-sidebar-active: #14353a; + --color-sidebar-hover: #121821; + --color-success: #3dd68c; + --color-success-light: #123528; + --color-success-dark: #6ee7b7; + --color-success-soft: #123528; + --color-warning: #f5c14a; + --color-warning-light: #3a2f14; + --color-warning-dark: #fcd34d; + --color-danger: #f47979; + --color-danger-light: #3f1d22; + --color-purple: #b39afa; + --color-purple-light: #2a2144; + --color-info: #7b9cff; + --color-info-light: #1b2740; + --color-bg: #0b0f14; + --color-surface: #121821; + --color-elevated: #1a2230; + --color-border: #2a3444; + --color-border-light: #1a2230; + --color-text: #eef2f8; + --color-text-muted: #9aa8bc; + --color-text-secondary: #9aa8bc; + --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.35); + --shadow-card: 0 1px 3px rgba(0, 0, 0, 0.4), 0 4px 16px rgba(0, 0, 0, 0.35); + --btn-primary-bg: #5eb8ad; + --btn-primary-hover: #7ad0c5; + --focus-ring: 0 0 0 3px rgba(94, 184, 173, 0.28); +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-size: 16px; + -webkit-text-size-adjust: 100%; + height: 100%; +} + +body { + margin: 0; + font-family: var(--font-family); + background: var(--color-bg); + color: var(--color-text); + line-height: 1.5; + direction: rtl; + height: 100%; +} + +#app { + height: 100dvh; +} + +/* Hide scrollbars across the admin panel (scroll still works) */ +html, +body, +#app, +#app *, +.admin-modal-backdrop, +.admin-modal-backdrop * { + scrollbar-width: none; + -ms-overflow-style: none; +} + +html::-webkit-scrollbar, +body::-webkit-scrollbar, +#app::-webkit-scrollbar, +#app *::-webkit-scrollbar, +.admin-modal-backdrop::-webkit-scrollbar, +.admin-modal-backdrop *::-webkit-scrollbar { + display: none; + width: 0; + height: 0; + background: transparent; +} + +a { + color: inherit; + text-decoration: none; +} + +button { + font-family: inherit; + cursor: pointer; +} + +button:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +@media (prefers-reduced-motion: reduce) { + *, + *::before, + *::after { + animation-duration: 0.01ms !important; + animation-iteration-count: 1 !important; + transition-duration: 0.01ms !important; + scroll-behavior: auto !important; + } +} + +input, +textarea, +select { + font-family: inherit; +} + +.sr-only { + position: absolute; + width: 1px; + height: 1px; + padding: 0; + margin: -1px; + overflow: hidden; + clip: rect(0, 0, 0, 0); + white-space: nowrap; + border: 0; +} diff --git a/src/assets/styles/responsive.css b/src/assets/styles/responsive.css new file mode 100644 index 0000000..31c86f1 --- /dev/null +++ b/src/assets/styles/responsive.css @@ -0,0 +1,414 @@ +/* Admin responsive breakpoints: + xs (small mobile): below 480px + sm (mobile): 480px – 767px + md (tablet): 768px – 1023px + lg (small desktop): 1024px – 1279px + xl (desktop): 1280px – 1439px + 2xl (large desktop): 1440px+ +*/ + +:root { + --page-padding-mobile: 16px; + --page-padding-tablet: 20px; + --page-padding-desktop: 28px; + --page-padding: var(--page-padding-mobile); + --mobile-nav-height: 0px; + --drawer-width: min(300px, 88vw); + --admin-desktop-min: 1280px; +} + +@media (min-width: 768px) { + :root { + --page-padding: var(--page-padding-tablet); + } +} + +@media (min-width: 1280px) { + :root { + --page-padding: var(--page-padding-desktop); + } +} + +/* Visibility utilities — desktop layout is source of truth at >= 1280px */ +.desktop-only { + display: none !important; +} + +.compact-only { + display: block; +} + +@media (min-width: 1280px) { + .desktop-only { + display: revert !important; + } + + .desktop-only.admin-shell__sidebar, + .desktop-only.admin-sidebar { + display: flex !important; + } + + .desktop-only.orders-page, + .desktop-only.dashboard { + display: block !important; + } + + .compact-only { + display: none !important; + } +} + +/* Mobile drawer overlay */ +.admin-drawer-backdrop { + position: fixed; + inset: 0; + z-index: 900; + background: rgba(15, 23, 42, 0.45); + opacity: 0; + visibility: hidden; + transition: opacity 0.2s, visibility 0.2s; +} + +.admin-drawer-backdrop.open { + opacity: 1; + visibility: visible; +} + +.admin-drawer { + position: fixed; + top: 0; + right: 0; + z-index: 901; + width: var(--drawer-width); + height: 100dvh; + background: var(--color-sidebar-bg); + color: #fff; + transform: translateX(100%); + transition: transform 0.25s ease; + display: flex; + flex-direction: column; + overflow: hidden; +} + +.admin-drawer.open { + transform: translateX(0); +} + +/* Compact card list pattern */ +.admin-card-list { + display: flex; + flex-direction: column; + gap: 10px; +} + +.admin-card-item { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + padding: 14px 16px; + text-align: right; + width: 100%; + transition: border-color 0.15s, background 0.15s; +} + +.admin-card-item:hover { + border-color: #cbd5e1; +} + +.admin-card-item.selected { + border-color: var(--color-primary); + background: var(--color-info-light); +} + +.admin-card-item__header { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 8px; +} + +.admin-card-item__header-actions { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; +} + +.admin-card-item__title { + margin: 0; + font-size: 0.875rem; + font-weight: 700; +} + +.admin-card-item__meta { + display: flex; + flex-wrap: wrap; + gap: 8px 16px; + font-size: 0.8125rem; + color: var(--color-text-muted); +} + +.admin-card-item__meta span strong { + color: var(--color-text); + font-weight: 600; +} + +.admin-card-item__actions { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 12px; + padding-top: 12px; + border-top: 1px solid var(--color-border-light); +} + +/* Full-screen detail panel (mobile) */ +.admin-detail-panel { + position: fixed; + inset: 0; + z-index: 850; + background: var(--color-bg); + display: flex; + flex-direction: column; + transform: translateX(100%); + transition: transform 0.25s ease; +} + +.admin-detail-panel.open { + transform: translateX(0); +} + +.admin-detail-panel__header { + flex-shrink: 0; + display: grid; + grid-template-columns: 40px 1fr 40px; + align-items: center; + gap: 12px; + padding: 12px var(--page-padding); + background: var(--color-surface); + border-bottom: 1px solid var(--color-border); +} + +.admin-detail-panel__back { + width: 40px; + height: 40px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: var(--color-surface); + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text); + flex-shrink: 0; + grid-column: 1; + transition: + background var(--transition-fast), + border-color var(--transition-fast); +} + +.admin-detail-panel__back:hover { + background: var(--color-border-light); + border-color: var(--color-border); +} + +.admin-detail-panel__title { + margin: 0; + font-size: 1rem; + font-weight: 700; + text-align: center; + grid-column: 2; +} + +.admin-detail-panel__body { + flex: 1; + overflow-y: auto; + padding: var(--page-padding); +} + +/* Compact page header */ +.compact-page-header { + display: flex; + flex-direction: column; + gap: 12px; + margin-bottom: 16px; +} + +.compact-page-header__row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 12px; +} + +.compact-page-header__title { + margin: 0; + font-size: 1.125rem; + font-weight: 700; +} + +.compact-page-header__actions { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +@media (min-width: 768px) { + .compact-page-header__row { + align-items: center; + } + + .compact-page-header__actions { + flex-shrink: 0; + } +} + +/* Stat grid for compact dashboard — 4 KPI cards in one row on tablet+ */ +.compact-stats-grid { + display: grid; + grid-template-columns: 1fr; + gap: 12px; + margin-bottom: 16px; +} + +@media (min-width: 480px) { + .compact-stats-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (min-width: 768px) { + .compact-stats-grid { + grid-template-columns: repeat(4, 1fr); + } +} + +.compact-section-grid { + display: flex; + flex-direction: column; + gap: 16px; +} + +.compact-section-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: 16px; + box-shadow: var(--shadow-sm); +} + +.compact-section-card__title { + margin: 0 0 12px; + font-size: 0.9375rem; + font-weight: 700; +} + +/* Tablet / compact desktop: keep multi-column layouts usable in modals */ +@media (max-width: 1279px) { + .admin-shell__content { + padding: var(--page-padding); + } + + .admin-summary-grid { + grid-template-columns: repeat(2, 1fr); + } + + .admin-form-grid { + grid-template-columns: repeat(2, 1fr); + } + + .admin-info-grid { + grid-template-columns: repeat(2, 1fr); + } + + .admin-pagination { + flex-direction: column; + gap: 12px; + align-items: stretch; + } + + .admin-pagination__pages { + justify-content: center; + flex-wrap: wrap; + } + + .admin-tab { + padding: 10px 12px; + font-size: 0.8125rem; + } + + .admin-page-header .admin-action-group { + flex-wrap: wrap; + gap: 8px; + } +} + +/* Phone only: stack to single column / action sheet */ +@media (max-width: 767px) { + :root { + --header-height: 60px; + } + + .admin-page-header { + flex-direction: column; + align-items: stretch; + } + + .admin-page-header .admin-btn, + .admin-page-header .admin-action-group { + width: 100%; + } + + .admin-page-header .admin-action-group .admin-btn { + flex: 1; + min-width: fit-content; + } + + .admin-summary-grid, + .admin-form-grid, + .admin-info-grid { + grid-template-columns: 1fr; + } + + .admin-footer-actions { + flex-direction: column; + } + + .admin-footer-actions .admin-btn { + width: 100%; + } + + .admin-form__row { + grid-template-columns: 1fr; + } + + .admin-tab { + padding: 8px 10px; + font-size: 0.75rem; + } + + .admin-modal-backdrop { + padding: 0; + align-items: flex-end; + } + + .admin-modal { + max-width: 100%; + max-height: 92dvh; + border-radius: var(--radius-lg) var(--radius-lg) 0 0; + } + + .checks-page__footer { + flex-direction: column; + align-items: stretch; + } + + .checks-page__footer .admin-action-group { + flex-direction: column; + width: 100%; + } + + .checks-page__footer .admin-action-group .admin-btn { + width: 100%; + } +} diff --git a/src/components/BasicPacks/BasicIcon.vue b/src/components/BasicPacks/BasicIcon.vue new file mode 100644 index 0000000..88cf004 --- /dev/null +++ b/src/components/BasicPacks/BasicIcon.vue @@ -0,0 +1,77 @@ + + + + + diff --git a/src/components/BasicPacks/tools/icons/icons.json b/src/components/BasicPacks/tools/icons/icons.json new file mode 100644 index 0000000..40c5978 --- /dev/null +++ b/src/components/BasicPacks/tools/icons/icons.json @@ -0,0 +1,67 @@ +{ + "vuesax-linear:add": "\n\n\n\n", + "vuesax-linear:arrow-down": "\n\n\n", + "vuesax-linear:arrow-left-1": "\n\n\n", + "vuesax-linear:arrow-right-1": "\n\n\n", + "vuesax-linear:bag-2": "\n\n\n\n\n\n", + "vuesax-linear:bag-cross": "\n\n\n\n\n\n\n\n", + "vuesax-linear:box-1": "\n\n\n\n\n", + "vuesax-linear:box-remove": "\n\n\n\n\n\n\n\n", + "vuesax-linear:box-search": "\n\n\n\n\n\n\n", + "vuesax-linear:building": "\n\n\n\n\n\n\n\n", + "vuesax-linear:buildings": "\n\n\n\n\n\n\n\n\n", + "vuesax-linear:calendar": "\n\n\n\n\n\n\n\n\n\n\n\n", + "vuesax-linear:call": "\n\n\n", + "vuesax-linear:card": "\n\n\n\n\n\n", + "vuesax-linear:card-receive": "\n\n\n\n\n\n\n\n", + "vuesax-linear:category": "\n\n\n\n\n\n", + "vuesax-linear:chart-2": "\n\n\n\n\n", + "vuesax-linear:clipboard-close": "\n\n\n\n\n\n", + "vuesax-linear:clock": "\n\n\n\n\n\n", + "vuesax-linear:close-circle": "\n\n\n\n\n", + "vuesax-linear:cpu": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n", + "vuesax-linear:diamonds": "\n\n\n\n", + "vuesax-linear:document-text": "\n\n\n\n\n\n", + "vuesax-linear:edit-2": "\n\n\n\n\n", + "vuesax-linear:element-3": "\n\n\n\n\n\n", + "vuesax-linear:eye": "\n\n\n\n", + "vuesax-linear:eye-slash": "\n\n\n\n\n\n\n\n", + "vuesax-linear:filter": "\n\n\n\n", + "vuesax-linear:flash": "\n\n\n\n\n\n", + "vuesax-linear:headphone": "\n\n\n", + "vuesax-linear:home": "\n\n\n\n", + "vuesax-linear:info-circle": "\n\n\n\n\n", + "vuesax-linear:lamp-on": "\n\n\n\n", + "vuesax-linear:location": "\n\n\n\n", + "vuesax-linear:lock": "\n\n\n\n\n\n\n", + "vuesax-linear:logout": "\n\n\n\n\n", + "vuesax-linear:menu": "\n\n\n\n\n", + "vuesax-linear:message": "\n\n\n\n\n\n", + "vuesax-linear:mobile": "\n\n\n\n\n", + "vuesax-linear:money-4": "\n\n\n\n\n\n\n\n", + "vuesax-linear:monitor": "\n\n\n\n\n\n", + "vuesax-linear:moon": "\n\n\n", + "vuesax-linear:more": "\n\n\n\n\n", + "vuesax-linear:note-remove": "\n\n\n\n\n\n\n\n\n", + "vuesax-linear:notification": "\n\n\n\n\n", + "vuesax-linear:pen-add": "\n\n\n\n\n\n\n\n\n", + "vuesax-linear:people": "\n\n\n\n\n\n\n\n", + "vuesax-linear:personalcard": "\n\n\n\n\n\n\n\n", + "vuesax-linear:printer": "\n\n\n\n\n\n\n", + "vuesax-linear:profile-2user": "\n\n\n\n\n\n", + "vuesax-linear:profile-circle": "\n\n\n\n\n", + "vuesax-linear:receipt-search": "\n\n\n\n\n\n\n", + "vuesax-linear:search-normal": "\n\n\n\n", + "vuesax-linear:search-status": "\n\n\n\n\n\n", + "vuesax-linear:setting-2": "\n\n\n\n", + "vuesax-linear:shopping-bag": "\n\n\n\n\n", + "vuesax-linear:sms": "\n\n\n\n", + "vuesax-linear:sun-1": "\n\n\n\n", + "vuesax-linear:tick-circle": "\n\n\n\n", + "vuesax-linear:timer-1": "\n\n\n\n\n", + "vuesax-linear:trash": "\n\n\n\n\n\n\n", + "vuesax-linear:truck-time": "\n\n\n\n\n\n\n\n\n", + "vuesax-linear:verify": "\n\n\n\n", + "vuesax-linear:wallet": "\n\n\n\n\n", + "vuesax-linear:warning-2": "\n\n\n\n\n" +} diff --git a/src/components/charts/SalesAreaChart.vue b/src/components/charts/SalesAreaChart.vue new file mode 100644 index 0000000..d9ca9b3 --- /dev/null +++ b/src/components/charts/SalesAreaChart.vue @@ -0,0 +1,228 @@ + + + + + diff --git a/src/components/icons/AdminIcon.vue b/src/components/icons/AdminIcon.vue new file mode 100644 index 0000000..28e4826 --- /dev/null +++ b/src/components/icons/AdminIcon.vue @@ -0,0 +1,77 @@ + + + diff --git a/src/components/layout/AdminHeader.vue b/src/components/layout/AdminHeader.vue new file mode 100644 index 0000000..52a23e8 --- /dev/null +++ b/src/components/layout/AdminHeader.vue @@ -0,0 +1,729 @@ + + + + + diff --git a/src/components/layout/AdminMobileDrawer.vue b/src/components/layout/AdminMobileDrawer.vue new file mode 100644 index 0000000..1fdb7fb --- /dev/null +++ b/src/components/layout/AdminMobileDrawer.vue @@ -0,0 +1,154 @@ + + + + + diff --git a/src/components/layout/AdminSidebar.vue b/src/components/layout/AdminSidebar.vue new file mode 100644 index 0000000..d769d3d --- /dev/null +++ b/src/components/layout/AdminSidebar.vue @@ -0,0 +1,139 @@ + + + + + diff --git a/src/components/ui/ActiveSwitchCell.vue b/src/components/ui/ActiveSwitchCell.vue new file mode 100644 index 0000000..171cf5e --- /dev/null +++ b/src/components/ui/ActiveSwitchCell.vue @@ -0,0 +1,57 @@ + + + diff --git a/src/components/ui/AdminCurrencyInput.vue b/src/components/ui/AdminCurrencyInput.vue new file mode 100644 index 0000000..37569a3 --- /dev/null +++ b/src/components/ui/AdminCurrencyInput.vue @@ -0,0 +1,65 @@ + + + + + diff --git a/src/components/ui/AdminImagePicker.vue b/src/components/ui/AdminImagePicker.vue new file mode 100644 index 0000000..490cc29 --- /dev/null +++ b/src/components/ui/AdminImagePicker.vue @@ -0,0 +1,127 @@ + + + + + diff --git a/src/components/ui/AdminPageSkeleton.vue b/src/components/ui/AdminPageSkeleton.vue new file mode 100644 index 0000000..df037a3 --- /dev/null +++ b/src/components/ui/AdminPageSkeleton.vue @@ -0,0 +1,129 @@ + + + + + diff --git a/src/components/ui/AdminSelect.vue b/src/components/ui/AdminSelect.vue new file mode 100644 index 0000000..5a0b446 --- /dev/null +++ b/src/components/ui/AdminSelect.vue @@ -0,0 +1,357 @@ + + + + + diff --git a/src/components/ui/BaseEmptyState.vue b/src/components/ui/BaseEmptyState.vue new file mode 100644 index 0000000..2fdef95 --- /dev/null +++ b/src/components/ui/BaseEmptyState.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/components/ui/BaseModal.vue b/src/components/ui/BaseModal.vue new file mode 100644 index 0000000..f9f03a0 --- /dev/null +++ b/src/components/ui/BaseModal.vue @@ -0,0 +1,180 @@ + + + + + diff --git a/src/components/ui/BaseSwitch.vue b/src/components/ui/BaseSwitch.vue new file mode 100644 index 0000000..a665aef --- /dev/null +++ b/src/components/ui/BaseSwitch.vue @@ -0,0 +1,164 @@ + + + + + diff --git a/src/components/ui/ConfirmDialog.vue b/src/components/ui/ConfirmDialog.vue new file mode 100644 index 0000000..57d644c --- /dev/null +++ b/src/components/ui/ConfirmDialog.vue @@ -0,0 +1,45 @@ + + + + + diff --git a/src/components/ui/StatusBadge.vue b/src/components/ui/StatusBadge.vue new file mode 100644 index 0000000..dc98966 --- /dev/null +++ b/src/components/ui/StatusBadge.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/src/components/ui/ToastContainer.vue b/src/components/ui/ToastContainer.vue new file mode 100644 index 0000000..dc76283 --- /dev/null +++ b/src/components/ui/ToastContainer.vue @@ -0,0 +1,171 @@ + + + + + diff --git a/src/composables/useAsyncToggle.ts b/src/composables/useAsyncToggle.ts new file mode 100644 index 0000000..71e2c20 --- /dev/null +++ b/src/composables/useAsyncToggle.ts @@ -0,0 +1,56 @@ +import { ref } from 'vue' +import { useToast } from '@/composables/useToast' + +export function mockPersistToggle(delayMs = 480): Promise { + return new Promise((resolve) => { + window.setTimeout(resolve, delayMs) + }) +} + +export function useAsyncToggle(options: { + onPersist: (value: boolean) => Promise + successMessage?: (value: boolean) => string + errorMessage?: string + confirmOff?: () => Promise +}) { + const loadingId = ref(null) + const errorId = ref(null) + const toast = useToast() + + async function toggle(id: string, current: boolean): Promise { + if (loadingId.value) return current + + const next = !current + + if (!next && options.confirmOff) { + const confirmed = await options.confirmOff() + if (!confirmed) return current + } + + loadingId.value = id + errorId.value = null + const previous = current + + try { + await options.onPersist(next) + toast.success(options.successMessage?.(next) ?? (next ? 'وضعیت فعال شد.' : 'وضعیت غیرفعال شد.')) + return next + } catch { + errorId.value = id + toast.error(options.errorMessage ?? 'به‌روزرسانی وضعیت انجام نشد.') + return previous + } finally { + loadingId.value = null + } + } + + function isLoading(id: string) { + return loadingId.value === id + } + + function hasError(id: string) { + return errorId.value === id + } + + return { toggle, isLoading, hasError } +} diff --git a/src/composables/useBreakpoint.ts b/src/composables/useBreakpoint.ts new file mode 100644 index 0000000..0be46fa --- /dev/null +++ b/src/composables/useBreakpoint.ts @@ -0,0 +1,42 @@ +import { computed } from 'vue' +import { useWindowSize } from '@vueuse/core' + +export type BreakpointName = 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl' + +const BREAKPOINTS = { + xs: 0, + sm: 480, + md: 768, + lg: 1024, + xl: 1280, + '2xl': 1440, +} as const + +function getBreakpoint(width: number): BreakpointName { + if (width >= BREAKPOINTS['2xl']) return '2xl' + if (width >= BREAKPOINTS.xl) return 'xl' + if (width >= BREAKPOINTS.lg) return 'lg' + if (width >= BREAKPOINTS.md) return 'md' + if (width >= BREAKPOINTS.sm) return 'sm' + return 'xs' +} + +export function useBreakpoint() { + const { width } = useWindowSize() + const breakpoint = computed(() => getBreakpoint(width.value)) + + const isDesktop = () => breakpoint.value === 'xl' || breakpoint.value === '2xl' + const isTablet = () => breakpoint.value === 'md' || breakpoint.value === 'lg' + const isMobile = () => breakpoint.value === 'xs' || breakpoint.value === 'sm' + const isCompact = () => !isDesktop() + + return { + width, + breakpoint, + isDesktop, + isTablet, + isMobile, + isCompact, + BREAKPOINTS, + } +} diff --git a/src/composables/useConfirm.ts b/src/composables/useConfirm.ts new file mode 100644 index 0000000..a9ea294 --- /dev/null +++ b/src/composables/useConfirm.ts @@ -0,0 +1,56 @@ +import { reactive } from 'vue' + +export interface ConfirmOptions { + title: string + message: string + confirmLabel?: string + cancelLabel?: string + tone?: 'danger' | 'primary' +} + +interface ConfirmState extends ConfirmOptions { + open: boolean + loading: boolean + resolve: ((value: boolean) => void) | null +} + +const state = reactive({ + open: false, + loading: false, + title: '', + message: '', + confirmLabel: 'تأیید', + cancelLabel: 'انصراف', + tone: 'primary', + resolve: null, +}) + +export function useConfirmState() { + return state +} + +export function confirm(options: ConfirmOptions): Promise { + return new Promise((resolve) => { + Object.assign(state, { + open: true, + loading: false, + title: options.title, + message: options.message, + confirmLabel: options.confirmLabel ?? 'تأیید', + cancelLabel: options.cancelLabel ?? 'انصراف', + tone: options.tone ?? 'primary', + resolve, + }) + }) +} + +export function resolveConfirm(value: boolean) { + state.resolve?.(value) + state.open = false + state.loading = false + state.resolve = null +} + +export function setConfirmLoading(loading: boolean) { + state.loading = loading +} diff --git a/src/composables/useDashboard.ts b/src/composables/useDashboard.ts new file mode 100644 index 0000000..173611f --- /dev/null +++ b/src/composables/useDashboard.ts @@ -0,0 +1,130 @@ +import { computed, onMounted, ref } from 'vue' +import { useRouter } from 'vue-router' +import { dashboardApi, mapAdminOrder, type DashboardStats } from '@/services/api' +import { ApiError } from '@/services/http' +import { useToast } from '@/composables/useToast' +import type { CheckDeadline, Order } from '@/types' + +export const iconBg: Record = { + info: 'var(--color-info-light)', + warning: 'var(--color-warning-light)', + purple: 'var(--color-purple-light)', + success: 'var(--color-success-light)', +} + +export const iconColor: Record = { + info: 'var(--color-info)', + warning: 'var(--color-warning-dark)', + purple: 'var(--color-purple)', + success: 'var(--color-success)', +} + +const emptyStats = (): DashboardStats => ({ + newOrders: 0, + pendingReview: 0, + pendingCheck: 0, + finalApproval: 0, + todaySales: 0, + todaySalesGrowth: 0, + monthSales: 0, +}) + +export function useDashboard() { + const router = useRouter() + const toast = useToast() + + const dashboardStats = ref(emptyStats()) + const recentOrders = ref([]) + const salesChartData = ref(Array.from({ length: 28 }, () => 0)) + const chartAxisLabels = ref(['۱', '۷', '۱۴', '۲۱', '۲۸']) + const checkDeadlines = ref([]) + const loading = ref(false) + + const statCards = computed(() => [ + { + label: 'سفارش‌های جدید', + value: dashboardStats.value.newOrders, + icon: 'cart', + tone: 'info', + link: '/orders', + }, + { + label: 'در انتظار بررسی', + value: dashboardStats.value.pendingReview, + icon: 'file', + tone: 'warning', + link: '/orders?tab=pending_review', + }, + { + label: 'بررسی چک', + value: dashboardStats.value.pendingCheck, + icon: 'wallet', + tone: 'purple', + link: '/orders?tab=pending_check', + }, + { + label: 'تأیید نهایی شده', + value: dashboardStats.value.finalApproval, + icon: 'check-circle', + tone: 'success', + link: '/orders?tab=final_approval', + }, + ] as const) + + const chartPoints = computed(() => { + const w = 280 + const h = 120 + const data = salesChartData.value + if (!data.length) return '' + const max = Math.max(...data, 0.001) + const step = data.length > 1 ? w / (data.length - 1) : w + return data + .map((v, i) => { + const x = i * step + const y = h - (v / max) * (h - 10) - 5 + return `${x},${y}` + }) + .join(' ') + }) + + async function loadDashboard() { + loading.value = true + try { + const data = await dashboardApi.get() + dashboardStats.value = data.stats + recentOrders.value = (data.recentOrders ?? []).map((o) => mapAdminOrder(o) as Order) + salesChartData.value = data.salesChartData?.length + ? data.salesChartData + : Array.from({ length: 28 }, () => 0) + chartAxisLabels.value = data.chartAxisLabels?.length + ? data.chartAxisLabels + : ['۱', '۷', '۱۴', '۲۱', '۲۸'] + checkDeadlines.value = data.checkDeadlines ?? [] + } catch (err) { + toast.error(err instanceof ApiError ? err.message : 'بارگذاری داشبورد انجام نشد.') + } finally { + loading.value = false + } + } + + onMounted(() => { + void loadDashboard() + }) + + function goOrders() { + router.push('/orders') + } + + return { + checkDeadlines, + dashboardStats, + recentOrders, + chartPoints, + salesChartData, + chartAxisLabels, + statCards, + loading, + goOrders, + loadDashboard, + } +} diff --git a/src/composables/useOrdersPage.ts b/src/composables/useOrdersPage.ts new file mode 100644 index 0000000..a642443 --- /dev/null +++ b/src/composables/useOrdersPage.ts @@ -0,0 +1,301 @@ +import { computed, inject, onMounted, provide, reactive, ref, watch, type InjectionKey } from 'vue' +import { useRoute, useRouter } from 'vue-router' +import { companiesApi, customersApi, mapAdminOrder, ordersApi } from '@/services/api' +import { ApiError } from '@/services/http' +import type { Company, Customer, Order, RawOrderStatus, SettlementMethod } from '@/types' +import { rawStatusLabel } from '@/utils/orderStatus' + +import { useToast } from '@/composables/useToast' + +export function useOrdersPage() { + const route = useRoute() + const router = useRouter() + const toast = useToast() + + const companies = ref([]) + const customers = ref([]) + const orderList = ref([]) + const activeTab = ref('all') + const selectedOrderId = ref('') + const searchQuery = ref('') + const showAddModal = ref(false) + const showDetailPanel = ref(false) + const showDetailModal = ref(false) + const formError = ref('') + const saving = ref(false) + + const emptyForm = () => ({ + customerId: '', + customerName: '', + companyId: companies.value[0]?.id ?? '', + settlementMethod: 'check' as SettlementMethod, + meterage: 1000, + customerPhone: '', + }) + + const form = reactive(emptyForm()) + + const isFormValid = computed( + () => form.customerId.length > 0 && form.companyId.length > 0, + ) + + const activeCustomers = computed(() => { + const list = [...customers.value] + list.sort((a, b) => Number(b.isActive) - Number(a.isActive) || a.name.localeCompare(b.name, 'fa')) + return list + }) + + function applyCustomer(customerId: string) { + const customer = customers.value.find((c) => c.id === customerId) + form.customerId = customerId + form.customerName = customer?.name ?? '' + form.customerPhone = customer?.phone ?? '' + } + + async function loadCustomers() { + try { + customers.value = await customersApi.list() + } catch (err) { + toast.error(err instanceof ApiError ? err.message : 'بارگذاری مشتریان انجام نشد.') + } + } + + const filteredOrders = computed(() => { + let list = orderList.value + if (activeTab.value !== 'all') { + list = list.filter((o) => o.status === activeTab.value) + } + if (searchQuery.value.trim()) { + const q = searchQuery.value.trim() + list = list.filter( + (o) => o.orderNumber.includes(q) || o.customerName.includes(q), + ) + } + return list + }) + + const selectedOrder = computed(() => + orderList.value.find((o) => o.id === selectedOrderId.value) ?? null, + ) + + function findOrderByRef(ref: string): Order | undefined { + const key = ref.trim() + if (!key) return undefined + return orderList.value.find( + (o) => o.id === key || o.orderNumber.toUpperCase() === key.toUpperCase(), + ) + } + + async function applyOrderDeepLink() { + const orderRef = typeof route.query.order === 'string' ? route.query.order : '' + if (!orderRef || !orderList.value.length) return + + const order = findOrderByRef(orderRef) + if (!order) { + searchQuery.value = orderRef + return + } + + const focus = typeof route.query.focus === 'string' ? route.query.focus : '' + if (focus === 'pricing') { + await router.replace(`/orders/${order.id}/pricing`) + return + } + if (focus === 'checks') { + await router.replace(`/orders/${order.id}/checks`) + return + } + + openOrderDetail(order) + searchQuery.value = order.orderNumber + } + + async function loadData() { + try { + const [ordersData, companiesData, customersData] = await Promise.all([ + ordersApi.list(), + companiesApi.list(), + customersApi.list(), + ]) + orderList.value = ordersData.map((o) => mapAdminOrder(o) as Order) + companies.value = companiesData + customers.value = customersData + if (!form.companyId && companiesData[0]) { + form.companyId = companiesData[0].id + } + await applyOrderDeepLink() + } catch (err) { + toast.error(err instanceof ApiError ? err.message : 'بارگذاری سفارش‌ها انجام نشد.') + } + } + + onMounted(() => { + void loadData() + }) + + watch( + () => [route.query.order, route.query.focus] as const, + () => { + void applyOrderDeepLink() + }, + ) + + function selectOrder(order: Order, openDetail = false) { + selectedOrderId.value = order.id + if (openDetail) { + showDetailPanel.value = true + } + } + + function openOrderDetail(order: Order) { + selectedOrderId.value = order.id + showDetailModal.value = true + } + + function closeDetailPanel() { + showDetailPanel.value = false + } + + function closeDetailModal() { + showDetailModal.value = false + } + + function settlementLabel(method?: string | null) { + if (!method) return 'انتخاب‌نشده' + return method === 'check' ? 'چکی' : 'نقدی' + } + + const statusSaving = ref(false) + + async function changeStatus(payload: { + orderId: string + status: RawOrderStatus + note?: string + reason?: string + force?: boolean + }) { + if (statusSaving.value) return null + statusSaving.value = true + try { + const updated = await ordersApi.updateStatus(payload.orderId, { + status: payload.status, + note: payload.note, + reason: payload.reason, + force: payload.force, + }) + const mapped = mapAdminOrder(updated) as Order + const index = orderList.value.findIndex((o) => o.id === payload.orderId) + if (index >= 0) orderList.value[index] = { ...orderList.value[index]!, ...mapped } + toast.success(`وضعیت سفارش به «${rawStatusLabel(payload.status)}» تغییر کرد.`) + return mapped + } catch (err) { + toast.error(err instanceof ApiError ? err.message : 'تغییر وضعیت انجام نشد.') + return null + } finally { + statusSaving.value = false + } + } + + function goPricing(order: Order) { + router.push(`/orders/${order.id}/pricing`) + } + + function goChecks(order: Order) { + router.push(`/orders/${order.id}/checks`) + } + + function goCashReceipt(order: Order) { + router.push({ path: '/cash-payments', query: { order: order.orderNumber } }) + } + + function openAddModal() { + Object.assign(form, emptyForm()) + formError.value = '' + showAddModal.value = true + void loadCustomers() + } + + function closeAddModal() { + showAddModal.value = false + formError.value = '' + } + + async function submitAddOrder() { + if (!isFormValid.value) { + formError.value = 'انتخاب مشتری و شرکت الزامی است.' + return + } + + saving.value = true + try { + const created = await ordersApi.create({ + companyId: form.companyId, + customerId: form.customerId || undefined, + userId: form.customerId || undefined, + customerName: form.customerName.trim(), + customerPhone: form.customerPhone.trim() || undefined, + settlementMethod: form.settlementMethod, + meterage: form.meterage, + }) + const mapped = mapAdminOrder(created) as Order + orderList.value.unshift(mapped) + selectedOrderId.value = mapped.id + toast.success('سفارش جدید ثبت شد.') + closeAddModal() + } catch (err) { + toast.error(err instanceof ApiError ? err.message : 'ثبت سفارش انجام نشد.') + } finally { + saving.value = false + } + } + + return { + companies, + customers, + activeCustomers, + applyCustomer, + loadCustomers, + orderList, + activeTab, + selectedOrderId, + searchQuery, + showAddModal, + showDetailPanel, + showDetailModal, + formError, + form, + isFormValid, + filteredOrders, + selectedOrder, + selectOrder, + openOrderDetail, + closeDetailPanel, + closeDetailModal, + settlementLabel, + changeStatus, + statusSaving, + goPricing, + goChecks, + goCashReceipt, + openAddModal, + closeAddModal, + submitAddOrder, + saving, + } +} + +export type OrdersPageContext = ReturnType + +export const ORDERS_PAGE_KEY: InjectionKey = Symbol('orders-page') + +export function provideOrdersPage() { + const ctx = useOrdersPage() + provide(ORDERS_PAGE_KEY, ctx) + return ctx +} + +export function useOrdersPageContext() { + const ctx = inject(ORDERS_PAGE_KEY) + if (!ctx) throw new Error('Orders page context is missing') + return ctx +} diff --git a/src/composables/useToast.ts b/src/composables/useToast.ts new file mode 100644 index 0000000..7e888bd --- /dev/null +++ b/src/composables/useToast.ts @@ -0,0 +1,37 @@ +import { reactive, toRef } from 'vue' + +export type ToastTone = 'success' | 'error' | 'info' | 'warning' + +export interface ToastItem { + id: string + message: string + tone: ToastTone +} + +const state = reactive<{ items: ToastItem[] }>({ + items: [], +}) + +function push(message: string, tone: ToastTone) { + const id = crypto.randomUUID() + state.items.push({ id, message, tone }) + window.setTimeout(() => dismiss(id), 3200) +} + +function dismiss(id: string) { + const index = state.items.findIndex((item) => item.id === id) + if (index !== -1) { + state.items.splice(index, 1) + } +} + +export function useToast() { + return { + toasts: toRef(state, 'items'), + dismiss, + success: (message: string) => push(message, 'success'), + error: (message: string) => push(message, 'error'), + info: (message: string) => push(message, 'info'), + warning: (message: string) => push(message, 'warning'), + } +} diff --git a/src/data/mockData.ts b/src/data/mockData.ts new file mode 100644 index 0000000..7906a86 --- /dev/null +++ b/src/data/mockData.ts @@ -0,0 +1,757 @@ +import type { + AdminNotification, + AdminUser, + BankAccount, + CashPayment, + Catalog, + Check, + CheckDeadline, + Company, + Customer, + InternalMessage, + Order, + Product, + Shipment, +} from '@/types' + +export const companies: Company[] = [ + { + id: 'company-par', + name: 'شرکت پَر', + description: 'تولید و عرضه انواع پارچه', + displayOrder: 1, + isActive: true, + logoUrl: null, + }, + { + id: 'company-fam-baft', + name: 'شرکت فام بافت', + description: 'تولید و عرضه انواع پارچه', + displayOrder: 2, + isActive: true, + logoUrl: null, + }, +] + +export const bankAccounts: BankAccount[] = [ + { + id: 'ba-1', + companyId: 'company-par', + bankName: '1', + accountNumber: '1234567890', + accountHolder: 'شرکت پَر', + cardNumber: '6104 3378 0077 1234', + iban: 'IR870120000000012345678901', + isActive: true, + displayOrder: 1, + }, + { + id: 'ba-2', + companyId: 'company-par', + bankName: '2', + accountNumber: '9876543210', + accountHolder: 'شرکت پَر', + cardNumber: '6037 9912 3456 7890', + iban: 'IR620190000000098765432101', + isActive: true, + displayOrder: 2, + }, +] + +export const orders: Order[] = [ + { + id: 'ord-1', + orderNumber: 'ORD-1403-1256', + customerName: 'شرکت پَر', + companyName: 'شرکت پَر', + companyId: 'company-par', + settlementMethod: 'check', + totalAmount: 2_450_000_000, + meterage: 4250, + status: 'pending_review', + createdAt: '2024-10-25T10:30:00', + customerPhone: '۰۹۱۲۱۲۳۴۵۶۷', + customerNationalId: '۱۰۱۰۳۴۵۶۷۸۹', + customerType: 'عمده‌فروش', + items: [ + { + id: 'oi-1', + catalogCode: '377', + productName: 'پارچه آبی', + color: 'آبی', + requestedMeterage: 2000, + confirmedMeterage: 2000, + supplyPrice: null, + totalAmount: null, + }, + { + id: 'oi-2', + catalogCode: '377', + productName: 'پارچه مشکی', + color: 'مشکی', + requestedMeterage: 1500, + confirmedMeterage: 1000, + supplyPrice: null, + totalAmount: null, + }, + { + id: 'oi-3', + catalogCode: '378', + productName: 'آبی پشت سفید', + color: 'آبی پشت سفید', + requestedMeterage: 750, + confirmedMeterage: 750, + supplyPrice: null, + totalAmount: null, + }, + ], + }, + { + id: 'ord-2', + orderNumber: 'ORD-1403-1255', + customerName: 'شرکت فام بافت', + companyName: 'شرکت فام بافت', + companyId: 'company-fam-baft', + settlementMethod: 'check', + totalAmount: 1_850_000_000, + meterage: 3200, + status: 'pending_check', + createdAt: '2024-10-24T14:15:00', + }, + { + id: 'ord-3', + orderNumber: 'ORD-1403-1254', + customerName: 'پارچه‌سرای نیکو', + companyName: 'شرکت پَر', + companyId: 'company-par', + settlementMethod: 'cash', + totalAmount: 980_000_000, + meterage: 1800, + status: 'final_approval', + createdAt: '2024-10-23T09:00:00', + }, + { + id: 'ord-4', + orderNumber: 'ORD-1403-1253', + customerName: 'بافت‌آسان', + companyName: 'شرکت فام بافت', + companyId: 'company-fam-baft', + settlementMethod: 'check', + totalAmount: 3_200_000_000, + meterage: 5100, + status: 'check_correction', + createdAt: '2024-10-22T16:45:00', + }, + { + id: 'ord-5', + orderNumber: 'ORD-1403-1252', + customerName: 'شرکت پَر', + companyName: 'شرکت پَر', + companyId: 'company-par', + settlementMethod: 'cash', + totalAmount: 750_000_000, + meterage: 1200, + status: 'delivered', + createdAt: '2024-10-21T11:20:00', + }, + { + id: 'ord-6', + orderNumber: 'ORD-1403-1251', + customerName: 'پارچه‌سرای نیکو', + companyName: 'شرکت پَر', + companyId: 'company-par', + settlementMethod: 'check', + totalAmount: 1_600_000_000, + meterage: 2900, + status: 'pending_review', + createdAt: '2024-10-20T08:30:00', + }, + { + id: 'ord-7', + orderNumber: 'ORD-1403-1250', + customerName: 'بافت‌آسان', + companyName: 'شرکت فام بافت', + companyId: 'company-fam-baft', + settlementMethod: 'check', + totalAmount: 2_100_000_000, + meterage: 3800, + status: 'pending_check', + createdAt: '2024-10-19T13:00:00', + }, +] + +export const checks: Check[] = [ + { + id: 'chk-1', + orderId: 'ord-1', + row: 1, + amount: 1_000_000_000, + bankName: 'ملت', + sayadId: '12345678901234567', + dueDate: '1403/07/30', + status: 'pending_review', + }, + { + id: 'chk-2', + orderId: 'ord-1', + row: 2, + amount: 800_000_000, + bankName: 'ملی', + sayadId: '23456789012345678', + dueDate: '1403/08/05', + status: 'pending_review', + }, + { + id: 'chk-3', + orderId: 'ord-1', + row: 3, + amount: 650_000_000, + bankName: 'ملت', + sayadId: '34567890123456789', + dueDate: '1403/08/10', + status: 'pending_review', + }, +] + +export const checkDeadlines: CheckDeadline[] = [ + { id: 'cd-1', label: 'امروز', tone: 'danger', count: 7, amount: 1_250_000_000 }, + { id: 'cd-2', label: 'فردا', tone: 'warning', count: 5, amount: 820_000_000 }, + { id: 'cd-3', label: '۴ روز دیگر', tone: 'neutral', count: 3, amount: 670_000_000 }, +] + +export const dashboardStats = { + newOrders: 12, + pendingReview: 18, + pendingCheck: 9, + finalApproval: 24, + todaySales: 2_450_000_000, + todaySalesGrowth: 12, + monthSales: 15_860_000_000, +} + +export const salesChartData = [ + 0.4, 0.6, 0.5, 0.8, 0.7, 1.0, 0.9, 1.2, 1.1, 1.4, 1.3, 1.6, 1.5, 1.8, + 1.7, 2.0, 1.9, 1.7, 1.8, 2.0, 1.9, 1.6, 1.8, 2.0, 1.7, 1.9, 1.8, 2.0, +] + +export const internalMessages: InternalMessage[] = [ + { + id: 'msg-1', + senderName: 'سارا احمدی', + subject: 'هماهنگی ارسال سفارش ORD-1403-1256', + preview: 'لطفاً وضعیت باربری سفارش مشتری پارچه‌سرای نیکو را بررسی کنید.', + sentAt: '2024-10-25T09:15:00', + isRead: false, + orderId: 'ord-1', + link: '/shipping?order=ORD-1403-1256', + }, + { + id: 'msg-2', + senderName: 'رضا کریمی', + subject: 'درخواست اصلاح قیمت', + preview: 'مشتری درخواست تخفیف ۵٪ روی متراژ بالای ۳۰۰۰ متر داده است.', + sentAt: '2024-10-25T08:40:00', + isRead: false, + orderId: 'ord-1', + link: '/orders/ord-1/pricing', + }, + { + id: 'msg-3', + senderName: 'مریم حسینی', + subject: 'تأیید چک‌های سفارش ۱۲۵۴', + preview: 'دو فقره چک بررسی شد؛ یک مورد نیاز به اصلاح دارد.', + sentAt: '2024-10-24T16:20:00', + isRead: false, + orderId: 'ord-3', + link: '/orders/ord-3/checks', + }, + { + id: 'msg-4', + senderName: 'امیر نوری', + subject: 'گزارش فروش هفتگی', + preview: 'گزارش فروش واحد تهران برای هفته جاری آماده است.', + sentAt: '2024-10-24T11:00:00', + isRead: false, + link: '/reports', + }, + { + id: 'msg-5', + senderName: 'فاطمه رضایی', + subject: 'ثبت مشتری جدید', + preview: 'مشتری «نساجی آریا» با مدارک کامل ثبت شد.', + sentAt: '2024-10-23T14:30:00', + isRead: false, + link: '/customers', + }, + { + id: 'msg-6', + senderName: 'حسین مرادی', + subject: 'یادآوری جلسه', + preview: 'جلسه هماهنگی انبار فردا ساعت ۱۰ برگزار می‌شود.', + sentAt: '2024-10-22T09:00:00', + isRead: true, + }, +] + +export const adminNotifications: AdminNotification[] = [ + { + id: 'ntf-1', + title: 'سفارش جدید ثبت شد', + body: 'سفارش ORD-1403-1260 از مشتری پارچه‌سرای نیکو در انتظار بررسی است.', + sentAt: '2024-10-25T10:05:00', + isRead: false, + tone: 'info', + link: '/orders?order=ORD-1403-1260', + }, + { + id: 'ntf-2', + title: 'چک در انتظار تأیید', + body: '۳ فقره چک برای سفارش ORD-1403-1254 نیاز به بررسی دارد.', + sentAt: '2024-10-25T09:50:00', + isRead: false, + tone: 'warning', + orderId: 'ord-3', + link: '/orders/ord-3/checks', + }, + { + id: 'ntf-3', + title: 'پیش‌فاکتور ارسال شد', + body: 'پیش‌فاکتور سفارش ORD-1403-1252 برای مشتری ارسال گردید.', + sentAt: '2024-10-25T09:20:00', + isRead: false, + tone: 'success', + orderId: 'ord-5', + link: '/orders/ord-5/pricing', + }, + { + id: 'ntf-4', + title: 'سررسید چک نزدیک است', + body: '۷ فقره چک با سررسید امروز — مجموع ۱٬۲۵۰٬۰۰۰٬۰۰۰ تومان.', + sentAt: '2024-10-25T08:00:00', + isRead: false, + tone: 'danger', + link: '/checks', + }, + { + id: 'ntf-5', + title: 'درخواست اصلاح سفارش', + body: 'مشتری برای سفارش ORD-1403-1248 درخواست تغییر متراژ داده است.', + sentAt: '2024-10-24T17:30:00', + isRead: false, + tone: 'warning', + link: '/orders?order=ORD-1403-1248&focus=pricing', + }, + { + id: 'ntf-6', + title: 'حساب بانکی جدید', + body: 'حساب بانکی جدید برای شرکت فام بافت ثبت شد.', + sentAt: '2024-10-24T15:00:00', + isRead: false, + tone: 'info', + link: '/companies/company-fam-baft/accounts', + }, + { + id: 'ntf-7', + title: 'تأیید نهایی سفارش', + body: 'سفارش ORD-1403-1245 آماده ارسال است.', + sentAt: '2024-10-24T12:45:00', + isRead: false, + tone: 'success', + link: '/shipping?order=ORD-1403-1245', + }, + { + id: 'ntf-8', + title: 'پیامک ارسال نشد', + body: 'ارسال پیامک برای مشتری ۰۹۱۲۱۲۳۴۵۶۷ با خطا مواجه شد.', + sentAt: '2024-10-24T11:20:00', + isRead: false, + tone: 'danger', + link: '/settings', + }, + { + id: 'ntf-9', + title: 'سفارش رد شد', + body: 'سفارش ORD-1403-1240 توسط واحد مالی رد شد.', + sentAt: '2024-10-23T16:00:00', + isRead: false, + tone: 'warning', + link: '/orders?order=ORD-1403-1240', + }, + { + id: 'ntf-10', + title: 'گزارش ماهانه آماده است', + body: 'گزارش فروش مهر ۱۴۰۳ قابل مشاهده است.', + sentAt: '2024-10-23T10:00:00', + isRead: false, + tone: 'info', + link: '/reports', + }, + { + id: 'ntf-11', + title: 'محصول جدید به کاتالوگ اضافه شد', + body: 'کالیته ۴۰۱ با ۱۲ رنگ جدید ثبت شد.', + sentAt: '2024-10-22T14:00:00', + isRead: false, + tone: 'info', + link: '/catalogs', + }, + { + id: 'ntf-12', + title: 'یادآوری پرداخت نقدی', + body: '۲ سفارش نقدی در انتظار تأیید پرداخت هستند.', + sentAt: '2024-10-22T09:30:00', + isRead: false, + tone: 'warning', + link: '/cash-payments', + }, + { + id: 'ntf-13', + title: 'پشتیبان‌گیری موفق', + body: 'پشتیبان‌گیری شبانه سامانه با موفقیت انجام شد.', + sentAt: '2024-10-21T06:00:00', + isRead: true, + tone: 'success', + link: '/settings', + }, +] + +export const customers: Customer[] = [ + { + id: 'cust-1', + name: 'پارچه‌سرای نیکو', + phone: '۰۹۱۲۱۲۳۴۵۶۷', + nationalId: '۱۰۱۰۳۴۵۶۷۸۹', + customerType: 'wholesale', + companyName: 'شرکت پَر', + orderCount: 24, + totalMeterage: 18500, + isActive: true, + registeredAt: '2024-03-12T10:00:00', + }, + { + id: 'cust-2', + name: 'نساجی آریا', + phone: '۰۹۱۳۵۵۵۱۲۳۴', + nationalId: '۱۰۳۰۵۶۷۸۹۰۱', + customerType: 'wholesale', + companyName: 'شرکت فام بافت', + orderCount: 11, + totalMeterage: 9200, + isActive: true, + registeredAt: '2024-05-20T14:30:00', + }, + { + id: 'cust-3', + name: 'فروشگاه پارچه مهر', + phone: '۰۲۱۸۸۷۷۶۶۵۵', + nationalId: '۰۰۱۲۳۴۵۶۷۸', + customerType: 'retail', + companyName: 'شرکت پَر', + orderCount: 6, + totalMeterage: 2100, + isActive: true, + registeredAt: '2024-07-08T09:15:00', + }, + { + id: 'cust-4', + name: 'پوشاک سپهر', + phone: '۰۹۳۶۹۸۷۶۵۴۳', + nationalId: '۱۰۵۰۹۸۷۶۵۴۳', + customerType: 'wholesale', + companyName: 'شرکت پَر', + orderCount: 3, + totalMeterage: 4500, + isActive: false, + registeredAt: '2024-08-01T11:00:00', + }, +] + +export const catalogs: Catalog[] = [ + { + id: 'cat-377', + companyId: 'company-par', + companyName: 'شرکت پَر', + code: '377', + name: 'کالیته ۳۷۷', + displayOrder: 1, + productCount: 8, + isActive: true, + }, + { + id: 'cat-378', + companyId: 'company-par', + companyName: 'شرکت پَر', + code: '378', + name: 'کالیته ۳۷۸', + displayOrder: 2, + productCount: 12, + isActive: true, + }, + { + id: 'cat-379', + companyId: 'company-par', + companyName: 'شرکت پَر', + code: '379', + name: 'کالیته ۳۷۹', + displayOrder: 3, + productCount: 6, + isActive: true, + }, + { + id: 'cat-401', + companyId: 'company-fam-baft', + companyName: 'شرکت فام بافت', + code: '401', + name: 'کالیته ۴۰۱', + displayOrder: 1, + productCount: 10, + isActive: true, + }, + { + id: 'cat-402', + companyId: 'company-fam-baft', + companyName: 'شرکت فام بافت', + code: '402', + name: 'کالیته ۴۰۲', + displayOrder: 2, + productCount: 4, + isActive: false, + }, +] + +export const products: Product[] = [ + { + id: 'prod-1', + catalogId: 'cat-377', + catalogCode: '377', + companyName: 'شرکت پَر', + name: 'پارچه آبی', + color: 'آبی', + productCode: '377-BLU', + minMeterage: 100, + orderStep: 50, + price: 185000, + internalStock: 12000, + isActive: true, + }, + { + id: 'prod-2', + catalogId: 'cat-377', + catalogCode: '377', + companyName: 'شرکت پَر', + name: 'پارچه مشکی', + color: 'مشکی', + productCode: '377-BLK', + minMeterage: 100, + orderStep: 50, + price: 192000, + internalStock: 8500, + isActive: true, + }, + { + id: 'prod-3', + catalogId: 'cat-378', + catalogCode: '378', + companyName: 'شرکت پَر', + name: 'آبی پشت سفید', + color: 'آبی / سفید', + productCode: '378-BW', + minMeterage: 200, + orderStep: 100, + price: 210000, + internalStock: 6000, + isActive: true, + }, + { + id: 'prod-4', + catalogId: 'cat-378', + catalogCode: '378', + companyName: 'شرکت پَر', + name: 'مشکی پشت سفید', + color: 'مشکی / سفید', + productCode: '378-BLKW', + minMeterage: 200, + orderStep: 100, + price: 215000, + internalStock: 4200, + isActive: true, + }, + { + id: 'prod-5', + catalogId: 'cat-401', + catalogCode: '401', + companyName: 'شرکت فام بافت', + name: 'پارچه کرم', + color: 'کرم', + productCode: '401-CRM', + minMeterage: 150, + orderStep: 50, + price: null, + internalStock: 3000, + isActive: true, + }, +] + +export const cashPayments: CashPayment[] = [ + { + id: 'cp-1', + orderId: 'ord-2', + orderNumber: 'ORD-1403-1254', + customerName: 'پارچه‌سرای نیکو', + amount: 1_850_000_000, + paidAmount: 1_850_000_000, + transferDate: '2024-10-25T08:30:00', + trackingCode: '۹۸۷۶۵۴۳۲۱۰', + expiresAt: '2024-10-25T17:00:00', + status: 'pending_review', + }, + { + id: 'cp-2', + orderId: 'ord-3', + orderNumber: 'ORD-1403-1248', + customerName: 'نساجی آریا', + amount: 920_000_000, + paidAmount: 900_000_000, + transferDate: '2024-10-24T15:20:00', + trackingCode: '۱۲۳۴۵۶۷۸۹۰', + expiresAt: '2024-10-24T17:00:00', + status: 'pending_review', + }, + { + id: 'cp-3', + orderId: 'ord-4', + orderNumber: 'ORD-1403-1240', + customerName: 'فروشگاه پارچه مهر', + amount: 450_000_000, + paidAmount: 450_000_000, + transferDate: '2024-10-23T11:00:00', + trackingCode: '۵۵۵۵۱۲۳۴۵۶', + expiresAt: '2024-10-23T17:00:00', + status: 'approved', + }, + { + id: 'cp-4', + orderId: 'ord-5', + orderNumber: 'ORD-1403-1235', + customerName: 'پوشاک سپهر', + amount: 680_000_000, + paidAmount: null, + transferDate: null, + trackingCode: '—', + expiresAt: '2024-10-22T17:00:00', + status: 'expired', + }, +] + +export const shipments: Shipment[] = [ + { + id: 'shp-1', + orderId: 'ord-6', + orderNumber: 'ORD-1403-1220', + customerName: 'پارچه‌سرای نیکو', + carrier: 'باربری تهران-اصفهان', + trackingNumber: 'BR-1403-88901', + meterage: 3200, + status: 'shipped', + shippedAt: '2024-10-24T09:00:00', + deliveredAt: null, + }, + { + id: 'shp-2', + orderId: 'ord-7', + orderNumber: 'ORD-1403-1215', + customerName: 'نساجی آریا', + carrier: 'باربری سریع', + trackingNumber: 'BR-1403-88902', + meterage: 1800, + status: 'ready', + shippedAt: null, + deliveredAt: null, + }, + { + id: 'shp-3', + orderId: 'ord-8', + orderNumber: 'ORD-1403-1208', + customerName: 'فروشگاه پارچه مهر', + carrier: 'پیک داخلی', + trackingNumber: 'PK-1403-0045', + meterage: 950, + status: 'preparing', + shippedAt: null, + deliveredAt: null, + }, + { + id: 'shp-4', + orderId: 'ord-9', + orderNumber: 'ORD-1403-1199', + customerName: 'پارچه‌سرای نیکو', + carrier: 'باربری تهران-مشهد', + trackingNumber: 'BR-1403-88750', + meterage: 4100, + status: 'delivered', + shippedAt: '2024-10-18T10:00:00', + deliveredAt: '2024-10-20T16:30:00', + }, +] + +export const adminUsers: AdminUser[] = [ + { + id: 'usr-1', + fullName: 'علی محمدی', + phone: '۰۹۱۲۱۱۱۲۲۲۲', + email: 'admin@fabrictrade.ir', + role: 'admin', + isActive: true, + lastLoginAt: '2024-10-25T08:00:00', + }, + { + id: 'usr-2', + fullName: 'سارا احمدی', + phone: '۰۹۱۳۳۳۳۴۴۴۴', + email: 'sales@fabrictrade.ir', + role: 'sales', + isActive: true, + lastLoginAt: '2024-10-25T07:45:00', + }, + { + id: 'usr-3', + fullName: 'رضا کریمی', + phone: '۰۹۱۵۵۵۵۶۶۶۶', + email: 'finance@fabrictrade.ir', + role: 'finance', + isActive: true, + lastLoginAt: '2024-10-24T17:10:00', + }, + { + id: 'usr-4', + fullName: 'مریم حسینی', + phone: '۰۹۱۷۷۷۷۸۸۸۸', + email: 'warehouse@fabrictrade.ir', + role: 'warehouse', + isActive: true, + lastLoginAt: '2024-10-24T14:00:00', + }, + { + id: 'usr-5', + fullName: 'امیر نوری', + phone: '۰۹۱۹۹۹۹۰۰۰۰', + email: 'amir.n@fabrictrade.ir', + role: 'sales', + isActive: false, + lastLoginAt: '2024-09-30T11:00:00', + }, +] + +export const reportSalesByCompany = [ + { companyName: 'شرکت پَر', orderCount: 68, totalAmount: 12_450_000_000, meterage: 28500 }, + { companyName: 'شرکت فام بافت', orderCount: 35, totalAmount: 6_820_000_000, meterage: 14200 }, +] + +export const reportOrdersByStatus = [ + { status: 'در انتظار بررسی', count: 18 }, + { status: 'بررسی چک', count: 9 }, + { status: 'نیاز به اصلاح', count: 6 }, + { status: 'تأیید نهایی', count: 24 }, + { status: 'ارسال شده', count: 12 }, + { status: 'تحویل شده', count: 34 }, +] diff --git a/src/layouts/AdminShell.vue b/src/layouts/AdminShell.vue new file mode 100644 index 0000000..d23b596 --- /dev/null +++ b/src/layouts/AdminShell.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..c4c80a2 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,23 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' +import { useAuthStore } from '@/stores/auth' +import { useThemeStore } from '@/stores/theme' + +import 'virtual:uno.css' +import '@/assets/styles/main.css' +import '@/assets/styles/admin.css' +import '@/assets/styles/responsive.css' + +const app = createApp(App) +const pinia = createPinia() + +app.use(pinia) +app.use(router) + +useThemeStore(pinia) +useAuthStore(pinia).hydrate() + +app.mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..c10f97f --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,186 @@ +import { createRouter, createWebHistory } from 'vue-router' +import AdminShell from '@/layouts/AdminShell.vue' +import { useAuthStore } from '@/stores/auth' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/login', + name: 'login', + component: () => import('@/views/auth/LoginView.vue'), + meta: { public: true, title: 'ورود به پنل مدیریت' }, + }, + { + path: '/', + component: AdminShell, + meta: { requiresAuth: true }, + children: [ + { + path: '', + name: 'dashboard', + component: () => import('@/views/dashboard/DashboardView.vue'), + meta: { title: 'داشبورد مدیریتی' }, + }, + { + path: 'orders', + name: 'orders', + component: () => import('@/views/orders/OrdersView.vue'), + meta: { title: 'سفارش‌ها' }, + }, + { + path: 'orders/:id/pricing', + name: 'order-pricing', + component: () => import('@/views/orders/OrderPricingView.vue'), + meta: { title: 'قیمت‌گذاری سفارش' }, + }, + { + path: 'checks', + name: 'checks', + component: () => import('@/views/checks/ChecksListView.vue'), + meta: { title: 'چک‌ها' }, + }, + { + path: 'orders/:id/checks', + name: 'order-checks', + component: () => import('@/views/checks/CheckManagementView.vue'), + meta: { title: 'مدیریت چک‌های سفارش' }, + }, + { + /* API links often use /orders/:id — open list + detail via query */ + path: 'orders/:id', + name: 'order-detail', + redirect: (to) => ({ + name: 'orders', + query: { order: String(to.params.id) }, + }), + }, + { + path: 'companies', + name: 'companies', + component: () => import('@/views/companies/CompaniesView.vue'), + meta: { title: 'مدیریت شرکت‌ها' }, + }, + { + path: 'companies/:companyId/accounts', + name: 'bank-accounts', + component: () => import('@/views/companies/BankAccountsView.vue'), + meta: { title: 'حساب‌های بانکی' }, + }, + { + path: 'customers', + name: 'customers', + component: () => import('@/views/customers/CustomersView.vue'), + meta: { title: 'مشتریان' }, + }, + { + path: 'products', + name: 'products', + component: () => import('@/views/products/ProductsView.vue'), + meta: { title: 'محصولات' }, + }, + { + path: 'categories', + name: 'categories', + component: () => import('@/views/categories/CategoriesView.vue'), + meta: { title: 'دسته‌بندی‌ها' }, + }, + { + path: 'banners', + name: 'banners', + component: () => import('@/views/banners/BannersView.vue'), + meta: { title: 'بنرها' }, + }, + { + path: 'catalogs', + name: 'catalogs', + component: () => import('@/views/catalogs/CatalogsView.vue'), + meta: { title: 'کالیته‌ها' }, + }, + { + path: 'catalog-requests', + name: 'catalog-requests', + component: () => import('@/views/catalog-requests/CatalogRequestsView.vue'), + meta: { title: 'درخواست کالیته فیزیکی' }, + }, + { + path: 'brands', + name: 'brands', + component: () => import('@/views/brands/BrandsView.vue'), + meta: { title: 'برندها' }, + }, + { + path: 'suggestions', + name: 'suggestions', + component: () => import('@/views/suggestions/SuggestionsView.vue'), + meta: { title: 'پیشنهاد محصول' }, + }, + { + path: 'stock-alerts', + name: 'stock-alerts', + component: () => import('@/views/stock-alerts/StockAlertsView.vue'), + meta: { title: 'خبر موجودی' }, + }, + { + path: 'levels', + name: 'levels', + component: () => import('@/views/levels/LevelsView.vue'), + meta: { title: 'سطوح مشتری' }, + }, + { + path: 'cash-payments', + name: 'cash-payments', + component: () => import('@/views/cash-payments/CashPaymentsView.vue'), + meta: { title: 'پرداخت‌های نقدی' }, + }, + { + path: 'shipping', + name: 'shipping', + component: () => import('@/views/shipping/ShippingView.vue'), + meta: { title: 'ارسال و باربری' }, + }, + { + path: 'reports', + name: 'reports', + component: () => import('@/views/reports/ReportsView.vue'), + meta: { title: 'گزارش‌ها' }, + }, + { + path: 'settings', + name: 'settings', + component: () => import('@/views/settings/SettingsView.vue'), + meta: { title: 'تنظیمات' }, + }, + { + path: 'users', + name: 'users', + component: () => import('@/views/users/UsersView.vue'), + meta: { title: 'کاربران و دسترسی‌ها' }, + }, + ], + }, + ], +}) + +router.beforeEach((to) => { + const auth = useAuthStore() + auth.hydrate() + + if (to.meta.public) { + if (auth.isAuthenticated && to.name === 'login') { + return { name: 'dashboard' } + } + return true + } + + if (to.matched.some((record) => record.meta.requiresAuth) && !auth.isAuthenticated) { + return { + name: 'login', + query: { redirect: to.fullPath }, + } + } + + return true +}) + +export default router diff --git a/src/services/api.ts b/src/services/api.ts new file mode 100644 index 0000000..956ff8d --- /dev/null +++ b/src/services/api.ts @@ -0,0 +1,628 @@ +import { apiRequest } from '@/services/http' +import type { + AdminNotification, + AdminUser, + BankAccount, + CashPayment, + Catalog, + Check, + CheckDeadline, + Company, + Customer, + InternalMessage, + Order, + OrderItem, + OrderStatus, + OrderStatusHistoryItem, + Product, + RawOrderStatus, + SettlementMethod, + Shipment, + ShipmentStatus, + UserRole, +} from '@/types' + +/** Normalize admin list order status badges */ +export function mapAdminOrder< + T extends { + status: string + adminStatus?: string + allowedTransitions?: string[] + settlementMethod?: string | null + settlementType?: string | null + meterage?: number + totalMeterage?: number + }, +>( + order: T, +): T & { + status: OrderStatus + rawStatus: RawOrderStatus + allowedTransitions: RawOrderStatus[] + settlementMethod: SettlementMethod | null + meterage: number +} { + return { + ...order, + status: (order.adminStatus ?? order.status) as OrderStatus, + rawStatus: order.status as RawOrderStatus, + allowedTransitions: (order.allowedTransitions ?? []) as RawOrderStatus[], + settlementMethod: (order.settlementMethod ?? + order.settlementType ?? + null) as SettlementMethod | null, + meterage: order.meterage ?? order.totalMeterage ?? 0, + } +} + +export function slugifyCompanyName(name: string): string { + const slug = name + .trim() + .toLowerCase() + .replace(/\s+/g, '-') + .replace(/[^a-z0-9-]/g, '') + .replace(/-+/g, '-') + .replace(/^-|-$/g, '') + return slug || `c-${Date.now()}` +} + +/* ── Companies ─────────────────────────────────────────────── */ + +export type CreateCompanyPayload = { + name: string + slug: string + description?: string + logoUrl?: string | null + displayOrder?: number + isActive?: boolean +} + +export type UpdateCompanyPayload = Partial> & { + slug?: string +} + +export const companiesApi = { + list: (activeOnly?: boolean) => + apiRequest('/companies', { query: { activeOnly: activeOnly ? 'true' : undefined } }), + get: (id: string) => apiRequest(`/companies/${id}`), + create: (body: CreateCompanyPayload) => apiRequest('/companies', { body }), + update: (id: string, body: UpdateCompanyPayload) => + apiRequest(`/companies/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/companies/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Bank accounts ─────────────────────────────────────────── */ + +export type CreateBankAccountPayload = { + bankName: string + accountHolder: string + accountNumber: string + cardNumber: string + iban: string + displayOrder?: number + isActive?: boolean + notes?: string +} + +export type UpdateBankAccountPayload = Partial + +export const bankAccountsApi = { + listByCompany: (companyId: string) => + apiRequest(`/companies/${companyId}/bank-accounts`), + create: (companyId: string, body: CreateBankAccountPayload) => + apiRequest(`/companies/${companyId}/bank-accounts`, { body }), + update: (id: string, body: UpdateBankAccountPayload) => + apiRequest(`/bank-accounts/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/bank-accounts/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Catalogs ──────────────────────────────────────────────── */ + +export type CreateCatalogPayload = { + companyId: string + name: string + code: string + description?: string + displayOrder?: number + isActive?: boolean +} + +export type UpdateCatalogPayload = Partial> + +export const catalogsApi = { + list: (params?: { companyId?: string; activeOnly?: boolean }) => + apiRequest('/catalogs', { + query: { + companyId: params?.companyId, + activeOnly: params?.activeOnly ? 'true' : undefined, + }, + }), + create: (body: CreateCatalogPayload) => apiRequest('/catalogs', { body }), + update: (id: string, body: UpdateCatalogPayload) => + apiRequest(`/catalogs/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/catalogs/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Products ──────────────────────────────────────────────── */ + +export type CreateProductPayload = { + companyId: string + catalogId: string + name: string + code?: string + productCode?: string + color: string + minMeterage?: number + orderStep?: number + orderMultiplier?: number + price?: number | null + basePrice?: number | null + internalStock?: number | null + stock?: number | null + isActive?: boolean + description?: string + usageCategory?: string + season?: string + composition?: string | null + weaveType?: string | null + subtitle?: string | null + rollMeters?: number + widthCm?: number | null + weightGrams?: number | null + isNew?: boolean + colorsJson?: string[] + imageUrlsJson?: string[] + tagsJson?: string[] +} + +export type UpdateProductPayload = Partial> + +export const productsApi = { + list: (params?: { catalogId?: string; companyId?: string; activeOnly?: boolean }) => + apiRequest('/products', { + query: { + catalogId: params?.catalogId, + companyId: params?.companyId, + activeOnly: params?.activeOnly ? 'true' : undefined, + }, + }), + create: (body: CreateProductPayload) => apiRequest('/products', { body }), + update: (id: string, body: UpdateProductPayload) => + apiRequest(`/products/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/products/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Customers ─────────────────────────────────────────────── */ + +export type CreateCustomerPayload = { + name?: string + firstName?: string + lastName?: string + phone: string + nationalId?: string + customerType?: Customer['customerType'] + companyId?: string | null + isActive?: boolean + levelDefId?: string | null + assignedAgentId?: string | null + appRole?: 'customer' | 'agent' + agentCode?: string | null + brandIds?: string[] +} + +export type UpdateCustomerPayload = Partial + +export const customersApi = { + list: (q?: string, appRole?: 'customer' | 'agent') => + apiRequest('/admin/customers', { query: { q, appRole } }), + create: (body: CreateCustomerPayload) => apiRequest('/admin/customers', { body }), + update: (id: string, body: UpdateCustomerPayload) => + apiRequest(`/admin/customers/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/admin/customers/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Orders ────────────────────────────────────────────────── */ + +export type AdminCreateOrderPayload = { + companyId: string + customerId?: string + customerName?: string + customerPhone?: string + userId?: string + settlementMethod?: SettlementMethod + settlementType?: SettlementMethod + meterage?: number + notes?: string +} + +export type OrderItemPricingPayload = { + id: string + confirmedMeterage?: number + unitPrice?: number + supplyPrice?: number +} + +export type UpdateOrderPricingPayload = { + items: OrderItemPricingPayload[] + shippingCost?: number + note?: string +} + +export type ApiOrder = Order & { + adminStatus?: string + settlementType?: SettlementMethod | null + totalMeterage?: number + shippingCost?: number | null + finalAmount?: number | null + checkRassDays?: number | null + checkRassDate?: string + items?: OrderItem[] + checks?: Check[] + statusHistory?: OrderStatusHistoryItem[] + /** وضعیت‌های مجاز بعدی از دید ماشین وضعیت سرور */ + allowedTransitions?: string[] + cashReceipt?: { id: string } | null +} + +export type UpdateOrderStatusPayload = { + status: string + note?: string + reason?: string + /** گذر خارج از ماشین وضعیت؛ سرور reason را اجباری می‌کند */ + force?: boolean +} + +export const ordersApi = { + list: (params?: { status?: string; q?: string }) => + apiRequest('/admin/orders', { query: { status: params?.status, q: params?.q } }), + get: (id: string) => apiRequest(`/admin/orders/${id}`), + create: (body: AdminCreateOrderPayload) => apiRequest('/admin/orders', { body }), + updatePricing: (id: string, body: UpdateOrderPricingPayload) => + apiRequest(`/admin/orders/${id}/pricing`, { method: 'PATCH', body }), + updateStatus: (id: string, body: UpdateOrderStatusPayload) => + apiRequest(`/admin/orders/${id}/status`, { method: 'PATCH', body }), +} + +/* ── Checks ────────────────────────────────────────────────── */ + +export const checksApi = { + list: (status?: Check['status']) => + apiRequest('/admin/checks', { query: { status } }), + listByOrder: (orderId: string) => + apiRequest(`/admin/orders/${orderId}/checks`), + updateStatus: (id: string, body: { status: Check['status']; note?: string }) => + apiRequest(`/admin/checks/${id}/status`, { method: 'PATCH', body }), +} + +/* ── Cash payments ─────────────────────────────────────────── */ + +export const cashPaymentsApi = { + list: (status?: CashPayment['status']) => + apiRequest('/admin/cash-payments', { query: { status } }), + updateStatus: (id: string, body: { status: CashPayment['status']; note?: string }) => + apiRequest(`/admin/cash-payments/${id}/status`, { method: 'PATCH', body }), +} + +/* ── Shipments ─────────────────────────────────────────────── */ + +export type CreateShipmentPayload = { + orderId: string + carrier: string + trackingNumber?: string + meterage?: number + status?: ShipmentStatus +} + +export const shipmentsApi = { + list: (status?: ShipmentStatus) => + apiRequest('/admin/shipments', { query: { status } }), + create: (body: CreateShipmentPayload) => apiRequest('/admin/shipments', { body }), + update: (id: string, body: Partial) => + apiRequest(`/admin/shipments/${id}`, { method: 'PATCH', body }), + advanceStatus: (id: string, body?: { status?: ShipmentStatus; trackingNumber?: string }) => + apiRequest(`/admin/shipments/${id}/status`, { method: 'PATCH', body: body ?? {} }), +} + +/* ── Admin users ───────────────────────────────────────────── */ + +export type CreateAdminUserPayload = { + fullName: string + phone: string + email?: string + password?: string + role?: UserRole + isActive?: boolean +} + +export type UpdateAdminUserPayload = Partial + +export const adminUsersApi = { + list: () => apiRequest('/admin/users'), + create: (body: CreateAdminUserPayload) => apiRequest('/admin/users', { body }), + update: (id: string, body: UpdateAdminUserPayload) => + apiRequest(`/admin/users/${id}`, { method: 'PATCH', body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/admin/users/${id}/active`, { method: 'PATCH', body: { isActive } }), +} + +/* ── Dashboard & reports ───────────────────────────────────── */ + +export type DashboardStats = { + newOrders: number + pendingReview: number + pendingCheck: number + finalApproval: number + todaySales: number + todaySalesGrowth: number + monthSales: number +} + +export type DashboardResponse = { + stats: DashboardStats + recentOrders: ApiOrder[] + salesChartData: number[] + chartAxisLabels: string[] + checkDeadlines: CheckDeadline[] + notifications?: AdminNotification[] + messages?: InternalMessage[] +} + +export type ReportsResponse = { + reportSalesByCompany: { + companyName: string + orderCount: number + totalAmount: number + meterage: number + }[] + reportOrdersByStatus: { status: string; count: number }[] + reportSalesByMonth?: { + month: string + orderCount: number + totalAmount: number + meterage: number + }[] + reportSalesByProduct?: { + productId: string + productName: string + productCode: string + orderCount: number + meterage: number + totalAmount: number + }[] + reportSalesByCustomer?: { + customerName: string + orderCount: number + totalAmount: number + meterage: number + }[] + reportCustomers?: { + active: number + inactive: number + newLast30Days: number + noPurchase: number + noPurchase90Days: number + withAgent: number + } +} + +export const dashboardApi = { + get: () => apiRequest('/admin/dashboard'), + reports: () => apiRequest('/admin/reports'), +} + +/* ── System settings ──────────────────────────────────────── */ + +export type SystemSettings = { + id: string + maxMeteragePerInvoice: number + cashInvoiceValidityHours: number + defaultSettlementCheck: boolean + defaultSettlementCash: boolean + minOrderRollsPerProduct?: number + showCatalogPublicPrice?: boolean + allowAgentPricing?: boolean + agentMinUnitPrice?: number | null + smsOrderRegistered: boolean + smsPricingReady: boolean + smsPaymentReminder: boolean + smsCheckReview: boolean + smsShippingUpdate: boolean + supportPhone: string | null + supportEmail: string | null + categoryImagesJson?: Record + updatedAt: string +} + +export type UpdateSettingsPayload = Partial> + +export const settingsApi = { + get: () => apiRequest('/admin/settings'), + update: (body: UpdateSettingsPayload) => + apiRequest('/admin/settings', { method: 'PATCH', body }), +} + +/* ── Admin notifications ──────────────────────────────────── */ + +export const notificationsApi = { + markRead: (id: string) => + apiRequest<{ ok: boolean }>(`/admin/notifications/${id}/read`, { method: 'PATCH' }), + markAllRead: () => + apiRequest<{ ok: boolean }>('/admin/notifications/read-all', { method: 'PATCH' }), + broadcast: (body: { title: string; body: string; customerIds?: string[]; tone?: string }) => + apiRequest<{ sent: number }>('/admin/notifications/broadcast', { method: 'POST', body }), +} + +/* ── Catalog requests (physical) ──────────────────────────── */ + +export type CatalogRequestRow = { + id: string + customerId: string + customerName: string + customerPhone: string + status: string + note?: string + createdAt: string + items: { + id: string + productId: string + productName: string + productCode: string + quantity: number + holderType: string + holderCustomerId?: string | null + movements?: { + id: string + fromHolder: string + toHolder: string + note?: string + movedAt: string + }[] + }[] +} + +export const catalogRequestsApi = { + list: (status?: string) => + apiRequest('/admin/catalog-requests', { + query: { status }, + }), + updateStatus: (id: string, status: string) => + apiRequest(`/admin/catalog-requests/${id}/status`, { + method: 'PATCH', + body: { status }, + }), + updateHolder: ( + itemId: string, + body: { holderType: string; holderCustomerId?: string | null; note?: string }, + ) => + apiRequest(`/admin/catalog-request-items/${itemId}/holder`, { + method: 'PATCH', + body, + }), +} + +/* ── Brands ───────────────────────────────────────────────── */ + +export type Brand = { + id: string + name: string + slug?: string + description?: string + isActive: boolean + displayOrder: number + customersCount?: number +} + +export type AppBanner = { + id: string + slot: string + title: string + subtitle: string + ctaLabel: string + ctaLink: string + imageUrl: string + displayOrder: number + isActive: boolean +} + +export type BannerPayload = { + slot: string + title: string + subtitle?: string | null + ctaLabel?: string | null + ctaLink?: string | null + imageUrl?: string | null + displayOrder?: number + isActive?: boolean +} + +export const bannersApi = { + list: (slot?: string) => + apiRequest('/admin/banners', { query: { slot } }), + create: (body: BannerPayload) => + apiRequest('/admin/banners', { body }), + update: (id: string, body: Partial) => + apiRequest(`/admin/banners/${id}`, { method: 'PATCH', body }), + remove: (id: string) => + apiRequest<{ ok: boolean }>(`/admin/banners/${id}`, { method: 'DELETE' }), +} + +export const brandsApi = { + list: () => apiRequest('/admin/brands'), + create: (body: Partial & { name: string }) => + apiRequest('/admin/brands', { body }), + update: (id: string, body: Partial) => + apiRequest(`/admin/brands/${id}`, { method: 'PATCH', body }), +} + +/* ── Levels ───────────────────────────────────────────────── */ + +export type CustomerLevel = { + id: string + code: string + label: string + sortOrder: number + isActive: boolean + customersCount: number + benefits: { id?: string; title: string; description?: string }[] +} + +export const levelsApi = { + list: () => apiRequest('/admin/levels'), + create: (body: { + code: string + label: string + sortOrder?: number + benefits?: { title: string; description?: string }[] + }) => apiRequest('/admin/levels', { body }), + update: (id: string, body: Partial & { benefits?: { title: string; description?: string }[] }) => + apiRequest(`/admin/levels/${id}`, { method: 'PATCH', body }), +} + +/* ── Suggestions ──────────────────────────────────────────── */ + +export type ProductSuggestion = { + id: string + customerId: string + customerName: string + productId: string + productName: string + productCode: string + note?: string + isActive: boolean + createdAt: string +} + +export const suggestionsApi = { + list: (customerId?: string) => + apiRequest('/admin/suggestions', { query: { customerId } }), + create: (body: { customerId: string; productId: string; note?: string }) => + apiRequest('/admin/suggestions', { body }), + setActive: (id: string, isActive: boolean) => + apiRequest(`/admin/suggestions/${id}/active`, { + method: 'PATCH', + body: { isActive }, + }), +} + +/* ── Stock alerts ─────────────────────────────────────────── */ + +export type StockAlert = { + id: string + customerName: string + customerPhone: string + productName: string + productCode: string + stock: number | null + active: boolean + createdAt: string +} + +export const stockAlertsApi = { + list: () => apiRequest('/admin/stock-alerts'), + notify: (id: string) => + apiRequest(`/admin/stock-alerts/${id}/notify`, { method: 'PATCH' }), +} diff --git a/src/services/authService.ts b/src/services/authService.ts new file mode 100644 index 0000000..f3bd1ca --- /dev/null +++ b/src/services/authService.ts @@ -0,0 +1,135 @@ +import type { AdminLoginPayload, AdminLoginResult, AdminSession } from '@/types/auth' +import { ApiError, apiRequest, getAccessToken, setAccessToken } from '@/services/http' + +const STORAGE_KEY = 'fabric-admin-session' +const TOKEN_KEY = 'fabric-admin-token' + +const USE_MOCK_AUTH = import.meta.env.VITE_USE_MOCK_AUTH === 'true' + +/** حساب موک توسعه — فقط وقتی VITE_USE_MOCK_AUTH=true */ +export const MOCK_ADMIN = { + phone: '09128081392', + password: '123456', + session: { + id: 'mock-admin-1', + fullName: 'مدیر سیستم (موک)', + phone: '09128081392', + email: 'admin@parche.ir', + role: 'admin' as const, + } satisfies AdminSession, +} + +function readSession(): AdminSession | null { + try { + const raw = localStorage.getItem(STORAGE_KEY) ?? sessionStorage.getItem(STORAGE_KEY) + if (!raw) return null + return JSON.parse(raw) as AdminSession + } catch { + return null + } +} + +function writeSession(session: AdminSession, remember: boolean) { + const payload = JSON.stringify(session) + localStorage.removeItem(STORAGE_KEY) + sessionStorage.removeItem(STORAGE_KEY) + if (remember) { + localStorage.setItem(STORAGE_KEY, payload) + } else { + sessionStorage.setItem(STORAGE_KEY, payload) + } +} + +function clearSession() { + localStorage.removeItem(STORAGE_KEY) + sessionStorage.removeItem(STORAGE_KEY) +} + +function isRememberedToken(): boolean { + return !!localStorage.getItem(TOKEN_KEY) +} + +function toSession(user: AdminSession): AdminSession { + return { + id: user.id, + fullName: user.fullName, + phone: user.phone, + email: user.email, + role: user.role, + } +} + +export function getStoredSession(): AdminSession | null { + return readSession() +} + +export function isMockAuthEnabled() { + return USE_MOCK_AUTH +} + +export async function loginAdmin(payload: AdminLoginPayload): Promise { + const phone = payload.phone.trim() + const password = payload.password + + if (!phone || !password) { + return { success: false, message: 'شماره موبایل و رمز عبور الزامی است.' } + } + + if (USE_MOCK_AUTH) { + if (phone === MOCK_ADMIN.phone && password === MOCK_ADMIN.password) { + setAccessToken('mock-admin-token', payload.remember) + writeSession(MOCK_ADMIN.session, payload.remember) + return { success: true } + } + return { + success: false, + message: `حالت موک: ${MOCK_ADMIN.phone} / ${MOCK_ADMIN.password}`, + } + } + + try { + const data = await apiRequest<{ accessToken: string; user: AdminSession }>( + '/admin/auth/login', + { + method: 'POST', + body: { phone, password }, + auth: false, + }, + ) + + setAccessToken(data.accessToken, payload.remember) + writeSession(toSession(data.user), payload.remember) + return { success: true } + } catch (err) { + if (err instanceof ApiError) { + return { success: false, message: err.message } + } + return { success: false, message: 'ورود انجام نشد.' } + } +} + +/** Refresh session from GET /auth/me when a token exists. */ +export async function refreshAdminSession(): Promise { + const token = getAccessToken() + if (!token) return readSession() + + if (USE_MOCK_AUTH || token === 'mock-admin-token') { + const session = readSession() ?? MOCK_ADMIN.session + writeSession(session, isRememberedToken()) + return session + } + + try { + const user = await apiRequest('/auth/me') + const session = toSession(user) + writeSession(session, isRememberedToken()) + return session + } catch { + return readSession() + } +} + +export function logoutAdmin() { + setAccessToken(null) + clearSession() +} diff --git a/src/services/http.ts b/src/services/http.ts new file mode 100644 index 0000000..d64ceaf --- /dev/null +++ b/src/services/http.ts @@ -0,0 +1,118 @@ +const TOKEN_KEY = 'fabric-admin-token' + +export function getApiBaseUrl(): string { + return (import.meta.env.VITE_API_BASE_URL as string | undefined)?.replace(/\/$/, '') + || 'https://parche.montest.ir/server/api' +} + +export function getAccessToken(): string | null { + return localStorage.getItem(TOKEN_KEY) ?? sessionStorage.getItem(TOKEN_KEY) +} + +export function setAccessToken(token: string | null, remember = true): void { + localStorage.removeItem(TOKEN_KEY) + sessionStorage.removeItem(TOKEN_KEY) + if (!token) return + if (remember) localStorage.setItem(TOKEN_KEY, token) + else sessionStorage.setItem(TOKEN_KEY, token) +} + +export class ApiError extends Error { + status: number + constructor(status: number, message: string) { + super(message) + this.status = status + } +} + +type RequestOptions = { + method?: string + body?: unknown + auth?: boolean + query?: Record +} + +function buildUrl(path: string, query?: RequestOptions['query']): string { + const base = getApiBaseUrl() + const joined = path.startsWith('http') + ? path + : `${base.replace(/\/$/, '')}/${path.replace(/^\//, '')}` + + const url = joined.startsWith('http') + ? new URL(joined) + : new URL(joined, typeof window !== 'undefined' ? window.location.origin : 'http://127.0.0.1') + + if (query) { + for (const [key, value] of Object.entries(query)) { + if (value === undefined || value === null || value === '') continue + url.searchParams.set(key, String(value)) + } + } + return url.toString() +} + +function errorMessageFromBody(data: unknown, status: number): string { + if (typeof data === 'object' && data && 'message' in data) { + const message = (data as { message: unknown }).message + if (Array.isArray(message)) return message.join('، ') + return String(message) + } + if (typeof data === 'string') { + if (/upstream error/i.test(data)) { + return 'سرور API در دسترس نیست. کمی بعد دوباره تلاش کنید.' + } + if (data.trim() && !data.trimStart().startsWith('<')) { + return data.trim().slice(0, 200) + } + } + return `خطای سرور (${status})` +} + +export async function apiRequest(path: string, options: RequestOptions = {}): Promise { + const headers: Record = { + Accept: 'application/json', + } + if (options.body !== undefined) { + headers['Content-Type'] = 'application/json' + } + if (options.auth !== false) { + const token = getAccessToken() + if (token) headers.Authorization = `Bearer ${token}` + } + + let res: Response + try { + res = await fetch(buildUrl(path, options.query), { + method: options.method ?? (options.body !== undefined ? 'POST' : 'GET'), + headers, + body: options.body !== undefined ? JSON.stringify(options.body) : undefined, + signal: AbortSignal.timeout(20_000), + }) + } catch (err) { + const timedOut = + (err instanceof DOMException && err.name === 'TimeoutError') || + (err instanceof Error && err.name === 'TimeoutError') + throw new ApiError( + 0, + timedOut + ? 'پاسخ سرور طول کشید. دوباره تلاش کنید.' + : 'اتصال به سرور برقرار نشد. اینترنت یا آدرس API را بررسی کنید.', + ) + } + + const text = await res.text() + let data: unknown = null + if (text) { + try { + data = JSON.parse(text) + } catch { + data = text + } + } + + if (!res.ok) { + throw new ApiError(res.status, errorMessageFromBody(data, res.status)) + } + + return data as T +} diff --git a/src/stores/auth.ts b/src/stores/auth.ts new file mode 100644 index 0000000..ee3ab0d --- /dev/null +++ b/src/stores/auth.ts @@ -0,0 +1,73 @@ +import { defineStore } from 'pinia' +import { computed, ref } from 'vue' +import type { AdminSession } from '@/types/auth' +import { + getStoredSession, + loginAdmin, + logoutAdmin, + refreshAdminSession, +} from '@/services/authService' + +export const useAuthStore = defineStore('auth', () => { + const session = ref(getStoredSession()) + const loading = ref(false) + const error = ref(null) + + const isAuthenticated = computed(() => !!session.value) + const fullName = computed(() => session.value?.fullName ?? '') + const roleLabel = computed(() => { + const map = { + admin: 'مدیر سیستم', + sales: 'واحد فروش', + finance: 'واحد مالی', + warehouse: 'انبار', + } as const + return session.value ? map[session.value.role] : '' + }) + + function clearError() { + error.value = null + } + + function hydrate() { + session.value = getStoredSession() + void refreshAdminSession().then((refreshed) => { + if (refreshed) session.value = refreshed + }) + } + + async function login(phone: string, password: string, remember: boolean) { + loading.value = true + error.value = null + + const result = await loginAdmin({ phone, password, remember }) + loading.value = false + + if (result.success) { + session.value = getStoredSession() + return true + } + + error.value = result.message ?? 'ورود انجام نشد.' + return false + } + + function logout() { + logoutAdmin() + session.value = null + error.value = null + } + + return { + session, + loading, + error, + isAuthenticated, + fullName, + roleLabel, + clearError, + hydrate, + login, + logout, + } +}) diff --git a/src/stores/theme.ts b/src/stores/theme.ts new file mode 100644 index 0000000..920d00c --- /dev/null +++ b/src/stores/theme.ts @@ -0,0 +1,34 @@ +import { defineStore } from 'pinia' +import { computed, watchEffect } from 'vue' +import { usePreferredDark, useStorage } from '@vueuse/core' + +export type ThemePreference = 'light' | 'dark' | 'system' + +export const useThemeStore = defineStore('theme', () => { + const preference = useStorage('ft_admin_theme', 'system') + const prefersDark = usePreferredDark() + + const resolved = computed<'light' | 'dark'>(() => { + if (preference.value === 'system') return prefersDark.value ? 'dark' : 'light' + return preference.value + }) + + const isDark = computed(() => resolved.value === 'dark') + + watchEffect(() => { + const root = document.documentElement + root.classList.toggle('dark', isDark.value) + root.style.colorScheme = resolved.value + }) + + function setPreference(value: ThemePreference) { + preference.value = value + } + + return { + preference, + resolved, + isDark, + setPreference, + } +}) diff --git a/src/types/auth.ts b/src/types/auth.ts new file mode 100644 index 0000000..b9593b6 --- /dev/null +++ b/src/types/auth.ts @@ -0,0 +1,18 @@ +export interface AdminSession { + id: string + fullName: string + phone: string + email: string + role: 'admin' | 'sales' | 'finance' | 'warehouse' +} + +export interface AdminLoginPayload { + phone: string + password: string + remember: boolean +} + +export interface AdminLoginResult { + success: boolean + message?: string +} diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..5c9457d --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,276 @@ +/** سطل‌های نمایشی پنل ادمین که سرور از وضعیت واقعی سفارش می‌سازد */ +export type OrderStatus = + | 'pending_review' + | 'awaiting_customer' + | 'pending_check' + | 'pending_payment' + | 'needs_correction' + | 'check_correction' + | 'final_approval' + | 'shipped' + | 'delivered' + | 'cancelled' + | 'rejected' + | 'expired' + +/** وضعیت واقعی سفارش در ماشین وضعیت سرور */ +export type RawOrderStatus = + | 'cart' + | 'submitted' + | 'awaiting_review' + | 'pricing' + | 'awaiting_settlement' + | 'awaiting_settlement_fix' + | 'cash_in_progress' + | 'cash_invoice_issued' + | 'awaiting_cash_payment' + | 'cash_payment_submitted' + | 'awaiting_cash_confirmation' + | 'cash_confirmed' + | 'check_in_progress' + | 'awaiting_check_review' + | 'check_needs_fix' + | 'check_rejected' + | 'checks_approved' + | 'final_approved' + | 'preparing' + | 'ready_to_ship' + | 'shipped' + | 'delivered' + | 'needs_correction' + | 'cancelled' + | 'rejected' + | 'expired' + +export type SettlementMethod = 'check' | 'cash' + +export type CheckStatus = 'pending_review' | 'approved' | 'rejected' + +export interface Company { + id: string + name: string + description: string + displayOrder: number + isActive: boolean + logoUrl: string | null +} + +export interface BankAccount { + id: string + companyId: string + bankName: string + accountNumber: string + accountHolder: string + cardNumber: string + iban: string + isActive: boolean + displayOrder: number +} + +export interface OrderItem { + id: string + catalogCode: string + productName: string + color: string + requestedMeterage: number + confirmedMeterage: number | null + supplyPrice: number | null + totalAmount: number | null + companyId?: string + companyName?: string +} + +export interface Order { + id: string + orderNumber: string + customerName: string + companyName: string + companyId: string + settlementMethod: SettlementMethod | null + totalAmount: number | null + meterage: number + status: OrderStatus + rawStatus?: RawOrderStatus + allowedTransitions?: RawOrderStatus[] + createdAt: string + customerPhone?: string + customerNationalId?: string + customerType?: string + items?: OrderItem[] +} + +export interface Check { + id: string + orderId: string + row: number + amount: number + bankName: string + sayadId: string + dueDate: string + status: CheckStatus + checkNumber?: string + ownerNationalId?: string + ownerFirstName?: string + ownerLastName?: string + branchName?: string + frontImage?: string + backImage?: string + notes?: string + mode?: string + createdAt?: string + updatedAt?: string + /** فقط در لیست سراسری چک‌ها */ + orderNumber?: string + customerName?: string + orderStatus?: string + settlementType?: SettlementMethod | null +} + +export interface OrderStatusHistoryItem { + id: string + fromStatus?: string | null + toStatus: string + changedBy: string + note?: string + reason?: string + changedAt: string +} + +export interface CheckDeadline { + id: string + label: string + tone: 'danger' | 'warning' | 'neutral' + count: number + amount: number +} + +export interface NavItem { + name: string + label: string + path: string + icon: string +} + +export interface InternalMessage { + id: string + senderName: string + subject: string + preview: string + sentAt: string + isRead: boolean + link?: string + orderId?: string +} + +export interface AdminNotification { + id: string + title: string + body: string + sentAt: string + isRead: boolean + tone?: 'info' | 'warning' | 'success' | 'danger' + link?: string + orderId?: string +} + +export type CustomerType = 'wholesale' | 'retail' + +export interface Customer { + id: string + name: string + phone: string + nationalId: string + customerType: CustomerType + companyName: string + companyId?: string | null + orderCount: number + totalMeterage: number + isActive: boolean + registeredAt: string + appRole?: 'customer' | 'agent' + agentCode?: string + levelDefId?: string | null + levelCode?: string + levelLabel?: string + assignedAgentId?: string | null + assignedAgentName?: string + brandIds?: string[] + brands?: { id: string; name: string }[] +} + +export interface Catalog { + id: string + companyId: string + companyName: string + code: string + name: string + displayOrder: number + productCount: number + isActive: boolean +} + +export interface Product { + id: string + catalogId: string + catalogCode: string + companyName: string + name: string + color: string + productCode: string + minMeterage: number + orderStep: number + price: number | null + internalStock: number + isActive: boolean + usageCategory?: string + season?: string + composition?: string + weaveType?: string + subtitle?: string + rollMeters?: number + isNew?: boolean + colors?: string[] + imageUrls?: string[] +} + +export type CashPaymentStatus = 'pending_review' | 'approved' | 'rejected' | 'expired' + +export interface CashPayment { + id: string + orderId: string + orderNumber: string + customerName: string + amount: number + paidAmount: number | null + transferDate: string | null + trackingCode: string + expiresAt: string + status: CashPaymentStatus +} + +export type ShipmentStatus = 'preparing' | 'ready' | 'shipped' | 'delivered' + +export interface Shipment { + id: string + orderId: string + orderNumber: string + customerName: string + carrier: string + trackingNumber: string + meterage: number + status: ShipmentStatus + shippedAt: string | null + deliveredAt: string | null +} + +export type UserRole = 'admin' | 'sales' | 'finance' | 'warehouse' + +export interface AdminUser { + id: string + fullName: string + phone: string + email: string + role: UserRole + isActive: boolean + lastLoginAt: string | null +} diff --git a/src/utils/adminLabels.ts b/src/utils/adminLabels.ts new file mode 100644 index 0000000..6a7e595 --- /dev/null +++ b/src/utils/adminLabels.ts @@ -0,0 +1,41 @@ +import type { CashPaymentStatus, CustomerType, ShipmentStatus, UserRole } from '@/types' + +export const CUSTOMER_TYPE_LABELS: Record = { + wholesale: 'عمده‌فروش', + retail: 'خرده‌فروش', +} + +export const USER_ROLE_LABELS: Record = { + admin: 'مدیر سیستم', + sales: 'واحد فروش', + finance: 'واحد مالی', + warehouse: 'انبار', +} + +export const CASH_PAYMENT_STATUS_LABELS: Record = { + pending_review: 'در انتظار تأیید', + approved: 'تأیید شده', + rejected: 'رد شده', + expired: 'منقضی‌شده', +} + +export const CASH_PAYMENT_STATUS_BADGE: Record = { + pending_review: 'admin-badge--warning', + approved: 'admin-badge--success', + rejected: 'admin-badge--danger', + expired: 'admin-badge--neutral', +} + +export const SHIPMENT_STATUS_LABELS: Record = { + preparing: 'در حال آماده‌سازی', + ready: 'آماده ارسال', + shipped: 'ارسال شده', + delivered: 'تحویل شده', +} + +export const SHIPMENT_STATUS_BADGE: Record = { + preparing: 'admin-badge--warning', + ready: 'admin-badge--info', + shipped: 'admin-badge--purple', + delivered: 'admin-badge--success', +} diff --git a/src/utils/catalogImage.ts b/src/utils/catalogImage.ts new file mode 100644 index 0000000..a2049e3 --- /dev/null +++ b/src/utils/catalogImage.ts @@ -0,0 +1,46 @@ +const MAX_EDGE = 960 +const JPEG_QUALITY = 0.82 + +export async function fileToCatalogImage(file: File): Promise { + if (!file.type.startsWith('image/')) { + throw new Error('فقط فایل تصویری مجاز است.') + } + if (file.size > 8 * 1024 * 1024) { + throw new Error('حجم تصویر نباید بیشتر از ۸ مگابایت باشد.') + } + + const dataUrl = await readFileAsDataUrl(file) + return resizeDataUrl(dataUrl) +} + +function readFileAsDataUrl(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader() + reader.onload = () => resolve(String(reader.result ?? '')) + reader.onerror = () => reject(new Error('خواندن تصویر ناموفق بود.')) + reader.readAsDataURL(file) + }) +} + +function resizeDataUrl(src: string): Promise { + return new Promise((resolve, reject) => { + const image = new Image() + image.onload = () => { + const scale = Math.min(1, MAX_EDGE / Math.max(image.width, image.height)) + const width = Math.max(1, Math.round(image.width * scale)) + const height = Math.max(1, Math.round(image.height * scale)) + const canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height + const ctx = canvas.getContext('2d') + if (!ctx) { + reject(new Error('پردازش تصویر ناموفق بود.')) + return + } + ctx.drawImage(image, 0, 0, width, height) + resolve(canvas.toDataURL('image/jpeg', JPEG_QUALITY)) + } + image.onerror = () => reject(new Error('تصویر نامعتبر است.')) + image.src = src + }) +} diff --git a/src/utils/format.ts b/src/utils/format.ts new file mode 100644 index 0000000..52b2a3d --- /dev/null +++ b/src/utils/format.ts @@ -0,0 +1,100 @@ +const persianDigits = '۰۱۲۳۴۵۶۷۸۹' +const numberFormatter = new Intl.NumberFormat('fa-IR', { useGrouping: true }) + +export function normalizeDigits(input: string): string { + return input.replace(/[۰-۹]/g, (digit) => String(persianDigits.indexOf(digit))) +} + +export function extractNumericString(input: string): string { + return normalizeDigits(input).replace(/[^\d]/g, '') +} + +export function parseFormattedNumber(value: string): number { + const numeric = extractNumericString(value) + return numeric ? Number(numeric) : 0 +} + +export function formatNumber(value: number): string { + if (!Number.isFinite(value)) return '—' + return numberFormatter.format(value) +} + +export function formatCurrency(value: number): string { + return `${formatNumber(value)} تومان` +} + +export function formatMeterage(value: number): string { + return `${formatNumber(value)} متر` +} + +export function toPersianDigits(input: string | number): string { + return String(input).replace(/\d/g, (d) => persianDigits[Number(d)]!) +} + +const persianDateFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', { + year: 'numeric', + month: '2-digit', + day: '2-digit', +}) + +const persianDateTimeFormatter = new Intl.DateTimeFormat('fa-IR-u-ca-persian', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit', +}) + +/** Detect already-Jalali date strings like 1403/07/30 or 1403-07-30 */ +function isJalaliDateString(value: string): boolean { + const normalized = normalizeDigits(value.trim()).replace(/-/g, '/') + const match = normalized.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})/) + if (!match) return false + const year = Number(match[1]) + return year >= 1300 && year <= 1500 +} + +function toDateValue(date: string | Date): Date { + if (typeof date !== 'string') return date + const trimmed = date.trim() + // فقط تاریخِ بدون ساعت (YYYY-MM-DD) را به‌صورت تقویم محلی بخوان تا شیفت UTC روز را جابه‌جا نکند. + // رشته‌های دارای ساعت (…T10:30:00 یا … 10:30) باید کامل پارس شوند. + const dateOnly = trimmed.match(/^(\d{4})-(\d{2})-(\d{2})$/) + if (dateOnly && Number(dateOnly[1]) >= 1700) { + return new Date(Number(dateOnly[1]), Number(dateOnly[2]) - 1, Number(dateOnly[3])) + } + const parsed = new Date(trimmed) + if (Number.isNaN(parsed.getTime())) return new Date(NaN) + return parsed +} + +export function formatDate(date: string | Date | null | undefined): string { + if (!date) return '—' + if (typeof date === 'string' && isJalaliDateString(date)) { + const normalized = normalizeDigits(date.trim()).replace(/-/g, '/') + const match = normalized.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})/) + if (!match) return toPersianDigits(normalized) + const [, y, m, d] = match + return toPersianDigits(`${y}/${m!.padStart(2, '0')}/${d!.padStart(2, '0')}`) + } + const value = toDateValue(date) + if (Number.isNaN(value.getTime())) return '—' + return persianDateFormatter.format(value) +} + +export function formatDateTime(date: string | Date | null | undefined): string { + if (!date) return '—' + if (typeof date === 'string' && isJalaliDateString(date) && !/[T\s]\d/.test(date)) { + return formatDate(date) + } + const value = toDateValue(date) + if (Number.isNaN(value.getTime())) return '—' + return persianDateTimeFormatter.format(value) +} + +export function generateOrderNumber(): string { + const year = new Intl.DateTimeFormat('fa-IR-u-ca-persian', { year: 'numeric' }).format(new Date()) + const persianYear = year.replace(/[^\d]/g, '') || '1403' + const seq = Math.floor(Math.random() * 9000) + 1000 + return `ORD-${persianYear}-${seq}` +} diff --git a/src/utils/inboxLinks.ts b/src/utils/inboxLinks.ts new file mode 100644 index 0000000..a9e07fe --- /dev/null +++ b/src/utils/inboxLinks.ts @@ -0,0 +1,112 @@ +/** Resolve admin header message/notification click targets. */ + +const ORDER_NUMBER_RE = /ORD-?\d{2,4}-?\d{2,6}/i +const BARE_ORDER_PATH_RE = /^\/?(?:admin\/)?orders\/([^/?#]+)\/?$/i +const ORDER_SUBPATH_RE = /^\/?(?:admin\/)?orders\/([^/?#]+)\/(pricing|checks)\/?$/i + +export function extractOrderNumber(text: string): string | null { + const match = text.match(ORDER_NUMBER_RE) + if (!match?.[0]) return null + const digits = match[0].toUpperCase().replace(/^ORD-?/, '').replace(/-/g, '') + if (digits.length < 6) return match[0].toUpperCase() + const year = digits.slice(0, 4) + const seq = digits.slice(4) + return `ORD-${year}-${seq}` +} + +function hasKeyword(text: string, patterns: RegExp[]): boolean { + return patterns.some((pattern) => pattern.test(text)) +} + +/** Rewrite API links to routes that exist in the admin app. */ +export function normalizeAdminInboxLink(link: string): string { + let path = link.trim() + if (!path) return path + + try { + if (/^https?:\/\//i.test(path)) { + const url = new URL(path) + path = `${url.pathname}${url.search}` + } + } catch { + /* keep raw path */ + } + + path = path.replace(/^\/admin(?=\/)/, '') + if (!path.startsWith('/')) path = `/${path}` + + const sub = path.match(ORDER_SUBPATH_RE) + if (sub?.[1] && sub[2]) { + return `/orders/${sub[1]}/${sub[2]}` + } + + const bare = path.match(BARE_ORDER_PATH_RE) + if (bare?.[1]) { + return `/orders?order=${encodeURIComponent(bare[1])}` + } + + return path +} + +export type InboxLinkInput = { + link?: string | null + orderId?: string | null + title?: string | null + body?: string | null +} + +/** + * Prefer explicit `link`, then `orderId` + keywords, then order number / keyword heuristics. + */ +export function resolveAdminInboxLink(input: InboxLinkInput): string | null { + const explicit = input.link?.trim() + if (explicit) return normalizeAdminInboxLink(explicit) + + const title = input.title?.trim() ?? '' + const body = input.body?.trim() ?? '' + const text = `${title} ${body}` + const orderId = input.orderId?.trim() || null + const orderNumber = extractOrderNumber(text) + + const isSms = hasKeyword(text, [/پیامک/]) + const isCheck = hasKeyword(text, [/چک/]) + const isPricing = hasKeyword(text, [/قیمت/, /تخفیف/, /پیش[‌\s]?فاکتور/, /قیمت‌گذاری/, /اصلاح قیمت/]) + const isShipping = !isSms && hasKeyword(text, [/ارسال/, /باربری/, /حمل/, /بارنامه/]) + const isCash = hasKeyword(text, [/نقدی/, /پرداخت نقد/, /رسید پرداخت/]) + const isReport = hasKeyword(text, [/گزارش/]) + const isCustomer = hasKeyword(text, [/مشتری جدید/, /ثبت مشتری/]) + const isCatalog = hasKeyword(text, [/کالیته/]) + const isProduct = hasKeyword(text, [/محصول/]) + const isCompany = hasKeyword(text, [/شرکت/, /حساب بانکی/]) + const isOrderish = hasKeyword(text, [/سفارش/]) + const isSettings = isSms || hasKeyword(text, [/پشتیبان/, /تنظیمات/]) + + if (orderId) { + if (isCheck) return `/orders/${orderId}/checks` + if (isPricing) return `/orders/${orderId}/pricing` + if (isShipping) return `/shipping?order=${encodeURIComponent(orderId)}` + if (isCash) return `/cash-payments?order=${encodeURIComponent(orderId)}` + return `/orders?order=${encodeURIComponent(orderId)}` + } + + if (orderNumber) { + if (isCheck) return `/orders?order=${encodeURIComponent(orderNumber)}&focus=checks` + if (isPricing) return `/orders?order=${encodeURIComponent(orderNumber)}&focus=pricing` + if (isShipping) return `/shipping?order=${encodeURIComponent(orderNumber)}` + if (isCash) return `/cash-payments?order=${encodeURIComponent(orderNumber)}` + return `/orders?order=${encodeURIComponent(orderNumber)}` + } + + if (isCheck) return '/checks' + if (isShipping) return '/shipping' + if (isCash) return '/cash-payments' + if (isReport) return '/reports' + if (isCustomer) return '/customers' + if (isCatalog) return '/catalogs' + if (isProduct) return '/products' + if (isCompany) return '/companies' + if (isSettings) return '/settings' + if (isPricing || isOrderish) return '/orders' + + return null +} diff --git a/src/utils/navigation.ts b/src/utils/navigation.ts new file mode 100644 index 0000000..5ec09b0 --- /dev/null +++ b/src/utils/navigation.ts @@ -0,0 +1,38 @@ +import type { NavItem } from '@/types' + +export const ADMIN_NAV_ITEMS: NavItem[] = [ + { name: 'dashboard', label: 'داشبورد', path: '/', icon: 'home' }, + { name: 'orders', label: 'سفارش‌ها', path: '/orders', icon: 'orders' }, + { name: 'customers', label: 'مشتریان', path: '/customers', icon: 'customers' }, + { name: 'products', label: 'محصولات', path: '/products', icon: 'products' }, + { name: 'categories', label: 'دسته‌بندی‌ها', path: '/categories', icon: 'catalogs' }, + { name: 'banners', label: 'بنرها', path: '/banners', icon: 'image' }, + { name: 'catalogs', label: 'کالیته‌ها', path: '/catalogs', icon: 'catalogs' }, + { + name: 'catalog-requests', + label: 'درخواست کالیته فیزیکی', + path: '/catalog-requests', + icon: 'file', + }, + { name: 'brands', label: 'برندها', path: '/brands', icon: 'building' }, + { name: 'suggestions', label: 'پیشنهاد محصول', path: '/suggestions', icon: 'cart' }, + { name: 'stock-alerts', label: 'خبر موجودی', path: '/stock-alerts', icon: 'bell' }, + { name: 'levels', label: 'سطوح مشتری', path: '/levels', icon: 'users' }, + { name: 'companies', label: 'شرکت‌ها', path: '/companies', icon: 'companies' }, + { name: 'checks', label: 'چک‌ها', path: '/checks', icon: 'checks' }, + { name: 'cash-payments', label: 'پرداخت‌های نقدی', path: '/cash-payments', icon: 'cash' }, + { name: 'shipping', label: 'ارسال و باربری', path: '/shipping', icon: 'shipping' }, + { name: 'reports', label: 'گزارش‌ها', path: '/reports', icon: 'reports' }, + { name: 'settings', label: 'تنظیمات', path: '/settings', icon: 'settings' }, + { name: 'users', label: 'کاربران و دسترسی‌ها', path: '/users', icon: 'users' }, +] + +export function isNavActive(path: string, currentPath: string): boolean { + if (path === '/') return currentPath === '/' + // چک‌های یک سفارش زیر منوی «چک‌ها» فعال می‌شود، نه «سفارش‌ها» + if (/^\/orders\/[^/]+\/checks/.test(currentPath)) { + if (path === '/checks') return true + if (path === '/orders') return false + } + return currentPath === path || currentPath.startsWith(`${path}/`) +} diff --git a/src/utils/orderStatus.ts b/src/utils/orderStatus.ts new file mode 100644 index 0000000..1da7c83 --- /dev/null +++ b/src/utils/orderStatus.ts @@ -0,0 +1,88 @@ +import type { OrderStatus, RawOrderStatus } from '@/types' + +export interface StatusMeta { + label: string + tone: 'warning' | 'purple' | 'success' | 'danger' | 'info' | 'neutral' | 'delivered' +} + +export const ORDER_STATUS_META: Record = { + pending_review: { label: 'در انتظار بررسی', tone: 'warning' }, + awaiting_customer: { label: 'در انتظار مشتری', tone: 'info' }, + pending_check: { label: 'بررسی چک', tone: 'purple' }, + pending_payment: { label: 'بررسی رسید پرداخت', tone: 'purple' }, + needs_correction: { label: 'نیاز به اصلاح', tone: 'danger' }, + check_correction: { label: 'نیاز به اصلاح چک', tone: 'warning' }, + final_approval: { label: 'تأیید نهایی', tone: 'success' }, + shipped: { label: 'ارسال شده', tone: 'info' }, + delivered: { label: 'تحویل شده', tone: 'delivered' }, + cancelled: { label: 'لغو شده', tone: 'neutral' }, + rejected: { label: 'رد شده', tone: 'danger' }, + expired: { label: 'منقضی شده', tone: 'neutral' }, +} + +/** برچسب وضعیت واقعی سفارش؛ باید با ORDER_STATUS_LABELS سرور یکسان بماند. */ +export const RAW_ORDER_STATUS_LABELS: Record = { + cart: 'سبد خرید', + submitted: 'ثبت‌شده', + awaiting_review: 'در انتظار بررسی', + pricing: 'قیمت‌گذاری', + awaiting_settlement: 'در انتظار تسویه', + awaiting_settlement_fix: 'اصلاح تسویه', + cash_in_progress: 'در حال ثبت نقدی', + cash_invoice_issued: 'صدور فاکتور نقدی', + awaiting_cash_payment: 'در انتظار پرداخت نقدی', + cash_payment_submitted: 'رسید نقدی ارسال‌شده', + awaiting_cash_confirmation: 'تأیید پرداخت نقدی', + cash_confirmed: 'پرداخت نقدی تأیید شد', + check_in_progress: 'در حال ثبت چک', + awaiting_check_review: 'بررسی چک', + check_needs_fix: 'اصلاح چک', + check_rejected: 'رد چک', + checks_approved: 'تأیید چک‌ها', + final_approved: 'تأیید نهایی', + preparing: 'آماده‌سازی', + ready_to_ship: 'آماده ارسال', + shipped: 'ارسال‌شده', + delivered: 'تحویل‌شده', + needs_correction: 'نیاز به اصلاح', + cancelled: 'لغو شده', + rejected: 'رد شده', + expired: 'منقضی', +} + +export function rawStatusLabel(status?: string): string { + if (!status) return '—' + return RAW_ORDER_STATUS_LABELS[status as RawOrderStatus] ?? status +} + +/** وضعیت‌هایی که هنوز فاکتور صادر نشده و قیمت‌گذاری اقدام اصلی است. */ +export const PRE_INVOICE_RAW_STATUSES: RawOrderStatus[] = [ + 'cart', + 'submitted', + 'awaiting_review', + 'pricing', + 'needs_correction', +] + +const PRE_INVOICE_ADMIN_STATUSES: OrderStatus[] = ['pending_review', 'needs_correction'] + +export function canPriceOrder(order: { + status: OrderStatus + rawStatus?: RawOrderStatus +}): boolean { + if (order.rawStatus) return PRE_INVOICE_RAW_STATUSES.includes(order.rawStatus) + return PRE_INVOICE_ADMIN_STATUSES.includes(order.status) +} + +export const ORDER_TABS = [ + { key: 'all', label: 'همه' }, + { key: 'pending_review', label: 'در انتظار بررسی' }, + { key: 'awaiting_customer', label: 'در انتظار مشتری' }, + { key: 'pending_check', label: 'بررسی چک' }, + { key: 'pending_payment', label: 'بررسی رسید' }, + { key: 'check_correction', label: 'اصلاح چک' }, + { key: 'needs_correction', label: 'نیاز به اصلاح' }, + { key: 'final_approval', label: 'تأیید نهایی' }, + { key: 'shipped', label: 'ارسال شده' }, + { key: 'delivered', label: 'تحویل شده' }, +] as const diff --git a/src/views/auth/LoginView.vue b/src/views/auth/LoginView.vue new file mode 100644 index 0000000..c224701 --- /dev/null +++ b/src/views/auth/LoginView.vue @@ -0,0 +1,301 @@ + + + + + diff --git a/src/views/banners/BannersView.vue b/src/views/banners/BannersView.vue new file mode 100644 index 0000000..c4ff747 --- /dev/null +++ b/src/views/banners/BannersView.vue @@ -0,0 +1,240 @@ + + + + + diff --git a/src/views/brands/BrandsView.vue b/src/views/brands/BrandsView.vue new file mode 100644 index 0000000..d58c4d8 --- /dev/null +++ b/src/views/brands/BrandsView.vue @@ -0,0 +1,130 @@ + + +