commit 5ae2d41f39cb7586e066a6cd99261fbdfddf277f Author: ochenstarik Date: Thu Sep 10 20:01:31 2026 +0700 feat: initial commit of Krona Universal Business OS interactive prototype diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.oxlintrc.json b/.oxlintrc.json new file mode 100644 index 0000000..6fa991d --- /dev/null +++ b/.oxlintrc.json @@ -0,0 +1,8 @@ +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "typescript", "oxc"], + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..d6af7e3 --- /dev/null +++ b/README.md @@ -0,0 +1,32 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some Oxlint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs) +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the Oxlint configuration + +If you are developing a production application, we recommend enabling type-aware lint rules by installing `oxlint-tsgolint` and editing `.oxlintrc.json`: + +```json +{ + "$schema": "./node_modules/oxlint/configuration_schema.json", + "plugins": ["react", "typescript", "oxc"], + "options": { + "typeAware": true + }, + "rules": { + "react/rules-of-hooks": "error", + "react/only-export-components": ["warn", { "allowConstantExport": true }] + } +} +``` + +See the [Oxlint rules documentation](https://oxc.rs/docs/guide/usage/linter/rules) for the full list of rules and categories. diff --git a/index.html b/index.html new file mode 100644 index 0000000..668acfa --- /dev/null +++ b/index.html @@ -0,0 +1,16 @@ + + + + + + + Крона — Universal Business OS + + + + + +
+ + + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..5f4db7c --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3001 @@ +{ + "name": "krona-front", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "krona-front", + "version": "0.0.0", + "dependencies": { + "@tanstack/react-table": "^9.2.4", + "clsx": "^2.1.1", + "lucide-react": "^1.43.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "react-router-dom": "^7.18.3", + "recharts": "^3.10.1", + "tailwind-merge": "^3.6.0", + "zustand": "^5.0.15" + }, + "devDependencies": { + "@types/node": "^24.13.4", + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.4", + "@vitejs/plugin-react": "^6.1.0", + "autoprefixer": "^10.5.5", + "oxlint": "^1.79.0", + "postcss": "^8.5.28", + "tailwindcss": "^3.4.19", + "typescript": "~6.0.2", + "vite": "^8.2.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz", + "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@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.149.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/oxc-project" + } + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.82.0.tgz", + "integrity": "sha512-a3LB+C5Dsj5b/qtmG/mv5WrzuiXEpg1KF5nXWcEvaoN5TYAqkIvxPOwTPp3Jy/FoGpRo8zsTFhMElMXfeoOEzA==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.82.0.tgz", + "integrity": "sha512-OBlhRgNqFblGpGenno/aqOfJLOkQ2B8Ig3iDAalfn0H8hJGZKXPeexCRTDm6uwv6YUjSA9Xnwt1y/Bgj5ZH8uw==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.82.0.tgz", + "integrity": "sha512-dsopxqtY5ZdyT9uLHyGt1SyiLop6hi7hWI3PKpePodkRQOkLaCm+OE4fR9CAz9qdfjiFO8531tX/QDyP/psjFg==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.82.0.tgz", + "integrity": "sha512-94Lu0SgTClKColU66g1VDuigV3HkcbkJBnTtZjGYfE8UPugaWDgKrm2icjC6HJVUYler2OXaHP/X0TBy8+CowQ==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.82.0.tgz", + "integrity": "sha512-hne/V06ewhh1i0w8+l7GDNROAGCGPmyFuOwiP7YTRu0JycyStJ4785dmF8xU5p0uUwt2emvIF9vc7Xjis+cJ0g==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.82.0.tgz", + "integrity": "sha512-aWY2xtbZf1LneW9Qsv/n2Sp8gOu74JrlQzEtj4coHX2SHFrCfhmAumaU+sI/A5nr+yoTRTSmI/pL2s6ADlNSkw==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.82.0.tgz", + "integrity": "sha512-Fe+TtXCXMh/5f7kWlZ2VAwsMumZWtraFlKVk1NJlL52/beGwfDE7ov+/8gVirHzWokzGu7X65hSPq0ucPDskWQ==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.82.0.tgz", + "integrity": "sha512-6azCZ6OJudlvipNttXCCQcyeFfcJ/NvUZdSN1z8elo73kCHtyQC7WTiUcSjWYvJ1jaq9KDUyMAoAS/vNzhBomA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.82.0.tgz", + "integrity": "sha512-PLEaSD8IAIIlwW4dwOd9YaxuxeOpwiXL4J24rcnE4iNtyM5j9Q9/3+gti08oXpx0u2ygNjRDx9xjWWpQonuJEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.82.0.tgz", + "integrity": "sha512-D94em/BwknNTn4vqxjHh5wb2oL566eFhArabqKIr0cNZMHOJuiraFp1A8tXpH05bbE5tqwEfLXTI0MWEGtn3Dw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.82.0.tgz", + "integrity": "sha512-MOprxBaoYU2D4VgxXCl3ghydThWtx7Um1lL51kGYNeQ5Al7WzsH7/tqGdNtbLrIWnjq3bsm13+nz/gRIxjrOXw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.82.0.tgz", + "integrity": "sha512-5h55QsfJ/luDXZzC20k6SNOY1Az+dCP9WvntKtcUWh2JhckAdwApY2ZusaBTwLENnReXU+A2fJtSrYvZJNKNPg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.82.0.tgz", + "integrity": "sha512-IE8NJNLlHr0CaXyGJPGVn0eTkUyoj1I2UfA8x7I4PSOYKsQ/6btVC7Pywrj5onk0cMH25r6Z38SoN3AvE5Zuog==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.82.0.tgz", + "integrity": "sha512-XUUUxaBo9XKl+J1B9EmP1cTGQPddzeURvoGkfwh/94PGnbW+hBprDljneoI2M1jzC1bzrIV3ihc7iM9UXl8+tg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.82.0.tgz", + "integrity": "sha512-SWLSFulX9TDuH6yvbPYp4+VNn6jkkIvvI+KiujDM5rWBRHEfkesCC/pCneIIUr6ovkxZ5fRtpi2v5Cz5FrMJZg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.82.0.tgz", + "integrity": "sha512-BQy35f6ZUdNr9a6c7B7orxQTcLjByGT2z3WAgmRovpRwmPYAaJ+NTplmMzhdjdJ4qSchfMNZy/Ukg+qRg6zseQ==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.82.0.tgz", + "integrity": "sha512-V4QhSTg5gctZue8RJjsGi7NpQPThr/p1/HfmiMC5kfe1KFEup9SQRVub4A6kijQjdHfxj7bLL1KO3QO7/5bwMQ==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.82.0.tgz", + "integrity": "sha512-TUSCLaKB2yktpFAJ/r3HAUYsaV/3DT7JS4iNKyoh3a9YNwD0UG7Ezh4D8m23654vQcU6P/RQrCAjRPKe4peP/A==", + "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.82.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.82.0.tgz", + "integrity": "sha512-VTVoRIWJTb+wvUX8EYoPArfFH02whuR10goFXE/LHRRX33ajRrFgqbcONXZMiF4C5rnattfkm87HqYn8jb8hmQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.12.0.tgz", + "integrity": "sha512-KiT+RzZbp6mQET+Mg+h2c97+9j1sNflUxQkIHI7Yuzf6Peu+OYpmkn6nbHWmLLWj+1ZODUJFwGZ7gx3L9R9EOw==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^11.0.0", + "redux": "^5.0.1", + "redux-thunk": "^3.1.0", + "reselect": "^5.1.0" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || ^18 || ^19", + "react-redux": "^7.2.1 || ^8.1.3 || ^9.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", + "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.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", + "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/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "license": "MIT" + }, + "node_modules/@standard-schema/utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/@standard-schema/utils/-/utils-0.3.0.tgz", + "integrity": "sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==", + "license": "MIT" + }, + "node_modules/@tanstack/react-store": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@tanstack/react-store/-/react-store-0.11.1.tgz", + "integrity": "sha512-HaIGKI3YLmjBYIvy5DFDY23oNaYZIsTZfngey07Uh5iLVJgM3bIGCnZeOFOqzjFld9JHWcaHJnasD/bKoGKwJQ==", + "license": "MIT", + "dependencies": { + "@tanstack/store": "0.11.1", + "use-sync-external-store": "^1.6.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/react-table": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-9.2.4.tgz", + "integrity": "sha512-Rzp1Q4e0/nIgEjmISYR5HeEgLTNtrG+C7NFZf/AbCxPO5hg+zC3yNGwcoECigUk8SFzzvhXbd2rFdtP2ZiGrfA==", + "license": "MIT", + "dependencies": { + "@tanstack/react-store": "^0.11.1", + "@tanstack/table-core": "9.2.4" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": ">=18" + } + }, + "node_modules/@tanstack/store": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/@tanstack/store/-/store-0.11.1.tgz", + "integrity": "sha512-mzTOBhypOuDJAy/D8n2MfUZ1HFkXnmSETviRyhqEC8LUE7/IZQExOTxMANj3KjTofYTkFNpBY67qaVrT41YccA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/table-core": { + "version": "9.2.4", + "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-9.2.4.tgz", + "integrity": "sha512-GwdDyGGr6UXAtubF14yAwcXvdaogqfsQgIk89Suebjxob/Rjq2xvfmXsjDF1rQmKmhHsJm9TOY7myxv3i6geJw==", + "license": "MIT", + "dependencies": { + "@tanstack/store": "^0.11.1" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@types/d3-array": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.2.tgz", + "integrity": "sha512-hOLWVbm7uRza0BYXpIIW5pxfrKe0W+D5lrFiAEYR+pb6w3N2SwSMaJbXdUfSEv+dT4MfHBLtn5js0LAWaO6otw==", + "license": "MIT" + }, + "node_modules/@types/d3-color": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", + "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==", + "license": "MIT" + }, + "node_modules/@types/d3-ease": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", + "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==", + "license": "MIT" + }, + "node_modules/@types/d3-interpolate": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", + "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==", + "license": "MIT", + "dependencies": { + "@types/d3-color": "*" + } + }, + "node_modules/@types/d3-path": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.1.tgz", + "integrity": "sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==", + "license": "MIT" + }, + "node_modules/@types/d3-scale": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.9.tgz", + "integrity": "sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==", + "license": "MIT", + "dependencies": { + "@types/d3-time": "*" + } + }, + "node_modules/@types/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-kVd74ta9eof3eJOvbNd1vGKS/XERRyQbT26Og63hIsvDO84cjD5gEOhsXf26w3FSoNlPVz84DOFcKv/oou+fMw==", + "license": "MIT", + "dependencies": { + "@types/d3-path": "*" + } + }, + "node_modules/@types/d3-time": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.4.tgz", + "integrity": "sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==", + "license": "MIT" + }, + "node_modules/@types/d3-timer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", + "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "24.13.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.4.tgz", + "integrity": "sha512-YJ7EqCstVTzIr0fMr7qul/977en+pQHrfmuKIo6Zr9i75Be21dr3MovcfvGtyvi2HAUrRerWps5sMO9I7WaxDw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.18.0" + } + }, + "node_modules/@types/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.3.0.tgz", + "integrity": "sha512-N0rFCuH9YoxG9/m61l9MfpJKfmLOVU0em7ipIz6TRgSSkvReLB9vL85GB+yr8Bs5leqpvg96JSwF4ZS1s4viQg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-ZI7bU42mZXXKHn/qNLEw2IrbiINU7X5+vfgdixBHkCNpYWXjKgfQ/P+uyGb5CjOLB9UcnTeg3rylQtV2hym44Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.3.0" + } + }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, + "node_modules/@vitejs/plugin-react": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz", + "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rolldown/pluginutils": "^1.0.1" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "oxc-transform-react": "^0.145.0", + "vite": "^8.0.0" + }, + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "oxc-transform-react": { + "optional": true + } + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/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/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "node_modules/autoprefixer": { + "version": "10.5.5", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.5.tgz", + "integrity": "sha512-uiRYvQYe/nNSzBJ7OUnd2/TZVsAdob3blml44teEpee9Cc1f4rGZFewO+JT3Wo8mgFOSzNqes4FHZn/Qz8WOuw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.9", + "caniuse-lite": "^1.0.30001810", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.21", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.21.tgz", + "integrity": "sha512-uh8vpY/1/YyFkunIDFH/12p7/7VdPKA1hejMVEbdkEaWnUz0Hesvx5EbiU6XxjyHZIOju+ZMbQJkRh+es3/spQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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.9", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.9.tgz", + "integrity": "sha512-EWazOblFYUvlGZcfGhPUPmYh3nikUxBVb+y9MJun5f3hBi812X+8MSQTujLBtgK3cf51fJWbWfOjyeO954d+Eg==", + "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.11.20", + "caniuse-lite": "^1.0.30001810", + "electron-to-chromium": "^1.5.420", + "node-releases": "^2.0.54", + "update-browserslist-db": "^1.3.2" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001810", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001810.tgz", + "integrity": "sha512-TITQPUkaz+aVk5GL6NhOdwk1aEaNTSDPsGFWrTuhKGtjTF70jL/Oht2W4c6rXUe5fu7Ie19VIahAXHIIiWWNeg==", + "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": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/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/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "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==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/d3-array": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz", + "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==", + "license": "ISC", + "dependencies": { + "internmap": "1 - 2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-color": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", + "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-ease": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", + "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-format": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.2.tgz", + "integrity": "sha512-AJDdYOdnyRDV5b6ArilzCPPwc1ejkHcoyFarqlPqT7zRYjhavcT3uSrqcMvsgh2CgoPbK3RCwyHaVyxYcP2Arg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-interpolate": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", + "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", + "license": "ISC", + "dependencies": { + "d3-color": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz", + "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-scale": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz", + "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==", + "license": "ISC", + "dependencies": { + "d3-array": "2.10.0 - 3", + "d3-format": "1 - 3", + "d3-interpolate": "1.2.0 - 3", + "d3-time": "2.1.1 - 3", + "d3-time-format": "2 - 4" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-shape": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz", + "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==", + "license": "ISC", + "dependencies": { + "d3-path": "^3.1.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz", + "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==", + "license": "ISC", + "dependencies": { + "d3-array": "2 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-time-format": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-4.1.0.tgz", + "integrity": "sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==", + "license": "ISC", + "dependencies": { + "d3-time": "1 - 3" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/d3-timer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", + "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/decimal.js-light": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz", + "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.425", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.425.tgz", + "integrity": "sha512-QvPtl41EUOnuT1HBvMKgxXRIaHNcagBPs50u7VULzhZXaGfqTbZyE16LQsctZ/RQHlGu+FOWeDTR4mY6YbeF1g==", + "dev": true, + "license": "ISC" + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-toolkit": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.52.0.tgz", + "integrity": "sha512-XTNEJQh1tY1ZJVcf6ayP/2n4ZPyaHlW2FWs7xvw5ddPuhUVjLD3olQVQS7kf58JbAB48iL0uL/jerTrjtV3lDA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks", + "tests/types", + "tests/browser-compat" + ] + }, + "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/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "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/fastq": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.3.tgz", + "integrity": "sha512-XKv5nnLs6nLF71NgiKJLIZFLkPyIEuOselLG7ujZnGrRfQK8HpvY+WqKhAJUAdLomwVHErVS4LfxFlPq0/FTAw==", + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "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/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "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/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/immer": { + "version": "11.1.18", + "resolved": "https://registry.npmjs.org/immer/-/immer-11.1.18.tgz", + "integrity": "sha512-EQyQtLiYW029lyoczMl/Hh4Xu7cDecSc58JRYpHyL4tIAu3eqd1yJzQX04d2BZHDkzFFvm6qJEJWOtfDSWAXbQ==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/internmap": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz", + "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-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/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "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, + "libc": [ + "glibc" + ], + "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, + "libc": [ + "musl" + ], + "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, + "libc": [ + "glibc" + ], + "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, + "libc": [ + "musl" + ], + "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/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lucide-react": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-1.43.0.tgz", + "integrity": "sha512-ubtnda1fVK5ky0PNEpOmB0wiwhpZUyJiol4K14KCm+QKvuCkfUu54Et/rIjyupJpwiJ5Hg+BLQE86/GEsS+IgQ==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.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/micromatch/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/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/node-releases": { + "version": "2.0.55", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.55.tgz", + "integrity": "sha512-mIrE/Cw9y+9Au6dS5vDKDhQza9YvG6w+ZrS6X+ZzA7yFW/soAeaups4Qzn1bL6g5FVy8WtP79+0j82oPIbqRjQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/oxlint": { + "version": "1.82.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.82.0.tgz", + "integrity": "sha512-+iFM1BGw1ntYJt3QngbJmjbrGxPaKMUADOXOijpWGnYcBPq8YZnQftSS1C+pVcDYy9YxqDVJKQqQkTazTQMboQ==", + "dev": true, + "license": "MIT", + "bin": { + "oxlint": "bin/oxlint" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/sponsors/oxc-project" + }, + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.82.0", + "@oxlint/binding-android-arm64": "1.82.0", + "@oxlint/binding-darwin-arm64": "1.82.0", + "@oxlint/binding-darwin-x64": "1.82.0", + "@oxlint/binding-freebsd-x64": "1.82.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.82.0", + "@oxlint/binding-linux-arm-musleabihf": "1.82.0", + "@oxlint/binding-linux-arm64-gnu": "1.82.0", + "@oxlint/binding-linux-arm64-musl": "1.82.0", + "@oxlint/binding-linux-ppc64-gnu": "1.82.0", + "@oxlint/binding-linux-riscv64-gnu": "1.82.0", + "@oxlint/binding-linux-riscv64-musl": "1.82.0", + "@oxlint/binding-linux-s390x-gnu": "1.82.0", + "@oxlint/binding-linux-x64-gnu": "1.82.0", + "@oxlint/binding-linux-x64-musl": "1.82.0", + "@oxlint/binding-openharmony-arm64": "1.82.0", + "@oxlint/binding-win32-arm64-msvc": "1.82.0", + "@oxlint/binding-win32-ia32-msvc": "1.82.0", + "@oxlint/binding-win32-x64-msvc": "1.82.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=7.0.2001", + "vite-plus": "*" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + }, + "vite-plus": { + "optional": true + } + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "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==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.5.28", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz", + "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.18", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "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/react": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react/-/react-19.3.0.tgz", + "integrity": "sha512-E8LUcbtBWt20bbl2YoHfx4ZDBdxVTfOKtCZn9cDSJ4l6/nuoApcpIBcj47t2wZoVX8g2ZHuMHbiShgCR1T5Sog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.3.0.tgz", + "integrity": "sha512-JDk8dgif51OjFoDE70+OT9ICyYr+69HlmihNwp1+Nsfbna3t5sIiCa9ZJktDmQ4/1b/rn26hIAR2uYXDMr5r0Q==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.28.0" + }, + "peerDependencies": { + "react": "^19.3.0" + } + }, + "node_modules/react-is": { + "version": "19.3.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.3.0.tgz", + "integrity": "sha512-UpMYezM4v5/18F28aC66AEsjXIgE02kyEMH6yLdgLXu/UTfa1Ntwck/nNLrbqJsEXW7gPb0coNO9FQse9WTovA==", + "license": "MIT", + "peer": true + }, + "node_modules/react-redux": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.3.0.tgz", + "integrity": "sha512-KQopgqFo/p/fgmAs5qz6p5RWaNAzq40WAu7fJIXnQpYxFPbJYtsJPWvGeF2rOBaY/kEuV77AVsX8TsQzKm+A/g==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "use-sync-external-store": "^1.4.0" + }, + "peerDependencies": { + "@types/react": "^18.2.25 || ^19", + "react": "^18.0 || ^19", + "redux": "^5.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "redux": { + "optional": true + } + } + }, + "node_modules/react-router": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.3.tgz", + "integrity": "sha512-gyXgtdr5uACJ5b1Q4udzjVV+tb/rlHIMJKuJ0e89R4Kzgz47z/rgP0dIKxktqIEUhDHluGTPJJH/wRha7CyqsA==", + "license": "MIT", + "dependencies": { + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } + } + }, + "node_modules/react-router-dom": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.3.tgz", + "integrity": "sha512-ytVbyBBM7vMfRCam25r0WMhSVSom909A8p+8m0/f1w853dz/xfFu6etAT2SEbVoSnI+ZoPRDqIsQXVT89gp7kg==", + "license": "MIT", + "dependencies": { + "react-router": "7.18.3" + }, + "engines": { + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" + } + }, + "node_modules/read-cache": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.2.tgz", + "integrity": "sha512-/peqiBB/n07gQGLsWaHho3WfvUyRscw0gYTsEFMhrIe/nWLkYaf5SbKYjGYqtRV3aPwykJgF2VEMo1ac4bnsGA==", + "dev": true, + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/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/recharts": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.10.1.tgz", + "integrity": "sha512-QXFrvt6IVcw7eeZCoyXTwkIJAX3Dv1nyVhMicXJ47GsGDDpcN8z6o644DibE9XjpBTThtsomLKnTV6lc+cVFUA==", + "license": "MIT", + "workspaces": [ + "www" + ], + "dependencies": { + "@reduxjs/toolkit": "^1.9.0 || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^11.1.8", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.2.0", + "tiny-invariant": "^1.3.3", + "use-sync-external-store": "^1.2.2", + "victory-vendor": "^37.0.2" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-is": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/redux": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", + "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", + "license": "MIT" + }, + "node_modules/redux-thunk": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-3.1.0.tgz", + "integrity": "sha512-NW2r5T6ksUKXCabzhL9z+h206HQw/NJkcLm1GPImRQ8IzfXwRGqjVhKJGauHirT0DAuyy6hjdnMZaRoAcy0Klw==", + "license": "MIT", + "peerDependencies": { + "redux": "^5.0.0" + } + }, + "node_modules/reselect": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.2.0.tgz", + "integrity": "sha512-AgZ3UOZm3YndfrJ4OYjgrT7bmCm/1iqkjvEfH/oYjzh6PD2qw4QuT3jjnXIrpdt4MTpMXclMT3lXbmRY+XRakw==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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.8", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@oxc-project/types": "=0.149.0", + "@rolldown/pluginutils": "^1.0.0" + }, + "bin": { + "rolldown": "bin/cli.mjs" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "optionalDependencies": { + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" + } + }, + "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/scheduler": { + "version": "0.28.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.28.0.tgz", + "integrity": "sha512-juorfCmIkIw8tT+p5BXSm6PJjQF/ycEYmKyzURCIt/RaZIhL+PulbQ9Yu2z1HdOJDdqDTlxA1+xKBmHXJsczAw==", + "license": "MIT" + }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.6.0.tgz", + "integrity": "sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "license": "MIT" + }, + "node_modules/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/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/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.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/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/update-browserslist-db": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.2.tgz", + "integrity": "sha512-UQ+MSxlhRm1bzjhU+DcuXfjFO1FzNtqhK5+9Yvlp90ItDLk5vT932A0rFu619nf7RVS+Y/VeaUW1jaRDqZ8VJw==", + "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/use-sync-external-store": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz", + "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.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/victory-vendor": { + "version": "37.3.6", + "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-37.3.6.tgz", + "integrity": "sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==", + "license": "MIT AND ISC", + "dependencies": { + "@types/d3-array": "^3.0.3", + "@types/d3-ease": "^3.0.0", + "@types/d3-interpolate": "^3.0.1", + "@types/d3-scale": "^4.0.2", + "@types/d3-shape": "^3.1.0", + "@types/d3-time": "^3.0.0", + "@types/d3-timer": "^3.0.0", + "d3-array": "^3.1.6", + "d3-ease": "^3.0.1", + "d3-interpolate": "^3.0.1", + "d3-scale": "^4.0.2", + "d3-shape": "^3.1.0", + "d3-time": "^3.0.0", + "d3-timer": "^3.0.1" + } + }, + "node_modules/vite": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.2.2.tgz", + "integrity": "sha512-cFKLV/PRgAUlIRm5WjMjJ86jrftzpqcgH+Us+DS8mI3CDNiH30Whrz8uHL3+MOLPAgqbMBAqWdAHAphOAM+z/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "lightningcss": "^1.33.0", + "picomatch": "^4.0.5", + "postcss": "^8.5.26", + "rolldown": "~1.2.4", + "tinyglobby": "^0.2.17" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.4.0 || ^0.5.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/zustand": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.15.tgz", + "integrity": "sha512-MpSEjRiBkA9crSYeOUH32rJC7SVqAbm0Fqcqge/bUi2PPoLcBWKOsG+C8mevmpr8TwXHBVkChbbJiyvkE+i/3A==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..2895872 --- /dev/null +++ b/package.json @@ -0,0 +1,35 @@ +{ + "name": "krona-front", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "oxlint", + "preview": "vite preview" + }, + "dependencies": { + "@tanstack/react-table": "^9.2.4", + "clsx": "^2.1.1", + "lucide-react": "^1.43.0", + "react": "^19.2.8", + "react-dom": "^19.2.8", + "react-router-dom": "^7.18.3", + "recharts": "^3.10.1", + "tailwind-merge": "^3.6.0", + "zustand": "^5.0.15" + }, + "devDependencies": { + "@types/node": "^24.13.4", + "@types/react": "^19.2.18", + "@types/react-dom": "^19.2.4", + "@vitejs/plugin-react": "^6.1.0", + "autoprefixer": "^10.5.5", + "oxlint": "^1.79.0", + "postcss": "^8.5.28", + "tailwindcss": "^3.4.19", + "typescript": "~6.0.2", + "vite": "^8.2.2" + } +} diff --git a/postcss.config.js b/postcss.config.js new file mode 100644 index 0000000..2e7af2b --- /dev/null +++ b/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/public/branding/krona-logo.png b/public/branding/krona-logo.png new file mode 100644 index 0000000..3d0c2e6 Binary files /dev/null and b/public/branding/krona-logo.png differ diff --git a/public/branding/krona-symbol.png b/public/branding/krona-symbol.png new file mode 100644 index 0000000..3ec8716 Binary files /dev/null and b/public/branding/krona-symbol.png differ diff --git a/public/favicon.svg b/public/favicon.svg new file mode 100644 index 0000000..6893eb1 --- /dev/null +++ b/public/favicon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/icons.svg b/public/icons.svg new file mode 100644 index 0000000..e952219 --- /dev/null +++ b/public/icons.svg @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/App.tsx b/src/App.tsx new file mode 100644 index 0000000..dc9c1f7 --- /dev/null +++ b/src/App.tsx @@ -0,0 +1,9 @@ +import React from 'react'; +import { RouterProvider } from 'react-router-dom'; +import { router } from './app/router'; + +export function App() { + return ; +} + +export default App; diff --git a/src/app/layouts/AppShell.tsx b/src/app/layouts/AppShell.tsx new file mode 100644 index 0000000..004b02d --- /dev/null +++ b/src/app/layouts/AppShell.tsx @@ -0,0 +1,133 @@ +import React, { useEffect } from 'react'; +import { Outlet } from 'react-router-dom'; +import { useDemoStore } from '../../mock/store'; +import { Sidebar } from '../shell/Sidebar'; +import { Topbar } from '../shell/Topbar'; +import { RightCommandPanel } from '../shell/RightCommandPanel'; +import { BottomNav } from '../shell/BottomNav'; +import { CommandPalette } from '../shell/CommandPalette'; +import { QuickActionsModal } from '../shell/QuickActionsModal'; +import { NotificationsDrawer } from '../shell/NotificationsDrawer'; +import { Drawer } from '../../shared/components/Drawer'; +import { Sparkles, Bot, Send } from 'lucide-react'; +import { Button } from '../../shared/components/Button'; + +export const AppShell: React.FC = () => { + const { + theme, + viewportMode, + isAiDrawerOpen, + setIsAiDrawerOpen, + getActiveProfile, + activeLocation, + } = useDemoStore(); + + const profile = getActiveProfile(); + + useEffect(() => { + document.documentElement.setAttribute('data-theme', theme); + }, [theme]); + + // Viewport mode constraints + const getViewportContainerStyles = () => { + switch (viewportMode) { + case 'mobile': + return 'max-w-[420px] h-[880px] my-6 border-8 border-[#3A3D35] rounded-[36px] overflow-hidden shadow-2xl relative'; + case 'tablet-portrait': + return 'max-w-[820px] h-[1050px] my-6 border-8 border-[#3A3D35] rounded-[28px] overflow-hidden shadow-2xl relative'; + case 'tablet-landscape': + return 'max-w-[1180px] h-[800px] my-6 border-8 border-[#3A3D35] rounded-[24px] overflow-hidden shadow-2xl relative'; + case 'desktop': + default: + return 'w-full min-h-screen'; + } + }; + + const isEmulatedDevice = viewportMode !== 'desktop'; + const showMobileNav = viewportMode === 'mobile'; + + return ( +
+
+ {/* App Main Shell Container */} +
+ {/* Left Sidebar (hidden in mobile mode) */} + {!showMobileNav && } + + {/* Center Work Area */} +
+ + + {/* Main Content Router Outlet */} +
+ +
+
+ + {/* Right Command Panel (Desktop and Tablet-Landscape) */} + {viewportMode === 'desktop' && } +
+ + {/* Mobile Bottom Navigation */} + {showMobileNav && } + + {/* Global Modals & Drawers */} + + + + + {/* Standalone AI Drawer (triggered via Topbar ✦ button on any screen) */} + setIsAiDrawerOpen(false)} + title="✦ Krona AI — Бизнес-оркестратор" + subtitle={`Контекст: ${profile.name} • ${activeLocation}`} + width="md" + > +
+
+ Krona AI Core v1: Интеллектуальный помощник подключен к локальной модели данных бизнеса, остаткам, расписанию смен и фискальным отчетам. +
+ +
+ + Ролевые агенты команды: + +
+
+
Бизнес-аналитик
+
Food cost, выручка, чеки
+
+
+
Складской агент
+
Списания, закупки, пороги
+
+
+
Маркетолог
+
Сегменты, LTV, рассылки
+
+
+
Финансовый аудитор
+
Кассовые смены, ДДС, P&L
+
+
+
+ +
+ +
+
+
+
+
+ ); +}; diff --git a/src/app/router/index.tsx b/src/app/router/index.tsx new file mode 100644 index 0000000..01f1126 --- /dev/null +++ b/src/app/router/index.tsx @@ -0,0 +1,47 @@ +import React from 'react'; +import { createBrowserRouter, Navigate } from 'react-router-dom'; +import { AppShell } from '../layouts/AppShell'; +import { DynamicDashboard } from '../../features/dashboard/DynamicDashboard'; +import { OperationsModule } from '../../features/operations/OperationsModule'; +import { CrmModule } from '../../features/crm/CrmModule'; +import { SalesModule } from '../../features/sales/SalesModule'; +import { InventoryModule } from '../../features/inventory/InventoryModule'; +import { FinanceModule } from '../../features/finance/FinanceModule'; +import { EmployeesModule } from '../../features/employees/EmployeesModule'; +import { CommunicationsModule } from '../../features/communications/CommunicationsModule'; +import { HelpDeskModule } from '../../features/helpdesk/HelpDeskModule'; +import { TasksModule } from '../../features/tasks/TasksModule'; +import { CmsModule } from '../../features/cms/CmsModule'; +import { MarketingModule } from '../../features/marketing/MarketingModule'; +import { AnalyticsModule } from '../../features/analytics/AnalyticsModule'; +import { AutomationModule } from '../../features/automation/AutomationModule'; +import { AiCenterModule } from '../../features/ai/AiCenterModule'; +import { AppsCatalogModule } from '../../features/apps/AppsCatalogModule'; +import { SettingsModule } from '../../features/settings/SettingsModule'; + +export const router = createBrowserRouter([ + { + path: '/', + element: , + children: [ + { index: true, element: }, + { path: 'operations/*', element: }, + { path: 'crm/*', element: }, + { path: 'sales/*', element: }, + { path: 'inventory/*', element: }, + { path: 'finance/*', element: }, + { path: 'employees/*', element: }, + { path: 'communications/*', element: }, + { path: 'helpdesk/*', element: }, + { path: 'tasks/*', element: }, + { path: 'cms/*', element: }, + { path: 'marketing/*', element: }, + { path: 'analytics/*', element: }, + { path: 'automation/*', element: }, + { path: 'ai/*', element: }, + { path: 'apps/*', element: }, + { path: 'settings/*', element: }, + { path: '*', element: }, + ], + }, +]); diff --git a/src/app/shell/BottomNav.tsx b/src/app/shell/BottomNav.tsx new file mode 100644 index 0000000..6809f68 --- /dev/null +++ b/src/app/shell/BottomNav.tsx @@ -0,0 +1,119 @@ +import React, { useState } from 'react'; +import { NavLink, useNavigate } from 'react-router-dom'; +import { useDemoStore } from '../../mock/store'; +import { + LayoutDashboard, + Workflow, + Plus, + MessageSquare, + Menu, + X, + Boxes, + BadgeDollarSign, + Users, + Settings, + Sparkles, +} from 'lucide-react'; +import { SYSTEM_MODULES } from '../../core/modules/registry'; + +export const BottomNav: React.FC = () => { + const { setIsQuickActionsOpen, setIsAiDrawerOpen } = useDemoStore(); + const [isMoreMenuOpen, setIsMoreMenuOpen] = useState(false); + const navigate = useNavigate(); + + return ( + <> + {/* More menu drawer on mobile */} + {isMoreMenuOpen && ( +
+
setIsMoreMenuOpen(false)} + /> +
+
+ Все разделы Кроны + +
+ +
+ {SYSTEM_MODULES.map((m) => ( + + ))} +
+
+
+ )} + + {/* Persistent Bottom Bar */} + + + ); +}; diff --git a/src/app/shell/CommandPalette.tsx b/src/app/shell/CommandPalette.tsx new file mode 100644 index 0000000..90b1844 --- /dev/null +++ b/src/app/shell/CommandPalette.tsx @@ -0,0 +1,202 @@ +import React, { useState, useEffect } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { useDemoStore } from '../../mock/store'; +import { SYSTEM_MODULES } from '../../core/modules/registry'; +import { BUSINESS_PROFILES } from '../../core/profiles/profiles'; +import { SYSTEM_ROLES, SystemRoleId } from '../../core/permissions/types'; +import { Search, ArrowRight, Sun, Moon, Sparkles, Plus, X } from 'lucide-react'; + +export const CommandPalette: React.FC = () => { + const { + isCommandPaletteOpen, + setIsCommandPaletteOpen, + setProfileId, + setRoleId, + setTheme, + setIsQuickActionsOpen, + theme, + } = useDemoStore(); + + const [query, setQuery] = useState(''); + const navigate = useNavigate(); + + useEffect(() => { + const handleKeyDown = (e: KeyboardEvent) => { + if ((e.ctrlKey || e.metaKey) && e.key.toLowerCase() === 'k') { + e.preventDefault(); + setIsCommandPaletteOpen(!isCommandPaletteOpen); + } + if (e.key === 'Escape' && isCommandPaletteOpen) { + setIsCommandPaletteOpen(false); + } + }; + window.addEventListener('keydown', handleKeyDown); + return () => window.removeEventListener('keydown', handleKeyDown); + }, [isCommandPaletteOpen, setIsCommandPaletteOpen]); + + if (!isCommandPaletteOpen) return null; + + const filteredModules = SYSTEM_MODULES.filter( + (m) => m.label.toLowerCase().includes(query.toLowerCase()) || m.route.toLowerCase().includes(query.toLowerCase()) + ); + + const filteredProfiles = Object.values(BUSINESS_PROFILES).filter((p) => + p.name.toLowerCase().includes(query.toLowerCase()) || p.label.toLowerCase().includes(query.toLowerCase()) + ); + + const filteredRoles = Object.values(SYSTEM_ROLES).filter((r) => + r.label.toLowerCase().includes(query.toLowerCase()) || r.badge.toLowerCase().includes(query.toLowerCase()) + ); + + return ( +
+
setIsCommandPaletteOpen(false)} + /> + +
+ {/* Search header */} +
+ + setQuery(e.target.value)} + placeholder="Поиск по Кроне, модулям, профилям, ролям или действиям (Ctrl+K)..." + className="w-full bg-transparent text-krona-primary placeholder:text-krona-secondary text-sm focus:outline-none" + /> + +
+ + {/* Results */} +
+ {/* Quick Actions */} +
+
+ Быстрые действия +
+
+ + + +
+
+ + {/* Modules */} + {filteredModules.length > 0 && ( +
+
+ Модули платформы +
+
+ {filteredModules.slice(0, 8).map((mod) => ( + + ))} +
+
+ )} + + {/* Business Profiles Switcher */} +
+
+ + Сменить бизнес-профиль +
+
+ {filteredProfiles.map((p) => ( + + ))} +
+
+ + {/* Roles Switcher */} +
+
+ Сменить роль (RBAC) +
+
+ {filteredRoles.slice(0, 6).map((role) => ( + + ))} +
+
+
+ + {/* Footer */} +
+ Навигация: ↑ ↓  |  Выбор: Enter  |  Закрыть: Esc + Крона AGI Universal OS +
+
+
+ ); +}; diff --git a/src/app/shell/NotificationsDrawer.tsx b/src/app/shell/NotificationsDrawer.tsx new file mode 100644 index 0000000..432420f --- /dev/null +++ b/src/app/shell/NotificationsDrawer.tsx @@ -0,0 +1,108 @@ +import React from 'react'; +import { useDemoStore } from '../../mock/store'; +import { Drawer } from '../../shared/components/Drawer'; +import { Button } from '../../shared/components/Button'; +import { Badge } from '../../shared/components/Badge'; +import { Bell, AlertTriangle, AlertCircle, CheckCircle2, Info, Check, Trash2 } from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; + +export const NotificationsDrawer: React.FC = () => { + const { + isNotificationsOpen, + setIsNotificationsOpen, + notifications, + dismissNotification, + markAllNotificationsRead, + } = useDemoStore(); + + const navigate = useNavigate(); + + const getIcon = (type: string) => { + switch (type) { + case 'danger': + return ; + case 'warning': + return ; + case 'success': + return ; + default: + return ; + } + }; + + return ( + setIsNotificationsOpen(false)} + title="Центр внимания и уведомлений" + subtitle="Срочные алерты, статус кассы, стоп-листы и опоздания" + width="md" + footer={ +
+ + +
+ } + > +
+ {notifications.length === 0 ? ( +
+ + Нет активных уведомлений. Все системы в норме! +
+ ) : ( + notifications.map((n) => ( +
+
+
{getIcon(n.type)}
+
+
+
{n.title}
+ {n.timestamp} +
+

{n.message}

+ +
+ {n.actionUrl ? ( + + ) : ( + + )} + + +
+
+
+
+ )) + )} +
+
+ ); +}; diff --git a/src/app/shell/QuickActionsModal.tsx b/src/app/shell/QuickActionsModal.tsx new file mode 100644 index 0000000..cfdf717 --- /dev/null +++ b/src/app/shell/QuickActionsModal.tsx @@ -0,0 +1,220 @@ +import React, { useState } from 'react'; +import { useDemoStore } from '../../mock/store'; +import { Modal } from '../../shared/components/Modal'; +import { Button } from '../../shared/components/Button'; +import { Input } from '../../shared/components/Input'; +import { + ShoppingBag, + Calendar, + UserPlus, + Car, + Wrench, + PackagePlus, + Receipt, + FileText, + CheckCircle2, +} from 'lucide-react'; + +export const QuickActionsModal: React.FC = () => { + const { + isQuickActionsOpen, + setIsQuickActionsOpen, + getActiveProfile, + addBooking, + addWorkOrder, + activeLocation, + } = useDemoStore(); + + const profile = getActiveProfile(); + const [activeTab, setActiveTab] = useState('order'); + const [successMessage, setSuccessMessage] = useState(null); + + // Form states + const [clientName, setClientName] = useState(''); + const [clientPhone, setClientPhone] = useState(''); + const [bookingTime, setBookingTime] = useState('19:00'); + const [resource, setResource] = useState('Стол 3'); + const [vehicle, setVehicle] = useState('Toyota Camry (А123АА 154)'); + const [amount, setAmount] = useState('1500'); + + const handleCreate = (e: React.FormEvent) => { + e.preventDefault(); + if (activeTab === 'booking') { + addBooking({ + clientName: clientName || 'Новый клиент', + clientPhone: clientPhone || '+7 (900) 000-00-00', + resourceName: resource, + time: bookingTime, + status: 'confirmed', + deposit: Number(amount) || 0, + }); + setSuccessMessage(`Бронирование ресурса "${resource}" успешно создано!`); + } else if (activeTab === 'work_order') { + addWorkOrder({ + vehicle: vehicle || 'Автомобиль клиента', + ownerName: clientName || 'Владелец', + phone: clientPhone || '+7 (900) 000-00-00', + bay: 'Пост 1', + masterName: 'Иван Кузнецов', + services: ['Комплексная диагностика', 'Мойка / ТО'], + partsAmount: 1200, + laborAmount: Number(amount) || 2500, + status: 'in_progress', + }); + setSuccessMessage(`Заказ-наряд на ${vehicle} открыт!`); + } else { + setSuccessMessage(`Действие успешно выполнено для точки "${activeLocation}"!`); + } + + setTimeout(() => { + setSuccessMessage(null); + setIsQuickActionsOpen(false); + }, 1200); + }; + + return ( + setIsQuickActionsOpen(false)} + title="Быстрое создание" + subtitle={`Профиль: ${profile.name} • ${activeLocation}`} + maxWidth="lg" + > + {successMessage ? ( +
+ +

{successMessage}

+

Данные синхронизированы в локальном mock API

+
+ ) : ( +
+ {/* Action Types selector */} +
+ + + + + +
+ +
+
+ setClientName(e.target.value)} + placeholder="Иван Петров" + required + /> + setClientPhone(e.target.value)} + placeholder="+7 (913) 000-00-00" + required + /> +
+ + {activeTab === 'booking' && ( +
+ setResource(e.target.value)} + placeholder="Стол 4 / Пост 2 / Мастер" + /> + setBookingTime(e.target.value)} + /> +
+ )} + + {activeTab === 'work_order' && ( +
+ setVehicle(e.target.value)} + placeholder="BMW X5 (А001АА 154)" + icon={} + /> +
+ )} + +
+ setAmount(e.target.value)} + placeholder="2500" + /> +
+ + +
+
+ +
+ + +
+
+
+ )} +
+ ); +}; diff --git a/src/app/shell/RightCommandPanel.tsx b/src/app/shell/RightCommandPanel.tsx new file mode 100644 index 0000000..d5b9c8b --- /dev/null +++ b/src/app/shell/RightCommandPanel.tsx @@ -0,0 +1,411 @@ +import React, { useState } from 'react'; +import { useDemoStore } from '../../mock/store'; +import { Button } from '../../shared/components/Button'; +import { Input } from '../../shared/components/Input'; +import { Badge } from '../../shared/components/Badge'; +import { + Sparkles, + Send, + MessageSquare, + Zap, + ChevronRight, + ChevronLeft, + ShoppingBag, + Calendar, + CheckSquare, + UserPlus, + Car, + Receipt, + RotateCcw, + Bot, + User, +} from 'lucide-react'; +import { useNavigate } from 'react-router-dom'; + +export const RightCommandPanel: React.FC = () => { + const { + isRightPanelCollapsed, + setIsRightPanelCollapsed, + getActiveProfile, + setIsQuickActionsOpen, + activeLocation, + } = useDemoStore(); + + const profile = getActiveProfile(); + const navigate = useNavigate(); + + const [activeTab, setActiveTab] = useState<'ai' | 'chat' | 'actions'>('ai'); + + // AI Mock Chat state + const [messages, setMessages] = useState<{ id: string; sender: 'user' | 'ai'; text: string; time: string }[]>([ + { + id: '1', + sender: 'ai', + text: `Приветствую! Я Krona AI. Анализирую точку «${activeLocation}» (${profile.name}). Выручка в норме, но обратите внимание на запас охлажденного лосося — осталось 2.4 кг. Чем помочь?`, + time: '12:30', + }, + ]); + const [prompt, setPrompt] = useState(''); + const [isAiTyping, setIsAiTyping] = useState(false); + + // Communications mini state + const [chatCategory, setChatCategory] = useState<'all' | 'clients' | 'team'>('all'); + + const QUICK_QUESTIONS = [ + 'Что требует внимания сегодня?', + 'Какие позиции скоро закончатся?', + 'Самые прибыльные позиции?', + 'Каких клиентов стоит вернуть?', + ]; + + const handleSendPrompt = (textToSend?: string) => { + const q = textToSend || prompt; + if (!q.trim()) return; + + const userMsg = { + id: `usr-${Date.now()}`, + sender: 'user' as const, + text: q, + time: new Date().toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }), + }; + + setMessages((prev) => [...prev, userMsg]); + setPrompt(''); + setIsAiTyping(true); + + setTimeout(() => { + let aiReply = 'Анализирую операционные данные Кроны...'; + if (q.includes('внимания')) { + aiReply = '⚠️ 3 критических алерта: 1) Запас лосося ниже минимума (2.4 кг из 6 кг); 2) Заказ #104 готовится уже 18 минут; 3) Курьер Алексей завершил смену с 24 500 ₽ наличных к инкассации.'; + } else if (q.includes('закончатся') || q.includes('склад')) { + aiReply = '📦 Скоро закончатся: Лосось атлантический (2.4 кг), Угорь копченый (0.0 кг — в стоп-листе!), Тигровые креветки (4.8 кг). Рекомендую сформировать авто-заявку в СибРыбТорг.'; + } else if (q.includes('прибыльные') || q.includes('блюда')) { + aiReply = '💰 Топ по маржинальности: 1) Гёдза свинина (маржа 76.1%, food cost 23.9%); 2) Рамен Тонкоцу (маржа 72.1%); 3) Филадельфия Премиум (выручка 58 650 ₽/день).'; + } else if (q.includes('клиент')) { + aiReply = '👥 В зоне риска 14 постоянных клиентов (не было визитов более 30 дней). Например: Дмитрий Мельников (LTV 18 500 ₽). Предлагаю запустить триггерную рассылку со скидкой 15% в Telegram-боте.'; + } else { + aiReply = `Ответ AI по профилю «${profile.name}»: Задача зафиксирована в оркестраторе Кроны. Контекст передан специализированным агентам.`; + } + + setMessages((prev) => [ + ...prev, + { + id: `ai-${Date.now()}`, + sender: 'ai', + text: aiReply, + time: new Date().toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' }), + }, + ]); + setIsAiTyping(false); + }, 650); + }; + + if (isRightPanelCollapsed) { + return ( + + ); + } + + return ( + + ); +}; diff --git a/src/app/shell/Sidebar.tsx b/src/app/shell/Sidebar.tsx new file mode 100644 index 0000000..4060144 --- /dev/null +++ b/src/app/shell/Sidebar.tsx @@ -0,0 +1,159 @@ +import React, { useState } from 'react'; +import { NavLink } from 'react-router-dom'; +import { useDemoStore } from '../../mock/store'; +import { SYSTEM_MODULES } from '../../core/modules/registry'; +import { SYSTEM_ROLES } from '../../core/permissions/types'; +import { + LayoutDashboard, + Workflow, + Users, + ShoppingBag, + Boxes, + BadgeDollarSign, + UserCheck, + MessageSquareText, + Headset, + CheckSquare, + Globe, + Megaphone, + BarChart3, + Cpu, + Sparkles, + Grid, + Settings, + ChevronLeft, + ChevronRight, + ShieldAlert, +} from 'lucide-react'; + +const ICON_MAP: Record = { + LayoutDashboard: , + Workflow: , + Users: , + ShoppingBag: , + Boxes: , + BadgeDollarSign: , + UserCheck: , + MessageSquareText: , + Headset: , + CheckSquare: , + Globe: , + Megaphone: , + BarChart3: , + Cpu: , + Sparkles: , + Grid: , + Settings: , +}; + +export const Sidebar: React.FC = () => { + const [collapsed, setCollapsed] = useState(false); + const { currentRoleId, getActiveCapabilities } = useDemoStore(); + const capabilities = getActiveCapabilities(); + const role = SYSTEM_ROLES[currentRoleId]; + + // Filter modules by role permissions and active capabilities + const visibleModules = SYSTEM_MODULES.filter((m) => { + // Role check + if (!role.allowedModules.includes('*') && !role.allowedModules.includes(m.id)) { + return false; + } + // Capability check + if (m.requiredCapability && !capabilities[m.requiredCapability]) { + return false; + } + return true; + }); + + return ( + + ); +}; diff --git a/src/app/shell/Topbar.tsx b/src/app/shell/Topbar.tsx new file mode 100644 index 0000000..ff7cd6e --- /dev/null +++ b/src/app/shell/Topbar.tsx @@ -0,0 +1,368 @@ +import React, { useState } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { useDemoStore, ThemeMode, ViewportMode } from '../../mock/store'; +import { BUSINESS_PROFILES } from '../../core/profiles/profiles'; +import { SYSTEM_ROLES, SystemRoleId } from '../../core/permissions/types'; +import { SYSTEM_MODULES } from '../../core/modules/registry'; +import { Button } from '../../shared/components/Button'; +import { Badge } from '../../shared/components/Badge'; +import { + Search, + Plus, + Bell, + Sun, + Moon, + Sparkles, + Monitor, + Tablet, + Smartphone, + ChevronDown, + MapPin, + Shield, + Layers, +} from 'lucide-react'; + +export const Topbar: React.FC = () => { + const { + theme, + setTheme, + viewportMode, + setViewportMode, + currentProfileId, + setProfileId, + currentRoleId, + setRoleId, + activeLocation, + setActiveLocation, + setIsCommandPaletteOpen, + setIsQuickActionsOpen, + setIsNotificationsOpen, + setIsAiDrawerOpen, + notifications, + getActiveProfile, + getActiveCapabilities, + } = useDemoStore(); + + const location = useLocation(); + const navigate = useNavigate(); + + const profile = getActiveProfile(); + const capabilities = getActiveCapabilities(); + const currentRole = SYSTEM_ROLES[currentRoleId]; + + const unreadNotificationsCount = notifications.filter((n) => !n.read).length; + + // Determine current active module from route + const currentPath = location.pathname; + const currentModule = SYSTEM_MODULES.find((m) => { + if (m.route === '/') return currentPath === '/'; + return currentPath.startsWith(m.route); + }) || SYSTEM_MODULES[0]; + + // For operations, tabs are dynamic based on active profile & capabilities! + const getSubtabs = () => { + if (currentModule.id === 'operations') { + return profile.operationsTabs.filter((tab) => { + if (!tab.requiredCapability) return true; + return capabilities[tab.requiredCapability]; + }); + } + return currentModule.sections.filter((sec) => { + if (!sec.requiredCapability) return true; + return capabilities[sec.requiredCapability]; + }); + }; + + const activeSubtabs = getSubtabs(); + + return ( +
+ {/* Upper Control Bar */} +
+ {/* Left: Profile & Location controls */} +
+ {/* Profile Switcher */} +
+
+ +
+ + Профиль бизнеса + + + {profile.name} + +
+ +
+ + {/* Dropdown Menu */} +
+
+ Отраслевые профили Кроны +
+
+ {Object.values(BUSINESS_PROFILES).map((p) => ( + + ))} +
+
+
+ + {/* Location Selector */} +
+
+ + {activeLocation} + +
+ +
+
+ Точки продаж / Локации +
+ {profile.locations.map((loc) => ( + + ))} +
+
+ + {/* Role (RBAC) Switcher */} +
+
+ +
+ Роль + + {currentRole.badge} + +
+ +
+ +
+
+ Переключение роли (RBAC) +
+
+ {Object.values(SYSTEM_ROLES).map((r) => ( + + ))} +
+
+
+
+ + {/* Center: Global Search & Shortcuts */} +
+ +
+ + {/* Right: Quick actions, AI, Themes, Viewports, Notifications */} +
+ {/* AI trigger */} + + + {/* Quick Action (+) button */} + + + {/* Viewport Switcher */} +
+ + + + +
+ + {/* Theme Switcher */} +
+ + + +
+ + {/* Notifications bell */} + +
+
+ + {/* Horizontal Module Subnavigation Tabs */} + {activeSubtabs.length > 0 && ( + + )} +
+ ); +}; diff --git a/src/assets/hero.png b/src/assets/hero.png new file mode 100644 index 0000000..02251f4 Binary files /dev/null and b/src/assets/hero.png differ diff --git a/src/assets/react.svg b/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/assets/vite.svg b/src/assets/vite.svg new file mode 100644 index 0000000..5101b67 --- /dev/null +++ b/src/assets/vite.svg @@ -0,0 +1 @@ +Vite diff --git a/src/core/capabilities/types.ts b/src/core/capabilities/types.ts new file mode 100644 index 0000000..5aee6fc --- /dev/null +++ b/src/core/capabilities/types.ts @@ -0,0 +1,53 @@ +export type CapabilityId = + | 'crm' + | 'sales' + | 'communications' + | 'helpdesk' + | 'tasks' + | 'cms' + | 'marketing' + | 'analytics' + | 'finance' + | 'employees' + | 'inventory' + | 'purchasing' + | 'delivery' + | 'booking' + | 'pos' + | 'kds' + | 'dining' + | 'work_orders' + | 'production' + | 'automation' + | 'ai'; + +export interface CapabilityMeta { + id: CapabilityId; + name: string; + description: string; + category: 'core' | 'operations' | 'growth' | 'management'; +} + +export const CAPABILITIES_LIST: CapabilityMeta[] = [ + { id: 'crm', name: 'CRM & Клиенты', description: 'Управление клиентами, лидами, сделками и воронками', category: 'core' }, + { id: 'sales', name: 'Продажи & Заказы', description: 'Обработка заказов, счетов и оплат', category: 'core' }, + { id: 'communications', name: 'Омниканальные коммуникации', description: 'Единый inbox: Telegram, WhatsApp, MAX, VK, почта', category: 'core' }, + { id: 'helpdesk', name: 'HelpDesk & Поддержка', description: 'Тикеты, SLA, база знаний и решение инцидентов', category: 'core' }, + { id: 'tasks', name: 'Задачи & Проекты', description: 'Канбан, списки задач, спринты и контроль сроков', category: 'management' }, + { id: 'cms', name: 'Сайты & Krona CMS', description: 'Конструктор страниц, блог, формы, SEO и витрины', category: 'growth' }, + { id: 'marketing', name: 'Маркетинг & Рассылки', description: 'Контент-план, акции, рассылки, AI-маркетолог', category: 'growth' }, + { id: 'analytics', name: 'Аналитика & BI', description: 'Сквозная аналитика, финансовые отчеты и дашборды', category: 'management' }, + { id: 'finance', name: 'Финансы & ДДС', description: 'Доходы, расходы, кассовые смены, P&L и казначейство', category: 'management' }, + { id: 'employees', name: 'Сотрудники & Смены', description: 'Графики, учет рабочего времени, роли и KPI', category: 'management' }, + { id: 'inventory', name: 'Склад & Остатки', description: 'Остатки, партии, списания, перемещения, инвентаризация', category: 'operations' }, + { id: 'purchasing', name: 'Закупки & Поставщики', description: 'Заказы поставщикам, приходные накладные, сверки', category: 'operations' }, + { id: 'delivery', name: 'Доставка & Курьеры', description: 'Маршруты, статусы курьеров, расчет зон и стоимости', category: 'operations' }, + { id: 'booking', name: 'Бронирование & Слоты', description: 'Запись клиентов, онлайн-слоты, бронь ресурсов', category: 'operations' }, + { id: 'pos', name: 'Кассовый терминал (POS)', description: 'Быстрое оформление чеков, скидки, фискализация', category: 'operations' }, + { id: 'kds', name: 'Кухонный экран (KDS)', description: 'Дисплей кухни/сборки с таймерами и статусами', category: 'operations' }, + { id: 'dining', name: 'Зал & Столы', description: 'Схема залов, рассадка, открытые чеки и официанты', category: 'operations' }, + { id: 'work_orders', name: 'Заказ-наряды', description: 'Ремонтные работы, материалы, посты и нормо-часы', category: 'operations' }, + { id: 'production', name: 'Производство & Техкарты', description: 'Рецептуры, списание сырья, калькуляция себестоимости', category: 'operations' }, + { id: 'automation', name: 'Автоматизация & Workflows', description: 'Триггеры, цепочки действий, сценарии без кода', category: 'growth' }, + { id: 'ai', name: 'Krona AI Center', description: 'AI-команда: оркестратор, бизнес-аналитик, маркетолог', category: 'growth' }, +]; diff --git a/src/core/modules/registry.ts b/src/core/modules/registry.ts new file mode 100644 index 0000000..0187c05 --- /dev/null +++ b/src/core/modules/registry.ts @@ -0,0 +1,237 @@ +import { ModuleDefinition } from './types'; + +export const SYSTEM_MODULES: ModuleDefinition[] = [ + { + id: 'dashboard', + label: 'Главная', + iconName: 'LayoutDashboard', + route: '/', + sections: [ + { id: 'overview', label: 'Сводка дня', route: '/' }, + { id: 'alerts', label: 'Требует внимания', route: '/?tab=alerts', badge: '3' }, + { id: 'live', label: 'Операционный статус', route: '/?tab=live' }, + ], + }, + { + id: 'operations', + label: 'Операции', + iconName: 'Workflow', + route: '/operations', + sections: [], // Populated dynamically from active Business Profile operationsTabs + }, + { + id: 'crm', + label: 'CRM', + iconName: 'Users', + route: '/crm', + requiredCapability: 'crm', + sections: [ + { id: 'overview', label: 'Обзор CRM', route: '/crm' }, + { id: 'clients', label: 'Клиенты', route: '/crm/clients', badge: '1,420' }, + { id: 'deals', label: 'Сделки & Воронка', route: '/crm/deals', badge: '18' }, + { id: 'leads', label: 'Лиды', route: '/crm/leads', badge: '9' }, + { id: 'companies', label: 'Компании', route: '/crm/companies' }, + { id: 'segments', label: 'Сегменты', route: '/crm/segments' }, + { id: 'activities', label: 'Активности', route: '/crm/activities' }, + ], + }, + { + id: 'sales', + label: 'Продажи', + iconName: 'ShoppingBag', + route: '/sales', + requiredCapability: 'sales', + sections: [ + { id: 'overview', label: 'Обзор', route: '/sales' }, + { id: 'orders', label: 'Все заказы', route: '/sales/orders', badge: '42' }, + { id: 'invoices', label: 'Счета', route: '/sales/invoices' }, + { id: 'payments', label: 'Оплаты', route: '/sales/payments' }, + { id: 'refunds', label: 'Возвраты', route: '/sales/refunds' }, + { id: 'funnels', label: 'Конверсия', route: '/sales/funnels' }, + ], + }, + { + id: 'inventory', + label: 'Склад', + iconName: 'Boxes', + route: '/inventory', + requiredCapability: 'inventory', + sections: [ + { id: 'overview', label: 'Обзор склада', route: '/inventory' }, + { id: 'items', label: 'Остатки товаров', route: '/inventory/items' }, + { id: 'warehouses', label: 'Склады & Локации', route: '/inventory/warehouses' }, + { id: 'batches', label: 'Партии & Сроки', route: '/inventory/batches' }, + { id: 'movements', label: 'Перемещения', route: '/inventory/movements' }, + { id: 'writeoffs', label: 'Списания', route: '/inventory/writeoffs' }, + { id: 'audit', label: 'Инвентаризация', route: '/inventory/audit' }, + ], + }, + { + id: 'finance', + label: 'Финансы', + iconName: 'BadgeDollarSign', + route: '/finance', + requiredCapability: 'finance', + sections: [ + { id: 'overview', label: 'Обзор & Сальдо', route: '/finance' }, + { id: 'cashflow', label: 'ДДС (Cash Flow)', route: '/finance/cashflow' }, + { id: 'pnl', label: 'P&L (Прибыли и убытки)', route: '/finance/pnl' }, + { id: 'shifts', label: 'Кассовые смены', route: '/finance/shifts', badge: '2 открыты' }, + { id: 'transactions', label: 'Платежи', route: '/finance/transactions' }, + { id: 'debt', label: 'Задолженности', route: '/finance/debt' }, + ], + }, + { + id: 'employees', + label: 'Сотрудники', + iconName: 'UserCheck', + route: '/employees', + requiredCapability: 'employees', + sections: [ + { id: 'list', label: 'Команда', route: '/employees' }, + { id: 'schedule', label: 'Графики & Смены', route: '/employees/schedule' }, + { id: 'timetrack', label: 'Рабочее время & Табель', route: '/employees/timetrack' }, + { id: 'roles', label: 'Должности & Ставки', route: '/employees/roles' }, + { id: 'kpi', label: 'KPI & Мотивация', route: '/employees/kpi' }, + ], + }, + { + id: 'communications', + label: 'Коммуникации', + iconName: 'MessageSquareText', + route: '/communications', + requiredCapability: 'communications', + badge: '3', + sections: [ + { id: 'inbox', label: 'Единый Inbox', route: '/communications' }, + { id: 'telegram', label: 'Telegram Bot & Чат', route: '/communications?channel=telegram' }, + { id: 'whatsapp', label: 'WhatsApp', route: '/communications?channel=whatsapp' }, + { id: 'team', label: 'Командный чат', route: '/communications?channel=team' }, + { id: 'channels', label: 'Подключенные каналы', route: '/communications/channels' }, + ], + }, + { + id: 'helpdesk', + label: 'HelpDesk', + iconName: 'Headset', + route: '/helpdesk', + requiredCapability: 'helpdesk', + sections: [ + { id: 'overview', label: 'Обзор поддержки', route: '/helpdesk' }, + { id: 'tickets', label: 'Очередь тикетов', route: '/helpdesk/tickets', badge: '5' }, + { id: 'sla', label: 'SLA & Эскалации', route: '/helpdesk/sla' }, + { id: 'kb', label: 'База знаний', route: '/helpdesk/kb' }, + { id: 'analytics', label: 'Метрики поддержки', route: '/helpdesk/analytics' }, + ], + }, + { + id: 'tasks', + label: 'Задачи и проекты', + iconName: 'CheckSquare', + route: '/tasks', + requiredCapability: 'tasks', + sections: [ + { id: 'my', label: 'Мои задачи', route: '/tasks' }, + { id: 'kanban', label: 'Канбан-доска', route: '/tasks/kanban' }, + { id: 'projects', label: 'Проекты', route: '/tasks/projects' }, + { id: 'calendar', label: 'Календарь дедлайнов', route: '/tasks/calendar' }, + { id: 'overdue', label: 'Просроченные', route: '/tasks/overdue', badge: '2' }, + ], + }, + { + id: 'cms', + label: 'Сайты', + iconName: 'Globe', + route: '/cms', + requiredCapability: 'cms', + sections: [ + { id: 'sites', label: 'Мои сайты', route: '/cms' }, + { id: 'pages', label: 'Страницы & Конструктор', route: '/cms/pages' }, + { id: 'forms', label: 'Лид-формы', route: '/cms/forms' }, + { id: 'media', label: 'Медиабиблиотека', route: '/cms/media' }, + { id: 'seo', label: 'SEO & Аналитика', route: '/cms/seo' }, + { id: 'domains', label: 'Домены', route: '/cms/domains' }, + ], + }, + { + id: 'marketing', + label: 'Маркетинг', + iconName: 'Megaphone', + route: '/marketing', + requiredCapability: 'marketing', + sections: [ + { id: 'overview', label: 'Обзор маркетинга', route: '/marketing' }, + { id: 'promos', label: 'Акции & Промокоды', route: '/marketing/promos' }, + { id: 'broadcasts', label: 'Рассылки', route: '/marketing/broadcasts' }, + { id: 'content', label: 'Контент-план', route: '/marketing/content' }, + { id: 'ai_marketer', label: 'AI Маркетолог', route: '/marketing/ai' }, + ], + }, + { + id: 'analytics', + label: 'Аналитика', + iconName: 'BarChart3', + route: '/analytics', + requiredCapability: 'analytics', + sections: [ + { id: 'overview', label: 'Общий дашборд', route: '/analytics' }, + { id: 'sales_bi', label: 'Продажи & Выручка', route: '/analytics/sales' }, + { id: 'abc', label: 'ABC/XYZ анализ', route: '/analytics/abc' }, + { id: 'retention', label: 'Когорты & LTV', route: '/analytics/retention' }, + { id: 'forecasts', label: 'ИИ-прогнозы', route: '/analytics/forecasts' }, + ], + }, + { + id: 'automation', + label: 'Автоматизация', + iconName: 'Cpu', + route: '/automation', + requiredCapability: 'automation', + sections: [ + { id: 'scenarios', label: 'Сценарии & Workflows', route: '/automation' }, + { id: 'builder', label: 'Конструктор цепочек', route: '/automation/builder' }, + { id: 'triggers', label: 'Триггеры событий', route: '/automation/triggers' }, + { id: 'history', label: 'Лог выполнения', route: '/automation/history' }, + ], + }, + { + id: 'ai', + label: 'ИИ-центр', + iconName: 'Sparkles', + route: '/ai', + requiredCapability: 'ai', + badge: '✦', + sections: [ + { id: 'chat', label: 'Диалог с AI', route: '/ai' }, + { id: 'team', label: 'AI Команда', route: '/ai/team' }, + { id: 'tasks', label: 'ИИ-задачи в фоне', route: '/ai/tasks' }, + { id: 'history', label: 'История & Контекст', route: '/ai/history' }, + { id: 'usage', label: 'Лимиты & Токены', route: '/ai/usage' }, + ], + }, + { + id: 'apps', + label: 'Приложения', + iconName: 'Grid', + route: '/apps', + sections: [ + { id: 'catalog', label: 'Каталог расширений', route: '/apps' }, + { id: 'installed', label: 'Установленные', route: '/apps/installed' }, + { id: 'integrations', label: 'Интеграции', route: '/apps/integrations' }, + ], + }, + { + id: 'settings', + label: 'Настройки', + iconName: 'Settings', + route: '/settings', + sections: [ + { id: 'company', label: 'Организация & Точки', route: '/settings' }, + { id: 'profile', label: 'Бизнес-профиль', route: '/settings/profile' }, + { id: 'capabilities', label: 'Configuration Studio', route: '/settings/capabilities' }, + { id: 'users', label: 'Пользователи & Роли', route: '/settings/users' }, + { id: 'integrations', label: 'API & Webhooks', route: '/settings/api' }, + { id: 'appearance', label: 'Тема & Брендинг', route: '/settings/appearance' }, + ], + }, +]; diff --git a/src/core/modules/types.ts b/src/core/modules/types.ts new file mode 100644 index 0000000..e18b72d --- /dev/null +++ b/src/core/modules/types.ts @@ -0,0 +1,19 @@ +import { CapabilityId } from '../capabilities/types'; + +export interface ModuleSection { + id: string; + label: string; + route: string; + badge?: string; + requiredCapability?: CapabilityId; +} + +export interface ModuleDefinition { + id: string; + label: string; + iconName: string; + route: string; + badge?: string; + requiredCapability?: CapabilityId; + sections: ModuleSection[]; +} diff --git a/src/core/permissions/types.ts b/src/core/permissions/types.ts new file mode 100644 index 0000000..854cd39 --- /dev/null +++ b/src/core/permissions/types.ts @@ -0,0 +1,103 @@ +export type SystemRoleId = + | 'owner' + | 'administrator' + | 'manager' + | 'cashier' + | 'cook' + | 'courier' + | 'specialist' + | 'marketer' + | 'warehouse' + | 'support'; + +export interface RoleInfo { + id: SystemRoleId; + label: string; + badge: string; + description: string; + allowedModules: string[]; + defaultRoute: string; +} + +export const SYSTEM_ROLES: Record = { + owner: { + id: 'owner', + label: 'Владелец бизнеса', + badge: 'Owner', + description: 'Полный доступ ко всем модулям, финансовой аналитике, настройкам и AI-центру', + allowedModules: ['*'], + defaultRoute: '/', + }, + administrator: { + id: 'administrator', + label: 'Администратор', + badge: 'Admin', + description: 'Управление процессами, персоналом, точками, правами и операционной деятельностью', + allowedModules: ['*'], + defaultRoute: '/', + }, + manager: { + id: 'manager', + label: 'Управляющий', + badge: 'Manager', + description: 'Операции, смены, заказы, доставка, склад, контроль персонала и операционная аналитика', + allowedModules: ['dashboard', 'operations', 'crm', 'sales', 'inventory', 'employees', 'tasks', 'communications', 'analytics'], + defaultRoute: '/operations', + }, + cashier: { + id: 'cashier', + label: 'Кассир / Оператор', + badge: 'POS', + description: 'Кассовый терминал, оформление заказов, прием оплаты, клиентская база', + allowedModules: ['operations', 'sales', 'crm'], + defaultRoute: '/operations/pos', + }, + cook: { + id: 'cook', + label: 'Повар / Шеф-повар', + badge: 'KDS', + description: 'Кухонный дисплей (KDS), отметка готовности блюд, стоп-лист', + allowedModules: ['operations'], + defaultRoute: '/operations/kds', + }, + courier: { + id: 'courier', + label: 'Курьер / Доставка', + badge: 'Courier', + description: 'Мобильный экран доставки: маршруты, заказы, адрес клиента, отметка вручения', + allowedModules: ['operations'], + defaultRoute: '/operations/courier', + }, + specialist: { + id: 'specialist', + label: 'Специалист / Мастер', + badge: 'Service', + description: 'Журнал записи, заказ-наряды постов, расписание смен, услуги', + allowedModules: ['operations', 'crm', 'tasks'], + defaultRoute: '/operations/work-orders', + }, + marketer: { + id: 'marketer', + label: 'Маркетолог', + badge: 'Marketing', + description: 'Маркетинговые кампании, CRM сегменты, сайты/CMS, рассылки, сквозная аналитика, AI', + allowedModules: ['dashboard', 'crm', 'marketing', 'cms', 'communications', 'analytics', 'ai'], + defaultRoute: '/marketing', + }, + warehouse: { + id: 'warehouse', + label: 'Складской оператор', + badge: 'Warehouse', + description: 'Приходные накладные, списания, партии, инвентаризация и поставщики', + allowedModules: ['operations', 'inventory', 'tasks'], + defaultRoute: '/operations/inventory', + }, + support: { + id: 'support', + label: 'Специалист поддержки', + badge: 'Support', + description: 'Очередь тикетов, омниканальные чаты, база знаний и SLA', + allowedModules: ['helpdesk', 'communications', 'crm'], + defaultRoute: '/helpdesk', + }, +}; diff --git a/src/core/profiles/profiles.ts b/src/core/profiles/profiles.ts new file mode 100644 index 0000000..a58c74a --- /dev/null +++ b/src/core/profiles/profiles.ts @@ -0,0 +1,635 @@ +import { BusinessProfile } from './types'; + +export const BUSINESS_PROFILES: Record = { + restaurant_hall_delivery: { + id: 'restaurant_hall_delivery', + name: 'Ресторан: Зал + Доставка', + label: 'Суши & Гёдза (Зал + Доставка)', + category: 'Общепит', + companyName: 'Суши & Гёдза', + locations: ['Горский 1/1', 'Красный пр-т 186а'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: true, + booking: true, + pos: true, + kds: true, + dining: true, + work_orders: false, + production: true, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'orders', label: 'Заказы', route: '/operations/orders', badge: '14' }, + { id: 'pos', label: 'Касса (POS)', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'dining', label: 'Зал', route: '/operations/dining', requiredCapability: 'dining', badge: '82%' }, + { id: 'kds', label: 'Кухня (KDS)', route: '/operations/kds', requiredCapability: 'kds', badge: '6' }, + { id: 'catalog', label: 'Меню', route: '/operations/catalog' }, + { id: 'recipes', label: 'Техкарты', route: '/operations/recipes', requiredCapability: 'production' }, + { id: 'inventory', label: 'Склад', route: '/operations/inventory', requiredCapability: 'inventory' }, + { id: 'purchasing', label: 'Закупки', route: '/operations/purchasing', requiredCapability: 'purchasing' }, + { id: 'delivery', label: 'Доставка', route: '/operations/delivery', requiredCapability: 'delivery', badge: '5' }, + { id: 'booking', label: 'Бронирования', route: '/operations/booking', requiredCapability: 'booking' }, + ], + terminology: { + itemLabel: 'Блюдо', + itemsLabel: 'Меню и напитки', + bookingResourceLabel: 'Стол', + orderSourceLabel: 'Зал / Доставка / Навынос', + clientIdentifierLabel: 'Гость ресторана', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'orders_count', 'avg_check', 'hall_occupancy', 'food_cost'], + quickActionIds: ['new_order', 'book_table', 'create_task', 'new_client', 'new_expense', 'write_off'], + }, + }, + + restaurant_delivery_only: { + id: 'restaurant_delivery_only', + name: 'Ресторан: Только Доставка / Dark Kitchen', + label: 'Суши & Гёдза Express (Dark Kitchen)', + category: 'Общепит / Dark Kitchen', + companyName: 'Суши & Гёдза Express', + locations: ['Красный пр-т 186а (Кухня 1)'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: true, + booking: false, // OFF for Delivery Only + pos: true, + kds: true, + dining: false, // OFF for Delivery Only + work_orders: false, + production: true, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'orders', label: 'Заказы', route: '/operations/orders', badge: '19' }, + { id: 'pos', label: 'Касса (POS)', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'kds', label: 'Кухня (KDS)', route: '/operations/kds', requiredCapability: 'kds', badge: '9' }, + { id: 'catalog', label: 'Меню', route: '/operations/catalog' }, + { id: 'recipes', label: 'Техкарты', route: '/operations/recipes', requiredCapability: 'production' }, + { id: 'inventory', label: 'Склад', route: '/operations/inventory', requiredCapability: 'inventory' }, + { id: 'purchasing', label: 'Закупки', route: '/operations/purchasing', requiredCapability: 'purchasing' }, + { id: 'delivery', label: 'Доставка', route: '/operations/delivery', requiredCapability: 'delivery', badge: '12' }, + ], + terminology: { + itemLabel: 'Позиция доставки', + itemsLabel: 'Ассортимент Dark Kitchen', + bookingResourceLabel: 'Линия сборки', + orderSourceLabel: 'Доставка / Агрегаторы', + clientIdentifierLabel: 'Получатель заказа', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'orders_count', 'avg_check', 'delivery_avg_time', 'food_cost'], + quickActionIds: ['new_order', 'assign_courier', 'create_task', 'new_client', 'inventory_check'], + }, + }, + + retail: { + id: 'retail', + name: 'Розничная торговля / Retail', + label: 'Krona Retail & Store', + category: 'Торговля', + companyName: 'Krona Concept Store', + locations: ['Флагманский магазин — Ленина 12', 'Островок в ТЦ'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: false, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: false, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'orders', label: 'Продажи', route: '/operations/orders', badge: '31' }, + { id: 'pos', label: 'Касса', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'catalog', label: 'Товары & Штрихкоды', route: '/operations/catalog' }, + { id: 'inventory', label: 'Склад & Остатки', route: '/operations/inventory', requiredCapability: 'inventory' }, + { id: 'purchasing', label: 'Закупки', route: '/operations/purchasing', requiredCapability: 'purchasing' }, + { id: 'suppliers', label: 'Поставщики', route: '/operations/purchasing?tab=suppliers' }, + { id: 'audit', label: 'Инвентаризация', route: '/operations/inventory?tab=audit' }, + { id: 'pricing', label: 'Цены & Скидки', route: '/operations/catalog?tab=pricing' }, + ], + terminology: { + itemLabel: 'Товар', + itemsLabel: 'Товары и SKU', + bookingResourceLabel: 'Торговая точка', + orderSourceLabel: 'Касса / Интернет-магазин', + clientIdentifierLabel: 'Покупатель', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'orders_count', 'avg_check', 'stock_turnover', 'margin_rate'], + quickActionIds: ['pos_sale', 'stock_intake', 'new_client', 'inventory_scan', 'create_task'], + }, + }, + + car_wash: { + id: 'car_wash', + name: 'Автомойка', + label: 'Автомойка Крона', + category: 'Автоуслуги', + companyName: 'Автомойка Крона', + locations: ['Бокс 1-6 — ул. Станционная 42'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: false, + tasks: true, + cms: false, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: true, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Запись & Очередь', route: '/operations/booking', requiredCapability: 'booking', badge: '7' }, + { id: 'work_orders', label: 'Заказ-наряды', route: '/operations/work-orders', requiredCapability: 'work_orders', badge: '3' }, + { id: 'vehicles', label: 'Автомобили', route: '/crm?tab=vehicles' }, + { id: 'pos', label: 'Касса & Оплата', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'bays', label: 'Боксы', route: '/operations/bays' }, + { id: 'catalog', label: 'Услуги & Прайс', route: '/operations/catalog' }, + { id: 'inventory', label: 'Материалы & Склад', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Услуга', + itemsLabel: 'Услуги', + bookingResourceLabel: 'Бокс', + orderSourceLabel: 'Прямой заезд / Запись', + clientIdentifierLabel: 'Владелец (Госномер)', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'bay_load', 'avg_ticket', 'repeat_rate'], + quickActionIds: ['new_booking', 'new_vehicle', 'new_payment', 'create_task'], + }, + }, + + beauty_services: { + id: 'beauty_services', + name: 'Салон красоты / Бьюти', + label: 'Студия Красоты Крона Эстетик', + category: 'Сфера услуг', + companyName: 'Студия Красоты Крона', + locations: ['Центр — Советская 25'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: false, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Запись клиентов', route: '/operations/booking', requiredCapability: 'booking', badge: '11' }, + { id: 'schedule', label: 'Расписание мастеров', route: '/employees?tab=schedule' }, + { id: 'pos', label: 'Касса & Визиты', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'masters', label: 'Специалисты', route: '/employees' }, + { id: 'catalog', label: 'Услуги салона', route: '/operations/catalog' }, + { id: 'resources', label: 'Рабочие места', route: '/operations/bays' }, + { id: 'inventory', label: 'Расходники', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Услуга мастера', + itemsLabel: 'Услуги и уходовая косметика', + bookingResourceLabel: 'Мастер / Кресло', + orderSourceLabel: 'Онлайн-запись / Стойка', + clientIdentifierLabel: 'Клиент салона', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'appointments_today', 'master_load', 'avg_check', 'retention_rate'], + quickActionIds: ['new_booking', 'new_client', 'pos_sale', 'chat_message', 'create_task'], + }, + }, + + wholesale_b2b: { + id: 'wholesale_b2b', + name: 'Оптовая торговля / B2B', + label: 'Торговый Дом Крона Опт', + category: 'Опт & Дистрибуция', + companyName: 'Торговый Дом Крона Опт', + locations: ['Центральный распределительный склад — Северный проезд 8'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: false, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: true, + booking: false, + pos: false, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'orders', label: 'B2B Заказы & Спецификации', route: '/operations/orders', badge: '18' }, + { id: 'companies', label: 'Компании & Договоры', route: '/crm?tab=companies' }, + { id: 'inventory', label: 'Оптовый склад & Партии', route: '/operations/inventory', requiredCapability: 'inventory' }, + { id: 'purchasing', label: 'Контракты & Закупки', route: '/operations/purchasing', requiredCapability: 'purchasing' }, + { id: 'suppliers', label: 'Поставщики', route: '/operations/purchasing?tab=suppliers' }, + { id: 'documents', label: 'УПД & Документы', route: '/finance?tab=docs' }, + { id: 'delivery', label: 'Логистика & Отгрузки', route: '/operations/delivery', requiredCapability: 'delivery' }, + ], + terminology: { + itemLabel: 'Товарная позиция', + itemsLabel: 'Номенклатурный каталог', + bookingResourceLabel: 'Складская зона', + orderSourceLabel: 'B2B Договор / EDI', + clientIdentifierLabel: 'Контрагент / ИНН', + }, + dashboardPreset: { + primaryKpis: ['revenue_month', 'active_contracts', 'receivables', 'warehouse_capacity', 'b2b_avg_deal'], + quickActionIds: ['new_deal', 'new_contract', 'stock_receipt', 'create_invoice', 'create_task'], + }, + }, + + auto_service: { + id: 'auto_service', + name: 'Автосервис / СТО', + label: 'СТО Крона', + category: 'Автоуслуги', + companyName: 'СТО Крона', + locations: ['Главный сервис'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: false, + tasks: true, + cms: false, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: true, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Запись & Очередь', route: '/operations/booking', requiredCapability: 'booking', badge: '7' }, + { id: 'vehicles', label: 'Автомобили', route: '/crm?tab=vehicles' }, + { id: 'work_orders', label: 'Заказ-наряды', route: '/operations/work-orders', requiredCapability: 'work_orders', badge: '4' }, + { id: 'pos', label: 'Касса & Оплата', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'bays', label: 'Посты & Подъёмники', route: '/operations/bays' }, + { id: 'catalog', label: 'Услуги & Прайс', route: '/operations/catalog' }, + { id: 'inventory', label: 'Запчасти & Склад', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Услуга / Деталь', + itemsLabel: 'Работы и запчасти', + bookingResourceLabel: 'Подъёмник', + orderSourceLabel: 'Заказ-наряд', + clientIdentifierLabel: 'Владелец ТС (Госномер)', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'work_orders_active', 'bay_load', 'avg_ticket', 'repeat_rate'], + quickActionIds: ['new_booking', 'new_work_order', 'new_vehicle', 'new_payment', 'create_task'], + }, + }, + + fitness: { + id: 'fitness', + name: 'Фитнес-клуб', + label: 'Крона Фитнес', + category: 'Спорт и здоровье', + companyName: 'Крона Фитнес', + locations: ['Клуб на Ленина'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Расписание & Запись', route: '/operations/booking', requiredCapability: 'booking' }, + { id: 'pos', label: 'Касса & Ресепшн', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'trainers', label: 'Тренеры', route: '/employees' }, + { id: 'catalog', label: 'Абонементы & Услуги', route: '/operations/catalog' }, + { id: 'inventory', label: 'Склад (Бар/Мерч)', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Абонемент / Тренировка', + itemsLabel: 'Прайс-лист', + bookingResourceLabel: 'Зал / Тренер', + orderSourceLabel: 'Онлайн / Ресепшн', + clientIdentifierLabel: 'Член клуба', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'active_memberships', 'visits_today', 'avg_check'], + quickActionIds: ['new_booking', 'new_client', 'pos_sale', 'create_task'], + }, + }, + + clinic: { + id: 'clinic', + name: 'Медицинская клиника / Стоматология', + label: 'Крона Мед', + category: 'Здоровье', + companyName: 'Крона Мед', + locations: ['Главный филиал'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Приемы & Расписание', route: '/operations/booking', requiredCapability: 'booking' }, + { id: 'pos', label: 'Касса', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'doctors', label: 'Врачи', route: '/employees' }, + { id: 'catalog', label: 'Услуги', route: '/operations/catalog' }, + { id: 'inventory', label: 'Медикаменты & Расходники', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Услуга', + itemsLabel: 'Услуги', + bookingResourceLabel: 'Врач / Кабинет', + orderSourceLabel: 'Запись', + clientIdentifierLabel: 'Пациент', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'visits_today', 'avg_check'], + quickActionIds: ['new_booking', 'new_client', 'pos_sale', 'create_task'], + }, + }, + + coworking: { + id: 'coworking', + name: 'Коворкинг / Аренда пространств', + label: 'Крона Коворкинг', + category: 'Недвижимость', + companyName: 'Крона Коворкинг', + locations: ['Кампус'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: false, + booking: true, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'booking', label: 'Бронирование', route: '/operations/booking', requiredCapability: 'booking' }, + { id: 'pos', label: 'Оплата', route: '/operations/pos', requiredCapability: 'pos' }, + { id: 'catalog', label: 'Тарифы', route: '/operations/catalog' }, + { id: 'inventory', label: 'Склад', route: '/operations/inventory', requiredCapability: 'inventory' }, + ], + terminology: { + itemLabel: 'Тариф / Опция', + itemsLabel: 'Тарифы', + bookingResourceLabel: 'Переговорная / Стол', + orderSourceLabel: 'Онлайн / Ресепшн', + clientIdentifierLabel: 'Резидент', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'occupancy_rate', 'active_memberships'], + quickActionIds: ['new_booking', 'new_client', 'pos_sale', 'create_task'], + }, + }, + + logistics: { + id: 'logistics', + name: 'Логистика / Курьерская служба', + label: 'Крона Доставка', + category: 'Логистика', + companyName: 'Крона Доставка', + locations: ['Сортировочный центр'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: false, + purchasing: false, + delivery: true, + booking: false, + pos: true, + kds: false, + dining: false, + work_orders: false, + production: false, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'delivery', label: 'Заказы & Маршруты', route: '/operations/delivery', requiredCapability: 'delivery' }, + { id: 'pos', label: 'Оплата', route: '/operations/pos', requiredCapability: 'pos' }, + ], + terminology: { + itemLabel: 'Услуга доставки', + itemsLabel: 'Тарифы', + bookingResourceLabel: 'Курьер / Машина', + orderSourceLabel: 'Заказ', + clientIdentifierLabel: 'Отправитель / Получатель', + }, + dashboardPreset: { + primaryKpis: ['orders_today', 'avg_delivery_time', 'success_rate'], + quickActionIds: ['new_order', 'assign_courier', 'create_task'], + }, + }, + + custom_meta: { + id: 'custom_meta', + name: 'Кастомный профиль / Meta-profile', + label: 'Универсальный Business OS (Все модули)', + category: 'Конфигурируемый', + companyName: 'Бизнес-экосистема Крона', + locations: ['Главный офис', 'Локация 2'], + capabilities: { + crm: true, + sales: true, + communications: true, + helpdesk: true, + tasks: true, + cms: true, + marketing: true, + analytics: true, + finance: true, + employees: true, + inventory: true, + purchasing: true, + delivery: true, + booking: true, + pos: true, + kds: true, + dining: true, + work_orders: true, + production: true, + automation: true, + ai: true, + }, + operationsTabs: [ + { id: 'overview', label: 'Обзор', route: '/operations' }, + { id: 'orders', label: 'Заказы', route: '/operations/orders' }, + { id: 'pos', label: 'Касса (POS)', route: '/operations/pos' }, + { id: 'dining', label: 'Зал', route: '/operations/dining' }, + { id: 'kds', label: 'KDS', route: '/operations/kds' }, + { id: 'work_orders', label: 'Заказ-наряды', route: '/operations/work-orders' }, + { id: 'catalog', label: 'Каталог', route: '/operations/catalog' }, + { id: 'inventory', label: 'Склад', route: '/operations/inventory' }, + { id: 'purchasing', label: 'Закупки', route: '/operations/purchasing' }, + { id: 'delivery', label: 'Доставка', route: '/operations/delivery' }, + { id: 'booking', label: 'Бронирования', route: '/operations/booking' }, + ], + terminology: { + itemLabel: 'Единица продукции', + itemsLabel: 'Каталог сущностей', + bookingResourceLabel: 'Бизнес-ресурс', + orderSourceLabel: 'Канал продаж', + clientIdentifierLabel: 'Клиент / Субъект', + }, + dashboardPreset: { + primaryKpis: ['revenue_today', 'orders_count', 'avg_check', 'tasks_open', 'ai_insights'], + quickActionIds: ['new_order', 'new_client', 'create_task', 'new_expense', 'chat_message'], + }, + }, +}; diff --git a/src/core/profiles/types.ts b/src/core/profiles/types.ts new file mode 100644 index 0000000..d80234b --- /dev/null +++ b/src/core/profiles/types.ts @@ -0,0 +1,31 @@ +import { CapabilityId } from '../capabilities/types'; + +export interface OperationsTabConfig { + id: string; + label: string; + route: string; + badge?: string; + requiredCapability?: CapabilityId; +} + +export interface BusinessProfile { + id: string; + name: string; + label: string; + category: string; + companyName: string; + locations: string[]; + capabilities: Record; + operationsTabs: OperationsTabConfig[]; + terminology: { + itemLabel: string; + itemsLabel: string; + bookingResourceLabel: string; + orderSourceLabel: string; + clientIdentifierLabel: string; + }; + dashboardPreset: { + primaryKpis: string[]; + quickActionIds: string[]; + }; +} diff --git a/src/features/ai/AiCenterModule.tsx b/src/features/ai/AiCenterModule.tsx new file mode 100644 index 0000000..b1918d7 --- /dev/null +++ b/src/features/ai/AiCenterModule.tsx @@ -0,0 +1,182 @@ +import React, { useState } from 'react'; +import { Badge } from '../../shared/components/Badge'; +import { Button } from '../../shared/components/Button'; +import { Sparkles, Bot, Brain, Send, Cpu, CheckCircle2, Shield, Activity } from 'lucide-react'; + +interface AiAgent { + id: string; + name: string; + role: string; + description: string; + tools: string[]; + status: 'active' | 'busy' | 'idle'; + tasksCompleted: number; +} + +const AI_AGENTS: AiAgent[] = [ + { + id: 'orch', + name: 'Главный Оркестратор', + role: 'Orchestrator', + description: 'Декомпозирует глобальные бизнес-цели и распределяет задачи между агентами-специалистами', + tools: ['Task Delegator', 'Cross-module Context', 'Guardian Policy'], + status: 'active', + tasksCompleted: 342, + }, + { + id: 'analyst', + name: 'Бизнес-аналитик', + role: 'BI & Financial Analyst', + description: 'Анализирует чеки, food cost, маржинальность, динамику продаж и выявляет аномалии', + tools: ['SQL Query', 'Revenue Forecast', 'ABC Matrix', 'Shift Audit'], + status: 'active', + tasksCompleted: 819, + }, + { + id: 'marketer', + name: 'Бизнес-маркетолог', + role: 'Growth & Retention', + description: 'Генерирует контент-планы, офферы для рассылок, анализирует сегменты клиентов в зоне риска', + tools: ['Promo Engine', 'Telegram Bot Sender', 'Copywriter', 'Cohort Analysis'], + status: 'active', + tasksCompleted: 420, + }, + { + id: 'warehouse_agent', + name: 'Складской су-шеф', + role: 'Supply Chain Agent', + description: 'Мониторит критические остатки, сроки годности и формирует авто-заказы поставщикам', + tools: ['Supplier Auto-Order', 'Waste Tracker', 'Inventory Audit'], + status: 'active', + tasksCompleted: 612, + }, +]; + +export const AiCenterModule: React.FC = () => { + const [activeAgentId, setActiveAgentId] = useState('orch'); + const [chatMessages, setChatMessages] = useState<{ sender: 'user' | 'ai'; text: string; time: string }[]>([ + { + sender: 'ai', + text: 'Здравствуйте! Я Главный Оркестратор Кроны. Моя команда специалистов (Аналитик, Маркетолог, Склад) готова помочь вам оптимизировать операционные процессы, снизить списания и поднять средний чек.', + time: '12:00', + }, + ]); + const [prompt, setPrompt] = useState(''); + + const handleSend = (e: React.FormEvent) => { + e.preventDefault(); + if (!prompt.trim()) return; + + const userText = prompt; + setChatMessages((prev) => [ + ...prev, + { sender: 'user', text: userText, time: 'Только что' }, + ]); + setPrompt(''); + + setTimeout(() => { + setChatMessages((prev) => [ + ...prev, + { + sender: 'ai', + text: `Агент «${AI_AGENTS.find(a => a.id === activeAgentId)?.name}»: Анализ запроса «${userText}» завершен. Сформирован проект решения в задачах. Выручка и себестоимость учтены в сводном отчете.`, + time: 'Только что', + }, + ]); + }, 450); + }; + + return ( +
+
+
+
+

+ ✦ Krona AI Center & Автономная бизнес-команда +

+ Крона Модель v1.8 Flash +
+

+ Специализированные агенты с прямым доступом к инструментам платформы и памяти заведения +

+
+ +
+ Токены: 48 200 / 100 000 +
+
+ + {/* Agents Selection Cards */} +
+ {AI_AGENTS.map((agent) => ( +
setActiveAgentId(agent.id)} + className={`p-4 rounded-xl border cursor-pointer transition-all shadow-krona-soft flex flex-col justify-between space-y-2.5 ${ + agent.id === activeAgentId + ? 'border-krona-gold bg-krona-gold/10 ring-2 ring-krona-gold/20' + : 'border-krona-border bg-krona-surface hover:border-krona-border-strong' + }`} + > +
+
+ {agent.role} + +
+

{agent.name}

+

{agent.description}

+
+ +
+ Инструментов: {agent.tools.length} + {agent.tasksCompleted} задач +
+
+ ))} +
+ + {/* Interactive AI Dialog Box */} +
+
+
+ + + Диалог с агентом: {AI_AGENTS.find(a => a.id === activeAgentId)?.name} + +
+ Контекст синхронизирован +
+ +
+ {chatMessages.map((m, i) => ( +
+

{m.text}

+ {m.time} +
+ ))} +
+ +
+ setPrompt(e.target.value)} + placeholder="Сформулируйте задачу для агента (например: 'Оптимизируй закупку лосося')..." + className="flex-1 bg-krona-workspace border border-krona-border rounded-lg px-3 py-2 text-xs text-krona-primary placeholder:text-krona-secondary focus:outline-none focus:border-krona-gold" + /> + +
+
+
+ ); +}; diff --git a/src/features/analytics/AnalyticsModule.tsx b/src/features/analytics/AnalyticsModule.tsx new file mode 100644 index 0000000..12b5bfd --- /dev/null +++ b/src/features/analytics/AnalyticsModule.tsx @@ -0,0 +1,152 @@ +import React from 'react'; +import { StatCard } from '../../shared/components/StatCard'; +import { Badge } from '../../shared/components/Badge'; +import { formatCurrency } from '../../shared/utils/formatters'; +import { + BarChart, + Bar, + XAxis, + YAxis, + CartesianGrid, + Tooltip, + ResponsiveContainer, + PieChart, + Pie, + Cell, +} from 'recharts'; +import { BarChart3, TrendingUp, DollarSign, Users, Award } from 'lucide-react'; + +const SALES_CHANNEL_DATA = [ + { name: 'Зал ресторана', value: 48, color: '#2F684C' }, + { name: 'Собственная доставка', value: 26, color: '#B78335' }, + { name: 'Telegram-бот', value: 14, color: '#527286' }, + { name: 'Яндекс Еда / Агрегаторы', value: 12, color: '#B16D50' }, +]; + +const ABC_ITEMS_DATA = [ + { name: 'Филадельфия', revenue: 420000, category: 'A' }, + { name: 'Том Ям', revenue: 310000, category: 'A' }, + { name: 'Калифорния', revenue: 265000, category: 'A' }, + { name: 'Рамен Тонкоцу', revenue: 195000, category: 'B' }, + { name: 'Гёдза', revenue: 160000, category: 'B' }, + { name: 'Эби Темпура', revenue: 84000, category: 'C' }, +]; + +export const AnalyticsModule: React.FC = () => { + return ( +
+
+
+

+ Сквозная бизнес-аналитика & BI +

+

+ Анализ маржинальности, ABC-классификация блюд, когорты и LTV +

+
+ +
+ Отчетный период: Сентябрь 2026 +
+
+ +
+ } + /> + } + /> + } + /> + } + /> +
+ +
+ {/* Sales by channel pie chart */} +
+

