commit fd3e5e512610ddbb0571b0505b3c6c016dbed709 Author: safavimohadeseh78 Date: Mon Aug 3 09:57:24 2026 +0200 Initial commit: fabric-trade-user Vue 3 app with mobile and desktop layouts 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/.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..cd68f14 --- /dev/null +++ b/.gitignore @@ -0,0 +1,39 @@ +# 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 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..c2c0f87 --- /dev/null +++ b/README.md @@ -0,0 +1,48 @@ +# fabric-trade + +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/env.d.ts b/env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/env.d.ts @@ -0,0 +1 @@ +/// 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..f7b2849 --- /dev/null +++ b/index.html @@ -0,0 +1,14 @@ + + + + + + + + سامانه سفارش عمده پارچه + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..a3b0773 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5167 @@ +{ + "name": "fabric-trade", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "fabric-trade", + "version": "0.0.0", + "dependencies": { + "jalaali-js": "^2.0.0", + "pinia": "^4.0.2", + "vue": "^3.5.40", + "vue-router": "^5.2.0" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.4", + "@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/@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/@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==", + "dev": true, + "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-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==", + "dev": true, + "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==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/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/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/@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/@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/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.10", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.10.tgz", + "integrity": "sha512-35JEvJ5/KKlbCHjMCsONI2w6HE88STjVdHk+C7d8LtcFxUjZR1KeLP9izofn2qs0KUxX5r4z73bwH/rd+JHacw==", + "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/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/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/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/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/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.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/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/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/jalaali-js": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/jalaali-js/-/jalaali-js-2.0.0.tgz", + "integrity": "sha512-HkWlwO3KxuYwERP1jsn+5M+QA+EKpIJ+zGesLee5VJNn2d2Melue0uQIvd9C/0QYFR7XVWvfF/uiNEz9Jbr9Hw==", + "license": "MIT", + "engines": { + "node": ">=20" + } + }, + "node_modules/jiti": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "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/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-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/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==", + "dev": true, + "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-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/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/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/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/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==", + "dev": true, + "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/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==", + "dev": true, + "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==", + "dev": true, + "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/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/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/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..a91e206 --- /dev/null +++ b/package.json @@ -0,0 +1,47 @@ +{ + "name": "fabric-trade", + "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": { + "jalaali-js": "^2.0.0", + "pinia": "^4.0.2", + "vue": "^3.5.40", + "vue-router": "^5.2.0" + }, + "devDependencies": { + "@tsconfig/node24": "^24.0.4", + "@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/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..d8a0da8 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,24 @@ + + + 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/app-shell.css b/src/assets/styles/app-shell.css new file mode 100644 index 0000000..2c69a5a --- /dev/null +++ b/src/assets/styles/app-shell.css @@ -0,0 +1,128 @@ +/* Application shell — global (unscoped) layout breakpoints */ + +.app-shell { + height: 100dvh; + display: flex; + width: 100%; + background: var(--color-shell-bg); + overflow: hidden; +} + +.app-layout { + display: flex; + flex-direction: row; + width: 100%; + height: 100%; + min-height: 0; +} + +.app-frame { + width: 100%; + height: 100%; + background: var(--color-bg); + display: flex; + flex-direction: column; + overflow: hidden; + min-width: 0; + flex: 1; +} + +.app-main { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + overflow: hidden; +} + +.app-main__content { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + overflow: hidden; +} + +.app-content { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + width: 100%; + max-width: var(--content-max-width); + margin-inline: auto; + padding-inline: var(--page-padding); +} + +@media (min-width: 768px) { + .app-content { + padding-inline: var(--page-padding-tablet); + } +} + +@media (min-width: 1200px) { + .app-content { + padding-inline: var(--page-padding-desktop); + } +} + +/* ── Mobile: full-width native app (< 768px) ── */ +.app-shell--with-nav { + justify-content: stretch; +} + +.app-shell--with-nav .app-frame { + max-width: 100%; + margin: 0; + border-radius: 0; + box-shadow: none; +} + +/* ── Tablet + Desktop: sidebar + header shell (>= 768px) ── */ +@media (min-width: 768px) { + .app-shell--with-nav { + background: var(--color-page-background); + } + + .app-shell--with-nav .app-frame { + background: var(--color-page-background); + } + + .app-shell--with-nav .app-main__content { + overflow-y: auto; + } +} + +/* ── Guest pages (login, checkout) ── */ +@media (min-width: 768px) { + .app-shell--no-nav { + align-items: center; + justify-content: center; + padding: 24px; + background: var(--color-page-background); + } + + .app-shell--no-nav .app-layout { + max-width: var(--form-max-width); + width: 100%; + height: auto; + max-height: calc(100dvh - 48px); + } + + .app-shell--no-nav .app-frame { + max-width: var(--form-max-width); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-frame); + max-height: calc(100dvh - 48px); + background: var(--color-surface); + } + + .app-shell--no-nav.app-shell--wide .app-layout, + .app-shell--no-nav.app-shell--wide .app-frame { + max-width: min(var(--content-max-width), calc(100vw - 48px)); + } + + .app-shell--no-nav.app-shell--wide .app-frame { + background: var(--color-bg); + } +} diff --git a/src/assets/styles/desktop-pages.css b/src/assets/styles/desktop-pages.css new file mode 100644 index 0000000..cb36c24 --- /dev/null +++ b/src/assets/styles/desktop-pages.css @@ -0,0 +1,230 @@ +/* Desktop page composition — >= 768px shell, >= 1200px full desktop */ + +@media (min-width: 768px) { + .desktop-page { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + width: 100%; + max-width: var(--content-max-width); + margin-inline: auto; + padding: 20px 0 28px; + background: transparent; + } + + .desktop-page__head { + margin-bottom: 20px; + } + + .desktop-page__title { + margin: 0 0 6px; + font-size: 1.375rem; + font-weight: 700; + color: var(--color-text); + } + + .desktop-page__subtitle { + margin: 0; + font-size: 0.875rem; + color: var(--color-text-muted); + } + + .desktop-two-col { + display: grid; + grid-template-columns: minmax(0, 1fr) var(--summary-panel-width, 320px); + gap: 24px; + align-items: start; + } + + .desktop-two-col__main { + min-width: 0; + } + + .desktop-summary-panel { + position: sticky; + top: 16px; + padding: 20px; + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + box-shadow: var(--shadow-card); + } + + .desktop-summary-panel__title { + margin: 0 0 16px; + padding-bottom: 12px; + border-bottom: 1px solid var(--color-border); + font-size: 0.9375rem; + font-weight: 700; + } + + .desktop-summary-panel__row { + display: flex; + justify-content: space-between; + align-items: center; + gap: 12px; + padding: 8px 0; + font-size: 0.875rem; + } + + .desktop-summary-panel__row span:first-child { + color: var(--color-text-muted); + } + + .desktop-summary-panel__row strong { + color: var(--color-text); + font-variant-numeric: tabular-nums; + } + + .desktop-summary-panel__action { + margin-top: 16px; + } + + .desktop-table-wrap { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + box-shadow: var(--shadow-card); + overflow: hidden; + } + + .desktop-table-scroll { + overflow-x: auto; + } + + .desktop-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; + min-width: 640px; + } + + .desktop-table th { + padding: 12px 16px; + text-align: start; + font-size: 0.8125rem; + font-weight: 600; + color: var(--color-text-muted); + background: #f8fafc; + border-bottom: 1px solid var(--color-border); + white-space: nowrap; + } + + .desktop-table td { + padding: 14px 16px; + border-bottom: 1px solid #f1f5f9; + color: var(--color-text); + vertical-align: middle; + } + + .desktop-table tbody tr:last-child td { + border-bottom: none; + } + + .desktop-table tbody tr:hover td { + background: #fafbfc; + } + + .desktop-grid-2 { + display: grid; + grid-template-columns: repeat(2, minmax(280px, 1fr)); + gap: 16px; + } + + .desktop-grid-3 { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; + } + + .desktop-grid-4 { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 14px; + } + + .desktop-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 16px; + flex-wrap: wrap; + } + + .desktop-toolbar__actions { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; + } + + .desktop-btn-compact { + width: auto !important; + min-width: 120px; + padding-inline: 20px !important; + } + + .desktop-form-grid { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 16px; + } + + .desktop-form-grid__full { + grid-column: 1 / -1; + } + + .desktop-checkout-shell { + width: 100%; + max-width: min(var(--content-max-width), calc(100vw - 48px)); + margin-inline: auto; + padding: 24px 0 32px; + } + + .desktop-settlement-grid { + display: grid; + grid-template-columns: repeat(2, minmax(280px, 380px)); + gap: 20px; + justify-content: center; + max-width: 820px; + margin-inline: auto; + } + + .desktop-company-grid { + display: grid; + grid-template-columns: repeat(2, minmax(280px, 400px)); + gap: 20px; + justify-content: center; + max-width: 900px; + margin-inline: auto; + width: 100%; + } +} + +@media (min-width: 1200px) { + .desktop-page { + padding: 24px 0 32px; + } + + .desktop-page__head { + margin-bottom: 24px; + } + + .desktop-grid-3 { + grid-template-columns: repeat(3, minmax(0, 1fr)); + gap: 20px; + } + + .desktop-grid-4 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 16px; + } +} + +@media (min-width: 1440px) { + .desktop-grid-3 { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } +} diff --git a/src/assets/styles/desktop.css b/src/assets/styles/desktop.css new file mode 100644 index 0000000..2fed109 --- /dev/null +++ b/src/assets/styles/desktop.css @@ -0,0 +1,652 @@ +/* App shell page layouts — 768px and above */ + +@media (min-width: 768px) { + :root { + --page-padding: var(--page-padding-tablet); + --nav-height: 0px; + } + + .page { + padding: 20px var(--page-padding-tablet) 28px; + background: transparent; + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + .page__scroll { + overflow: visible; + flex: none; + } + + .page__scroll--with-nav { + padding-bottom: 0; + } + + /* Shared page headings */ + .page-head { + margin-bottom: 20px; + } + + .page-head__title { + margin: 0 0 4px; + font-size: 1.25rem; + font-weight: 700; + color: var(--color-text); + } + + .page-head__subtitle { + margin: 0; + font-size: 0.875rem; + color: var(--color-text-muted); + } + + /* Orders dashboard */ + .orders-page__desktop-head { + margin-bottom: 20px; + } + + .orders-page__desktop-title { + margin: 0 0 6px; + font-size: 1.375rem; + font-weight: 700; + color: var(--color-text); + } + + .orders-page__desktop-subtitle { + margin: 0; + font-size: 0.875rem; + color: var(--color-text-muted); + } + + .orders-stats { + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 14px; + margin-bottom: 20px; + } + + .orders-stat-card { + padding: 16px 18px 14px; + background: var(--color-surface); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + box-shadow: var(--shadow-sm); + display: flex; + flex-direction: column; + align-items: stretch; + gap: 0; + min-height: 0; + } + + .orders-stat-card__head { + display: flex; + align-items: center; + justify-content: space-between; + gap: 10px; + margin-bottom: 10px; + } + + .orders-stat-card__label { + font-size: 0.8125rem; + font-weight: 600; + line-height: 1.4; + } + + .orders-stat-card__label--total, + .orders-stat-card__label--review { + color: var(--color-text); + } + + .orders-stat-card__label--active { + color: #ea580c; + } + + .orders-stat-card__label--done { + color: var(--color-success); + } + + .orders-stat-card__value { + font-size: 1.75rem; + font-weight: 700; + color: var(--color-text); + line-height: 1.15; + margin: 0 0 12px; + font-variant-numeric: tabular-nums; + } + + .orders-stat-card__link { + margin-top: auto; + padding: 0; + border: none; + background: none; + color: var(--color-primary); + font-family: inherit; + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + text-decoration: underline; + text-underline-offset: 3px; + align-self: flex-start; + } + + .orders-stat-card__link:hover { + color: var(--color-primary-hover); + } + + .orders-stat-card__icon { + width: 40px; + height: 40px; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + } + + .orders-stat-card__icon--total { + background: var(--color-primary-soft); + color: var(--color-primary); + } + + .orders-stat-card__icon--review { + background: var(--color-primary-soft); + color: var(--color-primary); + } + + .orders-stat-card__icon--active { + background: var(--color-warning-light); + color: #ea580c; + } + + .orders-stat-card__icon--done { + background: var(--color-success-soft); + color: var(--color-success); + } + + .orders-toolbar { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + margin-bottom: 16px; + flex-wrap: wrap; + } + + .orders-toolbar__actions { + display: flex; + align-items: center; + gap: 8px; + flex-shrink: 0; + } + + .orders-toolbar__filter-btn { + display: inline-flex; + align-items: center; + gap: 8px; + height: 40px; + padding: 0 18px; + border: none; + border-radius: var(--radius-sm); + background: var(--color-primary); + color: #fff; + font-family: inherit; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + white-space: nowrap; + } + + .orders-toolbar__filter-btn:hover { + background: var(--color-primary-hover); + } + + .orders-toolbar__layout-btn { + width: 40px; + height: 40px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: var(--color-surface); + color: var(--color-text-muted); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + } + + .orders-toolbar__layout-btn:hover { + border-color: var(--color-primary); + color: var(--color-primary); + } + + .orders-toolbar__pills { + display: flex; + align-items: center; + gap: 8px; + flex-wrap: wrap; + flex: 1; + min-width: 0; + justify-content: flex-end; + } + + .orders-filter-pill { + height: 36px; + padding: 0 16px; + border: 1px solid var(--color-border); + border-radius: 999px; + background: var(--color-surface); + color: var(--color-text-muted); + font-family: inherit; + font-size: 0.8125rem; + font-weight: 500; + cursor: pointer; + white-space: nowrap; + transition: + background 0.15s, + color 0.15s, + border-color 0.15s; + } + + .orders-filter-pill:hover { + border-color: #cbd5e1; + color: var(--color-text); + } + + .orders-filter-pill--active { + background: var(--color-primary-soft); + border-color: #c7d7ff; + color: var(--color-primary); + font-weight: 600; + } + + .orders-table-wrap { + background: var(--color-surface); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + box-shadow: var(--shadow-card); + overflow: hidden; + } + + .orders-table-scroll { + overflow-x: auto; + } + + .orders-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; + min-width: 720px; + } + + .orders-table th { + padding: 14px 16px; + text-align: start; + font-weight: 600; + font-size: 0.8125rem; + color: var(--color-text-muted); + background: #f8fafc; + border-bottom: 1px solid var(--color-border); + white-space: nowrap; + } + + .orders-table td { + padding: 16px; + border-bottom: 1px solid #f1f5f9; + color: var(--color-text); + vertical-align: middle; + } + + .orders-table tr:last-child td { + border-bottom: none; + } + + .orders-table tbody tr:hover td { + background: #fafbfc; + } + + .orders-table__number { + font-weight: 700; + color: var(--color-text); + white-space: nowrap; + } + + .orders-table__amount { + font-weight: 600; + font-variant-numeric: tabular-nums; + white-space: nowrap; + } + + .orders-table__date { + color: var(--color-text-muted); + font-size: 0.8125rem; + white-space: nowrap; + } + + .orders-table__actions { + display: flex; + align-items: center; + gap: 8px; + } + + .orders-table__action { + padding: 7px 16px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: var(--color-surface); + color: var(--color-primary); + font-size: 0.8125rem; + font-weight: 600; + cursor: pointer; + font-family: inherit; + white-space: nowrap; + } + + .orders-table__action:hover { + background: var(--color-primary-soft); + border-color: #c7d7ff; + } + + .orders-table__menu { + width: 34px; + height: 34px; + border: none; + border-radius: var(--radius-sm); + background: transparent; + color: var(--color-text-muted); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + } + + .orders-table__menu:hover { + background: #f1f5f9; + color: var(--color-text); + } + + .orders-pagination { + display: flex; + align-items: center; + justify-content: space-between; + gap: 16px; + padding: 14px 16px; + border-top: 1px solid var(--color-border); + font-size: 0.8125rem; + color: var(--color-text-muted); + flex-wrap: wrap; + } + + .orders-pagination__summary { + white-space: nowrap; + } + + .orders-pagination__controls { + display: flex; + align-items: center; + gap: 4px; + } + + .orders-pagination__arrow { + width: 32px; + height: 32px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: var(--color-surface); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + padding: 0; + color: var(--color-text); + } + + .orders-pagination__arrow:disabled { + opacity: 0.4; + cursor: not-allowed; + } + + .orders-pagination__arrow:not(:disabled):hover { + border-color: var(--color-primary); + color: var(--color-primary); + } + + .orders-pagination__arrow-icon--prev { + transform: scaleX(-1); + } + + .orders-pagination__arrow-icon--next { + transform: none; + } + + .orders-pagination__ellipsis { + min-width: 24px; + text-align: center; + color: var(--color-text-muted); + } + + .orders-pagination__page { + min-width: 32px; + height: 32px; + padding: 0 6px; + border: 1px solid var(--color-border); + border-radius: var(--radius-sm); + background: var(--color-surface); + cursor: pointer; + font-family: inherit; + font-size: 0.8125rem; + color: var(--color-text); + } + + .orders-pagination__page:hover:not(.orders-pagination__page--active) { + border-color: var(--color-primary); + color: var(--color-primary); + } + + .orders-pagination__page--active { + background: var(--color-primary); + border-color: var(--color-primary); + color: #fff; + font-weight: 600; + } + + /* Product page desktop layout */ + .product-page__layout { + display: grid; + grid-template-columns: minmax(0, 1fr) 300px; + gap: 24px; + align-items: start; + } + + .product-page__main { + min-width: 0; + } + + .product-page__sidebar { + position: sticky; + top: 16px; + } + + .cart-summary-panel { + padding: 20px; + background: var(--color-surface); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + box-shadow: var(--shadow-card); + } + + .cart-summary-panel__title { + margin: 0 0 16px; + font-size: 0.9375rem; + font-weight: 700; + color: var(--color-text); + padding-bottom: 12px; + border-bottom: 1px solid var(--color-border); + } + + .cart-summary-panel__row { + display: flex; + justify-content: space-between; + align-items: center; + padding: 8px 0; + font-size: 0.875rem; + } + + .cart-summary-panel__row span:first-child { + color: var(--color-text-muted); + } + + .cart-summary-panel__row strong { + color: var(--color-text); + } + + .cart-summary-panel__btn { + margin-top: 16px; + } + + .product-page__scroll { + padding-bottom: 0; + } + + .product-page .sticky-footer { + display: none; + } + + .product-list { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + + /* Cart desktop */ + .cart-page { + max-width: var(--content-max-width); + margin-inline: auto; + padding: 20px var(--page-padding-tablet) 28px; + background: transparent; + } + + .cart-page__desktop-title { + margin: 0 0 16px; + font-size: 1.25rem; + font-weight: 700; + } + + .cart-page__body { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(280px, 320px); + gap: 20px 24px; + align-items: start; + } + + .cart-page__company { + grid-column: 1 / -1; + } + + /* Order detail desktop */ + .order-detail-page { + max-width: var(--content-max-width); + margin-inline: auto; + padding: 24px var(--page-padding-desktop) 32px; + background: transparent; + } + + .order-detail-page__tracking { + display: grid; + grid-template-columns: minmax(0, 1fr) 340px; + gap: 24px; + align-items: start; + } + + .order-detail-page__tracking > .status-hero { + grid-column: 1 / -1; + } + + .order-detail-page__tracking > .order-detail-back { + grid-column: 1 / -1; + } + + .order-detail-page__tracking > .tracking-card:first-of-type { + grid-column: 1; + } + + .order-detail-page__tracking > .tracking-summary { + grid-column: 2; + grid-row: 2 / span 2; + position: sticky; + top: 16px; + align-self: start; + } + + .order-detail-back { + display: inline-flex; + align-items: center; + gap: 6px; + margin-bottom: 20px; + padding: 0; + border: none; + background: none; + color: var(--color-primary); + font-family: inherit; + font-size: 0.875rem; + font-weight: 600; + cursor: pointer; + } + + /* Company select desktop */ + .company-select-page { + max-width: var(--content-max-width); + margin-inline: auto; + padding: 24px var(--page-padding-desktop); + background: transparent; + } + + /* Catalog desktop */ + .catalog-page { + background: transparent; + } + + .catalog-list { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + /* Profile desktop */ + .profile-page { + background: transparent; + } + + .profile-hero { + border-radius: var(--radius-md); + margin-inline: 0; + } +} + +@media (min-width: 1200px) { + :root { + --page-padding: var(--page-padding-desktop); + } + + .page { + padding: 24px var(--page-padding-desktop) 32px; + } + + .orders-stats { + gap: 16px; + margin-bottom: 24px; + } + + .orders-page__desktop-head { + margin-bottom: 24px; + } + + .orders-toolbar { + margin-bottom: 20px; + } + + .catalog-list { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .product-list { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} diff --git a/src/assets/styles/fonts.css b/src/assets/styles/fonts.css new file mode 100644 index 0000000..00e1d03 --- /dev/null +++ b/src/assets/styles/fonts.css @@ -0,0 +1,55 @@ +@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)_UltraLight.woff2') format('woff2'); + font-weight: 200; + 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)_Medium.woff2') format('woff2'); + font-weight: 600; + 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..58dcffa --- /dev/null +++ b/src/assets/styles/main.css @@ -0,0 +1,350 @@ +:root { + --color-primary: #17379f; + --color-primary-hover: #102b83; + --color-primary-soft: #eef3ff; + --color-primary-dark: #102b83; + --color-primary-light: #eef3ff; + --color-success: #159660; + --color-success-light: #eaf8f1; + --color-success-soft: #eaf8f1; + --color-warning: #f59e0b; + --color-warning-light: #fff6e5; + --color-danger: #dc3545; + --color-danger-light: #fee2e2; + --color-purple: #7c3aed; + --color-purple-light: #ede9fe; + --color-info: #17379f; + --color-info-light: #eef3ff; + --color-bg: #f6f7fb; + --color-page-background: #f6f7fb; + --color-shell-bg: #eef0f5; + --color-surface: #ffffff; + --color-border: #e5e8ef; + --color-text: #182033; + --color-text-primary: #182033; + --color-text-muted: #667085; + --color-text-secondary: #667085; + --color-tab-inactive-bg: #f1f5f9; + --color-tab-inactive-text: #64748b; + --color-summary-bg: #f1f5f9; + --radius-sm: 8px; + --radius-md: 12px; + --radius-lg: 16px; + --shadow-sm: 0 1px 2px rgba(16, 24, 40, 0.04); + --shadow-md: 0 4px 16px rgba(16, 24, 40, 0.06); + --shadow-card: 0 1px 2px rgba(16, 24, 40, 0.04), 0 4px 16px rgba(16, 24, 40, 0.04); + --shadow-frame: 0 8px 32px rgba(15, 23, 42, 0.1); + --nav-height: 64px; + --page-padding: 16px; + --page-padding-tablet: 20px; + --page-padding-desktop: 28px; + --page-gap: 12px; + --content-max-width: 1360px; + --form-max-width: 520px; + --auth-form-max-width: 440px; + --summary-panel-width: 320px; + --sidebar-width: 240px; + --sidebar-width-compact: 72px; + --header-height: 70px; + --app-shell-breakpoint: 768px; + --font-family: 'IRANSans', 'Tahoma', sans-serif; + --btn-height: 48px; + --desktop-breakpoint: 1200px; +} + +*, +*::before, +*::after { + box-sizing: border-box; +} + +html { + font-size: 16px; + -webkit-text-size-adjust: 100%; + overflow: hidden; + height: 100%; +} + +body { + margin: 0; + font-family: var(--font-family); + background: var(--color-shell-bg); + color: var(--color-text); + line-height: 1.5; + direction: rtl; + overflow: hidden; + height: 100%; +} + +#app { + height: 100dvh; + overflow: hidden; +} + +* { + scrollbar-width: none; + -ms-overflow-style: none; +} + +*::-webkit-scrollbar { + width: 0; + height: 0; + display: none; +} + +a { + color: var(--color-primary); + text-decoration: none; +} + +button, +input, +select, +textarea { + font-family: inherit; +} + +input[type='number']::-webkit-inner-spin-button, +input[type='number']::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type='number'] { + -moz-appearance: textfield; +} + +.page { + flex: 1; + display: flex; + flex-direction: column; + min-height: 0; + overflow: hidden; + padding: 12px var(--page-padding) 0; + background: #ffffff; +} + +.page__scroll { + flex: 1; + min-height: 0; + overflow-y: auto; + overscroll-behavior: contain; + -webkit-overflow-scrolling: touch; +} + +.page__scroll--with-nav { + padding-bottom: 12px; +} + +.page-title { + font-size: 1.25rem; + font-weight: 700; + line-height: 1.35; + margin: 0 0 4px; + color: var(--color-text); +} + +.page-subtitle { + font-size: 0.875rem; + color: var(--color-text-muted); + margin: 0; + line-height: 1.5; +} + +.card { + background: var(--color-surface); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + padding: 16px; + box-shadow: var(--shadow-sm); +} + +.card + .card { + margin-top: var(--page-gap); +} + +.alert { + padding: 12px 14px; + border-radius: var(--radius-sm); + font-size: 0.875rem; + line-height: 1.5; +} + +.alert-info { + background: var(--color-primary-light); + color: var(--color-primary); + border: 1px solid #cbd5e1; +} + +.alert-warning { + background: var(--color-warning-light); + color: #9a3412; + border: 1px solid #fed7aa; +} + +.alert-success { + background: var(--color-success-light); + color: #155724; + border: 1px solid #c3e6cb; +} + +.alert-danger { + background: var(--color-danger-light); + color: #991b1b; + border: 1px solid #fecaca; +} + +.form-group { + margin-bottom: 16px; +} + +.form-label { + display: block; + font-size: 0.875rem; + font-weight: 600; + margin-bottom: 6px; + color: var(--color-text); +} + +.form-hint { + font-size: 0.75rem; + color: var(--color-text-muted); + margin-top: 4px; +} + +.divider { + height: 1px; + background: var(--color-border); + margin: 16px 0; +} + +.text-muted { + color: var(--color-text-muted); +} + +.text-sm { + font-size: 0.875rem; +} + +.text-center { + text-align: center; +} + +.mt-2 { + margin-top: 8px; +} + +.mt-4 { + margin-top: 16px; +} + +.mb-4 { + margin-bottom: 16px; +} + +.flex-between { + display: flex; + justify-content: space-between; + align-items: center; + gap: 8px; +} + +.sticky-footer { + position: fixed; + bottom: var(--nav-height); + inset-inline: 0; + width: 100%; + max-width: 100%; + z-index: 50; + padding-inline: var(--page-padding); + box-sizing: border-box; +} + +.sticky-footer-inner { + max-width: 100%; +} + +.no-nav .page { + padding-bottom: 0; +} + +.no-nav .sticky-footer { + bottom: 0; +} + +.dialog-overlay { + position: fixed; + inset: 0; + background: rgba(15, 23, 42, 0.4); + display: flex; + align-items: center; + justify-content: center; + padding: 24px; + z-index: 200; +} + +.dialog-overlay .dialog { + width: 100%; + max-width: 400px; +} + +.dialog-actions { + display: flex; + flex-direction: column; + gap: 8px; + margin-top: 16px; +} + +/* Responsive visibility */ +.mobile-only, +.mobile-block { + display: block; +} + +.desktop-only { + display: none !important; +} + +.mobile-hidden { + display: block; +} + +.desktop-hidden { + display: none !important; +} + +@media (min-width: 768px) { + .mobile-only, + .mobile-block { + display: none !important; + } + + .desktop-only { + display: block !important; + } + + .mobile-hidden { + display: none !important; + } + + .desktop-hidden { + display: block !important; + } + + .desktop-only-flex { + display: flex !important; + } + + .desktop-only-grid { + display: grid !important; + } + + .page { + padding: 0; + background: transparent; + } + + .page__scroll--with-nav { + padding-bottom: 0; + } +} diff --git a/src/assets/styles/responsive.css b/src/assets/styles/responsive.css new file mode 100644 index 0000000..943f541 --- /dev/null +++ b/src/assets/styles/responsive.css @@ -0,0 +1,362 @@ +/* Responsive breakpoints: + Mobile: < 768px + Tablet: 768px – 1199px + Desktop: >= 1200px + Large desktop: >= 1440px +*/ + +@media (min-width: 768px) { + :root { + --page-padding: var(--page-padding-tablet); + --nav-height: 0px; + } + + html, + body { + overflow: auto; + height: auto; + } + + #app { + height: 100dvh; + overflow: hidden; + } + + * { + scrollbar-width: thin; + scrollbar-color: #cbd5e1 transparent; + } + + *::-webkit-scrollbar { + width: 6px; + height: 6px; + display: block; + } + + *::-webkit-scrollbar-thumb { + background: #cbd5e1; + border-radius: 999px; + } + + .sticky-footer { + bottom: 0; + max-width: min(var(--content-max-width), calc(100% - 2 * var(--page-padding))); + } + + .no-nav .sticky-footer { + bottom: 0; + } + + /* Auth pages */ + .auth-page__scroll { + display: flex; + flex-direction: column; + align-items: center; + padding-top: 48px; + padding-bottom: 48px; + } + + .auth-header, + .auth-page .card, + .auth-footer { + width: 100%; + max-width: var(--form-max-width); + } + + /* Company selection */ + .company-select-page__list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; + align-content: start; + } + + .company-brand-card { + min-height: 220px; + } + + /* Catalog & product grids */ + .catalog-list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--page-gap); + } + + .product-list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: var(--page-gap); + align-items: start; + } + + .product-page__scroll { + padding-bottom: 88px; + } + + /* Settlement & check mode */ + .settlement-options, + .mode-options { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 20px; + max-width: 720px; + margin-inline: auto; + } + + /* Company page container */ + .company-select-page { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + padding-inline: var(--page-padding); + } + + .company-select-page__header { + max-width: 560px; + margin-inline: auto; + } + + /* Catalog & orders page containers */ + .catalog-page .page__scroll, + .orders-page__scroll, + .product-page .product-page__scroll { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + /* Cart two-column layout */ + .cart-page { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + padding-inline: var(--page-padding); + } + + .cart-page__body { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(260px, 300px); + grid-template-rows: auto 1fr; + gap: 16px 20px; + align-items: start; + } + + .cart-page__company { + grid-column: 1 / -1; + font-size: 0.9375rem; + margin-bottom: 0; + } + + .cart-page__scroll { + grid-column: 1; + max-height: none; + overflow: visible; + } + + .cart-page__footer { + grid-column: 2; + grid-row: 1 / -1; + position: sticky; + top: 16px; + margin: 0; + padding: 16px; + border-top: none; + box-shadow: var(--shadow-md); + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + } + + .cart-table__head { + position: static; + } + + /* Check list */ + .check-list-page { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + padding-inline: var(--page-padding); + } + + .check-list-page__scroll { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + .summary-cards { + gap: 16px; + } + + .checks-list { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + align-items: start; + } + + .rass-panel { + max-width: 480px; + margin-inline: auto; + } + + /* Profile */ + .profile-page__scroll { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + .profile-menu { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + } + + .profile-menu__item { + border-radius: var(--radius-md); + border: 1px solid var(--color-border); + background: var(--color-surface); + box-shadow: var(--shadow-sm); + } + + /* Order detail & tracking */ + .order-detail-page__body { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + .order-detail-page__tracking { + display: grid; + grid-template-columns: minmax(0, 1fr) minmax(280px, 340px); + gap: 20px; + align-items: start; + } + + .order-detail-page__tracking > .status-hero { + grid-column: 1 / -1; + } + + .order-detail-page__tracking > .tracking-card { + grid-column: 1; + } + + .order-detail-page__tracking > .tracking-summary { + grid-column: 2; + grid-row: 2; + position: sticky; + top: 16px; + align-self: start; + } + + .order-detail-page__footer { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + padding-inline: var(--page-padding); + } + + /* Checkout forms */ + .checkout-page__scroll, + .cash-page__scroll, + .settlement-page__scroll, + .check-mode-page__scroll { + max-width: var(--form-max-width); + margin-inline: auto; + width: 100%; + } + + /* Cash settlement desktop */ + .cash-page { + max-width: var(--content-max-width); + margin-inline: auto; + width: 100%; + } + + .cash-page__footer { + max-width: var(--form-max-width); + margin-inline: auto; + width: 100%; + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + border-top: none; + box-shadow: none; + padding-top: 16px; + } + + .accounts-panel { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; + } + + .bank-card + .bank-card { + margin-top: 0; + } + + .cash-page__submit { + margin-top: 0; + } + + .order-info-card { + max-width: 520px; + margin-inline: auto; + } + + /* Profile edit */ + .profile-edit-page .page__scroll { + max-width: var(--form-max-width); + margin-inline: auto; + width: 100%; + } + + /* Success page */ + .success-page__scroll { + display: flex; + flex-direction: column; + align-items: center; + max-width: var(--form-max-width); + margin-inline: auto; + width: 100%; + } + + /* Dialogs */ + .dialog-overlay .dialog, + .dialog-overlay .card.dialog { + max-width: 480px; + width: 100%; + } + + .dialog-actions { + flex-direction: row; + justify-content: flex-end; + } +} + +@media (min-width: 1200px) { + :root { + --page-padding: var(--page-padding-desktop); + } + + .catalog-list { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + + .checks-list { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } +} + +@media (min-width: 1440px) { + .product-list { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } +} + +@media (min-width: 1920px) { + :root { + --content-max-width: 1120px; + } +} diff --git a/src/components/icons/IconBell.vue b/src/components/icons/IconBell.vue new file mode 100644 index 0000000..ddd7c1d --- /dev/null +++ b/src/components/icons/IconBell.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/icons/IconBolt.vue b/src/components/icons/IconBolt.vue new file mode 100644 index 0000000..c445861 --- /dev/null +++ b/src/components/icons/IconBolt.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/components/icons/IconBuilding.vue b/src/components/icons/IconBuilding.vue new file mode 100644 index 0000000..4108e66 --- /dev/null +++ b/src/components/icons/IconBuilding.vue @@ -0,0 +1,21 @@ + + + diff --git a/src/components/icons/IconCart.vue b/src/components/icons/IconCart.vue new file mode 100644 index 0000000..933ac0d --- /dev/null +++ b/src/components/icons/IconCart.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/components/icons/IconCash.vue b/src/components/icons/IconCash.vue new file mode 100644 index 0000000..92b8c12 --- /dev/null +++ b/src/components/icons/IconCash.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/icons/IconCashSettlement.vue b/src/components/icons/IconCashSettlement.vue new file mode 100644 index 0000000..5dc53cf --- /dev/null +++ b/src/components/icons/IconCashSettlement.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/icons/IconCatalog.vue b/src/components/icons/IconCatalog.vue new file mode 100644 index 0000000..5bc74e6 --- /dev/null +++ b/src/components/icons/IconCatalog.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/components/icons/IconCheckBook.vue b/src/components/icons/IconCheckBook.vue new file mode 100644 index 0000000..3dfd43d --- /dev/null +++ b/src/components/icons/IconCheckBook.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/components/icons/IconCheckCircleOutline.vue b/src/components/icons/IconCheckCircleOutline.vue new file mode 100644 index 0000000..a9bad91 --- /dev/null +++ b/src/components/icons/IconCheckCircleOutline.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/icons/IconChevronBack.vue b/src/components/icons/IconChevronBack.vue new file mode 100644 index 0000000..45c145a --- /dev/null +++ b/src/components/icons/IconChevronBack.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/icons/IconChevronLeft.vue b/src/components/icons/IconChevronLeft.vue new file mode 100644 index 0000000..521e9c3 --- /dev/null +++ b/src/components/icons/IconChevronLeft.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/icons/IconClipboardEmpty.vue b/src/components/icons/IconClipboardEmpty.vue new file mode 100644 index 0000000..b605030 --- /dev/null +++ b/src/components/icons/IconClipboardEmpty.vue @@ -0,0 +1,75 @@ + + + + + diff --git a/src/components/icons/IconDiamond.vue b/src/components/icons/IconDiamond.vue new file mode 100644 index 0000000..5ccd3db --- /dev/null +++ b/src/components/icons/IconDiamond.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/components/icons/IconEditPen.vue b/src/components/icons/IconEditPen.vue new file mode 100644 index 0000000..bda5184 --- /dev/null +++ b/src/components/icons/IconEditPen.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/icons/IconFamBaftLogo.vue b/src/components/icons/IconFamBaftLogo.vue new file mode 100644 index 0000000..60b0f1a --- /dev/null +++ b/src/components/icons/IconFamBaftLogo.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/icons/IconFeather.vue b/src/components/icons/IconFeather.vue new file mode 100644 index 0000000..9e2b591 --- /dev/null +++ b/src/components/icons/IconFeather.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/icons/IconFilter.vue b/src/components/icons/IconFilter.vue new file mode 100644 index 0000000..6f76880 --- /dev/null +++ b/src/components/icons/IconFilter.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/icons/IconHeadset.vue b/src/components/icons/IconHeadset.vue new file mode 100644 index 0000000..50d320b --- /dev/null +++ b/src/components/icons/IconHeadset.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/icons/IconHome.vue b/src/components/icons/IconHome.vue new file mode 100644 index 0000000..563ddb4 --- /dev/null +++ b/src/components/icons/IconHome.vue @@ -0,0 +1,27 @@ + + + diff --git a/src/components/icons/IconHourglass.vue b/src/components/icons/IconHourglass.vue new file mode 100644 index 0000000..c74e8bf --- /dev/null +++ b/src/components/icons/IconHourglass.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/icons/IconIdCard.vue b/src/components/icons/IconIdCard.vue new file mode 100644 index 0000000..4cd9ac0 --- /dev/null +++ b/src/components/icons/IconIdCard.vue @@ -0,0 +1,11 @@ + + + diff --git a/src/components/icons/IconLayoutGrid.vue b/src/components/icons/IconLayoutGrid.vue new file mode 100644 index 0000000..5ef52e1 --- /dev/null +++ b/src/components/icons/IconLayoutGrid.vue @@ -0,0 +1,25 @@ + + + diff --git a/src/components/icons/IconLightbulb.vue b/src/components/icons/IconLightbulb.vue new file mode 100644 index 0000000..dcf03d8 --- /dev/null +++ b/src/components/icons/IconLightbulb.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/icons/IconLock.vue b/src/components/icons/IconLock.vue new file mode 100644 index 0000000..08330e1 --- /dev/null +++ b/src/components/icons/IconLock.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/icons/IconMail.vue b/src/components/icons/IconMail.vue new file mode 100644 index 0000000..6a51a63 --- /dev/null +++ b/src/components/icons/IconMail.vue @@ -0,0 +1,10 @@ + + + diff --git a/src/components/icons/IconMapPin.vue b/src/components/icons/IconMapPin.vue new file mode 100644 index 0000000..ed3266b --- /dev/null +++ b/src/components/icons/IconMapPin.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/icons/IconMoreVertical.vue b/src/components/icons/IconMoreVertical.vue new file mode 100644 index 0000000..1342aea --- /dev/null +++ b/src/components/icons/IconMoreVertical.vue @@ -0,0 +1,23 @@ + + + diff --git a/src/components/icons/IconOrders.vue b/src/components/icons/IconOrders.vue new file mode 100644 index 0000000..ae85291 --- /dev/null +++ b/src/components/icons/IconOrders.vue @@ -0,0 +1,41 @@ + + + diff --git a/src/components/icons/IconParLogo.vue b/src/components/icons/IconParLogo.vue new file mode 100644 index 0000000..652d95f --- /dev/null +++ b/src/components/icons/IconParLogo.vue @@ -0,0 +1,26 @@ + + + diff --git a/src/components/icons/IconPhone.vue b/src/components/icons/IconPhone.vue new file mode 100644 index 0000000..6106975 --- /dev/null +++ b/src/components/icons/IconPhone.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/components/icons/IconProfile.vue b/src/components/icons/IconProfile.vue new file mode 100644 index 0000000..53e6688 --- /dev/null +++ b/src/components/icons/IconProfile.vue @@ -0,0 +1,28 @@ + + + diff --git a/src/components/icons/IconProgressClock.vue b/src/components/icons/IconProgressClock.vue new file mode 100644 index 0000000..b826761 --- /dev/null +++ b/src/components/icons/IconProgressClock.vue @@ -0,0 +1,29 @@ + + + diff --git a/src/components/icons/IconSearch.vue b/src/components/icons/IconSearch.vue new file mode 100644 index 0000000..a24a679 --- /dev/null +++ b/src/components/icons/IconSearch.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/icons/IconSettings.vue b/src/components/icons/IconSettings.vue new file mode 100644 index 0000000..406b0a3 --- /dev/null +++ b/src/components/icons/IconSettings.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/icons/IconShoppingBag.vue b/src/components/icons/IconShoppingBag.vue new file mode 100644 index 0000000..1950982 --- /dev/null +++ b/src/components/icons/IconShoppingBag.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/icons/IconSuccessCircle.vue b/src/components/icons/IconSuccessCircle.vue new file mode 100644 index 0000000..b7af4c7 --- /dev/null +++ b/src/components/icons/IconSuccessCircle.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/icons/IconTrash.vue b/src/components/icons/IconTrash.vue new file mode 100644 index 0000000..a91b068 --- /dev/null +++ b/src/components/icons/IconTrash.vue @@ -0,0 +1,48 @@ + + + diff --git a/src/components/icons/IconVerified.vue b/src/components/icons/IconVerified.vue new file mode 100644 index 0000000..504ade9 --- /dev/null +++ b/src/components/icons/IconVerified.vue @@ -0,0 +1,16 @@ + + + diff --git a/src/components/layout/AppLayout.vue b/src/components/layout/AppLayout.vue new file mode 100644 index 0000000..16f8f55 --- /dev/null +++ b/src/components/layout/AppLayout.vue @@ -0,0 +1,9 @@ + + + diff --git a/src/components/layout/BottomNav.vue b/src/components/layout/BottomNav.vue new file mode 100644 index 0000000..36181bd --- /dev/null +++ b/src/components/layout/BottomNav.vue @@ -0,0 +1,108 @@ + + + + + diff --git a/src/components/layout/CheckoutStepper.vue b/src/components/layout/CheckoutStepper.vue new file mode 100644 index 0000000..eb96b1d --- /dev/null +++ b/src/components/layout/CheckoutStepper.vue @@ -0,0 +1,141 @@ + + + + + diff --git a/src/components/layout/DesktopHeader.vue b/src/components/layout/DesktopHeader.vue new file mode 100644 index 0000000..4d5a47b --- /dev/null +++ b/src/components/layout/DesktopHeader.vue @@ -0,0 +1,292 @@ + + + + + diff --git a/src/components/layout/DesktopSidebar.vue b/src/components/layout/DesktopSidebar.vue new file mode 100644 index 0000000..f9ac060 --- /dev/null +++ b/src/components/layout/DesktopSidebar.vue @@ -0,0 +1,296 @@ + + + + + diff --git a/src/components/layout/PageHeader.vue b/src/components/layout/PageHeader.vue new file mode 100644 index 0000000..aa3dca6 --- /dev/null +++ b/src/components/layout/PageHeader.vue @@ -0,0 +1,148 @@ + + + + + diff --git a/src/components/orders/OrderStatusHero.vue b/src/components/orders/OrderStatusHero.vue new file mode 100644 index 0000000..79d4ac0 --- /dev/null +++ b/src/components/orders/OrderStatusHero.vue @@ -0,0 +1,76 @@ + + + + + diff --git a/src/components/orders/OrderTrackingSummary.vue b/src/components/orders/OrderTrackingSummary.vue new file mode 100644 index 0000000..d258271 --- /dev/null +++ b/src/components/orders/OrderTrackingSummary.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/src/components/orders/OrderTrackingTimeline.vue b/src/components/orders/OrderTrackingTimeline.vue new file mode 100644 index 0000000..96f3f81 --- /dev/null +++ b/src/components/orders/OrderTrackingTimeline.vue @@ -0,0 +1,167 @@ + + + + + diff --git a/src/components/ui/BaseBadge.vue b/src/components/ui/BaseBadge.vue new file mode 100644 index 0000000..e1e8b49 --- /dev/null +++ b/src/components/ui/BaseBadge.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/components/ui/BaseButton.vue b/src/components/ui/BaseButton.vue new file mode 100644 index 0000000..a656777 --- /dev/null +++ b/src/components/ui/BaseButton.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/components/ui/BaseInput.vue b/src/components/ui/BaseInput.vue new file mode 100644 index 0000000..fea2b89 --- /dev/null +++ b/src/components/ui/BaseInput.vue @@ -0,0 +1,67 @@ + + + + + diff --git a/src/components/ui/CapacitySummary.vue b/src/components/ui/CapacitySummary.vue new file mode 100644 index 0000000..0232184 --- /dev/null +++ b/src/components/ui/CapacitySummary.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/src/components/ui/CartMeterageFooter.vue b/src/components/ui/CartMeterageFooter.vue new file mode 100644 index 0000000..8110769 --- /dev/null +++ b/src/components/ui/CartMeterageFooter.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/src/components/ui/CurrencyInput.vue b/src/components/ui/CurrencyInput.vue new file mode 100644 index 0000000..13d02db --- /dev/null +++ b/src/components/ui/CurrencyInput.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/components/ui/EmptyState.vue b/src/components/ui/EmptyState.vue new file mode 100644 index 0000000..06583db --- /dev/null +++ b/src/components/ui/EmptyState.vue @@ -0,0 +1,52 @@ + + + + + diff --git a/src/components/ui/FilterTabs.vue b/src/components/ui/FilterTabs.vue new file mode 100644 index 0000000..861e38a --- /dev/null +++ b/src/components/ui/FilterTabs.vue @@ -0,0 +1,90 @@ + + + + + diff --git a/src/components/ui/FormErrorBanner.vue b/src/components/ui/FormErrorBanner.vue new file mode 100644 index 0000000..ad48720 --- /dev/null +++ b/src/components/ui/FormErrorBanner.vue @@ -0,0 +1,25 @@ + + + + + diff --git a/src/components/ui/MeterageBar.vue b/src/components/ui/MeterageBar.vue new file mode 100644 index 0000000..aa36bef --- /dev/null +++ b/src/components/ui/MeterageBar.vue @@ -0,0 +1,73 @@ + + + + + diff --git a/src/components/ui/PersianDateInput.vue b/src/components/ui/PersianDateInput.vue new file mode 100644 index 0000000..d999e12 --- /dev/null +++ b/src/components/ui/PersianDateInput.vue @@ -0,0 +1,328 @@ + + + + + diff --git a/src/components/ui/SearchField.vue b/src/components/ui/SearchField.vue new file mode 100644 index 0000000..9cddb1e --- /dev/null +++ b/src/components/ui/SearchField.vue @@ -0,0 +1,47 @@ + + + + + diff --git a/src/components/ui/StatusBadge.vue b/src/components/ui/StatusBadge.vue new file mode 100644 index 0000000..7d0c6c9 --- /dev/null +++ b/src/components/ui/StatusBadge.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/composables/useCartPage.ts b/src/composables/useCartPage.ts new file mode 100644 index 0000000..17b2274 --- /dev/null +++ b/src/composables/useCartPage.ts @@ -0,0 +1,56 @@ +import { computed, ref, onMounted } from 'vue' +import { useRouter } from 'vue-router' +import { useCartStore } from '@/stores/cart' + +export function useCartPage() { + const router = useRouter() + const cartStore = useCartStore() + const showFullDialog = ref(false) + + const items = computed(() => cartStore.activeCart?.items ?? []) + const isEmpty = computed(() => items.value.length === 0) + const companyName = computed(() => cartStore.activeCart?.companyName ?? '') + + function removeItem(itemId: string) { + cartStore.removeItem(itemId) + } + + function proceedToCheckout() { + if (items.value.length === 0) return + if (cartStore.isFull) { + showFullDialog.value = true + return + } + router.push('/checkout/settlement') + } + + function proceedAnyway() { + showFullDialog.value = false + router.push('/checkout/settlement') + } + + function createNewInvoice() { + cartStore.createNewCartForSameCompany() + showFullDialog.value = false + const companyId = cartStore.activeCart?.companyId + if (companyId) { + router.push(`/companies/${companyId}/catalogs`) + } + } + + onMounted(() => { + cartStore.ensureActiveCartForCartPage() + }) + + return { + cartStore, + items, + isEmpty, + companyName, + showFullDialog, + removeItem, + proceedToCheckout, + proceedAnyway, + createNewInvoice, + } +} diff --git a/src/composables/useOrderList.ts b/src/composables/useOrderList.ts new file mode 100644 index 0000000..ddcbdcd --- /dev/null +++ b/src/composables/useOrderList.ts @@ -0,0 +1,155 @@ +import { computed, ref, watch } from 'vue' +import { useRouter } from 'vue-router' +import { useOrderStore } from '@/stores/order' +import { useAuthStore } from '@/stores/auth' +import { getCompanyById } from '@/data/mockData' +import type { Order } from '@/types' +import { + DELIVERED_STATUSES, + IN_PROGRESS_STATUSES, + REVIEW_STATUSES, + matchesDesktopOrderFilter, + matchesMobileOrderTab, + type DesktopOrderFilterId, +} from '@/utils/orderStatusGroups' + +const DESKTOP_PAGE_SIZE = 5 + +export function useOrderList() { + const router = useRouter() + const orderStore = useOrderStore() + const authStore = useAuthStore() + const currentPage = ref(1) + + const tab = computed({ + get: () => (router.currentRoute.value.query.tab as string) ?? 'all', + set: (v: string) => router.replace({ query: { ...router.currentRoute.value.query, tab: v } }), + }) + + const desktopFilter = computed({ + get: () => (router.currentRoute.value.query.filter as DesktopOrderFilterId) ?? 'all', + set: (v: DesktopOrderFilterId) => + router.replace({ + query: { ...router.currentRoute.value.query, filter: v === 'all' ? undefined : v }, + }), + }) + + const searchQuery = computed(() => (router.currentRoute.value.query.q as string) ?? '') + + const orders = computed(() => { + if (!authStore.user) return [] + return orderStore.userOrders(authStore.user.id) + }) + + const stats = computed(() => ({ + total: orders.value.length, + review: orders.value.filter((o) => REVIEW_STATUSES.includes(o.status)).length, + inProgress: orders.value.filter((o) => IN_PROGRESS_STATUSES.includes(o.status)).length, + done: orders.value.filter((o) => DELIVERED_STATUSES.includes(o.status)).length, + })) + + function matchesSearch(order: Order, q: string): boolean { + if (!q.trim()) return true + const needle = q.trim().toLowerCase() + return ( + order.orderNumber.toLowerCase().includes(needle) || + order.companyName.toLowerCase().includes(needle) + ) + } + + const filteredOrdersMobile = computed(() => + orders.value + .filter((o) => matchesSearch(o, searchQuery.value)) + .filter((o) => matchesMobileOrderTab(o.status, tab.value)), + ) + + const filteredOrdersDesktop = computed(() => + orders.value + .filter((o) => matchesSearch(o, searchQuery.value)) + .filter((o) => matchesDesktopOrderFilter(o.status, desktopFilter.value)), + ) + + const paginatedOrders = computed(() => { + const start = (currentPage.value - 1) * DESKTOP_PAGE_SIZE + return filteredOrdersDesktop.value.slice(start, start + DESKTOP_PAGE_SIZE) + }) + + const totalPages = computed(() => + Math.max(1, Math.ceil(filteredOrdersDesktop.value.length / DESKTOP_PAGE_SIZE)), + ) + + const paginationRange = computed(() => { + if (filteredOrdersDesktop.value.length === 0) return { start: 0, end: 0 } + const start = (currentPage.value - 1) * DESKTOP_PAGE_SIZE + 1 + const end = Math.min(currentPage.value * DESKTOP_PAGE_SIZE, filteredOrdersDesktop.value.length) + return { start, end } + }) + + const visiblePages = computed(() => { + const total = totalPages.value + const current = currentPage.value + if (total <= 7) return Array.from({ length: total }, (_, i) => i + 1) + + const pages: (number | 'ellipsis')[] = [1] + if (current > 3) pages.push('ellipsis') + + const rangeStart = Math.max(2, current - 1) + const rangeEnd = Math.min(total - 1, current + 1) + for (let p = rangeStart; p <= rangeEnd; p += 1) pages.push(p) + + if (current < total - 2) pages.push('ellipsis') + if (total > 1) pages.push(total) + + return pages + }) + + watch([filteredOrdersDesktop, desktopFilter, searchQuery], () => { + currentPage.value = 1 + }) + + function companySlug(order: Order) { + return getCompanyById(order.companyId)?.slug ?? 'par' + } + + function iconVariant(order: Order) { + if (DELIVERED_STATUSES.includes(order.status)) return 'success' + return companySlug(order) === 'fam-baft' ? 'fam-baft' : 'par' + } + + function goToOrder(id: string) { + router.push(`/orders/${id}`) + } + + function setPage(page: number) { + if (page < 1 || page > totalPages.value) return + currentPage.value = page + } + + function setDesktopFilter(filter: DesktopOrderFilterId) { + desktopFilter.value = desktopFilter.value === filter && filter !== 'all' ? 'all' : filter + } + + function viewStatFilter(filter: DesktopOrderFilterId) { + desktopFilter.value = filter + } + + return { + tab, + desktopFilter, + searchQuery, + stats, + filteredOrdersMobile, + filteredOrdersDesktop, + paginatedOrders, + totalPages, + paginationRange, + visiblePages, + currentPage, + companySlug, + iconVariant, + goToOrder, + setPage, + setDesktopFilter, + viewStatFilter, + } +} diff --git a/src/composables/useProductOrdering.ts b/src/composables/useProductOrdering.ts new file mode 100644 index 0000000..f436e23 --- /dev/null +++ b/src/composables/useProductOrdering.ts @@ -0,0 +1,94 @@ +import { ref, computed } from 'vue' +import { useRoute, useRouter } from 'vue-router' +import { useCatalogStore } from '@/stores/catalog' +import { useCartStore } from '@/stores/cart' + +export function useProductOrdering() { + const route = useRoute() + const router = useRouter() + const catalogStore = useCatalogStore() + const cartStore = useCartStore() + + const companyId = computed(() => route.params.companyId as string) + const catalogId = computed(() => route.params.catalogId as string) + const catalog = computed(() => catalogStore.getCatalog(catalogId.value)) + const company = computed(() => catalogStore.getCompany(companyId.value)) + + const colorFilter = ref('all') + const colors = computed(() => ['all', ...catalogStore.getUniqueColors(catalogId.value)]) + const colorLabels: Record = { all: 'همه' } + + const products = computed(() => + catalogStore.fetchProducts( + catalogId.value, + colorFilter.value === 'all' ? undefined : colorFilter.value, + ), + ) + + const meterages = ref>({}) + const errors = ref>({}) + const toast = ref('') + + function getMeterage(productId: string) { + return meterages.value[productId] ?? 0 + } + + function adjustMeterage(productId: string, delta: number, step: number) { + const current = getMeterage(productId) + meterages.value[productId] = Math.max(0, current + delta * step) + } + + function addProduct(productId: string) { + const product = catalogStore.getProduct(productId) + if (!product || !catalog.value) return + + const meterage = getMeterage(productId) + if (meterage <= 0) { + errors.value[productId] = 'متراژ را وارد کنید.' + return + } + + const result = cartStore.addItem(product, catalog.value.code, meterage) + if (result.success) { + errors.value[productId] = '' + toast.value = `${product.name} به سبد اضافه شد.` + setTimeout(() => { + toast.value = '' + }, 2000) + } else { + errors.value[productId] = result.message ?? 'خطا' + } + } + + function setMeterage(productId: string, value: number) { + meterages.value[productId] = Math.max(0, value) + } + + function goToCart() { + router.push('/cart') + } + + function goBack() { + router.push(`/companies/${companyId.value}/catalogs`) + } + + return { + companyId, + catalogId, + catalog, + company, + colorFilter, + colors, + colorLabels, + products, + meterages, + errors, + toast, + cartStore, + adjustMeterage, + setMeterage, + addProduct, + goToCart, + goBack, + } +} diff --git a/src/data/mockData.ts b/src/data/mockData.ts new file mode 100644 index 0000000..398da00 --- /dev/null +++ b/src/data/mockData.ts @@ -0,0 +1,248 @@ +import type { BankAccount, Catalog, Company, Product } from '@/types' + +export const companies: Company[] = [ + { + id: 'company-par', + name: 'شرکت پَر', + slug: 'par', + description: 'تولیدکننده پارچه‌های باکیفیت', + isActive: true, + displayOrder: 1, + maxMeteragePerInvoice: 5000, + cashInvoiceValidityHours: 8, + cashInvoiceValidUntilHour: 17, + }, + { + id: 'company-fam-baft', + name: 'فام‌بافت', + slug: 'fam-baft', + description: 'عرضه پارچه‌های تخصصی', + isActive: true, + displayOrder: 2, + maxMeteragePerInvoice: 5000, + cashInvoiceValidityHours: 8, + cashInvoiceValidUntilHour: 17, + }, +] + +export const bankAccounts: BankAccount[] = [ + { + id: 'ba-par-1', + companyId: 'company-par', + bankName: 'بانک ملی', + accountHolder: 'شرکت پَر', + accountNumber: '0123456789', + cardNumber: '6037-9912-3456-7890', + iban: 'IR120170000000012345678901', + isActive: true, + displayOrder: 1, + }, + { + id: 'ba-par-2', + companyId: 'company-par', + bankName: 'بانک صادرات', + accountHolder: 'شرکت پَر', + accountNumber: '9876543210', + cardNumber: '6037-6912-3456-7891', + iban: 'IR620190000000098765432101', + isActive: true, + displayOrder: 2, + }, + { + id: 'ba-fam-1', + companyId: 'company-fam-baft', + bankName: 'بانک ملت', + accountHolder: 'فام‌بافت', + accountNumber: '1122334455', + cardNumber: '6104-3378-9012-3456', + iban: 'IR450120000000011223344556', + isActive: true, + displayOrder: 1, + }, +] + +export const catalogs: Catalog[] = [ + { + id: 'cat-377', + companyId: 'company-par', + name: 'کالیته ۳۷۷', + code: '377', + displayOrder: 1, + isActive: true, + }, + { + id: 'cat-378', + companyId: 'company-par', + name: 'کالیته ۳۷۸', + code: '378', + displayOrder: 2, + isActive: true, + }, + { + id: 'cat-379', + companyId: 'company-par', + name: 'کالیته ۳۷۹', + code: '379', + displayOrder: 3, + isActive: true, + }, + { + id: 'cat-380', + companyId: 'company-par', + name: 'کالیته ۳۸۰', + code: '380', + displayOrder: 4, + isActive: true, + }, + { + id: 'cat-381', + companyId: 'company-par', + name: 'کالیته ۳۸۱', + code: '381', + displayOrder: 5, + isActive: true, + }, + { + id: 'cat-fam-401', + companyId: 'company-fam-baft', + name: 'کالیته ۴۰۱', + code: '401', + displayOrder: 1, + isActive: true, + }, + { + id: 'cat-fam-402', + companyId: 'company-fam-baft', + name: 'کالیته ۴۰۲', + code: '402', + displayOrder: 2, + isActive: true, + }, +] + +export const products: Product[] = [ + { + id: 'prod-377-blue', + companyId: 'company-par', + catalogId: 'cat-377', + name: 'پارچه آبی', + code: '377-BL', + color: 'آبی', + minMeterage: 30, + orderMultiplier: 10, + isActive: true, + stock: 10000, + }, + { + id: 'prod-377-black', + companyId: 'company-par', + catalogId: 'cat-377', + name: 'پارچه مشکی', + code: '377-BK', + color: 'مشکی', + minMeterage: 30, + orderMultiplier: 10, + isActive: true, + stock: 8000, + }, + { + id: 'prod-378-blue', + companyId: 'company-par', + catalogId: 'cat-378', + name: 'آبی', + code: '378-BL', + color: 'آبی', + minMeterage: 50, + orderMultiplier: 10, + isActive: true, + stock: 5000, + }, + { + id: 'prod-378-black', + companyId: 'company-par', + catalogId: 'cat-378', + name: 'مشکی', + code: '378-BK', + color: 'مشکی', + minMeterage: 50, + orderMultiplier: 10, + isActive: true, + stock: 5000, + }, + { + id: 'prod-378-blue-white', + companyId: 'company-par', + catalogId: 'cat-378', + name: 'آبی پشت سفید', + code: '378-BLW', + color: 'آبی پشت سفید', + minMeterage: 50, + orderMultiplier: 10, + isActive: true, + stock: 3000, + }, + { + id: 'prod-378-black-white', + companyId: 'company-par', + catalogId: 'cat-378', + name: 'مشکی پشت سفید', + code: '378-BKW', + color: 'مشکی پشت سفید', + minMeterage: 50, + orderMultiplier: 10, + isActive: true, + stock: 3000, + }, + { + id: 'prod-fam-401-1', + companyId: 'company-fam-baft', + catalogId: 'cat-fam-401', + name: 'پارچه مخمل', + code: '401-MV', + color: 'سرمه‌ای', + minMeterage: 40, + orderMultiplier: 10, + isActive: true, + stock: 6000, + }, + { + id: 'prod-fam-401-2', + companyId: 'company-fam-baft', + catalogId: 'cat-fam-401', + name: 'پارچه کجراه', + code: '401-KJ', + color: 'کرم', + minMeterage: 40, + orderMultiplier: 10, + isActive: true, + stock: 4000, + }, +] + +export function getCompanyById(id: string): Company | undefined { + return companies.find((c) => c.id === id) +} + +export function getCatalogsByCompany(companyId: string): Catalog[] { + return catalogs + .filter((c) => c.companyId === companyId && c.isActive) + .sort((a, b) => a.displayOrder - b.displayOrder) +} + +export function getProductsByCatalog(catalogId: string): Product[] { + return products.filter((p) => p.catalogId === catalogId && p.isActive) +} + +export function getBankAccountsByCompany(companyId: string): BankAccount[] { + return bankAccounts + .filter((b) => b.companyId === companyId && b.isActive) + .sort((a, b) => a.displayOrder - b.displayOrder) +} + +export function getCatalogById(id: string): Catalog | undefined { + return catalogs.find((c) => c.id === id) +} + +export function getProductById(id: string): Product | undefined { + return products.find((p) => p.id === id) +} diff --git a/src/layouts/DefaultLayout.vue b/src/layouts/DefaultLayout.vue new file mode 100644 index 0000000..98caa5a --- /dev/null +++ b/src/layouts/DefaultLayout.vue @@ -0,0 +1,61 @@ + + + diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..adea8df --- /dev/null +++ b/src/main.ts @@ -0,0 +1,18 @@ +import { createApp } from 'vue' +import { createPinia } from 'pinia' + +import App from './App.vue' +import router from './router' +import './assets/styles/fonts.css' +import './assets/styles/main.css' +import './assets/styles/app-shell.css' +import './assets/styles/responsive.css' +import './assets/styles/desktop.css' +import './assets/styles/desktop-pages.css' + +const app = createApp(App) + +app.use(createPinia()) +app.use(router) + +app.mount('#app') diff --git a/src/router/index.ts b/src/router/index.ts new file mode 100644 index 0000000..71f89aa --- /dev/null +++ b/src/router/index.ts @@ -0,0 +1,135 @@ +import { createRouter, createWebHistory } from 'vue-router' +import { getCurrentUser } from '@/services/authService' + +const router = createRouter({ + history: createWebHistory(import.meta.env.BASE_URL), + routes: [ + { + path: '/login', + name: 'login', + component: () => import('@/views/auth/LoginView.vue'), + meta: { guest: true, hideNav: true }, + }, + { + path: '/register', + name: 'register', + component: () => import('@/views/auth/RegisterView.vue'), + meta: { guest: true, hideNav: true }, + }, + { + path: '/otp', + name: 'otp', + component: () => import('@/views/auth/OtpView.vue'), + meta: { guest: true, hideNav: true }, + }, + { + path: '/', + name: 'home', + component: () => import('@/views/companies/CompanySelectView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/companies/:companyId/catalogs', + name: 'catalogs', + component: () => import('@/views/catalogs/CatalogListView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/companies/:companyId/catalogs/:catalogId/products', + name: 'products', + component: () => import('@/views/products/ProductListView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/cart', + name: 'cart', + component: () => import('@/views/cart/CartView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/checkout/settlement', + name: 'settlement', + component: () => import('@/views/checkout/SettlementTypeView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/checkout/cash', + name: 'cash-settlement', + component: () => import('@/views/checkout/CashSettlementView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/checkout/check-mode', + name: 'check-mode', + component: () => import('@/views/checkout/CheckModeSelectView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/checkout/check-form', + name: 'check-form', + component: () => import('@/views/checkout/CheckFormView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/checkout/check-list', + name: 'check-list', + component: () => import('@/views/checkout/CheckListView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/orders', + name: 'orders', + component: () => import('@/views/OrdersView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/orders/:id', + name: 'order-detail', + component: () => import('@/views/orders/OrderDetailView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/orders/:id/success', + name: 'order-success', + component: () => import('@/views/orders/OrderSuccessView.vue'), + meta: { requiresAuth: true, hideNav: true }, + }, + { + path: '/profile', + name: 'profile', + component: () => import('@/views/profile/ProfileView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/profile/edit', + name: 'profile-edit', + component: () => import('@/views/profile/ProfileEditView.vue'), + meta: { requiresAuth: true }, + }, + { + path: '/profile/checks', + name: 'profile-checks', + component: () => import('@/views/profile/ProfileChecksView.vue'), + meta: { requiresAuth: true }, + }, + ], + scrollBehavior() { + return { top: 0 } + }, +}) + +router.beforeEach((to) => { + const isAuthenticated = !!getCurrentUser() + + if (to.meta.requiresAuth && !isAuthenticated) { + return { name: 'login', query: { redirect: to.fullPath } } + } + + if (to.meta.guest && isAuthenticated) { + return { name: 'home' } + } + + return true +}) + +export default router diff --git a/src/services/authService.ts b/src/services/authService.ts new file mode 100644 index 0000000..1b59aa6 --- /dev/null +++ b/src/services/authService.ts @@ -0,0 +1,130 @@ +import { MOCK_OTP_CODE } from '@/utils/constants' +import { generateId, normalizePhone } from '@/utils/format' +import { getItem, setItem, STORAGE_KEYS } from './storage' +import type { User } from '@/types' + +interface PendingOtp { + phone: string + firstName?: string + lastName?: string + isRegister: boolean + code: string + expiresAt: string +} + +export function getUsers(): User[] { + return getItem(STORAGE_KEYS.users, []) +} + +function saveUsers(users: User[]): void { + setItem(STORAGE_KEYS.users, users) +} + +export function getSessionUserId(): string | null { + return getItem(STORAGE_KEYS.session, null) +} + +export function setSessionUserId(userId: string | null): void { + setItem(STORAGE_KEYS.session, userId) +} + +export function getCurrentUser(): User | null { + const id = getSessionUserId() + if (!id) return null + return getUsers().find((u) => u.id === id) ?? null +} + +export async function sendOtp( + phone: string, + options: { firstName?: string; lastName?: string; isRegister: boolean }, +): Promise<{ success: boolean; message: string }> { + const normalized = normalizePhone(phone) + if (!/^09\d{9}$/.test(normalized)) { + return { success: false, message: 'شماره موبایل معتبر نیست.' } + } + + if (options.isRegister) { + if (!options.firstName?.trim() || !options.lastName?.trim()) { + return { success: false, message: 'نام و نام خانوادگی الزامی است.' } + } + const exists = getUsers().some((u) => u.phone === normalized) + if (exists) { + return { success: false, message: 'این شماره قبلاً ثبت شده است. وارد شوید.' } + } + } else { + const exists = getUsers().some((u) => u.phone === normalized) + if (!exists) { + return { success: false, message: 'کاربری با این شماره یافت نشد. ثبت‌نام کنید.' } + } + } + + const pending: PendingOtp = { + phone: normalized, + firstName: options.firstName, + lastName: options.lastName, + isRegister: options.isRegister, + code: MOCK_OTP_CODE, + expiresAt: new Date(Date.now() + 5 * 60 * 1000).toISOString(), + } + setItem(STORAGE_KEYS.pendingOtp, pending) + + return { + success: true, + message: `کد تأیید ارسال شد. (نسخه آزمایشی: ${MOCK_OTP_CODE})`, + } +} + +export async function verifyOtp( + phone: string, + code: string, +): Promise<{ success: boolean; message: string; user?: User }> { + const pending = getItem(STORAGE_KEYS.pendingOtp, null) + const normalized = normalizePhone(phone) + + if (!pending || pending.phone !== normalized) { + return { success: false, message: 'ابتدا درخواست کد دهید.' } + } + if (new Date(pending.expiresAt) < new Date()) { + return { success: false, message: 'کد منقضی شده است. دوباره درخواست دهید.' } + } + if (code.trim() !== pending.code) { + return { success: false, message: 'کد تأیید نادرست است.' } + } + + let user: User + const users = getUsers() + + if (pending.isRegister) { + user = { + id: generateId(), + firstName: pending.firstName!, + lastName: pending.lastName!, + phone: normalized, + createdAt: new Date().toISOString(), + } + users.push(user) + saveUsers(users) + } else { + user = users.find((u) => u.phone === normalized)! + } + + setSessionUserId(user.id) + setItem(STORAGE_KEYS.pendingOtp, null) + return { success: true, message: 'ورود موفق.', user } +} + +export function logout(): void { + setSessionUserId(null) +} + +export function updateProfile( + userId: string, + data: Partial>, +): User | null { + const users = getUsers() + const index = users.findIndex((u) => u.id === userId) + if (index === -1) return null + users[index] = { ...users[index]!, ...data } + saveUsers(users) + return users[index]! +} diff --git a/src/services/storage.ts b/src/services/storage.ts new file mode 100644 index 0000000..2c4c4d2 --- /dev/null +++ b/src/services/storage.ts @@ -0,0 +1,26 @@ +export function getItem(key: string, fallback: T): T { + try { + const raw = localStorage.getItem(key) + if (!raw) return fallback + return JSON.parse(raw) as T + } catch { + return fallback + } +} + +export function setItem(key: string, value: T): void { + localStorage.setItem(key, JSON.stringify(value)) +} + +export function removeItem(key: string): void { + localStorage.removeItem(key) +} + +export const STORAGE_KEYS = { + users: 'ft_users', + session: 'ft_session', + carts: 'ft_carts', + activeCartId: 'ft_active_cart_id', + orders: 'ft_orders', + pendingOtp: 'ft_pending_otp', +} as const diff --git a/src/stores/auth.ts b/src/stores/auth.ts new file mode 100644 index 0000000..b97a43a --- /dev/null +++ b/src/stores/auth.ts @@ -0,0 +1,80 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import type { User } from '@/types' +import { + getCurrentUser, + logout as authLogout, + sendOtp, + verifyOtp, + updateProfile as authUpdateProfile, +} from '@/services/authService' + +export const useAuthStore = defineStore('auth', () => { + const user = ref(getCurrentUser()) + const loading = ref(false) + const error = ref(null) + + const isAuthenticated = computed(() => !!user.value) + const fullName = computed(() => + user.value ? `${user.value.firstName} ${user.value.lastName}` : '', + ) + + function clearError() { + error.value = null + } + + async function requestOtp( + phone: string, + options: { firstName?: string; lastName?: string; isRegister: boolean }, + ) { + loading.value = true + error.value = null + const result = await sendOtp(phone, options) + loading.value = false + if (!result.success) error.value = result.message + return result + } + + async function confirmOtp(phone: string, code: string) { + loading.value = true + error.value = null + const result = await verifyOtp(phone, code) + loading.value = false + if (result.success && result.user) { + user.value = result.user + } else { + error.value = result.message + } + return result + } + + function logout() { + authLogout() + user.value = null + } + + function updateProfile(data: Partial>) { + if (!user.value) return null + const updated = authUpdateProfile(user.value.id, data) + if (updated) user.value = updated + return updated + } + + function hydrate() { + user.value = getCurrentUser() + } + + return { + user, + loading, + error, + isAuthenticated, + fullName, + clearError, + requestOtp, + confirmOtp, + logout, + updateProfile, + hydrate, + } +}) diff --git a/src/stores/cart.ts b/src/stores/cart.ts new file mode 100644 index 0000000..b99ae2e --- /dev/null +++ b/src/stores/cart.ts @@ -0,0 +1,260 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import type { Cart, CartItem, Company, Product } from '@/types' +import { generateId } from '@/utils/format' +import { validateMeterage } from '@/utils/validation' +import { getItem, setItem, STORAGE_KEYS } from '@/services/storage' +import { getCompanyById } from '@/data/mockData' + +function loadCarts(): Cart[] { + return getItem(STORAGE_KEYS.carts, []) +} + +function saveCarts(carts: Cart[]) { + setItem(STORAGE_KEYS.carts, carts) +} + +function loadActiveCartId(): string | null { + return getItem(STORAGE_KEYS.activeCartId, null) +} + +function saveActiveCartId(id: string | null) { + setItem(STORAGE_KEYS.activeCartId, id) +} + +function getCartTotalMeterage(cart: Cart): number { + return cart.items.reduce((sum, item) => sum + item.meterage, 0) +} + +function findOpenCartForCompany(carts: Cart[], company: Company): Cart | undefined { + return carts.find( + (cart) => + cart.companyId === company.id && + getCartTotalMeterage(cart) < company.maxMeteragePerInvoice, + ) +} + +export const useCartStore = defineStore('cart', () => { + const carts = ref(loadCarts()) + const activeCartId = ref(loadActiveCartId()) + const selectedCompanyId = ref(null) + + const activeCart = computed(() => carts.value.find((c) => c.id === activeCartId.value) ?? null) + + const totalMeterage = computed( + () => activeCart.value?.items.reduce((sum, i) => sum + i.meterage, 0) ?? 0, + ) + + const itemCount = computed(() => activeCart.value?.items.length ?? 0) + + const maxMeterage = computed(() => { + if (!activeCart.value) return 5000 + const company = getCompanyById(activeCart.value.companyId) + return company?.maxMeteragePerInvoice ?? 5000 + }) + + const remainingCapacity = computed(() => Math.max(0, maxMeterage.value - totalMeterage.value)) + + const isFull = computed(() => totalMeterage.value >= maxMeterage.value) + + function persist() { + saveCarts(carts.value) + saveActiveCartId(activeCartId.value) + } + + function initCartForCompany(company: Company): Cart { + const existing = findOpenCartForCompany(carts.value, company) + if (existing) { + activeCartId.value = existing.id + selectedCompanyId.value = company.id + persist() + return existing + } + + const cart: Cart = { + id: generateId(), + companyId: company.id, + companyName: company.name, + items: [], + } + carts.value.push(cart) + activeCartId.value = cart.id + selectedCompanyId.value = company.id + persist() + return cart + } + + function switchCompanyWarning(currentCompanyName: string, newCompanyName: string): string { + return `سبد خرید فعلی مربوط به ${currentCompanyName} است. برای خرید از ${newCompanyName} باید سبد خرید جداگانه‌ای ایجاد کنید.` + } + + function canSwitchToCompany(companyId: string): { allowed: boolean; message?: string } { + if (!activeCart.value || activeCart.value.items.length === 0) { + return { allowed: true } + } + if (activeCart.value.companyId === companyId) { + return { allowed: true } + } + const newCompany = getCompanyById(companyId) + return { + allowed: false, + message: switchCompanyWarning(activeCart.value.companyName, newCompany?.name ?? ''), + } + } + + function createNewCartForSameCompany(): Cart | null { + if (!activeCart.value) return null + const company = getCompanyById(activeCart.value.companyId) + if (!company) return null + const cart: Cart = { + id: generateId(), + companyId: company.id, + companyName: company.name, + items: [], + } + carts.value.push(cart) + activeCartId.value = cart.id + persist() + return cart + } + + function addItem( + product: Product, + catalogCode: string, + meterage: number, + ): { success: boolean; message?: string } { + if (!activeCart.value) { + return { success: false, message: 'ابتدا شرکت را انتخاب کنید.' } + } + + if (activeCart.value.companyId !== product.companyId) { + const currentCompany = activeCart.value.companyName + const newCompany = getCompanyById(product.companyId) + return { + success: false, + message: switchCompanyWarning(currentCompany, newCompany?.name ?? ''), + } + } + + const validation = validateMeterage(meterage, product, totalMeterage.value, maxMeterage.value) + if (!validation.valid) { + return { success: false, message: validation.message } + } + + const existingIndex = activeCart.value.items.findIndex((i) => i.productId === product.id) + if (existingIndex >= 0) { + const existing = activeCart.value.items[existingIndex]! + const revalidation = validateMeterage( + meterage, + product, + totalMeterage.value, + maxMeterage.value, + existing.meterage, + ) + if (!revalidation.valid) { + return { success: false, message: revalidation.message } + } + existing.meterage = meterage + } else { + const item: CartItem = { + id: generateId(), + productId: product.id, + catalogCode, + productName: product.name, + productCode: product.code, + color: product.color, + meterage, + unitPrice: product.basePrice, + } + activeCart.value.items.push(item) + } + + persist() + return { success: true } + } + + function updateItemMeterage( + itemId: string, + meterage: number, + product: Product, + ): { success: boolean; message?: string } { + if (!activeCart.value) return { success: false, message: 'سبد خرید یافت نشد.' } + const item = activeCart.value.items.find((i) => i.id === itemId) + if (!item) return { success: false, message: 'آیتم یافت نشد.' } + + const validation = validateMeterage( + meterage, + product, + totalMeterage.value, + maxMeterage.value, + item.meterage, + ) + if (!validation.valid) { + return { success: false, message: validation.message } + } + + item.meterage = meterage + persist() + return { success: true } + } + + function removeItem(itemId: string) { + if (!activeCart.value) return + activeCart.value.items = activeCart.value.items.filter((i) => i.id !== itemId) + persist() + } + + function setNotes(notes: string) { + if (!activeCart.value) return + activeCart.value.notes = notes + persist() + } + + function clearActiveCart() { + if (!activeCart.value) return + activeCart.value.items = [] + activeCart.value.notes = undefined + persist() + } + + function ensureActiveCartForCartPage() { + if (activeCart.value?.items.length) return + + const cartWithItems = carts.value.find((cart) => cart.items.length > 0) + if (!cartWithItems) return + + activeCartId.value = cartWithItems.id + selectedCompanyId.value = cartWithItems.companyId + persist() + } + + function hydrate() { + carts.value = loadCarts() + activeCartId.value = loadActiveCartId() + if (activeCart.value) { + selectedCompanyId.value = activeCart.value.companyId + } + } + + return { + carts, + activeCartId, + selectedCompanyId, + activeCart, + totalMeterage, + itemCount, + maxMeterage, + remainingCapacity, + isFull, + initCartForCompany, + canSwitchToCompany, + createNewCartForSameCompany, + addItem, + updateItemMeterage, + removeItem, + setNotes, + clearActiveCart, + ensureActiveCartForCartPage, + hydrate, + } +}) diff --git a/src/stores/catalog.ts b/src/stores/catalog.ts new file mode 100644 index 0000000..8a732fe --- /dev/null +++ b/src/stores/catalog.ts @@ -0,0 +1,66 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { + companies as mockCompanies, + getCatalogsByCompany, + getProductsByCatalog, + getCatalogById, + getProductById, + getCompanyById, +} from '@/data/mockData' +import type { Catalog, Company, Product } from '@/types' + +export const useCatalogStore = defineStore('catalog', () => { + const companies = ref(mockCompanies.filter((c) => c.isActive)) + const searchQuery = ref('') + + function getActiveCompanies(): Company[] { + return [...companies.value].sort((a, b) => a.displayOrder - b.displayOrder) + } + + function getCompany(id: string): Company | undefined { + return getCompanyById(id) + } + + function fetchCatalogs(companyId: string, query = ''): Catalog[] { + let list = getCatalogsByCompany(companyId) + if (query.trim()) { + const q = query.trim() + list = list.filter((c) => c.code.includes(q) || c.name.includes(q)) + } + return list + } + + function fetchProducts(catalogId: string, colorFilter?: string): Product[] { + let list = getProductsByCatalog(catalogId) + if (colorFilter && colorFilter !== 'all') { + list = list.filter((p) => p.color.includes(colorFilter)) + } + return list + } + + function getCatalog(id: string) { + return getCatalogById(id) + } + + function getProduct(id: string) { + return getProductById(id) + } + + function getUniqueColors(catalogId: string): string[] { + const products = getProductsByCatalog(catalogId) + return [...new Set(products.map((p) => p.color))] + } + + return { + companies, + searchQuery, + getActiveCompanies, + getCompany, + fetchCatalogs, + fetchProducts, + getCatalog, + getProduct, + getUniqueColors, + } +}) diff --git a/src/stores/order.ts b/src/stores/order.ts new file mode 100644 index 0000000..f781edc --- /dev/null +++ b/src/stores/order.ts @@ -0,0 +1,248 @@ +import { defineStore } from 'pinia' +import { ref, computed } from 'vue' +import type { + Cart, + CheckData, + CashPaymentReceipt, + Order, + OrderItem, + OrderStatus, + OrderStatusHistoryEntry, + SettlementType, + CheckRegistrationMode, +} from '@/types' +import { generateId, generateOrderNumber } from '@/utils/format' +import { calculateCheckRass } from '@/utils/checkRass' +import { getItem, setItem, STORAGE_KEYS } from '@/services/storage' +import { getCompanyById, getBankAccountsByCompany } from '@/data/mockData' + +function loadOrders(): Order[] { + return getItem(STORAGE_KEYS.orders, []) +} + +function saveOrders(orders: Order[]) { + setItem(STORAGE_KEYS.orders, orders) +} + +function createStatusEntry( + from: OrderStatus | null, + to: OrderStatus, + note?: string, +): OrderStatusHistoryEntry { + return { + id: generateId(), + fromStatus: from, + toStatus: to, + changedAt: new Date().toISOString(), + changedBy: 'customer', + note, + } +} + +function cartToOrderItems(cart: Cart): OrderItem[] { + return cart.items.map((item) => ({ + id: generateId(), + productId: item.productId, + catalogCode: item.catalogCode, + productName: item.productName, + productCode: item.productCode, + color: item.color, + requestedMeterage: item.meterage, + unitPrice: item.unitPrice, + notes: item.notes, + })) +} + +function computeCashExpiry(companyId: string): string { + const company = getCompanyById(companyId) + const now = new Date() + if (company?.cashInvoiceValidUntilHour) { + const expiry = new Date(now) + expiry.setHours(company.cashInvoiceValidUntilHour, 0, 0, 0) + if (expiry <= now) { + expiry.setDate(expiry.getDate() + 1) + } + return expiry.toISOString() + } + const hours = company?.cashInvoiceValidityHours ?? 8 + return new Date(now.getTime() + hours * 60 * 60 * 1000).toISOString() +} + +export const useOrderStore = defineStore('order', () => { + const orders = ref(loadOrders()) + const draftChecks = ref([]) + const draftSettlementType = ref(null) + const draftCheckMode = ref(null) + const checkoutCartId = ref(null) + + const userOrders = computed( + () => (userId: string) => + orders.value + .filter((o) => o.userId === userId) + .sort((a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()), + ) + + function persist() { + saveOrders(orders.value) + } + + function getOrderById(id: string): Order | undefined { + return orders.value.find((o) => o.id === id) + } + + function startCheckout(cart: Cart, settlementType: SettlementType) { + checkoutCartId.value = cart.id + draftSettlementType.value = settlementType + draftChecks.value = [] + draftCheckMode.value = null + } + + function setCheckMode(mode: CheckRegistrationMode) { + draftCheckMode.value = mode + } + + function addDraftCheck(check: Omit) { + draftChecks.value.push({ ...check, id: generateId() }) + } + + function updateDraftCheck(id: string, data: Partial) { + const index = draftChecks.value.findIndex((c) => c.id === id) + if (index >= 0) { + draftChecks.value[index] = { ...draftChecks.value[index]!, ...data } + } + } + + function removeDraftCheck(id: string) { + draftChecks.value = draftChecks.value.filter((c) => c.id !== id) + } + + function getDraftRass(baseDate?: Date) { + return calculateCheckRass(draftChecks.value, baseDate ?? new Date()) + } + + function submitOrder( + userId: string, + cart: Cart, + settlementType: SettlementType, + checks?: CheckData[], + checkMode?: CheckRegistrationMode, + ): Order { + const items = cartToOrderItems(cart) + const totalMeterage = items.reduce((s, i) => s + i.requestedMeterage, 0) + const now = new Date().toISOString() + + let status: OrderStatus = 'awaiting_review' + let checkRassDays: number | undefined + let checkRassDate: string | undefined + let cashInvoiceExpiresAt: string | undefined + + if (settlementType === 'check' && checks && checks.length > 0) { + const rass = calculateCheckRass(checks, new Date()) + checkRassDays = rass.rassDays + checkRassDate = rass.rassDate ?? undefined + status = 'awaiting_review' + } + + if (settlementType === 'cash') { + cashInvoiceExpiresAt = computeCashExpiry(cart.companyId) + status = 'awaiting_review' + } + + const order: Order = { + id: generateId(), + orderNumber: generateOrderNumber(), + userId, + companyId: cart.companyId, + companyName: cart.companyName, + items, + totalMeterage, + settlementType, + checkMode, + checks: checks ? [...checks] : undefined, + checkRassDays, + checkRassDate, + status, + notes: cart.notes, + cashInvoiceExpiresAt, + statusHistory: [ + createStatusEntry(null, 'submitted', 'سفارش ثبت شد'), + createStatusEntry('submitted', status, 'ارسال برای بررسی مدیریت'), + ], + createdAt: now, + updatedAt: now, + } + + orders.value.unshift(order) + persist() + + draftChecks.value = [] + draftSettlementType.value = null + draftCheckMode.value = null + checkoutCartId.value = null + + return order + } + + function submitCashReceipt( + orderId: string, + receipt: Omit, + ) { + const order = getOrderById(orderId) + if (!order) return null + + const fullReceipt: CashPaymentReceipt = { + ...receipt, + id: generateId(), + submittedAt: new Date().toISOString(), + } + + const prevStatus = order.status + order.cashReceipt = fullReceipt + order.status = 'awaiting_cash_confirmation' + order.statusHistory.push( + createStatusEntry(prevStatus, 'awaiting_cash_confirmation', 'رسید پرداخت ثبت شد'), + ) + order.updatedAt = new Date().toISOString() + persist() + return order + } + + function updateOrderChecks(orderId: string, checks: CheckData[]) { + const order = getOrderById(orderId) + if (!order) return null + + const rass = calculateCheckRass(checks, new Date(order.createdAt)) + order.checks = checks + order.checkRassDays = rass.rassDays + order.checkRassDate = rass.rassDate ?? undefined + order.updatedAt = new Date().toISOString() + persist() + return order + } + + function hydrate() { + orders.value = loadOrders() + } + + return { + orders, + draftChecks, + draftSettlementType, + draftCheckMode, + checkoutCartId, + userOrders, + persist, + getOrderById, + startCheckout, + setCheckMode, + addDraftCheck, + updateDraftCheck, + removeDraftCheck, + getDraftRass, + submitOrder, + submitCashReceipt, + updateOrderChecks, + hydrate, + getBankAccountsForCompany: getBankAccountsByCompany, + } +}) diff --git a/src/types/index.ts b/src/types/index.ts new file mode 100644 index 0000000..976aed9 --- /dev/null +++ b/src/types/index.ts @@ -0,0 +1,204 @@ +export type SettlementType = 'cash' | 'check' +export type CheckRegistrationMode = 'full' | 'brief' + +export type OrderStatus = + | 'cart' + | 'awaiting_settlement' + | 'cash_in_progress' + | 'check_in_progress' + | 'submitted' + | 'awaiting_review' + | 'pricing' + | 'needs_correction' + | 'awaiting_settlement_fix' + | 'cash_invoice_issued' + | 'awaiting_cash_payment' + | 'cash_payment_submitted' + | 'awaiting_cash_confirmation' + | 'cash_confirmed' + | 'awaiting_check_review' + | 'check_needs_fix' + | 'check_rejected' + | 'checks_approved' + | 'final_approved' + | 'preparing' + | 'ready_to_ship' + | 'shipped' + | 'delivered' + | 'cancelled' + | 'rejected' + | 'expired' + +export interface User { + id: string + firstName: string + lastName: string + phone: string + nationalId?: string + createdAt: string +} + +export interface Company { + id: string + name: string + slug: string + logo?: string + description: string + isActive: boolean + displayOrder: number + maxMeteragePerInvoice: number + cashInvoiceValidityHours: number + cashInvoiceValidUntilHour?: number +} + +export interface BankAccount { + id: string + companyId: string + bankName: string + accountHolder: string + accountNumber: string + cardNumber: string + iban: string + isActive: boolean + displayOrder: number + notes?: string +} + +export interface Catalog { + id: string + companyId: string + name: string + code: string + description?: string + displayOrder: number + isActive: boolean +} + +export interface Product { + id: string + companyId: string + catalogId: string + name: string + code: string + color: string + description?: string + minMeterage: number + orderMultiplier: number + basePrice?: number + stock?: number + isActive: boolean +} + +export interface CartItem { + id: string + productId: string + catalogCode: string + productName: string + productCode: string + color: string + meterage: number + unitPrice?: number + notes?: string +} + +export interface Cart { + id: string + companyId: string + companyName: string + items: CartItem[] + notes?: string +} + +export interface CheckData { + id: string + amount: number + dueDate: string + sayadId?: string + checkNumber?: string + ownerNationalId?: string + ownerFirstName?: string + ownerLastName?: string + bankName?: string + branchName?: string + frontImage?: string + backImage?: string + notes?: string + mode: CheckRegistrationMode +} + +export interface CashPaymentReceipt { + id: string + amount: number + transferDate: string + transferTime: string + trackingNumber: string + destinationAccountId: string + receiptImage?: string + notes?: string + submittedAt: string +} + +export interface OrderItem { + id: string + productId: string + catalogCode: string + productName: string + productCode: string + color: string + requestedMeterage: number + confirmedMeterage?: number + unitPrice?: number + discount?: number + lineTotal?: number + notes?: string +} + +export interface OrderStatusHistoryEntry { + id: string + fromStatus: OrderStatus | null + toStatus: OrderStatus + changedAt: string + changedBy: string + note?: string + reason?: string +} + +export interface Order { + id: string + orderNumber: string + userId: string + companyId: string + companyName: string + items: OrderItem[] + totalMeterage: number + settlementType: SettlementType + checkMode?: CheckRegistrationMode + checks?: CheckData[] + checkRassDays?: number + checkRassDate?: string + status: OrderStatus + notes?: string + totalAmount?: number + shippingCost?: number + totalDiscount?: number + finalAmount?: number + cashInvoiceExpiresAt?: string + cashReceipt?: CashPaymentReceipt + statusHistory: OrderStatusHistoryEntry[] + createdAt: string + updatedAt: string +} + +export interface CheckRassResult { + checkCount: number + totalAmount: number + nearestDueDate: string | null + farthestDueDate: string | null + rassDays: number + rassDate: string | null +} + +export interface MeterageValidationResult { + valid: boolean + message?: string +} diff --git a/src/utils/checkRass.ts b/src/utils/checkRass.ts new file mode 100644 index 0000000..48a2c11 --- /dev/null +++ b/src/utils/checkRass.ts @@ -0,0 +1,58 @@ +import type { CheckData, CheckRassResult } from '@/types' +import { parseISODate } from '@/utils/jalali' + +export function calculateCheckRass( + checks: CheckData[], + baseDate: Date = new Date(), +): CheckRassResult { + if (checks.length === 0) { + return { + checkCount: 0, + totalAmount: 0, + nearestDueDate: null, + farthestDueDate: null, + rassDays: 0, + rassDate: null, + } + } + + const base = new Date(baseDate) + base.setHours(0, 0, 0, 0) + + let totalAmount = 0 + let weightedDays = 0 + const dueDates: Date[] = [] + + for (const check of checks) { + const due = parseISODate(check.dueDate) + due.setHours(0, 0, 0, 0) + dueDates.push(due) + const diffMs = due.getTime() - base.getTime() + const days = Math.max(0, Math.round(diffMs / (1000 * 60 * 60 * 24))) + totalAmount += check.amount + weightedDays += check.amount * days + } + + const rassDays = totalAmount > 0 ? Math.round(weightedDays / totalAmount) : 0 + const rassDate = new Date(base) + rassDate.setDate(rassDate.getDate() + rassDays) + + dueDates.sort((a, b) => a.getTime() - b.getTime()) + + return { + checkCount: checks.length, + totalAmount, + nearestDueDate: dueDates[0]?.toISOString() ?? null, + farthestDueDate: dueDates[dueDates.length - 1]?.toISOString() ?? null, + rassDays, + rassDate: rassDate.toISOString(), + } +} + +export function daysUntilDue(dueDate: string): number { + const base = new Date() + base.setHours(0, 0, 0, 0) + const due = parseISODate(dueDate) + due.setHours(0, 0, 0, 0) + return Math.max(0, Math.round((due.getTime() - base.getTime()) / (1000 * 60 * 60 * 24))) +} diff --git a/src/utils/constants.ts b/src/utils/constants.ts new file mode 100644 index 0000000..6b0a0cf --- /dev/null +++ b/src/utils/constants.ts @@ -0,0 +1,70 @@ +import type { OrderStatus } from '@/types' + +export const DEFAULT_MAX_METERAGE = 5000 +export const MOCK_OTP_CODE = '123456' + +export const ORDER_STATUS_LABELS: Record = { + cart: 'سبد خرید', + awaiting_settlement: 'در انتظار انتخاب روش تسویه', + cash_in_progress: 'در حال تکمیل اطلاعات نقدی', + check_in_progress: 'در حال ثبت چک‌ها', + submitted: 'سفارش ثبت‌شده', + awaiting_review: 'در انتظار بررسی', + pricing: 'در حال قیمت‌گذاری', + needs_correction: 'نیازمند اصلاح', + awaiting_settlement_fix: 'در انتظار اصلاح تسویه', + cash_invoice_issued: 'فاکتور نقدی صادرشده', + awaiting_cash_payment: 'در انتظار پرداخت نقدی', + cash_payment_submitted: 'پرداخت ثبت‌شده', + awaiting_cash_confirmation: 'در انتظار تأیید پرداخت', + cash_confirmed: 'پرداخت تأییدشده', + awaiting_check_review: 'در انتظار بررسی چک‌ها', + check_needs_fix: 'چک نیازمند اصلاح', + check_rejected: 'چک ردشده', + checks_approved: 'چک‌ها تایید شده', + final_approved: 'تأیید نهایی', + preparing: 'در حال آماده‌سازی', + ready_to_ship: 'آماده ارسال', + shipped: 'ارسال‌شده', + delivered: 'تحویل‌شده', + cancelled: 'لغوشده', + rejected: 'ردشده', + expired: 'منقضی‌شده', +} + +export const ORDER_TRACKING_STEPS: { status: OrderStatus; label: string }[] = [ + { status: 'submitted', label: 'ثبت سفارش' }, + { status: 'awaiting_review', label: 'در انتظار بررسی' }, + { status: 'pricing', label: 'قیمت‌گذاری توسط مدیریت' }, + { status: 'check_in_progress', label: 'ثبت چک' }, + { status: 'awaiting_check_review', label: 'در حال بررسی چک‌ها' }, + { status: 'checks_approved', label: 'چک‌ها تأیید شده' }, + { status: 'final_approved', label: 'تأیید نهایی' }, + { status: 'preparing', label: 'آماده‌سازی' }, + { status: 'ready_to_ship', label: 'آماده ارسال' }, + { status: 'shipped', label: 'ارسال شده' }, + { status: 'delivered', label: 'تحویل شده' }, +] + +export const STATUS_BADGE_VARIANT: Record< + string, + 'warning' | 'success' | 'info' | 'purple' | 'danger' | 'neutral' +> = { + awaiting_review: 'info', + awaiting_check_review: 'info', + pricing: 'warning', + preparing: 'warning', + ready_to_ship: 'warning', + check_in_progress: 'warning', + awaiting_cash_confirmation: 'warning', + checks_approved: 'success', + cash_confirmed: 'success', + final_approved: 'success', + shipped: 'purple', + delivered: 'success', + needs_correction: 'danger', + check_needs_fix: 'danger', + rejected: 'danger', + cancelled: 'neutral', + expired: 'danger', +} diff --git a/src/utils/formErrors.ts b/src/utils/formErrors.ts new file mode 100644 index 0000000..6c416b1 --- /dev/null +++ b/src/utils/formErrors.ts @@ -0,0 +1,14 @@ +export type FieldErrors = Record + +export function hasFieldErrors(errors: FieldErrors): boolean { + return Object.keys(errors).length > 0 +} + +export function clearFieldError(errors: FieldErrors, key: string): FieldErrors { + if (!errors[key]) return errors + const next = { ...errors } + delete next[key] + return next +} + +export const FORM_VALIDATION_SUMMARY = 'لطفاً خطاهای مشخص‌شده در فرم را برطرف کنید.' diff --git a/src/utils/format.ts b/src/utils/format.ts new file mode 100644 index 0000000..b29c70e --- /dev/null +++ b/src/utils/format.ts @@ -0,0 +1,88 @@ +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)} متر` +} + +import { parseISODate } from '@/utils/jalali' + +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', +}) + +function toDateValue(date: string | Date): Date { + if (typeof date !== 'string') return date + if (/^\d{4}-\d{2}-\d{2}$/.test(date)) return parseISODate(date) + return new Date(date) +} + +export function formatDate(date: string | Date): string { + return persianDateFormatter.format(toDateValue(date)) +} + +export function formatDateTime(date: string | Date): string { + return persianDateTimeFormatter.format(toDateValue(date)) +} + +export function formatTime(date: string | Date): string { + const d = typeof date === 'string' ? new Date(date) : date + return new Intl.DateTimeFormat('fa-IR', { + hour: '2-digit', + minute: '2-digit', + }).format(d) +} + +export function toPersianDigits(input: string): string { + return input.replace(/\d/g, (d) => persianDigits[Number(d)]!) +} + +export function normalizePhone(phone: string): string { + const digits = phone.replace(/\D/g, '') + if (digits.startsWith('98')) return '0' + digits.slice(2) + if (digits.startsWith('9') && digits.length === 10) return '0' + digits + return digits +} + +export function generateId(): string { + return crypto.randomUUID() +} + +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/jalali.ts b/src/utils/jalali.ts new file mode 100644 index 0000000..c724465 --- /dev/null +++ b/src/utils/jalali.ts @@ -0,0 +1,101 @@ +import { jalaaliMonthLength, toGregorian, toJalaali } from 'jalaali-js' + +const persianDigits = '۰۱۲۳۴۵۶۷۸۹' + +function toPersianDigits(input: string): string { + return input.replace(/\d/g, (d) => persianDigits[Number(d)]!) +} + +export const JALALI_MONTH_NAMES = [ + 'فروردین', + 'اردیبهشت', + 'خرداد', + 'تیر', + 'مرداد', + 'شهریور', + 'مهر', + 'آبان', + 'آذر', + 'دی', + 'بهمن', + 'اسفند', +] as const + +export const JALALI_WEEKDAY_NAMES = ['ش', 'ی', 'د', 'س', 'چ', 'پ', 'ج'] as const + +export interface JalaliDate { + jy: number + jm: number + jd: number +} + +export function parseISODate(iso: string): Date { + const [year, month, day] = iso.split('-').map(Number) + return new Date(year!, month! - 1, day!) +} + +export function toISODate(date: Date): string { + const year = date.getFullYear() + const month = String(date.getMonth() + 1).padStart(2, '0') + const day = String(date.getDate()).padStart(2, '0') + return `${year}-${month}-${day}` +} + +export function toJalali(date: Date): JalaliDate { + const { jy, jm, jd } = toJalaali(date.getFullYear(), date.getMonth() + 1, date.getDate()) + return { jy, jm, jd } +} + +export function fromJalali(jy: number, jm: number, jd: number): Date { + const { gy, gm, gd } = toGregorian(jy, jm, jd) + return new Date(gy, gm - 1, gd) +} + +export function isoToJalali(iso: string): JalaliDate | null { + if (!iso) return null + return toJalali(parseISODate(iso)) +} + +export function jalaliToISO(jy: number, jm: number, jd: number): string { + return toISODate(fromJalali(jy, jm, jd)) +} + +export function formatJalaliDate(jy: number, jm: number, jd: number): string { + const month = String(jm).padStart(2, '0') + const day = String(jd).padStart(2, '0') + return toPersianDigits(`${jy}/${month}/${day}`) +} + +export function formatJalaliLabel(jy: number, jm: number, jd: number): string { + return `${toPersianDigits(String(jd))} ${JALALI_MONTH_NAMES[jm - 1]} ${toPersianDigits(String(jy))}` +} + +export function getPersianWeekday(jy: number, jm: number, jd: number): number { + const { gy, gm, gd } = toGregorian(jy, jm, jd) + const jsDay = new Date(gy, gm - 1, gd).getDay() + return (jsDay + 1) % 7 +} + +export function getMonthLength(jy: number, jm: number): number { + return jalaaliMonthLength(jy, jm) +} + +export function buildCalendarDays(jy: number, jm: number): Array { + const length = getMonthLength(jy, jm) + const startWeekday = getPersianWeekday(jy, jm, 1) + const cells: Array = Array.from({ length: startWeekday }, () => null) + + for (let day = 1; day <= length; day += 1) { + cells.push(day) + } + + while (cells.length % 7 !== 0) { + cells.push(null) + } + + return cells +} + +export function todayJalali(): JalaliDate { + return toJalali(new Date()) +} diff --git a/src/utils/navigation.ts b/src/utils/navigation.ts new file mode 100644 index 0000000..cf1ea1e --- /dev/null +++ b/src/utils/navigation.ts @@ -0,0 +1,64 @@ +import type { Component } from 'vue' +import IconHome from '@/components/icons/IconHome.vue' +import IconCart from '@/components/icons/IconCart.vue' +import IconOrders from '@/components/icons/IconOrders.vue' +import IconProfile from '@/components/icons/IconProfile.vue' +import IconCatalog from '@/components/icons/IconCatalog.vue' +import IconCheckBook from '@/components/icons/IconCheckBook.vue' + +export interface NavItem { + name: string + path: string + label: string + icon: Component + dynamicPath?: boolean +} + +/** Mobile bottom navigation — unchanged */ +export const MAIN_NAV_ITEMS: NavItem[] = [ + { name: 'home', path: '/', label: 'خانه', icon: IconHome }, + { name: 'cart', path: '/cart', label: 'سبد خرید', icon: IconCart }, + { name: 'orders', path: '/orders', label: 'سفارش‌ها', icon: IconOrders }, + { name: 'profile', path: '/profile', label: 'پروفایل', icon: IconProfile }, +] + +/** Desktop sidebar — matches mockup */ +export const DESKTOP_NAV_ITEMS: NavItem[] = [ + { name: 'home', path: '/', label: 'خانه', icon: IconHome }, + { name: 'ordering', path: '/', label: 'سفارش‌گذاری', icon: IconCatalog, dynamicPath: true }, + { name: 'cart', path: '/cart', label: 'سبد خرید', icon: IconCart }, + { name: 'orders', path: '/orders', label: 'سفارش‌ها', icon: IconOrders }, + { name: 'checks', path: '/profile/checks', label: 'لیست چک‌ها', icon: IconCheckBook }, + { name: 'profile', path: '/profile', label: 'پروفایل', icon: IconProfile }, +] + +export function getOrderingPath(activeCompanyId: string | null | undefined): string { + if (activeCompanyId) return `/companies/${activeCompanyId}/catalogs` + return '/' +} + +export function isNavItemActive(name: string, path: string, currentPath: string): boolean { + if (name === 'ordering') { + return currentPath.startsWith('/companies/') + } + if (name === 'home') { + return currentPath === '/' + } + if (name === 'checks') { + return currentPath.startsWith('/profile/checks') + } + if (name === 'profile') { + return currentPath === '/profile' + } + if (path === '/profile') return currentPath === '/profile' + if (path === '/') return currentPath === '/' + return currentPath.startsWith(path) +} + +export function resolveNavPath( + item: NavItem, + activeCompanyId: string | null | undefined, +): string { + if (item.name === 'ordering') return getOrderingPath(activeCompanyId) + return item.path +} diff --git a/src/utils/orderStatusGroups.ts b/src/utils/orderStatusGroups.ts new file mode 100644 index 0000000..c7b6845 --- /dev/null +++ b/src/utils/orderStatusGroups.ts @@ -0,0 +1,69 @@ +import type { OrderStatus } from '@/types' + +export type DesktopOrderFilterId = + | 'all' + | 'review' + | 'in_progress' + | 'shipped' + | 'delivered' + | 'cancelled' + +export const REVIEW_STATUSES: OrderStatus[] = ['awaiting_review', 'awaiting_check_review'] + +export const IN_PROGRESS_STATUSES: OrderStatus[] = [ + 'submitted', + 'pricing', + 'check_in_progress', + 'awaiting_cash_confirmation', + 'preparing', + 'ready_to_ship', + 'needs_correction', + 'awaiting_settlement_fix', + 'cash_in_progress', + 'awaiting_cash_payment', + 'cash_payment_submitted', + 'check_needs_fix', + 'awaiting_settlement', + 'cash_invoice_issued', +] + +export const SHIPPED_STATUSES: OrderStatus[] = ['shipped'] + +export const DELIVERED_STATUSES: OrderStatus[] = [ + 'delivered', + 'final_approved', + 'checks_approved', + 'cash_confirmed', +] + +export const CANCELLED_STATUSES: OrderStatus[] = ['cancelled', 'rejected', 'expired', 'check_rejected'] + +export const MOBILE_ACTIVE_STATUSES: OrderStatus[] = [ + ...REVIEW_STATUSES, + ...IN_PROGRESS_STATUSES, + ...SHIPPED_STATUSES, +] + +export function matchesDesktopOrderFilter(status: OrderStatus, filter: DesktopOrderFilterId): boolean { + switch (filter) { + case 'review': + return REVIEW_STATUSES.includes(status) + case 'in_progress': + return IN_PROGRESS_STATUSES.includes(status) + case 'shipped': + return SHIPPED_STATUSES.includes(status) + case 'delivered': + return DELIVERED_STATUSES.includes(status) + case 'cancelled': + return CANCELLED_STATUSES.includes(status) + default: + return true + } +} + +export function matchesMobileOrderTab(status: OrderStatus, tabId: string): boolean { + if (tabId === 'active') return MOBILE_ACTIVE_STATUSES.includes(status) + if (tabId === 'done') return DELIVERED_STATUSES.includes(status) + if (tabId === 'cancelled') return CANCELLED_STATUSES.includes(status) + return true +} diff --git a/src/utils/orderTracking.ts b/src/utils/orderTracking.ts new file mode 100644 index 0000000..2156253 --- /dev/null +++ b/src/utils/orderTracking.ts @@ -0,0 +1,110 @@ +import type { Order, OrderStatus } from '@/types' +import { ORDER_TRACKING_STEPS } from '@/utils/constants' + +export type StatusHeroVariant = 'waiting' | 'success' | 'info' | 'none' + +export interface StatusHeroConfig { + variant: StatusHeroVariant + title: string + description?: string +} + +const STATUS_STEP_INDEX: Partial> = { + submitted: 0, + awaiting_review: 1, + pricing: 2, + check_in_progress: 3, + awaiting_check_review: 4, + check_needs_fix: 4, + check_rejected: 4, + checks_approved: 5, + final_approved: 6, + cash_confirmed: 6, + preparing: 7, + ready_to_ship: 8, + shipped: 9, + delivered: 10, +} + +const STATUS_HERO: Partial> = { + awaiting_review: { + variant: 'waiting', + title: 'در انتظار بررسی مدیریت', + description: 'سفارش شما ثبت شده و در صف بررسی مدیریت قرار دارد. پس از بررسی، نتیجه از طریق همین صفحه اطلاع‌رسانی می‌شود.', + }, + pricing: { + variant: 'waiting', + title: 'در حال قیمت‌گذاری', + description: 'مدیریت در حال تعیین مبلغ نهایی فاکتور است. لطفاً کمی صبر کنید.', + }, + awaiting_check_review: { + variant: 'waiting', + title: 'در حال بررسی چک‌ها', + description: 'چک‌های ثبت‌شده در حال بررسی هستند. نتیجه بررسی به‌زودی اعلام می‌شود.', + }, + checks_approved: { + variant: 'success', + title: 'چک‌ها تأیید شده', + description: 'چک‌های شما توسط مدیریت تأیید شد. سفارش وارد مراحل بعدی می‌شود.', + }, + cash_confirmed: { + variant: 'success', + title: 'پرداخت تأیید شد', + description: 'رسید پرداخت شما تأیید شد و سفارش وارد مراحل بعدی می‌شود.', + }, + final_approved: { + variant: 'success', + title: 'تأیید نهایی', + description: 'سفارش شما تأیید نهایی شد و آماده آماده‌سازی است.', + }, + preparing: { + variant: 'info', + title: 'در حال آماده‌سازی', + description: 'سفارش شما در انبار در حال آماده‌سازی است.', + }, + ready_to_ship: { + variant: 'info', + title: 'آماده ارسال', + description: 'سفارش آماده ارسال است و به‌زودی تحویل باربری می‌شود.', + }, + shipped: { + variant: 'info', + title: 'ارسال شده', + description: 'سفارش ارسال شده است. جزئیات بارنامه را می‌توانید مشاهده کنید.', + }, + delivered: { + variant: 'success', + title: 'تحویل شده', + description: 'سفارش با موفقیت تحویل داده شد.', + }, +} + +export function getTrackingStepIndex(status: OrderStatus): number { + return STATUS_STEP_INDEX[status] ?? 1 +} + +export function getStatusHero(status: OrderStatus): StatusHeroConfig | null { + return STATUS_HERO[status] ?? null +} + +export function getStepTimestamp(order: Order, stepStatus: OrderStatus): string | null { + if (stepStatus === 'submitted') { + return order.createdAt + } + + const entry = [...order.statusHistory] + .reverse() + .find((item) => item.toStatus === stepStatus) + + return entry?.changedAt ?? null +} + +export function getTrackingFooterLabel(status: OrderStatus): string { + if (status === 'shipped') return 'مشاهده جزئیات و بارنامه' + if (['checks_approved', 'cash_confirmed', 'delivered', 'final_approved'].includes(status)) { + return 'مشاهده جزئیات' + } + return 'مشاهده جزئیات سفارش' +} + +export { ORDER_TRACKING_STEPS } diff --git a/src/utils/validation.ts b/src/utils/validation.ts new file mode 100644 index 0000000..7598664 --- /dev/null +++ b/src/utils/validation.ts @@ -0,0 +1,74 @@ +import type { MeterageValidationResult, Product } from '@/types' + +export function validateNationalId(nationalId: string): boolean { + if (!/^\d{10}$/.test(nationalId)) return false + if (/^(\d)\1{9}$/.test(nationalId)) return false + const check = Number(nationalId[9]) + let sum = 0 + for (let i = 0; i < 9; i++) { + sum += Number(nationalId[i]) * (10 - i) + } + const remainder = sum % 11 + return remainder < 2 ? check === remainder : check === 11 - remainder +} + +export function validateSayadId(sayadId: string): boolean { + return /^\d{16}$/.test(sayadId.replace(/\s/g, '')) +} + +export function validatePhone(phone: string): boolean { + return /^09\d{9}$/.test(phone.replace(/\D/g, '').replace(/^9/, '09').slice(0, 11)) +} + +export function validateMeterage( + meterage: number, + product: Product, + currentCartTotal: number, + maxMeterage: number, + existingItemMeterage = 0, +): MeterageValidationResult { + if (!Number.isFinite(meterage) || meterage <= 0) { + return { valid: false, message: 'متراژ باید عددی بزرگ‌تر از صفر باشد.' } + } + if (meterage < product.minMeterage) { + return { + valid: false, + message: `حداقل متراژ سفارش برای این محصول ${product.minMeterage} متر است.`, + } + } + if (meterage % product.orderMultiplier !== 0) { + return { + valid: false, + message: `متراژ باید مضربی از ${product.orderMultiplier} باشد.`, + } + } + const newTotal = currentCartTotal - existingItemMeterage + meterage + if (newTotal > maxMeterage) { + const remaining = maxMeterage - (currentCartTotal - existingItemMeterage) + return { + valid: false, + message: `حداکثر متراژ قابل ثبت در هر فاکتور ${maxMeterage} متر است. شما فقط می‌توانید ${Math.max(0, remaining)} متر دیگر به این سفارش اضافه کنید.`, + } + } + return { valid: true } +} + +export function validateImageFile(file: File): { valid: boolean; message?: string } { + const allowed = ['image/jpeg', 'image/png', 'image/webp'] + if (!allowed.includes(file.type)) { + return { valid: false, message: 'فرمت تصویر مجاز نیست. (JPG, PNG, WEBP)' } + } + if (file.size > 5 * 1024 * 1024) { + return { valid: false, message: 'حجم تصویر نباید بیشتر از ۵ مگابایت باشد.' } + } + return { valid: true } +} + +export async function fileToBase64(file: File): Promise { + return new Promise((resolve, reject) => { + const reader = new FileReader() + reader.onload = () => resolve(reader.result as string) + reader.onerror = reject + reader.readAsDataURL(file) + }) +} diff --git a/src/views/OrdersView.vue b/src/views/OrdersView.vue new file mode 100644 index 0000000..30ebce7 --- /dev/null +++ b/src/views/OrdersView.vue @@ -0,0 +1,75 @@ + + + diff --git a/src/views/auth/LoginView.vue b/src/views/auth/LoginView.vue new file mode 100644 index 0000000..10dbeed --- /dev/null +++ b/src/views/auth/LoginView.vue @@ -0,0 +1,110 @@ + + + + + diff --git a/src/views/auth/OtpView.vue b/src/views/auth/OtpView.vue new file mode 100644 index 0000000..c168c14 --- /dev/null +++ b/src/views/auth/OtpView.vue @@ -0,0 +1,100 @@ + + + + + diff --git a/src/views/auth/RegisterView.vue b/src/views/auth/RegisterView.vue new file mode 100644 index 0000000..e1ebe03 --- /dev/null +++ b/src/views/auth/RegisterView.vue @@ -0,0 +1,135 @@ + + + + + diff --git a/src/views/cart/CartView.vue b/src/views/cart/CartView.vue new file mode 100644 index 0000000..72d6aa0 --- /dev/null +++ b/src/views/cart/CartView.vue @@ -0,0 +1,86 @@ + + + + + diff --git a/src/views/cart/components/DesktopCartPage.vue b/src/views/cart/components/DesktopCartPage.vue new file mode 100644 index 0000000..25dbfc1 --- /dev/null +++ b/src/views/cart/components/DesktopCartPage.vue @@ -0,0 +1,608 @@ + + + + + diff --git a/src/views/cart/components/MobileCartPage.vue b/src/views/cart/components/MobileCartPage.vue new file mode 100644 index 0000000..c33a227 --- /dev/null +++ b/src/views/cart/components/MobileCartPage.vue @@ -0,0 +1,241 @@ + + + + + diff --git a/src/views/catalogs/CatalogListView.vue b/src/views/catalogs/CatalogListView.vue new file mode 100644 index 0000000..611254b --- /dev/null +++ b/src/views/catalogs/CatalogListView.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/src/views/checkout/CashSettlementView.vue b/src/views/checkout/CashSettlementView.vue new file mode 100644 index 0000000..8e8900c --- /dev/null +++ b/src/views/checkout/CashSettlementView.vue @@ -0,0 +1,295 @@ + + + + + diff --git a/src/views/checkout/CheckFormView.vue b/src/views/checkout/CheckFormView.vue new file mode 100644 index 0000000..2e8be90 --- /dev/null +++ b/src/views/checkout/CheckFormView.vue @@ -0,0 +1,317 @@ + + + + + diff --git a/src/views/checkout/CheckListView.vue b/src/views/checkout/CheckListView.vue new file mode 100644 index 0000000..17e5de5 --- /dev/null +++ b/src/views/checkout/CheckListView.vue @@ -0,0 +1,549 @@ + + + + + diff --git a/src/views/checkout/CheckModeSelectView.vue b/src/views/checkout/CheckModeSelectView.vue new file mode 100644 index 0000000..21f8cfa --- /dev/null +++ b/src/views/checkout/CheckModeSelectView.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/src/views/checkout/SettlementTypeView.vue b/src/views/checkout/SettlementTypeView.vue new file mode 100644 index 0000000..1262ec8 --- /dev/null +++ b/src/views/checkout/SettlementTypeView.vue @@ -0,0 +1,146 @@ + + + + + diff --git a/src/views/companies/CompanySelectView.vue b/src/views/companies/CompanySelectView.vue new file mode 100644 index 0000000..40b37c5 --- /dev/null +++ b/src/views/companies/CompanySelectView.vue @@ -0,0 +1,107 @@ + + + + + diff --git a/src/views/companies/components/DesktopCompanySelect.vue b/src/views/companies/components/DesktopCompanySelect.vue new file mode 100644 index 0000000..f42e830 --- /dev/null +++ b/src/views/companies/components/DesktopCompanySelect.vue @@ -0,0 +1,102 @@ + + + + + diff --git a/src/views/companies/components/DesktopHomeDashboard.vue b/src/views/companies/components/DesktopHomeDashboard.vue new file mode 100644 index 0000000..11c596b --- /dev/null +++ b/src/views/companies/components/DesktopHomeDashboard.vue @@ -0,0 +1,573 @@ + + + + + diff --git a/src/views/companies/components/MobileCompanySelect.vue b/src/views/companies/components/MobileCompanySelect.vue new file mode 100644 index 0000000..45e92e5 --- /dev/null +++ b/src/views/companies/components/MobileCompanySelect.vue @@ -0,0 +1,126 @@ + + + + + diff --git a/src/views/orders/OrderDetailView.vue b/src/views/orders/OrderDetailView.vue new file mode 100644 index 0000000..beb648c --- /dev/null +++ b/src/views/orders/OrderDetailView.vue @@ -0,0 +1,686 @@ + + + + + diff --git a/src/views/orders/OrderSuccessView.vue b/src/views/orders/OrderSuccessView.vue new file mode 100644 index 0000000..1108f9f --- /dev/null +++ b/src/views/orders/OrderSuccessView.vue @@ -0,0 +1,84 @@ + + + + + diff --git a/src/views/orders/components/DesktopOrdersPage.vue b/src/views/orders/components/DesktopOrdersPage.vue new file mode 100644 index 0000000..263ebba --- /dev/null +++ b/src/views/orders/components/DesktopOrdersPage.vue @@ -0,0 +1,210 @@ + + + diff --git a/src/views/orders/components/MobileOrdersPage.vue b/src/views/orders/components/MobileOrdersPage.vue new file mode 100644 index 0000000..27a5223 --- /dev/null +++ b/src/views/orders/components/MobileOrdersPage.vue @@ -0,0 +1,199 @@ + + + + + diff --git a/src/views/products/ProductListView.vue b/src/views/products/ProductListView.vue new file mode 100644 index 0000000..8713bed --- /dev/null +++ b/src/views/products/ProductListView.vue @@ -0,0 +1,74 @@ + + + diff --git a/src/views/products/components/DesktopProductPage.vue b/src/views/products/components/DesktopProductPage.vue new file mode 100644 index 0000000..e91a3c5 --- /dev/null +++ b/src/views/products/components/DesktopProductPage.vue @@ -0,0 +1,303 @@ + + + + + diff --git a/src/views/products/components/MobileProductPage.vue b/src/views/products/components/MobileProductPage.vue new file mode 100644 index 0000000..e5e66b1 --- /dev/null +++ b/src/views/products/components/MobileProductPage.vue @@ -0,0 +1,227 @@ + + + + + diff --git a/src/views/profile/ProfileChecksView.vue b/src/views/profile/ProfileChecksView.vue new file mode 100644 index 0000000..2394d5c --- /dev/null +++ b/src/views/profile/ProfileChecksView.vue @@ -0,0 +1,7 @@ + + + diff --git a/src/views/profile/ProfileEditView.vue b/src/views/profile/ProfileEditView.vue new file mode 100644 index 0000000..44c1736 --- /dev/null +++ b/src/views/profile/ProfileEditView.vue @@ -0,0 +1,152 @@ + + + + + diff --git a/src/views/profile/ProfileView.vue b/src/views/profile/ProfileView.vue new file mode 100644 index 0000000..a02a20f --- /dev/null +++ b/src/views/profile/ProfileView.vue @@ -0,0 +1,19 @@ + + + diff --git a/src/views/profile/components/DesktopProfilePage.vue b/src/views/profile/components/DesktopProfilePage.vue new file mode 100644 index 0000000..9c7b095 --- /dev/null +++ b/src/views/profile/components/DesktopProfilePage.vue @@ -0,0 +1,723 @@ + + + + + diff --git a/src/views/profile/components/MobileProfilePage.vue b/src/views/profile/components/MobileProfilePage.vue new file mode 100644 index 0000000..d9070ce --- /dev/null +++ b/src/views/profile/components/MobileProfilePage.vue @@ -0,0 +1,224 @@ + + + + + diff --git a/tsconfig.app.json b/tsconfig.app.json new file mode 100644 index 0000000..c0f2d86 --- /dev/null +++ b/tsconfig.app.json @@ -0,0 +1,18 @@ +{ + "extends": "@vue/tsconfig/tsconfig.dom.json", + "include": ["env.d.ts", "src/**/*", "src/**/*.vue"], + "exclude": ["src/**/__tests__/*"], + "compilerOptions": { + // Extra safety for array and object lookups, but may have false positives. + "noUncheckedIndexedAccess": true, + + // Path mapping for cleaner imports. + "paths": { + "@/*": ["./src/*"] + }, + + // `vue-tsc --build` produces a .tsbuildinfo file for incremental type-checking. + // Specified here to keep it out of the root directory. + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo" + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..66b5e57 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,11 @@ +{ + "files": [], + "references": [ + { + "path": "./tsconfig.node.json" + }, + { + "path": "./tsconfig.app.json" + } + ] +} diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000..c9b2bad --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,27 @@ +// TSConfig for modules that run in Node.js environment via either transpilation or type-stripping. +{ + "extends": "@tsconfig/node24/tsconfig.json", + "include": [ + "vite.config.*", + "vitest.config.*", + "cypress.config.*", + "playwright.config.*", + "eslint.config.*" + ], + "compilerOptions": { + // Most tools use transpilation instead of Node.js's native type-stripping. + // Bundler mode provides a smoother developer experience. + "module": "preserve", + "moduleResolution": "bundler", + + // Include Node.js types and avoid accidentally including other `@types/*` packages. + "types": ["node"], + + // Disable emitting output during `vue-tsc --build`, which is used for type-checking only. + "noEmit": true, + + // `vue-tsc --build` produces a .tsbuildinfo file for incremental type-checking. + // Specified here to keep it out of the root directory. + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo" + } +} diff --git a/vite.config.ts b/vite.config.ts new file mode 100644 index 0000000..ace127e --- /dev/null +++ b/vite.config.ts @@ -0,0 +1,20 @@ +import { fileURLToPath, URL } from 'node:url' + +import { defineConfig } from 'vite' +import vue from '@vitejs/plugin-vue' +import vueJsx from '@vitejs/plugin-vue-jsx' +import vueDevTools from 'vite-plugin-vue-devtools' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [ + vue(), + vueJsx(), + vueDevTools(), + ], + resolve: { + alias: { + '@': fileURLToPath(new URL('./src', import.meta.url)), + }, + }, +})