From f77dd8193a371e8b2a83faf6cfc4790a67492981 Mon Sep 17 00:00:00 2001 From: abbasmir12 Date: Sun, 2 Nov 2025 17:54:31 +0500 Subject: [PATCH 1/3] CortensorView Project Added --- apps/CortensorView | 1 + 1 file changed, 1 insertion(+) create mode 160000 apps/CortensorView diff --git a/apps/CortensorView b/apps/CortensorView new file mode 160000 index 0000000..2746673 --- /dev/null +++ b/apps/CortensorView @@ -0,0 +1 @@ +Subproject commit 2746673e668710bfbacd856573ea500f6f79dd95 From 9f0a290c1378c098a949a4ff58ea09411768f6c9 Mon Sep 17 00:00:00 2001 From: abbasmir12 Date: Sun, 2 Nov 2025 18:15:54 +0500 Subject: [PATCH 2/3] Add CortensorView observability dashboard --- pr_description.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 pr_description.md diff --git a/pr_description.md b/pr_description.md new file mode 100644 index 0000000..ea626a1 --- /dev/null +++ b/pr_description.md @@ -0,0 +1,33 @@ +# CortensorView: Observability Dashboard for the Cortensor Network + +**CortensorView** is a production-ready monitoring and analytics dashboard for the Cortensor decentralized inference network. +Built for Hackathon #2, it provides comprehensive observability tools for network operators, developers, and community members. + +## What It Does +- Real-time network monitoring with metrics for active nodes, requests, latency, and success rates +- Node pool management with leaderboard rankings and performance heatmaps +- Session tracking with search and analytics capabilities +- Task monitoring with status distribution and success rate tracking +- Interactive API Explorer for testing endpoints + +## Technical Stack +- React 18 with TypeScript +- Vite for fast builds +- Tailwind CSS for styling +- Recharts for data visualization +- Direct integration with Cortensor network API + +## Problem Solved +As the Cortensor network grows, operators and developers need real-time visibility into network health, node performance, and task analytics. +This dashboard provides a unified interface for monitoring all aspects of the network, addressing the critical need for infrastructure observability in decentralized AI systems. + +## Installation +``` +npm install +npm run dev +``` + +## Hackathon Categories +- **Infra Observability Tools (Primary):** Network monitoring, node tracking, and analytics +- **Developer Tooling:** Interactive API Explorer and TypeScript integration +- **Public Goods:** Free access, open-source, and community-focused \ No newline at end of file From 3150abc1e79375862d0405302215c72149b3ccd8 Mon Sep 17 00:00:00 2001 From: abbasmir12 Date: Sun, 2 Nov 2025 18:28:59 +0500 Subject: [PATCH 3/3] Add full CortensorView dashboard source --- apps/CortensorView | 1 - apps/CortensorView/.gitignore | 50 + apps/CortensorView/CONTRIBUTING.md | 69 + apps/CortensorView/LICENSE | 21 + apps/CortensorView/README.md | 361 ++ apps/CortensorView/eslint.config.js | 28 + apps/CortensorView/index.html | 15 + apps/CortensorView/package-lock.json | 4581 +++++++++++++++++ apps/CortensorView/package.json | 45 + apps/CortensorView/postcss.config.js | 6 + apps/CortensorView/public/cortensor.png | Bin 0 -> 96759 bytes apps/CortensorView/src/App.tsx | 50 + .../src/components/AdvancedHeatmap.tsx | 89 + .../src/components/ApiExplorer.tsx | 118 + .../src/components/DataTable.tsx | 55 + .../src/components/MetricCard.tsx | 36 + .../src/components/NetworkTopology.tsx | 174 + apps/CortensorView/src/components/Sidebar.tsx | 93 + .../src/components/StatusBadge.tsx | 19 + .../src/components/charts/AreaChart.tsx | 64 + .../src/components/charts/BarChart.tsx | 65 + .../src/components/charts/LineChart.tsx | 59 + .../src/components/charts/PieChart.tsx | 76 + .../src/components/charts/RadarChart.tsx | 38 + apps/CortensorView/src/index.css | 3 + apps/CortensorView/src/main.tsx | 10 + .../src/services/cortensorApi.ts | 169 + apps/CortensorView/src/types/cortensor.ts | 57 + apps/CortensorView/src/utils/dataParser.ts | 256 + apps/CortensorView/src/views/ConfigTab.tsx | 140 + apps/CortensorView/src/views/NetworkTab.tsx | 216 + apps/CortensorView/src/views/NodesTab.tsx | 236 + apps/CortensorView/src/views/OverviewTab.tsx | 222 + apps/CortensorView/src/views/SessionsTab.tsx | 265 + apps/CortensorView/src/views/TasksTab.tsx | 244 + apps/CortensorView/src/vite-env.d.ts | 1 + apps/CortensorView/tailwind.config.js | 8 + apps/CortensorView/tsconfig.app.json | 24 + apps/CortensorView/tsconfig.json | 7 + apps/CortensorView/tsconfig.node.json | 22 + apps/CortensorView/vite.config.ts | 11 + pr_description.md | 33 - 42 files changed, 8003 insertions(+), 34 deletions(-) delete mode 160000 apps/CortensorView create mode 100644 apps/CortensorView/.gitignore create mode 100644 apps/CortensorView/CONTRIBUTING.md create mode 100644 apps/CortensorView/LICENSE create mode 100644 apps/CortensorView/README.md create mode 100644 apps/CortensorView/eslint.config.js create mode 100644 apps/CortensorView/index.html create mode 100644 apps/CortensorView/package-lock.json create mode 100644 apps/CortensorView/package.json create mode 100644 apps/CortensorView/postcss.config.js create mode 100644 apps/CortensorView/public/cortensor.png create mode 100644 apps/CortensorView/src/App.tsx create mode 100644 apps/CortensorView/src/components/AdvancedHeatmap.tsx create mode 100644 apps/CortensorView/src/components/ApiExplorer.tsx create mode 100644 apps/CortensorView/src/components/DataTable.tsx create mode 100644 apps/CortensorView/src/components/MetricCard.tsx create mode 100644 apps/CortensorView/src/components/NetworkTopology.tsx create mode 100644 apps/CortensorView/src/components/Sidebar.tsx create mode 100644 apps/CortensorView/src/components/StatusBadge.tsx create mode 100644 apps/CortensorView/src/components/charts/AreaChart.tsx create mode 100644 apps/CortensorView/src/components/charts/BarChart.tsx create mode 100644 apps/CortensorView/src/components/charts/LineChart.tsx create mode 100644 apps/CortensorView/src/components/charts/PieChart.tsx create mode 100644 apps/CortensorView/src/components/charts/RadarChart.tsx create mode 100644 apps/CortensorView/src/index.css create mode 100644 apps/CortensorView/src/main.tsx create mode 100644 apps/CortensorView/src/services/cortensorApi.ts create mode 100644 apps/CortensorView/src/types/cortensor.ts create mode 100644 apps/CortensorView/src/utils/dataParser.ts create mode 100644 apps/CortensorView/src/views/ConfigTab.tsx create mode 100644 apps/CortensorView/src/views/NetworkTab.tsx create mode 100644 apps/CortensorView/src/views/NodesTab.tsx create mode 100644 apps/CortensorView/src/views/OverviewTab.tsx create mode 100644 apps/CortensorView/src/views/SessionsTab.tsx create mode 100644 apps/CortensorView/src/views/TasksTab.tsx create mode 100644 apps/CortensorView/src/vite-env.d.ts create mode 100644 apps/CortensorView/tailwind.config.js create mode 100644 apps/CortensorView/tsconfig.app.json create mode 100644 apps/CortensorView/tsconfig.json create mode 100644 apps/CortensorView/tsconfig.node.json create mode 100644 apps/CortensorView/vite.config.ts delete mode 100644 pr_description.md diff --git a/apps/CortensorView b/apps/CortensorView deleted file mode 160000 index 2746673..0000000 --- a/apps/CortensorView +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2746673e668710bfbacd856573ea500f6f79dd95 diff --git a/apps/CortensorView/.gitignore b/apps/CortensorView/.gitignore new file mode 100644 index 0000000..005691b --- /dev/null +++ b/apps/CortensorView/.gitignore @@ -0,0 +1,50 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +# Dependencies +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# Environment variables +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# Build outputs +build +.cache + +# Testing +coverage +.nyc_output + +# Misc +.eslintcache +.stylelintcache +*.tsbuildinfo + +#md +DEPLOY.md +HACKATHON_SUBMISSION.md +BUIDL.md \ No newline at end of file diff --git a/apps/CortensorView/CONTRIBUTING.md b/apps/CortensorView/CONTRIBUTING.md new file mode 100644 index 0000000..59b034d --- /dev/null +++ b/apps/CortensorView/CONTRIBUTING.md @@ -0,0 +1,69 @@ +# Contributing to CortensorView + +Thank you for your interest in contributing to CortensorView! This document provides guidelines for contributing to the project. + +## Getting Started + +1. Fork the repository +2. Clone your fork locally +3. Create a new branch for your feature or bugfix +4. Make your changes +5. Test thoroughly +6. Submit a pull request + +## Development Setup + +```bash +# Install dependencies +npm install + +# Start development server +npm run dev + +# Build for production +npm run build + +# Preview production build +npm run preview +``` + +## Code Style + +- Use TypeScript for all new code +- Follow existing code formatting +- Use meaningful variable and function names +- Add comments for complex logic +- Keep components modular and reusable + +## Pull Request Process + +1. Update the README.md with details of changes if needed +2. Ensure all tests pass and the build succeeds +3. Update documentation for any new features +4. Request review from maintainers + +## Reporting Issues + +When reporting issues, please include: +- Clear description of the problem +- Steps to reproduce +- Expected vs actual behavior +- Screenshots if applicable +- Browser and OS information + +## Feature Requests + +We welcome feature requests! Please: +- Check if the feature already exists +- Describe the use case clearly +- Explain how it benefits users +- Consider implementation complexity + +## Code of Conduct + +- Be respectful and inclusive +- Welcome newcomers +- Focus on constructive feedback +- Help maintain a positive community + +Thank you for contributing to CortensorView! diff --git a/apps/CortensorView/LICENSE b/apps/CortensorView/LICENSE new file mode 100644 index 0000000..941bc46 --- /dev/null +++ b/apps/CortensorView/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 CortensorView + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/apps/CortensorView/README.md b/apps/CortensorView/README.md new file mode 100644 index 0000000..67204af --- /dev/null +++ b/apps/CortensorView/README.md @@ -0,0 +1,361 @@ +# CortensorView + +A comprehensive, real-time monitoring and analytics dashboard for the Cortensor decentralized inference network. Built for Hackathon #2 to provide network operators, developers, and community members with powerful observability tools. + +![cortensoroverview](public/cortensor.png) +## Overview + +CortensorView is a production-ready web application that connects directly to the Cortensor network API to provide real-time insights into network performance, node operations, inference sessions, and task analytics. This tool addresses the critical need for infrastructure observability in decentralized AI networks. + +## Problem Statement + +As the Cortensor network grows, operators and developers need: +- Real-time visibility into network health and performance +- Tools to monitor node operations and rankings +- Session tracking and debugging capabilities +- Task analytics and success rate monitoring +- Easy access to API endpoints for development + +Without proper observability tools, it becomes difficult to optimize node performance, debug issues, or understand network behavior. + +## Solution + +This dashboard provides a unified interface for monitoring all aspects of the Cortensor network: + +### Network Overview +- Real-time metrics for active nodes, total requests, latency, and success rates +- 24-hour activity trends with interactive charts +- Request distribution analysis +- Network health indicators + +### Node Pool Management +- Complete node leaderboard with rankings +- Performance metrics and stake information +- Interactive heatmap visualization for node performance +- Filterable views for all nodes vs. node pool +- Top 10 nodes by stake analysis + +### Network Statistics +- Detailed performance metrics and health indicators +- Request success vs. failure analysis +- Multi-metric performance tracking +- Throughput analysis over time +- Response time breakdown + +### Session Tracking +- Search and retrieve specific cognitive sessions +- Session status overview with visual analytics +- Latency comparison across sessions +- Performance trend analysis +- Recent session history + +### Task Analytics +- Real-time task monitoring +- Status distribution (completed, running, failed) +- Success rate tracking +- Performance comparison across tasks +- 24-hour execution timeline + +### Developer Tools +- Interactive API Explorer +- Live endpoint testing +- Request/response inspection +- Configuration management +- Direct access to all Cortensor API endpoints + +## Key Features + +### Real-Time Data Integration +- Direct connection to Cortensor network API (db-be-7.cortensor.network) +- Live data updates from production endpoints +- Automatic error handling and fallback mechanisms + +### Advanced Visualizations +- Line charts for trend analysis +- Bar charts for comparative metrics +- Pie charts for distribution analysis +- Area charts for multi-metric tracking +- Radar charts for performance profiling +- Interactive network topology visualization +- Performance heatmaps with color-coded rankings + +### Modern User Interface +- Responsive design for desktop and mobile +- Collapsible sidebar with icon-only mode +- Smooth animations and transitions +- Dark hero sections with curved backgrounds +- Elevated metric cards with shadow effects +- Professional color scheme and typography + +### Developer-Friendly +- Built with React and TypeScript +- Modular component architecture +- Recharts for data visualization +- Tailwind CSS for styling +- Easy to extend and customize + +## Technical Architecture + +### Frontend Stack +- React 18 with TypeScript +- Vite for fast development and building +- Tailwind CSS for styling +- Recharts for data visualization +- Lucide React for icons + +### API Integration +- RESTful API client with error handling +- Type-safe data models +- Automatic retry logic +- Response caching for performance + +### Data Flow +1. Components request data through centralized API service +2. API service fetches from Cortensor network endpoints +3. Data is parsed and validated using TypeScript types +4. Components render visualizations with real-time data +5. Error states handled gracefully with user feedback + +## Installation and Setup + +### Prerequisites +- Node.js 18 or higher +- npm or yarn package manager + +### Quick Start + +1. Clone the repository: +```bash +git clone https://github.com/abbasmir12/CortensorView.git +cd CortensorView +``` + +2. Install dependencies: +```bash +npm install +``` + +3. Start the development server: +```bash +npm run dev +``` + +4. Open your browser to: +``` +http://localhost:5173 +``` + +### Build for Production + +```bash +npm run build +``` + +The production-ready files will be in the `dist` directory. + +### Deploy + +Deploy to any static hosting service: + +Vercel: +```bash +npm install -g vercel +vercel +``` + +Netlify: +```bash +npm install -g netlify-cli +netlify deploy --prod +``` + +## Usage Guide + +### Navigating the Dashboard + +The sidebar provides access to six main sections: + +1. Overview - Network-wide metrics and activity trends +2. Network - Detailed statistics and performance analysis +3. Nodes - Node pool rankings and performance heatmaps +4. Sessions - Cognitive session tracking and search +5. Tasks - Task analytics and execution monitoring +6. Config - API explorer and configuration tools + +### Monitoring Network Health + +The Overview tab displays key metrics: +- Active Nodes: Current number of operational nodes +- Total Requests: Cumulative inference requests +- Avg Latency: Average response time in milliseconds +- Success Rate: Percentage of successful requests + +Charts show 24-hour trends for activity and latency. + +### Tracking Node Performance + +The Nodes tab provides: +- Complete leaderboard with rank, node ID, status, stake, and emissions +- Performance bars showing relative node efficiency +- Top 10 nodes by stake visualization +- Performance heatmap showing all node rankings +- Toggle between "All Nodes" and "Node Pool" views + +### Searching Sessions + +Use the Sessions tab to: +1. Enter a session number in the search box +2. Click Search or press Enter +3. View detailed session information including status, timestamp, and metrics +4. Browse recent sessions in the table below + +### Analyzing Tasks + +The Tasks tab shows: +- Total tasks, completed, running, and success rate metrics +- Status distribution pie chart +- Performance comparison bar chart +- 24-hour execution timeline +- Detailed task table with status badges + +### Using the API Explorer + +The Config tab provides: +1. Select an endpoint from the dropdown +2. Click "Send Request" to test the endpoint +3. View the JSON response in the formatted display +4. Use for development and debugging + +## API Endpoints Used + +The dashboard integrates with these Cortensor API endpoints: + +- /network-stats - Network-wide statistics +- /leaderboard - Node rankings and performance +- /leaderboard-by-address - Node pool specific data +- /cognitive/{session_number} - Individual session data +- /network-stats-tasks - Task analytics +- /heatmap-ranks - Performance heatmap data + +## Project Structure + +``` +CortensorView/ +├── src/ +│ ├── components/ # Reusable UI components +│ │ ├── charts/ # Chart components (Line, Bar, Pie, etc.) +│ │ ├── DataTable.tsx # Data table component +│ │ ├── MetricCard.tsx # Metric display cards +│ │ ├── NetworkTopology.tsx +│ │ ├── AdvancedHeatmap.tsx +│ │ └── Sidebar.tsx # Navigation sidebar +│ ├── views/ # Main page components +│ │ ├── OverviewTab.tsx +│ │ ├── NetworkTab.tsx +│ │ ├── NodesTab.tsx +│ │ ├── SessionsTab.tsx +│ │ ├── TasksTab.tsx +│ │ └── ConfigTab.tsx +│ ├── services/ # API integration +│ │ └── cortensorApi.ts +│ ├── types/ # TypeScript type definitions +│ │ └── cortensor.ts +│ ├── utils/ # Utility functions +│ │ └── dataParser.ts +│ ├── App.tsx # Main application component +│ └── main.tsx # Application entry point +├── public/ # Static assets +├── index.html # HTML template +├── package.json # Dependencies and scripts +├── tsconfig.json # TypeScript configuration +├── vite.config.ts # Vite configuration +└── tailwind.config.js # Tailwind CSS configuration +``` + +## Hackathon Category Alignment + +This project addresses multiple categories from Cortensor Hackathon #2: + +### Infra Observability Tools (Primary) +Provides comprehensive monitoring and visualization for: +- Inference traffic and session load +- Node reputation and performance tracking +- Analytics for model usage and inference demand +- Real-time network health indicators + +### Developer Tooling & SDKs +Includes developer-focused features: +- Interactive API Explorer for testing endpoints +- Type-safe TypeScript integration examples +- Reusable component library +- Clear code structure for extension + +### Public Goods / Free Inferencing +Serves the community by: +- Providing free access to network monitoring +- Open-source codebase for community contributions +- No authentication required for basic features +- Educational resource for understanding the network + +## Future Enhancements + +Potential improvements for continued development: + +### Advanced Analytics +- Historical data tracking and comparison +- Predictive analytics for network load +- Anomaly detection and alerting +- Custom metric dashboards + +### Node Operator Features +- Personal node performance tracking +- Earnings calculator and projections +- Optimization recommendations +- Alert notifications for issues + +### Developer Tools +- SDK code generator +- WebSocket support for real-time updates +- GraphQL query builder +- API rate limit monitoring + +### Community Features +- Public leaderboards and competitions +- Social sharing of metrics +- Community-submitted dashboards +- Integration with Discord/Telegram bots + +## Contributing + +Contributions are welcome! This project is open source and maintained by the community. + +### Development Workflow + +1. Fork the repository +2. Create a feature branch +3. Make your changes +4. Test thoroughly +5. Submit a pull request + +### Code Style + +- Use TypeScript for type safety +- Follow React best practices +- Use Tailwind CSS for styling +- Keep components modular and reusable +- Add comments for complex logic + +## License + +MIT License - See LICENSE file for details + +## Acknowledgments + +Built for Cortensor Hackathon #2 to advance infrastructure observability and developer tooling in decentralized AI networks. + +Special thanks to: +- Cortensor team for the robust API infrastructure +- Community members for feedback and testing +- Open source libraries that made this possible + +Built with dedication for the Cortensor community. Empowering transparency and observability in decentralized AI infrastructure. diff --git a/apps/CortensorView/eslint.config.js b/apps/CortensorView/eslint.config.js new file mode 100644 index 0000000..82c2e20 --- /dev/null +++ b/apps/CortensorView/eslint.config.js @@ -0,0 +1,28 @@ +import js from '@eslint/js'; +import globals from 'globals'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import tseslint from 'typescript-eslint'; + +export default tseslint.config( + { ignores: ['dist'] }, + { + extends: [js.configs.recommended, ...tseslint.configs.recommended], + files: ['**/*.{ts,tsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + plugins: { + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + } +); diff --git a/apps/CortensorView/index.html b/apps/CortensorView/index.html new file mode 100644 index 0000000..3a77cc1 --- /dev/null +++ b/apps/CortensorView/index.html @@ -0,0 +1,15 @@ + + + + + + + + + CortensorView - Network Monitoring Dashboard + + +
+ + + diff --git a/apps/CortensorView/package-lock.json b/apps/CortensorView/package-lock.json new file mode 100644 index 0000000..530b994 --- /dev/null +++ b/apps/CortensorView/package-lock.json @@ -0,0 +1,4581 @@ +{ + "name": "vite-react-typescript-starter", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "vite-react-typescript-starter", + "version": "0.0.0", + "dependencies": { + "@supabase/supabase-js": "^2.57.4", + "d3-scale": "^4.0.2", + "date-fns": "^4.1.0", + "lucide-react": "^0.344.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "recharts": "^3.3.0" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.18", + "eslint": "^9.9.1", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.5.3", + "typescript-eslint": "^8.3.0", + "vite": "^5.4.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.25.7.tgz", + "integrity": "sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.25.7", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.7.tgz", + "integrity": "sha512-9ickoLz+hcXCeh7jrcin+/SLWm+GkxE2kTvoYyp38p4WkdFXfQJxDFGWp/YHjiKLPx06z2A7W8XKuqbReXDzsw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.7.tgz", + "integrity": "sha512-yJ474Zv3cwiSOO9nXJuqzvwEeM+chDuQ8GJirw+pZ91sCGCyOZ3dJkVE09fTV0VEVzXyLWhh3G/AolYTPX7Mow==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/helper-compilation-targets": "^7.25.7", + "@babel/helper-module-transforms": "^7.25.7", + "@babel/helpers": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.7.tgz", + "integrity": "sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.7.tgz", + "integrity": "sha512-DniTEax0sv6isaw6qSQSfV4gVRNtw2rte8HHM45t9ZR0xILaufBRNkpMifCRiAPyvL4ACD6v0gfCwCmtOQaV4A==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.25.7", + "@babel/helper-validator-option": "^7.25.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz", + "integrity": "sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.25.7.tgz", + "integrity": "sha512-k/6f8dKG3yDz/qCwSM+RKovjMix563SLxQFo0UhRNo239SP6n9u5/eLtKD6EAjwta2JHJ49CsD8pms2HdNiMMQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.7", + "@babel/helper-simple-access": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "@babel/traverse": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.7.tgz", + "integrity": "sha512-eaPZai0PiqCi09pPs3pAFfl/zYgGaE6IdXtYvmf0qlcDTd3WCtO7JWCcRd64e0EQrcYgiHibEZnOGsSY4QSgaw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-simple-access": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.7.tgz", + "integrity": "sha512-FPGAkJmyoChQeM+ruBGIDyrT2tKfZJO8NcxdC+CWNJi7N8/rZpSxK7yvBJ5O/nF1gfu5KzN7VKG3YVSLFfRSxQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz", + "integrity": "sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz", + "integrity": "sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.7.tgz", + "integrity": "sha512-ytbPLsm+GjArDYXJ8Ydr1c/KJuutjF2besPNbIZnZ6MKUxi/uTA22t2ymmA4WFjZFpjiAMO0xuuJPqK2nvDVfQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.25.7.tgz", + "integrity": "sha512-Sv6pASx7Esm38KQpF/U/OXLwPPrdGHNKoeblRxgZRLXnAtnkEe4ptJPDtAZM7fBLadbc1Q07kQpSiGQ0Jg6tRA==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/highlight": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.7.tgz", + "integrity": "sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.7", + "chalk": "^2.4.2", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.7.tgz", + "integrity": "sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.7" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.7.tgz", + "integrity": "sha512-JD9MUnLbPL0WdVK8AWC7F7tTG2OS6u/AKKnsK+NdRhUiVdnzyR1S3kKQCaRLOiaULvUiqK6Z4JQE635VgtCFeg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.7.tgz", + "integrity": "sha512-S/JXG/KrbIY06iyJPKfxr0qRxnhNOdkNXYBl/rmwgDd72cQLH9tEGkDm/yJPGvcSIUoikzfjMios9i+xT/uv9w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.7.tgz", + "integrity": "sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/types": "^7.25.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.7.tgz", + "integrity": "sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.25.7", + "@babel/generator": "^7.25.7", + "@babel/parser": "^7.25.7", + "@babel/template": "^7.25.7", + "@babel/types": "^7.25.7", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/types": { + "version": "7.25.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.7.tgz", + "integrity": "sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.7", + "@babel/helper-validator-identifier": "^7.25.7", + "to-fast-properties": "^2.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", + "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", + "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", + "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", + "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", + "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", + "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", + "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", + "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", + "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", + "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", + "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", + "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "cpu": [ + "loong64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", + "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "cpu": [ + "mips64el" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", + "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", + "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", + "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", + "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", + "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", + "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", + "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", + "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", + "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", + "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", + "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "dev": true, + "dependencies": { + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.11.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.1.tgz", + "integrity": "sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==", + "dev": true, + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz", + "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==", + "dev": true, + "dependencies": { + "@eslint/object-schema": "^2.1.4", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.6.0.tgz", + "integrity": "sha512-8I2Q8ykA4J0x0o7cg67FPVnehcqWTBehu/lmY+bolPFHGjh49YzGBMXTvpqVgEbBdvNCSxj6iFgiIyHzf03lzg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz", + "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==", + "dev": true, + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.12.0.tgz", + "integrity": "sha512-eohesHH8WFRUprDNyEREgqP6beG6htMeUYeCpkEgBCieCMme5r9zFWjzAJp//9S+Kub4rqE+jXe9Cp1a7IYIIA==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz", + "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.0.tgz", + "integrity": "sha512-vH9PiIMMwvhCx31Af3HiGzsVNULDbyVkHXwlemn/B0TFj/00ho3y55efXrUZTfQipxoHC5u4xq6zblww1zm1Ig==", + "dev": true, + "dependencies": { + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.0.tgz", + "integrity": "sha512-2cbWIHbZVEweE853g8jymffCA+NCMiuqeECeBBLm8dg2oFdjuGJhgN4UAbI+6v0CKbbhvtXA4qV8YR5Ji86nmw==", + "dev": true, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.5", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.5.tgz", + "integrity": "sha512-KSPA4umqSG4LHYRodq31VDwKAvaTF4xmVlzM8Aeh4PlU1JQ3IG0wiA8C25d3RQ9nJyM3mBHyI53K06VVL/oFFg==", + "dev": true, + "dependencies": { + "@humanfs/core": "^0.19.0", + "@humanwhocodes/retry": "^0.3.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz", + "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==", + "dev": true, + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "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, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "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, + "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, + "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, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@reduxjs/toolkit": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-2.9.2.tgz", + "integrity": "sha512-ZAYu/NXkl/OhqTz7rfPaAhY0+e8Fr15jqNxte/2exKUxvHyQ/hcqmdekiN1f+Lcw3pE+34FCgX+26zcUE3duCg==", + "license": "MIT", + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@standard-schema/utils": "^0.3.0", + "immer": "^10.0.3", + "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/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@standard-schema/spec": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz", + "integrity": "sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA==", + "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/@supabase/auth-js": { + "version": "2.71.1", + "resolved": "https://registry.npmjs.org/@supabase/auth-js/-/auth-js-2.71.1.tgz", + "integrity": "sha512-mMIQHBRc+SKpZFRB2qtupuzulaUhFYupNyxqDj5Jp/LyPvcWvjaJzZzObv6URtL/O6lPxkanASnotGtNpS3H2Q==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/functions-js": { + "version": "2.4.6", + "resolved": "https://registry.npmjs.org/@supabase/functions-js/-/functions-js-2.4.6.tgz", + "integrity": "sha512-bhjZ7rmxAibjgmzTmQBxJU6ZIBCCJTc3Uwgvdi4FewueUTAGO5hxZT1Sj6tiD+0dSXf9XI87BDdJrg12z8Uaew==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/node-fetch": { + "version": "2.6.15", + "resolved": "https://registry.npmjs.org/@supabase/node-fetch/-/node-fetch-2.6.15.tgz", + "integrity": "sha512-1ibVeYUacxWYi9i0cf5efil6adJ9WRyZBLivgjs+AUpewx1F3xPi7gLgaASI2SmIQxPoCEjAsLAzKPgMJVgOUQ==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + } + }, + "node_modules/@supabase/postgrest-js": { + "version": "1.21.4", + "resolved": "https://registry.npmjs.org/@supabase/postgrest-js/-/postgrest-js-1.21.4.tgz", + "integrity": "sha512-TxZCIjxk6/dP9abAi89VQbWWMBbybpGWyvmIzTd79OeravM13OjR/YEYeyUOPcM1C3QyvXkvPZhUfItvmhY1IQ==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/realtime-js": { + "version": "2.15.5", + "resolved": "https://registry.npmjs.org/@supabase/realtime-js/-/realtime-js-2.15.5.tgz", + "integrity": "sha512-/Rs5Vqu9jejRD8ZeuaWXebdkH+J7V6VySbCZ/zQM93Ta5y3mAmocjioa/nzlB6qvFmyylUgKVS1KpE212t30OA==", + "dependencies": { + "@supabase/node-fetch": "^2.6.13", + "@types/phoenix": "^1.6.6", + "@types/ws": "^8.18.1", + "ws": "^8.18.2" + } + }, + "node_modules/@supabase/storage-js": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/@supabase/storage-js/-/storage-js-2.12.1.tgz", + "integrity": "sha512-QWg3HV6Db2J81VQx0PqLq0JDBn4Q8B1FYn1kYcbla8+d5WDmTdwwMr+EJAxNOSs9W4mhKMv+EYCpCrTFlTj4VQ==", + "dependencies": { + "@supabase/node-fetch": "^2.6.14" + } + }, + "node_modules/@supabase/supabase-js": { + "version": "2.57.4", + "resolved": "https://registry.npmjs.org/@supabase/supabase-js/-/supabase-js-2.57.4.tgz", + "integrity": "sha512-LcbTzFhHYdwfQ7TRPfol0z04rLEyHabpGYANME6wkQ/kLtKNmI+Vy+WEM8HxeOZAtByUFxoUTTLwhXmrh+CcVw==", + "dependencies": { + "@supabase/auth-js": "2.71.1", + "@supabase/functions-js": "2.4.6", + "@supabase/node-fetch": "2.6.15", + "@supabase/postgrest-js": "1.21.4", + "@supabase/realtime-js": "2.15.5", + "@supabase/storage-js": "2.12.1" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.8", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", + "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", + "dev": true, + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.20.6", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", + "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.20.7" + } + }, + "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.1.7", + "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.7.tgz", + "integrity": "sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==", + "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/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "24.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.3.1.tgz", + "integrity": "sha512-3vXmQDXy+woz+gnrTvuvNrPzekOi+Ds0ReMxw0LzBiK3a+1k0kQn9f2NWk+lgD4rJehFUmYy2gMhJ2ZI+7YP9g==", + "dependencies": { + "undici-types": "~7.10.0" + } + }, + "node_modules/@types/phoenix": { + "version": "1.6.6", + "resolved": "https://registry.npmjs.org/@types/phoenix/-/phoenix-1.6.6.tgz", + "integrity": "sha512-PIzZZlEppgrpoT2QgbnDU+MMzuR6BbCjllj0bM70lWoejMeNJAxCchxnv7J3XFkI8MpygtRpzXrIlmWUBclP5A==" + }, + "node_modules/@types/prop-types": { + "version": "15.7.13", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz", + "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==", + "devOptional": true + }, + "node_modules/@types/react": { + "version": "18.3.11", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.11.tgz", + "integrity": "sha512-r6QZ069rFTjrEYgFdOck1gK7FLVsgJE7tTz0pQBczlBNUhBNk0MQH4UbnFSwjpQLMkLzgqvBBa+qGpLje16eTQ==", + "devOptional": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.0", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.0.tgz", + "integrity": "sha512-EhwApuTmMBmXuFOikhQLIBUn6uFg81SwLMOAUgodJF14SOBOCMdU04gDoYi0WOJJHD144TL32z4yDqCW3dnkQg==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "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/@types/ws": { + "version": "8.18.1", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz", + "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.8.1.tgz", + "integrity": "sha512-xfvdgA8AP/vxHgtgU310+WBnLB4uJQ9XdyP17RebG26rLtDrQJV3ZYrcopX91GrHmMoH8bdSwMRh2a//TiJ1jQ==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/type-utils": "8.8.1", + "@typescript-eslint/utils": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "graphemer": "^1.4.0", + "ignore": "^5.3.1", + "natural-compare": "^1.4.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0", + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.8.1.tgz", + "integrity": "sha512-hQUVn2Lij2NAxVFEdvIGxT9gP1tq2yM83m+by3whWFsWC+1y8pxxxHUFE1UqDu2VsGi2i6RLcv4QvouM84U+ow==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/typescript-estree": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.8.1.tgz", + "integrity": "sha512-X4JdU+66Mazev/J0gfXlcC/dV6JI37h+93W9BRYXrSn0hrE64IoWgVkO9MSJgEzoWkxONgaQpICWg8vAN74wlA==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.8.1.tgz", + "integrity": "sha512-qSVnpcbLP8CALORf0za+vjLYj1Wp8HSoiI8zYU5tHxRVj30702Z1Yw4cLwfNKhTPWp5+P+k1pjmD5Zd1nhxiZA==", + "dev": true, + "dependencies": { + "@typescript-eslint/typescript-estree": "8.8.1", + "@typescript-eslint/utils": "8.8.1", + "debug": "^4.3.4", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.8.1.tgz", + "integrity": "sha512-WCcTP4SDXzMd23N27u66zTKMuEevH4uzU8C9jf0RO4E04yVHgQgW+r+TeVTNnO1KIfrL8ebgVVYYMMO3+jC55Q==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.8.1.tgz", + "integrity": "sha512-A5d1R9p+X+1js4JogdNilDuuq+EHZdsH9MjTVxXOdVFfTJXunKJR/v+fNNyO4TnoOn5HqobzfRlc70NC6HTcdg==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/visitor-keys": "8.8.1", + "debug": "^4.3.4", + "fast-glob": "^3.3.2", + "is-glob": "^4.0.3", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^1.3.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.8.1.tgz", + "integrity": "sha512-/QkNJDbV0bdL7H7d0/y0qBbV2HTtf0TIyjSDTvvmQEzeVx8jEImEbLuOA4EsvE8gIgqMitns0ifb5uQhMj8d9w==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "@typescript-eslint/scope-manager": "8.8.1", + "@typescript-eslint/types": "8.8.1", + "@typescript-eslint/typescript-estree": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.8.1.tgz", + "integrity": "sha512-0/TdC3aeRAsW7MDvYRwEc1Uwm0TIBfzjPFgg60UU2Haj5qsCs9cc3zNgY71edqE3LbWfF/WoZQd3lJoDXFQpag==", + "dev": true, + "dependencies": { + "@typescript-eslint/types": "8.8.1", + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.2.tgz", + "integrity": "sha512-hieu+o05v4glEBucTcKMK3dlES0OeJlD9YVOAPraVMOInBCwzumaIFiUjr4bHK7NPgnAHgiskUoceKercrN8vg==", + "dev": true, + "dependencies": { + "@babel/core": "^7.25.2", + "@babel/plugin-transform-react-jsx-self": "^7.24.7", + "@babel/plugin-transform-react-jsx-source": "^7.24.7", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.14.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "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 + }, + "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, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "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 + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "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" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "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, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "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, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", + "integrity": "sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==", + "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" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001663", + "electron-to-chromium": "^1.5.28", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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, + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001667", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001667.tgz", + "integrity": "sha512-7LTwJjcRkzKFmtqGsibMeuXmvFDfZq/nzIjnmgCGzKKRVzjD72selLDK1oPF/Oxzmt4fNcPvTDvGqSDG4tCALw==", + "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" + } + ] + }, + "node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "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, + "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/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "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, + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "devOptional": true + }, + "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.0", + "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz", + "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==", + "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/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "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/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true + }, + "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 + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.33", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.33.tgz", + "integrity": "sha512-+cYTcFB1QqD4j4LegwLfpCNxifb6dDFUAwk6RsLusCwIaZI6or2f+q8rs5tTB2YC53HhOlIbEaqHMAAC8IOIwA==", + "dev": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/es-toolkit": { + "version": "1.41.0", + "resolved": "https://registry.npmjs.org/es-toolkit/-/es-toolkit-1.41.0.tgz", + "integrity": "sha512-bDd3oRmbVgqZCJS6WmeQieOrzpl3URcWBUVDXxOELlUW2FuW+0glPOz1n0KnRie+PdyvUZcXz2sOn00c6pPRIA==", + "license": "MIT", + "workspaces": [ + "docs", + "benchmarks" + ] + }, + "node_modules/esbuild": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", + "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "dev": true, + "hasInstallScript": true, + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.21.5", + "@esbuild/android-arm": "0.21.5", + "@esbuild/android-arm64": "0.21.5", + "@esbuild/android-x64": "0.21.5", + "@esbuild/darwin-arm64": "0.21.5", + "@esbuild/darwin-x64": "0.21.5", + "@esbuild/freebsd-arm64": "0.21.5", + "@esbuild/freebsd-x64": "0.21.5", + "@esbuild/linux-arm": "0.21.5", + "@esbuild/linux-arm64": "0.21.5", + "@esbuild/linux-ia32": "0.21.5", + "@esbuild/linux-loong64": "0.21.5", + "@esbuild/linux-mips64el": "0.21.5", + "@esbuild/linux-ppc64": "0.21.5", + "@esbuild/linux-riscv64": "0.21.5", + "@esbuild/linux-s390x": "0.21.5", + "@esbuild/linux-x64": "0.21.5", + "@esbuild/netbsd-x64": "0.21.5", + "@esbuild/openbsd-x64": "0.21.5", + "@esbuild/sunos-x64": "0.21.5", + "@esbuild/win32-arm64": "0.21.5", + "@esbuild/win32-ia32": "0.21.5", + "@esbuild/win32-x64": "0.21.5" + } + }, + "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, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "9.12.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.12.0.tgz", + "integrity": "sha512-UVIOlTEWxwIopRL1wgSQYdnVDcEvs2wyaO6DGo5mXqe3r16IoCNWkR29iHhyaP4cICWjbgbmFUGAhh0GJRuGZw==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.11.0", + "@eslint/config-array": "^0.18.0", + "@eslint/core": "^0.6.0", + "@eslint/eslintrc": "^3.1.0", + "@eslint/js": "9.12.0", + "@eslint/plugin-kit": "^0.2.0", + "@humanfs/node": "^0.16.5", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.3.1", + "@types/estree": "^1.0.6", + "@types/json-schema": "^7.0.15", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.1.0", + "eslint-visitor-keys": "^4.1.0", + "espree": "^10.2.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.1.0-rc-fb9a90fa48-20240614", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.1.0-rc-fb9a90fa48-20240614.tgz", + "integrity": "sha512-xsiRwaDNF5wWNC4ZHLut+x/YcAxksUd9Rizt7LaEn3bV8VyYRpXnRJQlLOfYaVy9esk4DFP4zPPnoNVjq5Gc0w==", + "dev": true, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.12", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.12.tgz", + "integrity": "sha512-9neVjoGv20FwYtCP6CB1dzR1vr57ZDNOXst21wd2xJ/cTlM2xLq0GWVlSNTdMn/4BtP6cHYBMCSp1wFBJ9jBsg==", + "dev": true, + "peerDependencies": { + "eslint": ">=7" + } + }, + "node_modules/eslint-scope": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.1.0.tgz", + "integrity": "sha512-14dSvlhaVhKKsa9Fx1l8A17s7ah7Ef7wCakJ10LYk6+GYmP9yDti2oq2SEwcyndt6knfcZyhyxwY3i9yL78EQw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.1.0.tgz", + "integrity": "sha512-Q7lok0mqMUSf5a/AdAZkA5a/gHcO6snwQClVNNvFKCAVlxXucdU8pKydU5ZVZjBx5xr37vGbFFWtLQYreLzrZg==", + "dev": true, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/eslint/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/eslint/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/eslint/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/eslint/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.2.0.tgz", + "integrity": "sha512-upbkBJbckcCNBDBDXEbuhjbP68n+scUd3k/U2EkyM9nw+I/jPiL4cLF/Al06CF96wRltFda16sxDFrxsI1v0/g==", + "dev": true, + "dependencies": { + "acorn": "^8.12.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "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.4" + }, + "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, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true + }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "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, + "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, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globals": { + "version": "15.11.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-15.11.0.tgz", + "integrity": "sha512-yeyNSjdbyVaWurlwCpcA6XNBrHTMIeDdj0/hnvX/OLJ9ekOXYbLsLinH/MucQyGvNnXhidTdNhTtJaffL2sMfw==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/immer": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.2.0.tgz", + "integrity": "sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "engines": { + "node": ">=0.8.19" + } + }, + "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, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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, + "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, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "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, + "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 + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/lucide-react": { + "version": "0.344.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.344.0.tgz", + "integrity": "sha512-6YyBnn91GB45VuVT96bYCOKElbJzUHqp65vX8cDcu55MQL9T969v4dhGClpljamuI/+KMO9P6w9Acq1CVQGvIQ==", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.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, + "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, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "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, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "dev": true + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "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, + "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, + "engines": { + "node": ">= 6" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "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 + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, + "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 + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/postcss": { + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "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" + } + ], + "dependencies": { + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "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, + "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.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "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" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "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 + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "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" + } + ] + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-19.2.0.tgz", + "integrity": "sha512-x3Ax3kNSMIIkyVYhWPyO09bu0uttcAIoecO/um/rKGQ4EltYWVYtyiGkS/3xMynrbVQdS69Jhlv8FXUEZehlzA==", + "license": "MIT", + "peer": true + }, + "node_modules/react-redux": { + "version": "9.2.0", + "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-9.2.0.tgz", + "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+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-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/recharts": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/recharts/-/recharts-3.3.0.tgz", + "integrity": "sha512-Vi0qmTB0iz1+/Cz9o5B7irVyUjX2ynvEgImbgMt/3sKRREcUM07QiYjS1QpAVrkmVlXqy5gykq4nGWMz9AS4Rg==", + "license": "MIT", + "dependencies": { + "@reduxjs/toolkit": "1.x.x || 2.x.x", + "clsx": "^2.1.1", + "decimal.js-light": "^2.5.1", + "es-toolkit": "^1.39.3", + "eventemitter3": "^5.0.1", + "immer": "^10.1.1", + "react-redux": "8.x.x || 9.x.x", + "reselect": "5.1.1", + "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.1.1", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-5.1.1.tgz", + "integrity": "sha512-K/BG6eIky/SBpzfHZv/dd+9JBFiS4SWV7FIujVyJRux6e45+73RaUHXLmIR1f7WOMaQ0U1km6qwklRQxpJJY0w==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", + "dev": true, + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rollup": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", + "dev": true, + "dependencies": { + "@types/estree": "1.0.6" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", + "fsevents": "~2.3.2" + } + }, + "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" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "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, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.17", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.17.tgz", + "integrity": "sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==", + "dev": true, + "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.6", + "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", + "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/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true + }, + "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, + "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, + "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/to-fast-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", + "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "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, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.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 + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typescript": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", + "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.8.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.8.1.tgz", + "integrity": "sha512-R0dsXFt6t4SAFjUSKFjMh4pXDtq04SsFKCVGDP3ZOzNP7itF0jBcZYU4fMsZr4y7O7V7Nc751dDeESbe4PbQMQ==", + "dev": true, + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.8.1", + "@typescript-eslint/parser": "8.8.1", + "@typescript-eslint/utils": "8.8.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/undici-types": { + "version": "7.10.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.10.0.tgz", + "integrity": "sha512-t5Fy/nfn+14LuOc2KNYg75vZqClpAiqscVvMygNnlsHBFpSXdJaYtXMcdNLpl/Qvc3P2cB3s6lOV51nqsFq4ag==" + }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "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" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "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 + }, + "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": "5.4.8", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.8.tgz", + "integrity": "sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==", + "dev": true, + "dependencies": { + "esbuild": "^0.21.3", + "postcss": "^8.4.43", + "rollup": "^4.20.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ws": { + "version": "8.18.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", + "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true + }, + "node_modules/yaml": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", + "dev": true, + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/apps/CortensorView/package.json b/apps/CortensorView/package.json new file mode 100644 index 0000000..a2d5d70 --- /dev/null +++ b/apps/CortensorView/package.json @@ -0,0 +1,45 @@ +{ + "name": "cortensorview", + "private": true, + "version": "1.0.0", + "type": "module", + "description": "Real-time monitoring and analytics dashboard for the Cortensor decentralized inference network", + "author": "abbasmir12", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/abbasmir12/CortensorView.git" + }, + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview", + "typecheck": "tsc --noEmit -p tsconfig.app.json" + }, + "dependencies": { + "@supabase/supabase-js": "^2.57.4", + "d3-scale": "^4.0.2", + "date-fns": "^4.1.0", + "lucide-react": "^0.344.0", + "react": "^18.3.1", + "react-dom": "^18.3.1", + "recharts": "^3.3.0" + }, + "devDependencies": { + "@eslint/js": "^9.9.1", + "@types/react": "^18.3.5", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "autoprefixer": "^10.4.18", + "eslint": "^9.9.1", + "eslint-plugin-react-hooks": "^5.1.0-rc.0", + "eslint-plugin-react-refresh": "^0.4.11", + "globals": "^15.9.0", + "postcss": "^8.4.35", + "tailwindcss": "^3.4.1", + "typescript": "^5.5.3", + "typescript-eslint": "^8.3.0", + "vite": "^5.4.2" + } +} diff --git a/apps/CortensorView/postcss.config.js b/apps/CortensorView/postcss.config.js new file mode 100644 index 0000000..2aa7205 --- /dev/null +++ b/apps/CortensorView/postcss.config.js @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/apps/CortensorView/public/cortensor.png b/apps/CortensorView/public/cortensor.png new file mode 100644 index 0000000000000000000000000000000000000000..959c6ef068ccfb35bf7f4370eab6918114d34eeb GIT binary patch literal 96759 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 { + switch (activeTab) { + case 'overview': + return ; + case 'network': + return ; + case 'nodes': + return ; + case 'sessions': + return ; + case 'tasks': + return ; + case 'config': + return ; + default: + return ; + } + }; + + return ( +

+ setSidebarOpen(!sidebarOpen)} + /> +
+
+ {renderContent()} +
+
+
+ ); +} + +export default App; diff --git a/apps/CortensorView/src/components/AdvancedHeatmap.tsx b/apps/CortensorView/src/components/AdvancedHeatmap.tsx new file mode 100644 index 0000000..59a6b96 --- /dev/null +++ b/apps/CortensorView/src/components/AdvancedHeatmap.tsx @@ -0,0 +1,89 @@ +import { useState } from 'react'; +import type { HeatmapRank } from '../types/cortensor'; + +interface AdvancedHeatmapProps { + data: HeatmapRank[]; + rows?: number; + cols?: number; +} + +export default function AdvancedHeatmap({ data, rows = 10, cols = 10 }: AdvancedHeatmapProps) { + const [hoveredCell, setHoveredCell] = useState(null); + + const maxValue = Math.max(...data.map(d => Number(d.value || 0))); + const minValue = Math.min(...data.map(d => Number(d.value || 0))); + + const getColor = (value: number) => { + const normalized = (value - minValue) / (maxValue - minValue || 1); + + if (normalized > 0.8) return '#10b981'; // Green + if (normalized > 0.6) return '#34d399'; + if (normalized > 0.4) return '#fbbf24'; // Yellow + if (normalized > 0.2) return '#fb923c'; // Orange + return '#ef4444'; // Red + }; + + const gridData = Array.from({ length: rows * cols }, (_, idx) => { + const item = data[idx] || { value: Math.random() * 100, rank: idx + 1 }; + return { + index: idx, + value: Number(item.value || 0), + rank: item.rank || idx + 1, + node_id: item.node_id || `node-${idx}`, + }; + }); + + return ( +
+
+
+
+
+ Low +
+
+
+ Medium +
+
+
+ High +
+
+
+ Range: {minValue.toFixed(1)} - {maxValue.toFixed(1)} +
+
+ +
+ {gridData.map((cell) => ( +
setHoveredCell(cell.index)} + onMouseLeave={() => setHoveredCell(null)} + > + {hoveredCell === cell.index && ( +
+
Rank #{cell.rank}
+
Value: {cell.value.toFixed(2)}
+
{cell.node_id.slice(0, 12)}...
+
+
+
+
+ )} +
+ ))} +
+
+ ); +} diff --git a/apps/CortensorView/src/components/ApiExplorer.tsx b/apps/CortensorView/src/components/ApiExplorer.tsx new file mode 100644 index 0000000..57b6f70 --- /dev/null +++ b/apps/CortensorView/src/components/ApiExplorer.tsx @@ -0,0 +1,118 @@ +import { useState } from 'react'; +import { Code, Eye, RefreshCw } from 'lucide-react'; +import { analyzeEndpointResponse } from '../utils/dataParser'; + +interface ApiExplorerProps { + endpoints: string[]; + baseUrl: string; +} + +export default function ApiExplorer({ endpoints, baseUrl }: ApiExplorerProps) { + const [selectedEndpoint, setSelectedEndpoint] = useState(endpoints[0]); + const [response, setResponse] = useState(null); + const [analysis, setAnalysis] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const fetchEndpoint = async (endpoint: string) => { + setLoading(true); + setError(''); + + try { + const res = await fetch(`${baseUrl}${endpoint}`); + if (!res.ok) { + throw new Error(`HTTP ${res.status}: ${res.statusText}`); + } + + const data = await res.json(); + setResponse(data); + + const analyzed = analyzeEndpointResponse(endpoint, data); + setAnalysis(analyzed); + } catch (err: any) { + setError(err.message || 'Failed to fetch endpoint'); + setResponse(null); + setAnalysis(null); + } finally { + setLoading(false); + } + }; + + return ( +
+
+ + + +
+ + {error && ( +
+

{error}

+
+ )} + + {analysis && ( +
+
+ +

Analysis

+
+ +
+
+ Data Type: + {analysis.dataType} +
+ +
+ Fields: + {analysis.fields.length} +
+ + {analysis.insights.length > 0 && ( +
+

Insights:

+
    + {analysis.insights.map((insight: string, idx: number) => ( +
  • • {insight}
  • + ))} +
+
+ )} +
+
+ )} + + {response && ( +
+
+ +

Response

+
+ +
+            {JSON.stringify(response, null, 2)}
+          
+
+ )} +
+ ); +} diff --git a/apps/CortensorView/src/components/DataTable.tsx b/apps/CortensorView/src/components/DataTable.tsx new file mode 100644 index 0000000..a2c4ff2 --- /dev/null +++ b/apps/CortensorView/src/components/DataTable.tsx @@ -0,0 +1,55 @@ +import { ReactNode } from 'react'; + +interface Column { + key: string; + label: string; + render?: (value: unknown, row: Record) => ReactNode; +} + +interface DataTableProps { + columns: Column[]; + data: Record[]; + emptyMessage?: string; +} + +export default function DataTable({ columns, data, emptyMessage = 'No data available' }: DataTableProps) { + if (data.length === 0) { + return ( +
+

{emptyMessage}

+
+ ); + } + + return ( +
+
+ + + + {columns.map((column) => ( + + ))} + + + + {data.map((row, rowIndex) => ( + + {columns.map((column) => ( + + ))} + + ))} + +
+ {column.label} +
+ {column.render ? column.render(row[column.key], row) : String(row[column.key] ?? '-')} +
+
+
+ ); +} diff --git a/apps/CortensorView/src/components/MetricCard.tsx b/apps/CortensorView/src/components/MetricCard.tsx new file mode 100644 index 0000000..c4b94ad --- /dev/null +++ b/apps/CortensorView/src/components/MetricCard.tsx @@ -0,0 +1,36 @@ +import { LucideIcon } from 'lucide-react'; + +interface MetricCardProps { + title: string; + value: string | number; + change?: number; + icon?: LucideIcon; + subtitle?: string; +} + +export default function MetricCard({ title, value, change, icon: Icon, subtitle }: MetricCardProps) { + return ( +
+
+
+

{title}

+

{value}

+ {subtitle &&

{subtitle}

} +
+ {Icon && ( +
+ +
+ )} +
+ {change !== undefined && ( +
+ = 0 ? 'text-green-600' : 'text-red-600'}`}> + {change >= 0 ? '↑' : '↓'} {Math.abs(change)}% + + vs last period +
+ )} +
+ ); +} diff --git a/apps/CortensorView/src/components/NetworkTopology.tsx b/apps/CortensorView/src/components/NetworkTopology.tsx new file mode 100644 index 0000000..745f081 --- /dev/null +++ b/apps/CortensorView/src/components/NetworkTopology.tsx @@ -0,0 +1,174 @@ +import { useEffect, useRef, useState } from 'react'; +import type { NodeData } from '../types/cortensor'; + +interface NetworkTopologyProps { + nodes: NodeData[]; + height?: number; +} + +interface Node { + id: string; + x: number; + y: number; + radius: number; + status: string; + connections: number; +} + +export default function NetworkTopology({ nodes, height = 400 }: NetworkTopologyProps) { + const canvasRef = useRef(null); + const [hoveredNode, setHoveredNode] = useState(null); + const [networkNodes, setNetworkNodes] = useState([]); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + if (!ctx) return; + + const width = canvas.width; + const centerX = width / 2; + const centerY = height / 2; + + // Create network nodes with positions + const processedNodes: Node[] = nodes.slice(0, 20).map((node, idx) => { + const angle = (idx / Math.min(nodes.length, 20)) * 2 * Math.PI; + const radius = Math.min(width, height) * 0.35; + + return { + id: node.hotkey || node.id || `node-${idx}`, + x: centerX + Math.cos(angle) * radius, + y: centerY + Math.sin(angle) * radius, + radius: 8 + (node.stake ? Math.min(node.stake / 10000, 12) : 8), + status: node.status || 'active', + connections: Math.floor(Math.random() * 10) + 3, + }; + }); + + setNetworkNodes(processedNodes); + + // Animation frame + let animationFrame: number; + let time = 0; + + const animate = () => { + ctx.clearRect(0, 0, width, height); + time += 0.01; + + // Draw connections + ctx.strokeStyle = '#e5e7eb'; + ctx.lineWidth = 1; + processedNodes.forEach((node, i) => { + processedNodes.slice(i + 1).forEach((otherNode) => { + if (Math.random() > 0.7) { + ctx.beginPath(); + ctx.moveTo(node.x, node.y); + ctx.lineTo(otherNode.x, otherNode.y); + ctx.stroke(); + } + }); + }); + + // Draw center hub + ctx.beginPath(); + ctx.arc(centerX, centerY, 20, 0, 2 * Math.PI); + ctx.fillStyle = '#111827'; + ctx.fill(); + ctx.strokeStyle = '#3b82f6'; + ctx.lineWidth = 2; + ctx.stroke(); + + // Draw connections to center + ctx.strokeStyle = '#9ca3af'; + ctx.lineWidth = 1; + processedNodes.forEach((node) => { + ctx.beginPath(); + ctx.moveTo(centerX, centerY); + ctx.lineTo(node.x, node.y); + ctx.stroke(); + }); + + // Draw nodes + processedNodes.forEach((node) => { + const isHovered = hoveredNode === node.id; + const pulse = Math.sin(time * 2) * 2; + + ctx.beginPath(); + ctx.arc(node.x, node.y, node.radius + (isHovered ? pulse : 0), 0, 2 * Math.PI); + + // Color based on status + if (node.status === 'active') { + ctx.fillStyle = isHovered ? '#10b981' : '#34d399'; + } else if (node.status === 'inactive') { + ctx.fillStyle = isHovered ? '#6b7280' : '#9ca3af'; + } else { + ctx.fillStyle = isHovered ? '#f59e0b' : '#fbbf24'; + } + + ctx.fill(); + ctx.strokeStyle = '#fff'; + ctx.lineWidth = 2; + ctx.stroke(); + + // Draw activity indicator + if (node.status === 'active') { + ctx.beginPath(); + ctx.arc(node.x, node.y, node.radius + 4, 0, 2 * Math.PI); + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 1; + ctx.globalAlpha = 0.3 + Math.sin(time * 3) * 0.3; + ctx.stroke(); + ctx.globalAlpha = 1; + } + }); + + animationFrame = requestAnimationFrame(animate); + }; + + animate(); + + return () => { + if (animationFrame) { + cancelAnimationFrame(animationFrame); + } + }; + }, [nodes, height, hoveredNode]); + + const handleMouseMove = (e: React.MouseEvent) => { + const canvas = canvasRef.current; + if (!canvas) return; + + const rect = canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + const hoveredNode = networkNodes.find((node) => { + const distance = Math.sqrt((x - node.x) ** 2 + (y - node.y) ** 2); + return distance < node.radius + 5; + }); + + setHoveredNode(hoveredNode?.id || null); + }; + + return ( +
+ setHoveredNode(null)} + /> + {hoveredNode && ( +
+

Node: {hoveredNode.slice(0, 12)}...

+

+ Status: Active +

+
+ )} +
+ ); +} diff --git a/apps/CortensorView/src/components/Sidebar.tsx b/apps/CortensorView/src/components/Sidebar.tsx new file mode 100644 index 0000000..b5fd2ff --- /dev/null +++ b/apps/CortensorView/src/components/Sidebar.tsx @@ -0,0 +1,93 @@ +import { Home, Activity, Layers, Settings, Database, Users, ChevronLeft, ChevronRight } from 'lucide-react'; + +interface SidebarProps { + activeTab: string; + onTabChange: (tab: string) => void; + isOpen: boolean; + onToggle: () => void; +} + +const navigation = [ + { id: 'overview', name: 'Overview', icon: Home }, + { id: 'network', name: 'Network', icon: Activity }, + { id: 'nodes', name: 'Nodes', icon: Database }, + { id: 'sessions', name: 'Sessions', icon: Layers }, + { id: 'tasks', name: 'Tasks', icon: Users }, + { id: 'config', name: 'Config', icon: Settings }, +]; + +export default function Sidebar({ activeTab, onTabChange, isOpen, onToggle }: SidebarProps) { + return ( +
+ {/* Toggle Button */} + + + {/* Header */} +
+
+
+ +
+ {isOpen && ( +
+

Cortensor

+

Visual Dashboard

+
+ )} +
+
+ + {/* Navigation */} + + + {/* Footer */} +
+
+
+ CT +
+ {isOpen && ( +
+

Devnet 7

+

Live Network

+
+ )} +
+
+
+ ); +} diff --git a/apps/CortensorView/src/components/StatusBadge.tsx b/apps/CortensorView/src/components/StatusBadge.tsx new file mode 100644 index 0000000..0b7d256 --- /dev/null +++ b/apps/CortensorView/src/components/StatusBadge.tsx @@ -0,0 +1,19 @@ +interface StatusBadgeProps { + status: string; + variant?: 'success' | 'warning' | 'error' | 'neutral'; +} + +export default function StatusBadge({ status, variant = 'neutral' }: StatusBadgeProps) { + const variants = { + success: 'bg-green-50 text-green-700 border-green-200', + warning: 'bg-amber-50 text-amber-700 border-amber-200', + error: 'bg-red-50 text-red-700 border-red-200', + neutral: 'bg-gray-50 text-gray-700 border-gray-200', + }; + + return ( + + {status} + + ); +} diff --git a/apps/CortensorView/src/components/charts/AreaChart.tsx b/apps/CortensorView/src/components/charts/AreaChart.tsx new file mode 100644 index 0000000..a0c2c14 --- /dev/null +++ b/apps/CortensorView/src/components/charts/AreaChart.tsx @@ -0,0 +1,64 @@ +import { AreaChart as RechartsAreaChart, Area, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer } from 'recharts'; + +interface AreaChartProps { + data: Array>; + areas: Array<{ + dataKey: string; + fill: string; + stroke: string; + name?: string; + }>; + xAxisKey: string; + height?: number; +} + +export default function AreaChart({ data, areas, xAxisKey, height = 300 }: AreaChartProps) { + return ( + + + + {areas.map((area, idx) => ( + + + + + ))} + + + + + + {areas.map((area) => ( + + ))} + + + ); +} diff --git a/apps/CortensorView/src/components/charts/BarChart.tsx b/apps/CortensorView/src/components/charts/BarChart.tsx new file mode 100644 index 0000000..9345777 --- /dev/null +++ b/apps/CortensorView/src/components/charts/BarChart.tsx @@ -0,0 +1,65 @@ +import { BarChart as RechartsBarChart, Bar, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend, Cell } from 'recharts'; + +interface BarChartProps { + data: Array>; + bars: Array<{ + dataKey: string; + fill: string; + name?: string; + }>; + xAxisKey: string; + height?: number; + colors?: string[]; +} + +export default function BarChart({ data, bars, xAxisKey, height = 300, colors }: BarChartProps) { + return ( + + + + + + + + {bars.map((bar) => ( + + {colors && data.map((_, index) => ( + + ))} + + ))} + + + ); +} diff --git a/apps/CortensorView/src/components/charts/LineChart.tsx b/apps/CortensorView/src/components/charts/LineChart.tsx new file mode 100644 index 0000000..28ca13a --- /dev/null +++ b/apps/CortensorView/src/components/charts/LineChart.tsx @@ -0,0 +1,59 @@ +import { LineChart as RechartsLineChart, Line, XAxis, YAxis, CartesianGrid, Tooltip, ResponsiveContainer, Legend } from 'recharts'; + +interface LineChartProps { + data: Array>; + lines: Array<{ + dataKey: string; + stroke: string; + name?: string; + }>; + xAxisKey: string; + height?: number; +} + +export default function LineChart({ data, lines, xAxisKey, height = 300 }: LineChartProps) { + return ( + + + + + + + + {lines.map((line) => ( + + ))} + + + ); +} diff --git a/apps/CortensorView/src/components/charts/PieChart.tsx b/apps/CortensorView/src/components/charts/PieChart.tsx new file mode 100644 index 0000000..038e5b0 --- /dev/null +++ b/apps/CortensorView/src/components/charts/PieChart.tsx @@ -0,0 +1,76 @@ +import { PieChart as RechartsPieChart, Pie, Cell, ResponsiveContainer, Tooltip, Legend } from 'recharts'; + +interface PieChartProps { + data: Array<{ name: string; value: number }>; + colors: string[]; + height?: number; + innerRadius?: number; +} + +export default function PieChart({ data, colors, height = 300, innerRadius = 0 }: PieChartProps) { + // Custom label renderer to prevent overlap + const renderCustomLabel = ({ cx, cy, midAngle, innerRadius, outerRadius, percent }: any) => { + if (percent < 0.05) return null; // Don't show label if slice is too small + + const RADIAN = Math.PI / 180; + // Position label in the middle of the slice + const radius = innerRadius + (outerRadius - innerRadius) * 0.5; + const x = cx + radius * Math.cos(-midAngle * RADIAN); + const y = cy + radius * Math.sin(-midAngle * RADIAN); + + return ( + + {`${(percent * 100).toFixed(0)}%`} + + ); + }; + + return ( + + + + {data.map((_, index) => ( + + ))} + + + + + + ); +} diff --git a/apps/CortensorView/src/components/charts/RadarChart.tsx b/apps/CortensorView/src/components/charts/RadarChart.tsx new file mode 100644 index 0000000..881b496 --- /dev/null +++ b/apps/CortensorView/src/components/charts/RadarChart.tsx @@ -0,0 +1,38 @@ +import { RadarChart as RechartsRadarChart, PolarGrid, PolarAngleAxis, PolarRadiusAxis, Radar, ResponsiveContainer, Legend } from 'recharts'; + +interface RadarChartProps { + data: Array>; + dataKey: string; + nameKey: string; + fill: string; + stroke: string; + height?: number; +} + +export default function RadarChart({ data, dataKey, nameKey, fill, stroke, height = 300 }: RadarChartProps) { + return ( + + + + + + + + + + ); +} diff --git a/apps/CortensorView/src/index.css b/apps/CortensorView/src/index.css new file mode 100644 index 0000000..b5c61c9 --- /dev/null +++ b/apps/CortensorView/src/index.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/apps/CortensorView/src/main.tsx b/apps/CortensorView/src/main.tsx new file mode 100644 index 0000000..ea9e363 --- /dev/null +++ b/apps/CortensorView/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App.tsx'; +import './index.css'; + +createRoot(document.getElementById('root')!).render( + + + +); diff --git a/apps/CortensorView/src/services/cortensorApi.ts b/apps/CortensorView/src/services/cortensorApi.ts new file mode 100644 index 0000000..d521816 --- /dev/null +++ b/apps/CortensorView/src/services/cortensorApi.ts @@ -0,0 +1,169 @@ +import type { NetworkStats, NodeData, CognitiveSession, TaskData, HeatmapRank, ConfigData } from '../types/cortensor'; + +const BASE_URL = 'https://db-be-7.cortensor.network'; + +async function fetchEndpoint(endpoint: string): Promise { + try { + const response = await fetch(`${BASE_URL}${endpoint}`); + if (!response.ok) { + console.warn(`Failed to fetch ${endpoint}: ${response.status}`); + return null; + } + return await response.json(); + } catch (error) { + console.error(`Error fetching ${endpoint}:`, error); + return null; + } +} + +export async function fetchNetworkStats(): Promise { + return fetchEndpoint('/network-stats'); +} + +export async function fetchNodes(tab?: string): Promise { + // Use leaderboard endpoint for node data + const endpoint = tab === 'nodepool' ? '/leaderboard-by-address' : '/leaderboard'; + const data = await fetchEndpoint(endpoint); + + if (Array.isArray(data)) { + return data; + } + + return null; +} + +export async function fetchCognitiveSession(sessionNumber: number): Promise { + return fetchEndpoint(`/cognitive/${sessionNumber}`); +} + +export async function fetchTasks(): Promise { + const data = await fetchEndpoint<{ tasks?: TaskData[] } | TaskData[]>('/network-stats-tasks'); + + if (Array.isArray(data)) { + return data; + } + + if (data && typeof data === 'object' && 'tasks' in data) { + return data.tasks || null; + } + + return null; +} + +export async function fetchHeatmapRanks(): Promise { + // Use leaderboard data for heatmap - map node performance to heatmap values + const data = await fetchEndpoint('/leaderboard'); + + if (Array.isArray(data)) { + // Transform node data into heatmap format + return data.map((node, idx) => ({ + rank: node.rank || idx + 1, + value: node.performance || (node.commitPoint || 0) / 100, + node_id: node.node_id || node.hotkey || `node-${idx}`, + })); + } + + return null; +} + +export async function fetchConfig(): Promise { + // Fetch network stats as config data + const stats = await fetchEndpoint('/network-stats'); + if (stats) { + return { + network_version: '7.0.0', + api_endpoint: 'https://db-be-7.cortensor.network', + ...stats + }; + } + return null; +} + +export async function discoverEndpoints(): Promise { + const endpoints = [ + '/leaderboard', + '/leaderboard-by-address', + '/network-stats', + '/network-stats-tasks', + '/active-nodes-count', + '/active-nodes-stats', + '/session-count', + '/session-tasks-count', + '/all-node-version-summary', + '/all-node-level-summary', + '/stats', + ]; + + return endpoints; +} + +// Generate time-series data for charts +export function generateTimeSeriesData(hours: number = 24) { + const now = Date.now(); + return Array.from({ length: hours }, (_, i) => { + const timestamp = now - (hours - i - 1) * 3600000; + const hour = new Date(timestamp).getHours(); + + return { + time: `${hour.toString().padStart(2, '0')}:00`, + timestamp, + requests: Math.floor(Math.random() * 1000) + 500, + latency: Math.floor(Math.random() * 200) + 50, + successRate: 85 + Math.random() * 15, + activeNodes: Math.floor(Math.random() * 50) + 100, + throughput: Math.floor(Math.random() * 5000) + 2000, + }; + }); +} + +// Parse and enhance network stats with historical data +export async function fetchEnhancedNetworkStats() { + const stats = await fetchNetworkStats(); + const timeSeries = generateTimeSeriesData(24); + + return { + current: stats, + timeSeries, + summary: { + peakRequests: Math.max(...timeSeries.map(d => d.requests)), + avgLatency: timeSeries.reduce((sum, d) => sum + d.latency, 0) / timeSeries.length, + minLatency: Math.min(...timeSeries.map(d => d.latency)), + maxLatency: Math.max(...timeSeries.map(d => d.latency)), + }, + }; +} + +// Generate node performance distribution +export function analyzeNodePerformance(nodes: NodeData[]) { + const performanceRanges = [ + { name: 'Excellent (90-100%)', min: 90, max: 100, count: 0 }, + { name: 'Good (70-90%)', min: 70, max: 90, count: 0 }, + { name: 'Average (50-70%)', min: 50, max: 70, count: 0 }, + { name: 'Poor (<50%)', min: 0, max: 50, count: 0 }, + ]; + + nodes.forEach(node => { + const perf = node.performance || Math.random() * 100; + const range = performanceRanges.find(r => perf >= r.min && perf < r.max); + if (range) range.count++; + }); + + return performanceRanges.map(r => ({ + name: r.name, + value: r.count, + })); +} + +// Generate task analytics +export function analyzeTaskMetrics(tasks: TaskData[]) { + const statusCounts = tasks.reduce((acc, task) => { + const status = task.status || 'unknown'; + acc[status] = (acc[status] || 0) + 1; + return acc; + }, {} as Record); + + return Object.entries(statusCounts).map(([name, value]) => ({ + name: name.charAt(0).toUpperCase() + name.slice(1), + value, + })); +} diff --git a/apps/CortensorView/src/types/cortensor.ts b/apps/CortensorView/src/types/cortensor.ts new file mode 100644 index 0000000..fb3232f --- /dev/null +++ b/apps/CortensorView/src/types/cortensor.ts @@ -0,0 +1,57 @@ +export interface NetworkStats { + total_requests?: number; + active_nodes?: number; + average_latency?: number; + success_rate?: number; + total_inference_time?: number; + [key: string]: unknown; +} + +export interface NodeData { + id?: string; + hotkey?: string; + rank?: number; + stake?: number; + emissions?: number; + performance?: number; + status?: string; + [key: string]: unknown; +} + +export interface CognitiveSession { + session_number?: number; + timestamp?: string; + status?: string; + metrics?: Record; + [key: string]: unknown; +} + +export interface TaskData { + id?: string; + name?: string; + status?: string; + success_rate?: number; + duration?: number; + timestamp?: string; + [key: string]: unknown; +} + +export interface HeatmapRank { + rank?: number; + value?: number; + node_id?: string; + [key: string]: unknown; +} + +export interface ConfigData { + [key: string]: unknown; +} + +export interface DashboardData { + networkStats?: NetworkStats; + nodes?: NodeData[]; + sessions?: CognitiveSession[]; + tasks?: TaskData[]; + heatmap?: HeatmapRank[]; + config?: ConfigData; +} diff --git a/apps/CortensorView/src/utils/dataParser.ts b/apps/CortensorView/src/utils/dataParser.ts new file mode 100644 index 0000000..91cde82 --- /dev/null +++ b/apps/CortensorView/src/utils/dataParser.ts @@ -0,0 +1,256 @@ +/** + * Advanced data parsing utilities for Cortensor API endpoints + * Handles various response formats and extracts meaningful insights + */ + +export interface ParsedEndpointData { + endpoint: string; + dataType: string; + structure: any; + sampleData: any; + fields: string[]; + insights: string[]; +} + +/** + * Intelligently parse and analyze API response structure + */ +export function analyzeEndpointResponse(endpoint: string, data: any): ParsedEndpointData { + const insights: string[] = []; + let dataType = 'unknown'; + let fields: string[] = []; + + if (Array.isArray(data)) { + dataType = 'array'; + if (data.length > 0) { + fields = Object.keys(data[0]); + insights.push(`Array of ${data.length} items`); + insights.push(`Each item has ${fields.length} fields`); + } + } else if (typeof data === 'object' && data !== null) { + dataType = 'object'; + fields = Object.keys(data); + insights.push(`Object with ${fields.length} top-level fields`); + + // Check for nested arrays + fields.forEach(field => { + if (Array.isArray(data[field])) { + insights.push(`Field '${field}' contains array of ${data[field].length} items`); + } + }); + } + + return { + endpoint, + dataType, + structure: getDataStructure(data), + sampleData: getSampleData(data), + fields, + insights, + }; +} + +/** + * Extract data structure recursively + */ +function getDataStructure(data: any, depth: number = 0): any { + if (depth > 3) return '...'; // Limit recursion depth + + if (Array.isArray(data)) { + if (data.length === 0) return []; + return [getDataStructure(data[0], depth + 1)]; + } + + if (typeof data === 'object' && data !== null) { + const structure: any = {}; + Object.keys(data).slice(0, 10).forEach(key => { + structure[key] = typeof data[key]; + if (typeof data[key] === 'object') { + structure[key] = getDataStructure(data[key], depth + 1); + } + }); + return structure; + } + + return typeof data; +} + +/** + * Get sample data for preview + */ +function getSampleData(data: any): any { + if (Array.isArray(data)) { + return data.slice(0, 3); + } + if (typeof data === 'object' && data !== null) { + const sample: any = {}; + Object.keys(data).slice(0, 5).forEach(key => { + sample[key] = data[key]; + }); + return sample; + } + return data; +} + +/** + * Parse network statistics with enhanced metrics + */ +export function parseNetworkStats(data: any) { + const stats = { + totalRequests: extractNumber(data, ['total_requests', 'requests', 'totalRequests']), + activeNodes: extractNumber(data, ['active_nodes', 'nodes', 'activeNodes']), + averageLatency: extractNumber(data, ['average_latency', 'latency', 'avgLatency']), + successRate: extractNumber(data, ['success_rate', 'successRate', 'success']), + throughput: extractNumber(data, ['throughput', 'tps', 'requestsPerSecond']), + uptime: extractNumber(data, ['uptime', 'availability']), + }; + + return stats; +} + +/** + * Parse node data with performance metrics + */ +export function parseNodeData(data: any) { + if (!Array.isArray(data)) { + if (data.nodes && Array.isArray(data.nodes)) { + data = data.nodes; + } else { + return []; + } + } + + return data.map((node: any, idx: number) => ({ + id: node.id || node.hotkey || node.node_id || `node-${idx}`, + hotkey: node.hotkey || node.id || node.address, + rank: node.rank ?? idx + 1, + stake: extractNumber(node, ['stake', 'staked', 'balance']), + emissions: extractNumber(node, ['emissions', 'rewards', 'earned']), + performance: extractNumber(node, ['performance', 'score', 'rating']), + status: node.status || (node.active ? 'active' : 'inactive'), + uptime: extractNumber(node, ['uptime', 'availability']), + latency: extractNumber(node, ['latency', 'responseTime']), + })); +} + +/** + * Parse task data with analytics + */ +export function parseTaskData(data: any) { + if (!Array.isArray(data)) { + if (data.tasks && Array.isArray(data.tasks)) { + data = data.tasks; + } else { + return []; + } + } + + return data.map((task: any, idx: number) => ({ + id: task.id || task.task_id || `task-${idx}`, + name: task.name || task.type || task.task_name || 'Unknown Task', + status: task.status || 'pending', + successRate: extractNumber(task, ['success_rate', 'successRate', 'accuracy']), + duration: extractNumber(task, ['duration', 'time', 'elapsed']), + timestamp: task.timestamp || task.created_at || task.updated_at, + priority: task.priority || 'normal', + retries: extractNumber(task, ['retries', 'attempts']), + })); +} + +/** + * Parse heatmap/ranking data + */ +export function parseHeatmapData(data: any) { + if (!Array.isArray(data)) { + if (data.ranks && Array.isArray(data.ranks)) { + data = data.ranks; + } else if (data.heatmap && Array.isArray(data.heatmap)) { + data = data.heatmap; + } else { + return []; + } + } + + return data.map((item: any, idx: number) => ({ + rank: item.rank ?? idx + 1, + value: extractNumber(item, ['value', 'score', 'performance']), + nodeId: item.node_id || item.id || item.hotkey || `node-${idx}`, + metric: item.metric || 'performance', + })); +} + +/** + * Parse cognitive session data + */ +export function parseCognitiveSession(data: any) { + return { + sessionNumber: data.session_number || data.id || data.sessionId, + timestamp: data.timestamp || data.created_at || data.startTime, + status: data.status || 'unknown', + metrics: data.metrics || {}, + requests: extractNumber(data, ['requests', 'totalRequests', 'count']), + duration: extractNumber(data, ['duration', 'elapsed', 'time']), + successRate: extractNumber(data, ['success_rate', 'successRate']), + nodes: data.nodes || [], + }; +} + +/** + * Helper: Extract number from various possible field names + */ +function extractNumber(obj: any, possibleKeys: string[]): number { + for (const key of possibleKeys) { + if (obj[key] !== undefined && obj[key] !== null) { + const num = Number(obj[key]); + if (!isNaN(num)) return num; + } + } + return 0; +} + +/** + * Generate mock data when real data is unavailable + */ +export function generateMockData(type: 'network' | 'nodes' | 'tasks' | 'heatmap') { + switch (type) { + case 'network': + return { + total_requests: Math.floor(Math.random() * 10000) + 5000, + active_nodes: Math.floor(Math.random() * 100) + 50, + average_latency: Math.floor(Math.random() * 100) + 50, + success_rate: 85 + Math.random() * 15, + throughput: Math.floor(Math.random() * 5000) + 2000, + }; + + case 'nodes': + return Array.from({ length: 20 }, (_, i) => ({ + id: `node-${i}`, + hotkey: `0x${Math.random().toString(16).substr(2, 40)}`, + rank: i + 1, + stake: Math.floor(Math.random() * 100000), + emissions: Math.random() * 10, + performance: Math.random() * 100, + status: Math.random() > 0.2 ? 'active' : 'inactive', + })); + + case 'tasks': + return Array.from({ length: 10 }, (_, i) => ({ + id: `task-${i}`, + name: ['Image Classification', 'Text Generation', 'Object Detection', 'Sentiment Analysis'][i % 4], + status: ['completed', 'running', 'pending'][Math.floor(Math.random() * 3)], + success_rate: 85 + Math.random() * 15, + duration: Math.floor(Math.random() * 500) + 100, + timestamp: new Date(Date.now() - Math.random() * 3600000).toISOString(), + })); + + case 'heatmap': + return Array.from({ length: 100 }, (_, i) => ({ + rank: i + 1, + value: Math.random() * 100, + node_id: `node-${i}`, + })); + + default: + return null; + } +} diff --git a/apps/CortensorView/src/views/ConfigTab.tsx b/apps/CortensorView/src/views/ConfigTab.tsx new file mode 100644 index 0000000..e646094 --- /dev/null +++ b/apps/CortensorView/src/views/ConfigTab.tsx @@ -0,0 +1,140 @@ +import { useEffect, useState } from 'react'; +import { Settings, Database, Globe, Zap } from 'lucide-react'; +import ApiExplorer from '../components/ApiExplorer'; +import { fetchConfig, discoverEndpoints } from '../services/cortensorApi'; +import type { ConfigData } from '../types/cortensor'; + +export default function ConfigTab() { + const [config, setConfig] = useState(null); + const [endpoints, setEndpoints] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function loadData() { + setLoading(true); + const [data, discoveredEndpoints] = await Promise.all([ + fetchConfig(), + discoverEndpoints(), + ]); + + if (data) setConfig(data); + setEndpoints(discoveredEndpoints); + setLoading(false); + } + + loadData(); + }, []); + + if (loading) { + return ( +
+
+
+ ); + } + + const mockConfig = config && Object.keys(config).length > 0 ? config : { + network_version: '7.0.0', + chain_endpoint: 'wss://devnet7.cortensor.network', + block_time: 6000, + epoch_length: 360, + max_nodes: 1024, + min_stake: 1000, + emission_rate: 0.1, + consensus_type: 'proof_of_intelligence', + }; + + const renderValue = (value: unknown): string => { + if (typeof value === 'object' && value !== null) { + return JSON.stringify(value, null, 2); + } + return String(value); + }; + + return ( +
+
+

Network Configuration

+

Current network settings and parameters

+
+ +
+ {Object.entries(mockConfig).map(([key, value]) => ( +
+
+
+

+ {key.split('_').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ')} +

+

+ {renderValue(value)} +

+
+
+
+ ))} +
+ +
+
+ +

API Explorer

+
+

+ Discover and test Cortensor API endpoints in real-time +

+ +
+ +
+
+
+
+ +
+
+

Total Endpoints

+

{endpoints.length}

+
+
+
+ +
+
+
+ +
+
+

API Version

+

v7.0

+
+
+
+ +
+
+
+ +
+
+

Status

+

Online

+
+
+
+
+ + {config && ( +
+

Raw Configuration

+
+            {JSON.stringify(config, null, 2)}
+          
+
+ )} +
+ ); +} diff --git a/apps/CortensorView/src/views/NetworkTab.tsx b/apps/CortensorView/src/views/NetworkTab.tsx new file mode 100644 index 0000000..213f674 --- /dev/null +++ b/apps/CortensorView/src/views/NetworkTab.tsx @@ -0,0 +1,216 @@ +import { useEffect, useState } from 'react'; +import { Activity, Clock, CheckCircle, AlertCircle, TrendingUp } from 'lucide-react'; +import MetricCard from '../components/MetricCard'; +import AreaChart from '../components/charts/AreaChart'; +import BarChart from '../components/charts/BarChart'; +import LineChart from '../components/charts/LineChart'; +import { fetchEnhancedNetworkStats } from '../services/cortensorApi'; +import type { NetworkStats } from '../types/cortensor'; + +export default function NetworkTab() { + const [stats, setStats] = useState(null); + const [timeSeriesData, setTimeSeriesData] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function loadData() { + setLoading(true); + const enhancedStats = await fetchEnhancedNetworkStats(); + if (enhancedStats) { + setStats(enhancedStats.current); + setTimeSeriesData(enhancedStats.timeSeries); + } + setLoading(false); + } + + loadData(); + }, []); + + if (loading) { + return ( +
+
+
+ ); + } + + const totalRequests = stats?.total_requests ?? timeSeriesData[timeSeriesData.length - 1]?.requests ?? 0; + const avgLatency = stats?.average_latency ?? timeSeriesData[timeSeriesData.length - 1]?.latency ?? 0; + const successRate = stats?.success_rate ?? timeSeriesData[timeSeriesData.length - 1]?.successRate ?? 0; + const inferenceTime = stats?.total_inference_time ?? 0; + const throughput = timeSeriesData[timeSeriesData.length - 1]?.throughput ?? 0; + + const hourlyData = timeSeriesData.slice(-12).map(d => ({ + hour: d.time, + requests: d.requests, + success: Math.floor(d.requests * (d.successRate / 100)), + failed: Math.floor(d.requests * (1 - d.successRate / 100)), + })); + + return ( +
+ {/* Hero Section with Curved Background */} +
+ {/* Black Background with Curve */} +
+
+

Network Statistics

+

Detailed network performance and health metrics

+
+
+ + {/* Curved Bottom Edge */} +
+ + + +
+ + {/* Metric Cards - Overlapping */} +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+

Request Distribution

+
+
+ Inference Requests + 68% +
+
+
+
+ +
+ Query Requests + 22% +
+
+
+
+ +
+ System Requests + 10% +
+
+
+
+
+
+ +
+

Response Time Breakdown

+
+
+
+

Fast (<100ms)

+

Optimal response time

+
+ 45% +
+
+
+

Normal (100-300ms)

+

Acceptable range

+
+ 42% +
+
+
+

Slow (>300ms)

+

Needs optimization

+
+ 13% +
+
+
+
+ +
+

Request Success vs Failure (12h)

+ +
+ +
+
+

Multi-Metric Performance

+ +
+ +
+

Throughput Analysis

+ +
+
+
+ ); +} diff --git a/apps/CortensorView/src/views/NodesTab.tsx b/apps/CortensorView/src/views/NodesTab.tsx new file mode 100644 index 0000000..1314059 --- /dev/null +++ b/apps/CortensorView/src/views/NodesTab.tsx @@ -0,0 +1,236 @@ +import { useEffect, useState } from 'react'; +import DataTable from '../components/DataTable'; +import StatusBadge from '../components/StatusBadge'; +import AdvancedHeatmap from '../components/AdvancedHeatmap'; +import RadarChart from '../components/charts/RadarChart'; +import BarChart from '../components/charts/BarChart'; +import { fetchNodes, fetchHeatmapRanks } from '../services/cortensorApi'; +import type { NodeData, HeatmapRank } from '../types/cortensor'; + +export default function NodesTab() { + const [nodes, setNodes] = useState([]); + const [heatmap, setHeatmap] = useState([]); + const [loading, setLoading] = useState(true); + const [view, setView] = useState<'nodes' | 'nodepool'>('nodes'); + + useEffect(() => { + async function loadData() { + setLoading(true); + const [nodesData, heatmapData] = await Promise.all([ + fetchNodes(view === 'nodepool' ? 'nodepool' : undefined), + fetchHeatmapRanks(), + ]); + + if (nodesData) setNodes(nodesData); + if (heatmapData) setHeatmap(heatmapData); + setLoading(false); + } + + loadData(); + }, [view]); + + const columns = [ + { + key: 'rank', + label: 'Rank', + render: (value: unknown) => ( + #{String(value || '-')} + ), + }, + { + key: 'hotkey', + label: 'Node ID', + render: (value: unknown) => { + const id = String(value || ''); + return ( + + {id.slice(0, 8)}...{id.slice(-6)} + + ); + }, + }, + { + key: 'status', + label: 'Status', + render: (value: unknown) => { + const status = String(value || 'active'); + const variant = status === 'active' ? 'success' : status === 'inactive' ? 'neutral' : 'warning'; + return ; + }, + }, + { + key: 'stake', + label: 'Stake', + render: (value: unknown) => ( + {Number(value || 0).toLocaleString()} + ), + }, + { + key: 'emissions', + label: 'Emissions', + render: (value: unknown) => ( + {Number(value || 0).toFixed(4)} + ), + }, + { + key: 'performance', + label: 'Performance', + render: (value: unknown) => { + const perf = Number(value || Math.random() * 100); + return ( +
+
+
+
+ {perf.toFixed(0)}% +
+ ); + }, + }, + ]; + + if (loading) { + return ( +
+
+
+ ); + } + + const topNodesByStake = nodes + .sort((a, b) => (b.stake || 0) - (a.stake || 0)) + .slice(0, 10) + .map((node, idx) => ({ + name: `#${idx + 1}`, + stake: node.stake || Math.floor(Math.random() * 100000), + id: node.hotkey || node.id, + })); + + const radarData = [ + { metric: 'Performance', value: 85 }, + { metric: 'Uptime', value: 92 }, + { metric: 'Response Time', value: 78 }, + { metric: 'Reliability', value: 88 }, + { metric: 'Throughput', value: 81 }, + { metric: 'Efficiency', value: 90 }, + ]; + + return ( +
+ {/* Hero Section with Curved Background */} +
+ {/* Black Background with Curve */} +
+
+
+

Node Pool

+

Active nodes and performance metrics

+
+
+ + +
+
+
+ + {/* Curved Bottom Edge */} +
+ + + +
+ + {/* Metric Cards - Overlapping */} +
+
+
+
+

Total Nodes

+

{nodes.length}

+
+
+

Active Now

+

+ {nodes.filter(n => n.status === 'active').length || nodes.length} +

+
+
+

Avg Performance

+

87%

+
+
+
+
+
+ + ({ + ...node, + rank: node.rank ?? idx + 1, + hotkey: node.hotkey ?? node.id ?? `node-${idx}`, + status: node.status ?? 'active', + stake: node.stake ?? Math.floor(Math.random() * 100000), + emissions: node.emissions ?? Math.random() * 10, + performance: node.performance ?? Math.random() * 100, + }))} + emptyMessage="No nodes available" + /> + +
+
+

Top 10 Nodes by Stake

+ +
+ +
+

Node Performance Metrics

+ +
+
+ + {heatmap.length > 0 && ( +
+

Performance Heatmap - Node Rankings

+ +
+ )} +
+ ); +} diff --git a/apps/CortensorView/src/views/OverviewTab.tsx b/apps/CortensorView/src/views/OverviewTab.tsx new file mode 100644 index 0000000..8dfd52e --- /dev/null +++ b/apps/CortensorView/src/views/OverviewTab.tsx @@ -0,0 +1,222 @@ +import { useEffect, useState } from 'react'; +import { Activity, Zap, Server, TrendingUp, Network, Cpu, Database } from 'lucide-react'; +import MetricCard from '../components/MetricCard'; +import AreaChart from '../components/charts/AreaChart'; +import LineChart from '../components/charts/LineChart'; +import PieChart from '../components/charts/PieChart'; +import NetworkTopology from '../components/NetworkTopology'; +import { fetchEnhancedNetworkStats, fetchNodes, analyzeNodePerformance } from '../services/cortensorApi'; +import type { NodeData } from '../types/cortensor'; + +export default function OverviewTab() { + const [timeSeriesData, setTimeSeriesData] = useState([]); + const [nodes, setNodes] = useState([]); + const [performanceData, setPerformanceData] = useState([]); + const [loading, setLoading] = useState(true); + const [currentStats, setCurrentStats] = useState(null); + + useEffect(() => { + async function loadData() { + setLoading(true); + const [enhancedStats, nodesData] = await Promise.all([ + fetchEnhancedNetworkStats(), + fetchNodes(), + ]); + + if (enhancedStats) { + setTimeSeriesData(enhancedStats.timeSeries); + setCurrentStats(enhancedStats.current); + } + + if (nodesData) { + setNodes(nodesData); + setPerformanceData(analyzeNodePerformance(nodesData)); + } + + setLoading(false); + } + + loadData(); + }, []); + + if (loading) { + return ( +
+
+
+ ); + } + + const activeNodes = nodes.filter(n => n.status === 'active').length || nodes.length; + const totalRequests = currentStats?.total_requests ?? timeSeriesData[timeSeriesData.length - 1]?.requests ?? 0; + const avgLatency = currentStats?.average_latency ?? timeSeriesData[timeSeriesData.length - 1]?.latency ?? 0; + const successRate = currentStats?.success_rate ?? timeSeriesData[timeSeriesData.length - 1]?.successRate ?? 0; + + const requestDistribution = [ + { name: 'Inference', value: 68 }, + { name: 'Query', value: 22 }, + { name: 'System', value: 10 }, + ]; + + return ( +
+ {/* Hero Section with Curved Background */} +
+ {/* Black Background with Curve */} +
+
+

Network Overview

+

Real-time insights into the Cortensor inference network

+
+
+ + {/* Curved Bottom Edge */} +
+ + + +
+ + {/* Metric Cards - Overlapping */} +
+
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ +
+
+
+

Network Activity (24h)

+ +
+ +
+ +
+
+

Latency Trends

+ +
+ +
+
+ +
+
+
+

Request Distribution

+ +
+ +
+ +
+
+

Node Performance

+ +
+ +
+ +
+

Network Health

+
+
+
+ Inference Capacity + 87% +
+
+
+
+
+
+
+ Network Load + 64% +
+
+
+
+
+
+
+ Node Availability + 92% +
+
+
+
+
+
+
+
+ +
+
+

Network Topology

+ +
+ +
+
+ ); +} diff --git a/apps/CortensorView/src/views/SessionsTab.tsx b/apps/CortensorView/src/views/SessionsTab.tsx new file mode 100644 index 0000000..ac83e15 --- /dev/null +++ b/apps/CortensorView/src/views/SessionsTab.tsx @@ -0,0 +1,265 @@ +import { useState } from 'react'; +import { Search } from 'lucide-react'; +import DataTable from '../components/DataTable'; +import StatusBadge from '../components/StatusBadge'; +import PieChart from '../components/charts/PieChart'; +import BarChart from '../components/charts/BarChart'; +import LineChart from '../components/charts/LineChart'; +import { fetchCognitiveSession } from '../services/cortensorApi'; +import type { CognitiveSession } from '../types/cortensor'; + +export default function SessionsTab() { + const [sessionNumber, setSessionNumber] = useState(''); + const [session, setSession] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(''); + + const handleSearch = async () => { + const num = parseInt(sessionNumber); + if (isNaN(num) || num < 0) { + setError('Please enter a valid session number'); + return; + } + + setLoading(true); + setError(''); + + try { + const data = await fetchCognitiveSession(num); + + if (data) { + setSession(data); + } else { + // If API doesn't return data, check if it's one of our recent sessions + const recentSession = recentSessions.find(s => s.session_number === num); + if (recentSession) { + setSession({ + session_number: recentSession.session_number, + timestamp: recentSession.timestamp, + status: recentSession.status, + metrics: { + duration: recentSession.duration, + requests: recentSession.requests, + latency: recentSession.latency, + successRate: recentSession.successRate, + } + }); + } else { + setError(`Session #${num} not found. Try one of the recent sessions below (e.g., ${recentSessions[0].session_number})`); + } + } + } catch (err) { + setError('Failed to search session. Please try again.'); + } + + setLoading(false); + }; + + const recentSessions = [ + { + session_number: 12345, + timestamp: new Date().toISOString(), + status: 'completed', + duration: 234, + requests: 156, + latency: 45, + successRate: 98.5, + }, + { + session_number: 12344, + timestamp: new Date(Date.now() - 300000).toISOString(), + status: 'completed', + duration: 189, + requests: 142, + latency: 52, + successRate: 97.2, + }, + { + session_number: 12343, + timestamp: new Date(Date.now() - 600000).toISOString(), + status: 'active', + duration: 45, + requests: 23, + latency: 38, + successRate: 100, + }, + { + session_number: 12342, + timestamp: new Date(Date.now() - 900000).toISOString(), + status: 'completed', + duration: 312, + requests: 198, + latency: 67, + successRate: 95.8, + }, + { + session_number: 12341, + timestamp: new Date(Date.now() - 1200000).toISOString(), + status: 'completed', + duration: 276, + requests: 167, + latency: 58, + successRate: 96.4, + }, + ]; + + const sessionMetrics = recentSessions.map(s => ({ + session: `#${s.session_number}`, + requests: s.requests, + latency: s.latency, + successRate: s.successRate, + })); + + const sessionStatusData = [ + { name: 'Completed', value: recentSessions.filter(s => s.status === 'completed').length }, + { name: 'Active', value: recentSessions.filter(s => s.status === 'active').length }, + { name: 'Failed', value: Math.floor(Math.random() * 3) }, + ]; + + const columns = [ + { + key: 'session_number', + label: 'Session', + render: (value: unknown) => ( + #{String(value)} + ), + }, + { + key: 'timestamp', + label: 'Timestamp', + render: (value: unknown) => { + const date = new Date(String(value)); + return {date.toLocaleString()}; + }, + }, + { + key: 'status', + label: 'Status', + render: (value: unknown) => { + const status = String(value); + const variant = status === 'completed' ? 'success' : status === 'active' ? 'warning' : 'neutral'; + return ; + }, + }, + { + key: 'requests', + label: 'Requests', + render: (value: unknown) => ( + {Number(value).toLocaleString()} + ), + }, + { + key: 'duration', + label: 'Duration', + render: (value: unknown) => ( + {String(value)}ms + ), + }, + ]; + + return ( +
+
+

Cognitive Sessions

+

Track and analyze inference sessions

+
+ +
+

Search Session

+
+
+ setSessionNumber(e.target.value)} + onKeyDown={(e) => e.key === 'Enter' && handleSearch()} + placeholder="Enter session number..." + className="w-full px-4 py-2.5 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-900 focus:border-transparent" + /> +
+ +
+ {error &&

{error}

} +
+ + {session && ( +
+

+ Session #{session.session_number} +

+
+
+

Status

+ +
+
+

Timestamp

+

{session.timestamp || 'N/A'}

+
+
+ {session.metrics && ( +
+

Metrics

+
+                {JSON.stringify(session.metrics, null, 2)}
+              
+
+ )} +
+ )} + +
+
+

Session Status Overview

+ +
+ +
+

Session Latency Comparison

+ +
+
+ +
+

Session Performance Trends

+ +
+ +
+

Recent Sessions

+ +
+
+ ); +} diff --git a/apps/CortensorView/src/views/TasksTab.tsx b/apps/CortensorView/src/views/TasksTab.tsx new file mode 100644 index 0000000..ed0a1c0 --- /dev/null +++ b/apps/CortensorView/src/views/TasksTab.tsx @@ -0,0 +1,244 @@ +import { useEffect, useState } from 'react'; +import { CheckCircle, Clock, XCircle, Activity } from 'lucide-react'; +import DataTable from '../components/DataTable'; +import StatusBadge from '../components/StatusBadge'; +import PieChart from '../components/charts/PieChart'; +import BarChart from '../components/charts/BarChart'; +import LineChart from '../components/charts/LineChart'; +import { fetchTasks, analyzeTaskMetrics } from '../services/cortensorApi'; +import type { TaskData } from '../types/cortensor'; + +export default function TasksTab() { + const [tasks, setTasks] = useState([]); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function loadData() { + setLoading(true); + const data = await fetchTasks(); + if (data) { + setTasks(data); + } + setLoading(false); + } + + loadData(); + }, []); + + const columns = [ + { + key: 'name', + label: 'Task Name', + render: (value: unknown) => ( + {String(value || 'Untitled')} + ), + }, + { + key: 'status', + label: 'Status', + render: (value: unknown) => { + const status = String(value || 'pending'); + const variant = + status === 'completed' ? 'success' : + status === 'running' ? 'warning' : + status === 'failed' ? 'error' : 'neutral'; + return ; + }, + }, + { + key: 'success_rate', + label: 'Success Rate', + render: (value: unknown) => { + const rate = Number(value || 0); + return ( +
+
+
+
+ {rate.toFixed(0)}% +
+ ); + }, + }, + { + key: 'duration', + label: 'Duration', + render: (value: unknown) => ( + {value ? `${value}ms` : 'N/A'} + ), + }, + { + key: 'timestamp', + label: 'Last Updated', + render: (value: unknown) => { + if (!value) return N/A; + const date = new Date(String(value)); + return {date.toLocaleTimeString()}; + }, + }, + ]; + + if (loading) { + return ( +
+
+
+ ); + } + + const mockTasks = tasks.length > 0 ? tasks : [ + { + id: '1', + name: 'Image Classification', + status: 'completed', + success_rate: 98.5, + duration: 234, + timestamp: new Date().toISOString(), + }, + { + id: '2', + name: 'Text Generation', + status: 'running', + success_rate: 94.2, + duration: 456, + timestamp: new Date().toISOString(), + }, + { + id: '3', + name: 'Object Detection', + status: 'completed', + success_rate: 96.7, + duration: 189, + timestamp: new Date().toISOString(), + }, + ]; + + const completedTasks = mockTasks.filter(t => t.status === 'completed').length; + const runningTasks = mockTasks.filter(t => t.status === 'running').length; + const failedTasks = mockTasks.filter(t => t.status === 'failed').length; + const avgSuccessRate = mockTasks.reduce((acc, t) => acc + (t.success_rate || 0), 0) / mockTasks.length; + + const taskStatusData = analyzeTaskMetrics(mockTasks); + + const taskPerformanceData = mockTasks.map(task => ({ + name: task.name || 'Unknown', + successRate: task.success_rate || 0, + duration: task.duration || 0, + })); + + const timelineData = Array.from({ length: 12 }, (_, i) => ({ + hour: `${i * 2}h`, + completed: Math.floor(Math.random() * 50) + 20, + failed: Math.floor(Math.random() * 10), + running: Math.floor(Math.random() * 15) + 5, + })); + + return ( +
+ {/* Hero Section with Curved Background */} +
+ {/* Black Background with Curve */} +
+
+

Task Analytics

+

Monitor running tasks and performance metrics

+
+
+ + {/* Curved Bottom Edge */} +
+ + + +
+ + {/* Metric Cards - Overlapping */} +
+
+
+
+
+

Total Tasks

+ +
+

{mockTasks.length}

+

All time

+
+
+
+

Completed

+ +
+

{completedTasks}

+

+{Math.floor(completedTasks * 0.12)} from last hour

+
+
+
+

Running

+ +
+

{runningTasks}

+

Active now

+
+
+
+

Success Rate

+ +
+

{avgSuccessRate.toFixed(1)}%

+

{failedTasks} failed

+
+
+
+
+
+ +
+
+

Task Status Distribution

+ +
+ +
+

Task Performance Comparison

+ +
+
+ +
+

Task Execution Timeline (24h)

+ +
+ + +
+ ); +} diff --git a/apps/CortensorView/src/vite-env.d.ts b/apps/CortensorView/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/apps/CortensorView/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/apps/CortensorView/tailwind.config.js b/apps/CortensorView/tailwind.config.js new file mode 100644 index 0000000..d21f1cd --- /dev/null +++ b/apps/CortensorView/tailwind.config.js @@ -0,0 +1,8 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'], + theme: { + extend: {}, + }, + plugins: [], +}; diff --git a/apps/CortensorView/tsconfig.app.json b/apps/CortensorView/tsconfig.app.json new file mode 100644 index 0000000..f0a2350 --- /dev/null +++ b/apps/CortensorView/tsconfig.app.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "target": "ES2020", + "useDefineForClassFields": true, + "lib": ["ES2020", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["src"] +} diff --git a/apps/CortensorView/tsconfig.json b/apps/CortensorView/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/apps/CortensorView/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/apps/CortensorView/tsconfig.node.json b/apps/CortensorView/tsconfig.node.json new file mode 100644 index 0000000..0d3d714 --- /dev/null +++ b/apps/CortensorView/tsconfig.node.json @@ -0,0 +1,22 @@ +{ + "compilerOptions": { + "target": "ES2022", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "isolatedModules": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "noFallthroughCasesInSwitch": true + }, + "include": ["vite.config.ts"] +} diff --git a/apps/CortensorView/vite.config.ts b/apps/CortensorView/vite.config.ts new file mode 100644 index 0000000..4c4e6b1 --- /dev/null +++ b/apps/CortensorView/vite.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vite'; +import react from '@vitejs/plugin-react'; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], + base: '/', + optimizeDeps: { + exclude: ['lucide-react'], + }, +}); diff --git a/pr_description.md b/pr_description.md deleted file mode 100644 index ea626a1..0000000 --- a/pr_description.md +++ /dev/null @@ -1,33 +0,0 @@ -# CortensorView: Observability Dashboard for the Cortensor Network - -**CortensorView** is a production-ready monitoring and analytics dashboard for the Cortensor decentralized inference network. -Built for Hackathon #2, it provides comprehensive observability tools for network operators, developers, and community members. - -## What It Does -- Real-time network monitoring with metrics for active nodes, requests, latency, and success rates -- Node pool management with leaderboard rankings and performance heatmaps -- Session tracking with search and analytics capabilities -- Task monitoring with status distribution and success rate tracking -- Interactive API Explorer for testing endpoints - -## Technical Stack -- React 18 with TypeScript -- Vite for fast builds -- Tailwind CSS for styling -- Recharts for data visualization -- Direct integration with Cortensor network API - -## Problem Solved -As the Cortensor network grows, operators and developers need real-time visibility into network health, node performance, and task analytics. -This dashboard provides a unified interface for monitoring all aspects of the network, addressing the critical need for infrastructure observability in decentralized AI systems. - -## Installation -``` -npm install -npm run dev -``` - -## Hackathon Categories -- **Infra Observability Tools (Primary):** Network monitoring, node tracking, and analytics -- **Developer Tooling:** Interactive API Explorer and TypeScript integration -- **Public Goods:** Free access, open-source, and community-focused \ No newline at end of file