Структура выручки по каналам продаж

+
+ + + + {SALES_CHANNEL_DATA.map((entry, index) => ( + + ))} + + [`${val}%`, 'Доля']} + contentStyle={{ backgroundColor: '#F8F6F0', borderRadius: 8, fontSize: 12 }} + /> + + +
+ +
+ {SALES_CHANNEL_DATA.map((ch, idx) => ( +
+
+ + {ch.name} +
+ {ch.value}% +
+ ))} +
+
+ + {/* ABC Analysis Bar chart */} +
+
+

ABC анализ позиций меню

+ Группа A = 80% выручки +
+ +
+ + + + `${v / 1000}k`} fontSize={11} /> + + [formatCurrency(Number(val)), 'Выручка']} + contentStyle={{ backgroundColor: '#F8F6F0', borderRadius: 8, fontSize: 12 }} + /> + + + +
+ +
+ Позиции группы А формируют основную прибыль заведения. Контролируйте стоп-лист и остатки лосося и сыра ежедневно. +
+
+
+
+ ); +}; diff --git a/src/features/apps/AppsCatalogModule.tsx b/src/features/apps/AppsCatalogModule.tsx new file mode 100644 index 0000000..28d379a --- /dev/null +++ b/src/features/apps/AppsCatalogModule.tsx @@ -0,0 +1,64 @@ +import React from 'react'; +import { Badge } from '../../shared/components/Badge'; +import { Button } from '../../shared/components/Button'; +import { CAPABILITIES_LIST } from '../../core/capabilities/types'; +import { useDemoStore } from '../../mock/store'; +import { Grid, Check, Sparkles, Plus } from 'lucide-react'; + +export const AppsCatalogModule: React.FC = () => { + const { customCapabilities, toggleCapability } = useDemoStore(); + + return ( +
+
+
+

+ Каталог приложений & Модульная экосистема Кроны +

+

+ Подключайте и отключайте функциональные блоки для адаптации платформы под новые ниши +

+
+ + Всего модулей: {CAPABILITIES_LIST.length} +
+ +
+ {CAPABILITIES_LIST.map((app) => { + const isEnabled = customCapabilities[app.id]; + + return ( +
+
+
+ {app.category} + + {isEnabled ? 'Активен' : 'Отключен'} + +
+

{app.name}

+

+ {app.description} +

+
+ +
+ +
+
+ ); + })} +
+
+ ); +}; diff --git a/src/features/automation/AutomationModule.tsx b/src/features/automation/AutomationModule.tsx new file mode 100644 index 0000000..c94cdf4 --- /dev/null +++ b/src/features/automation/AutomationModule.tsx @@ -0,0 +1,109 @@ +import React from 'react'; +import { Badge } from '../../shared/components/Badge'; +import { Button } from '../../shared/components/Button'; +import { Cpu, ArrowDown, Play, Sparkles, MessageSquare, UserCheck, CheckSquare, Plus } from 'lucide-react'; + +interface WorkflowNode { + type: 'trigger' | 'condition' | 'ai' | 'action'; + title: string; + description: string; + badge: string; + badgeVariant: 'green' | 'gold' | 'info' | 'neutral'; +} + +const WORKFLOW_CHAIN: WorkflowNode[] = [ + { + type: 'trigger', + title: 'Триггер: Новое входящее сообщение в Telegram', + description: 'Срабатывает мгновенно при обращении гостя в бота заведения', + badge: 'Событие', + badgeVariant: 'gold', + }, + { + type: 'condition', + title: 'Условие: Поиск клиента в CRM платформы', + description: 'Проверка номера телефона и истории заказов: клиент найден или новый', + badge: 'CRM Match', + badgeVariant: 'neutral', + }, + { + type: 'ai', + title: '✦ Krona AI: Определение намерения гостя (Intent Analysis)', + description: 'Классификация: бронь столика / жалоба на доставку / повтор заказа', + badge: 'ИИ-анализ', + badgeVariant: 'gold', + }, + { + type: 'action', + title: 'Действие: Создание сделки и назначение менеджера', + description: 'Открытие карточки сделки в воронке со статусом «Бронирование стола»', + badge: 'Действие', + badgeVariant: 'green', + }, + { + type: 'action', + title: 'Действие: Отправка подтверждения гостю', + description: 'Формирование персонализированного ответа с кнопкой подтверждения слота', + badge: 'Telegram Reply', + badgeVariant: 'info', + }, +]; + +export const AutomationModule: React.FC = () => { + return ( +
+
+
+

+ Автоматизация & Visual Workflow Engine +

+

+ Бескодовые сценарии автоматизации рутинных процессов, триггеры и цепочки действий с AI +

+
+ +
+ +
+
+ +
+
+
+

+ Сценарий: «Автоматическая обработка брони стола из Telegram» +

+ Сработало 148 раз за неделю • Успешность 100% +
+ Активен (On) +
+ + {/* Visual Flow nodes chain */} +
+ {WORKFLOW_CHAIN.map((node, i) => ( + +
+
+
+ {node.title} +
+

{node.description}

+
+ {node.badge} +
+ + {i < WORKFLOW_CHAIN.length - 1 && ( +
+ +
+ )} +
+ ))} +
+
+
+ ); +}; diff --git a/src/features/cms/CmsModule.tsx b/src/features/cms/CmsModule.tsx new file mode 100644 index 0000000..2e704cc --- /dev/null +++ b/src/features/cms/CmsModule.tsx @@ -0,0 +1,357 @@ +import React, { useState, useEffect } from 'react'; +import { useLocation, useNavigate } from 'react-router-dom'; +import { Badge } from '../../shared/components/Badge'; +import { Button } from '../../shared/components/Button'; +import { Input } from '../../shared/components/Input'; +import { + Globe, + Layout, + Smartphone, + Monitor, + CheckCircle, + ExternalLink, + Plus, + Edit3, + Image, + Search, + Check, + ShieldCheck, + Server, + FileCode, +} from 'lucide-react'; + +interface CmsPage { + id: string; + title: string; + slug: string; + viewsToday: number; + status: 'published' | 'draft'; + lastEdited: string; +} + +const PAGES_LIST: CmsPage[] = [ + { id: 'p1', title: 'Главная страница доставки', slug: '/', viewsToday: 1420, status: 'published', lastEdited: 'Вчера, 18:40' }, + { id: 'p2', title: 'Меню & Корзина онлайн', slug: '/menu', viewsToday: 3890, status: 'published', lastEdited: '08.09.2026' }, + { id: 'p3', title: 'Акции и Сеты сентября', slug: '/promo-autumn', viewsToday: 840, status: 'published', lastEdited: '09.09.2026' }, + { id: 'p4', title: 'Бронирование столов / запись', slug: '/booking', viewsToday: 410, status: 'published', lastEdited: '05.09.2026' }, + { id: 'p5', title: 'Контакты и точки в городе', slug: '/contacts', viewsToday: 230, status: 'published', lastEdited: '01.09.2026' }, +]; + +export const CmsModule: React.FC = () => { + const location = useLocation(); + const navigate = useNavigate(); + + const [pages, setPages] = useState(PAGES_LIST); + const [activeTab, setActiveTab] = useState<'pages' | 'builder' | 'forms' | 'media' | 'seo' | 'domains'>('pages'); + + // Sync with topbar route + useEffect(() => { + const p = location.pathname; + if (p.includes('/cms/pages')) setActiveTab('pages'); + else if (p.includes('/cms/forms')) setActiveTab('forms'); + else if (p.includes('/cms/media')) setActiveTab('media'); + else if (p.includes('/cms/seo')) setActiveTab('seo'); + else if (p.includes('/cms/domains')) setActiveTab('domains'); + }, [location.pathname]); + + // SEO Form Mock State + const [seoTitle, setSeoTitle] = useState('Суши & Гёдза — Доставка роллов и паназиатской кухни в Новосибирске'); + const [seoDescription, setSeoDescription] = useState('Свежие суши, роллы, воки и супы с быстрой доставкой за 35 минут. Заказывайте любимые сеты онлайн со скидкой 20%!'); + + return ( +
+ {/* Header */} +
+
+
+

Сайты & Krona CMS

+ krona.site/sushi-nsk +
+

+ Конструктор страниц, лид-формы, медиатека, SEO и управление доменами +

+
+ +
+ {[ + { id: 'pages', label: 'Страницы', route: '/cms/pages' }, + { id: 'builder', label: 'Конструктор' }, + { id: 'forms', label: 'Формы', route: '/cms/forms' }, + { id: 'media', label: 'Медиа', route: '/cms/media' }, + { id: 'seo', label: 'SEO', route: '/cms/seo' }, + { id: 'domains', label: 'Домены', route: '/cms/domains' }, + ].map((tab) => ( + + ))} +
+
+ + {/* 1. PAGES TAB */} + {activeTab === 'pages' && ( +
+ + + + + + + + + + + + + {pages.map((p) => ( + + + + + + + + + ))} + +
Название страницыURL / SlugПросмотров сегодняДата редакцииСтатусДействие
+ + {p.title} + {p.slug}{p.viewsToday}{p.lastEdited} + Опубликована + + +
+
+ )} + + {/* 2. VISUAL BUILDER TAB */} + {activeTab === 'builder' && ( +
+
+
+

+ Блочный редактор: «Главная страница доставки» +

+ Auto-save +
+
+ + +
+
+ +
+
+
1. Hero блок: Баннер акции «Сет Осенний -20%»
+

Фоновое видео + кнопка заказа в 1 клик

+
+ +
+
2. Витрина популярных роллов (Филадельфия, Калифорния)
+

Автоматическая синхронизация с кассой и остатками

+
+ +
+
3. Интерактивная форма бронирования столиков
+

Интеграция со схемой залов Krona Hall Engine

+
+ + +
+
+ )} + + {/* 3. FORMS TAB */} + {activeTab === 'forms' && ( +
+
+
+

Лид-формы и виджеты захвата заявок

+

Формы автоматически создают лиды и сделки в CRM

+
+ +
+ +
+
+
+ Форма быстрой брони столика + Активна +
+

Поля: Имя, Телефон, Дата/Время, Персоны, Пожелания

+
+ Конверсия: 24.8% + 148 заявок +
+
+ +
+
+ Виджет подписки на скидку 20% + Всплывающее окно +
+

Поля: Номер телефона (с отправкой промокода в SMS/Telegram)

+
+ Конверсия: 14.2% + 312 лидов +
+
+
+
+ )} + + {/* 4. MEDIA LIBRARY TAB */} + {activeTab === 'media' && ( +
+
+
+

Медиабиблиотека сайта

+

Фотографии блюд, баннеры акций, логотипы и видеоматериалы

+
+ +
+ +
+ {[ + { name: 'philadelphia_banner.jpg', size: '1.2 MB', category: 'Баннеры' }, + { name: 'tom_yam_dish.png', size: '840 KB', category: 'Каталог' }, + { name: 'autumn_set_promo.jpg', size: '2.1 MB', category: 'Акции' }, + { name: 'krona_hall_interior.jpg', size: '1.8 MB', category: 'Интерьер' }, + ].map((media, idx) => ( +
+
+ +
+
+
{media.name}
+
+ {media.category} + {media.size} +
+
+
+ ))} +
+
+ )} + + {/* 5. SEO TAB */} + {activeTab === 'seo' && ( +
+
+

SEO настройки и Open Graph метаданные

+

Отображение сайта в поиске Яндекса, Google и при шеринге в мессенджерах

+
+ +
+ setSeoTitle(e.target.value)} + /> +
+ +