diff --git a/.cursor/rules/cursor-rules-location.mdc b/.cursor/rules/cursor-rules-location.mdc new file mode 100644 index 00000000..188738be --- /dev/null +++ b/.cursor/rules/cursor-rules-location.mdc @@ -0,0 +1,80 @@ +--- +description: Rules for placing and organizing Cursor rule files in the repository. +globs: +alwaysApply: false +--- +--- +description: Cursor Rules Location +globs: *.mdc +--- +# Cursor Rules Location + +Rules for placing and organizing Cursor rule files in the repository. + + +name: cursor_rules_location +description: Standards for placing Cursor rule files in the correct directory +filters: + # Match any .mdc files + - type: file_extension + pattern: "\\.mdc$" + # Match files that look like Cursor rules + - type: content + pattern: "(?s).*?" + # Match file creation events + - type: event + pattern: "file_create" + +actions: + - type: reject + conditions: + - pattern: "^(?!\\.\\/\\.cursor\\/rules\\/.*\\.mdc$)" + message: "Cursor rule files (.mdc) must be placed in the .cursor/rules directory" + + - type: suggest + message: | + When creating Cursor rules: + + 1. Always place rule files in PROJECT_ROOT/.cursor/rules/: + ``` + .cursor/rules/ + ├── your-rule-name.mdc + ├── another-rule.mdc + └── ... + ``` + + 2. Follow the naming convention: + - Use kebab-case for filenames + - Always use .mdc extension + - Make names descriptive of the rule's purpose + + 3. Directory structure: + ``` + PROJECT_ROOT/ + ├── .cursor/ + │ └── rules/ + │ ├── your-rule-name.mdc + │ └── ... + └── ... + ``` + + 4. Never place rule files: + - In the project root + - In subdirectories outside .cursor/rules + - In any other location + +examples: + - input: | + # Bad: Rule file in wrong location + rules/my-rule.mdc + my-rule.mdc + .rules/my-rule.mdc + + # Good: Rule file in correct location + .cursor/rules/my-rule.mdc + output: "Correctly placed Cursor rule file" + +metadata: + priority: high + version: 1.0 + \ No newline at end of file diff --git a/.cursor/rules/git-conventional-commits.mdc b/.cursor/rules/git-conventional-commits.mdc new file mode 100644 index 00000000..e93dc03a --- /dev/null +++ b/.cursor/rules/git-conventional-commits.mdc @@ -0,0 +1,84 @@ +--- +description: Rule for automatically committing changes made by CursorAI using conventional commits format. +globs: +alwaysApply: false +--- +# Git Conventional Commits + +Rule for automatically committing changes made by CursorAI using conventional commits format. + + +name: conventional_commits +description: Automatically commit changes made by CursorAI using conventional commits format +filters: + - type: event + pattern: "build_success" + - type: file_change + pattern: "*" + +actions: + - type: execute + command: | + # Extract the change type and scope from the changes + CHANGE_TYPE="" + case "$CHANGE_DESCRIPTION" in + *"add"*|*"create"*|*"implement"*) CHANGE_TYPE="feat";; + *"fix"*|*"correct"*|*"resolve"*) CHANGE_TYPE="fix";; + *"refactor"*|*"restructure"*) CHANGE_TYPE="refactor";; + *"test"*) CHANGE_TYPE="test";; + *"doc"*|*"comment"*) CHANGE_TYPE="docs";; + *"style"*|*"format"*) CHANGE_TYPE="style";; + *"perf"*|*"optimize"*) CHANGE_TYPE="perf";; + *) CHANGE_TYPE="chore";; + esac + + # Extract scope from file path + SCOPE=$(dirname "$FILE" | tr '/' '-') + + # Commit the changes + git add "$FILE" + git commit -m "$CHANGE_TYPE($SCOPE): $CHANGE_DESCRIPTION" + + - type: suggest + message: | + Changes should be committed using conventional commits format: + + Format: (): + + Types: + - feat: A new feature + - fix: A bug fix + - docs: Documentation only changes + - style: Changes that do not affect the meaning of the code + - refactor: A code change that neither fixes a bug nor adds a feature + - perf: A code change that improves performance + - test: Adding missing tests or correcting existing tests + - chore: Changes to the build process or auxiliary tools + + The scope should be derived from the file path or affected component. + The description should be clear and concise, written in imperative mood. + +examples: + - input: | + # After adding a new feature to track user activities + CHANGE_DESCRIPTION="add automatic idle detection feature" + FILE="electron/src/background/watchStates/idleService.ts" + output: "feat(electron-src-background): add automatic idle detection feature" + + - input: | + # After fixing a bug in the timeline component + CHANGE_DESCRIPTION="fix incorrect time calculation in timeline" + FILE="client/src/components/Timeline/TimelineItem.tsx" + output: "fix(client-src-components): fix incorrect time calculation in timeline" + + - input: | + # After improving database performance + CHANGE_DESCRIPTION="optimize track item queries for better performance" + FILE="electron/src/drizzle/trackItem.ts" + output: "perf(electron-src-drizzle): optimize track item queries for better performance" + + +metadata: + priority: high + version: 1.0 + diff --git a/.cursorrules b/.cursorrules new file mode 100644 index 00000000..15f42670 --- /dev/null +++ b/.cursorrules @@ -0,0 +1,192 @@ +# Tockler - Electron/React Time Tracking Application + +Tockler is an automatic time-tracking desktop application built with Electron, React, TypeScript, and Chakra UI. + +## Project Organization + +This project follows a clear separation of concerns: + +- **electron/** directory contains all Electron main process code: + - System-level operations + - Background activity tracking + - Database operations with better-sqlite3 + - IPC handlers + - Application lifecycle management + - Tray functionality + +- **client/** directory contains all React renderer code: + - React UI components + - State management with easy-peasy + - Chakra UI styling + - Data visualization components + - View controllers + - User interactions + +## Knowledge Model + +Tockler is a free application that automatically tracks computer usage and working time, providing insights into application usage, window titles, computer states, and visualizations. + +## System Design + +### Architecture +- **Main**: The application follows the Electron architecture with a main process and renderer process. +- **Main Process**: The main process (in electron/ directory) handles system-level operations, background tracking, and database operations. +- **Renderer Process**: The renderer process (in client/ directory) handles the React UI and user interactions. + +### Data Flow +User activities are tracked by the main process (electron/), stored in a SQLite database using better-sqlite3, and displayed through React components in the renderer process (client/). + +### Database Schema +The application uses better-sqlite3 with Drizzle ORM for data persistence, with database operations handled in the electron/ directory. + +## Common Patterns + +### State Management +Use easy-peasy for global state management in the client/ directory. + +### API Calls +Use IPC for communication between main (electron/) and renderer (client/) processes. + +### Error Handling +Use try/catch blocks with proper error logging via electron-log. + +### Logging +Use electron-log for consistent logging across the application. + +## Best Practices + +### General +- Follow the Single Responsibility Principle +- Use TypeScript interfaces/types for all data structures +- Prefer functional programming patterns where applicable +- Use proper error handling and logging +- Document complex functions and components + +### Electron (electron/ directory) +- Use IPC for main/renderer communication +- Minimize direct access to Node.js APIs from renderer +- Handle app lifecycle events properly +- Use proper window management techniques +- Implement proper auto-updates using electron-updater + +### React (client/ directory) +- Use functional components with hooks +- Avoid prop drilling by using context or state management +- Memoize expensive calculations and component renders +- Split components into smaller, reusable pieces +- Use Chakra UI components consistently + +### Styling (client/ directory) +- Use Chakra UI theming system +- Support both light and dark themes +- Maintain consistent spacing and sizing + +## Warnings +- Avoid synchronous IPC calls as they can block the UI +- Be careful with memory usage when tracking activities continuously +- Remember to handle permissions properly for system access features +- Consider performance implications when working with large datasets + +## TypeScript Guidelines + +### Rules +- Use strict type checking +- Define interfaces for all data structures +- Use TypeScript's utility types when appropriate +- Use union types for state management +- Properly type async functions and their return values + +### Naming Conventions +- **Interfaces**: IPascalCase (e.g., ITrackItem) +- **Types**: TPascalCase (e.g., TTimelineState) +- **Components**: PascalCase (e.g., TimelineChart) +- **Functions**: camelCase (e.g., trackActiveWindow) +- **Constants**: UPPER_SNAKE_CASE (e.g., DEFAULT_SETTINGS) + +### Import Organization +1. React imports first +2. Third-party library imports +3. Local component imports +4. Type/interface imports +5. Style/asset imports + +## Technology Guidelines + +### Electron (electron/ directory) + +#### Best Practices +- Use contextBridge for secure preload scripts +- Implement proper window management +- Handle app lifecycle events properly +- Use proper IPC patterns for main/renderer communication +- Implement auto-updates correctly + +#### Common Patterns +- **IPC**: Use ipcMain and ipcRenderer for communication +- **Window Management**: Properly handle window states (minimize, maximize, close) +- **Tray Integration**: Use menubar for tray window implementation +- **Auto Launch**: Implement auto-launch on system startup feature +- **System Access**: Use proper APIs for accessing system information + +### React (client/ directory) + +#### Best Practices +- Use functional components with hooks +- Implement proper state management with easy-peasy +- Use React Router for navigation +- Properly handle form state and validation +- Implement proper error boundaries + +#### Component Structure +- Organize components by feature, with shared components in a common directory +- Use compound components when appropriate +- Use Chakra UI for consistent styling + +### Chakra UI (client/ directory) + +#### Best Practices +- Use the theme provider for consistent styling +- Leverage Chakra's built-in responsive design utilities +- Use Chakra's color mode for light/dark theme support +- Use Chakra's layout components for consistent spacing + +### Data Visualization (client/ directory) + +#### Libraries +- Victory +- D3.js + +#### Patterns +- Use Victory for high-level chart components +- Use D3 for custom visualizations and data transformations +- Ensure visualizations are responsive and accessible + +## Project Structure +- **electron/**: Main process code, system-level operations, background tracking, database interactions +- **client/**: React client code for the renderer process, UI components, state management, visualization +- **screenshots/**: Application screenshots for documentation + +## Testing +- **Framework**: Vitest +- **Patterns**: + - Place test files adjacent to the files they test with a .test.ts(x) suffix + - Use proper mocking for dependencies + - Test components in isolation + - Cover edge cases and error handling + +## Deployment +- **Build**: Use electron-builder for packaging +- **Platforms**: Windows, macOS, Linux +- **Auto Updates**: Implement using electron-updater + +## Development + +### Tools +- **Package Manager**: pnpm +- **Build Tools**: vite, typescript +- **Linters**: eslint +- **Formatters**: prettier + +### Workflow +- **Development**: Run the client/ and electron/ processes separately during development +- **Building**: Build the client/ first, then package with electron-builder diff --git a/.gitattributes b/.gitattributes old mode 100755 new mode 100644 diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 8382faaf..edd1485e 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,12 +1,12 @@ # These are supported funding model platforms github: MayGo -patreon: MayGo_ -open_collective: # Replace with a single Open Collective username -ko_fi: # Replace with a single Ko-fi username +patreon: Tockler +open_collective: tockler +ko_fi: maigoerit tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry liberapay: # Replace with a single Liberapay username issuehunt: # Replace with a single IssueHunt username otechie: # Replace with a single Otechie username -custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] +custom: ['https://paypal.me/maigoerit'] # Replace with your PayPal.me link diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 04832176..569bf382 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -5,25 +5,235 @@ on: - master pull_request: types: [opened, synchronize, reopened] + +# Add concurrency to cancel outdated builds +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + jobs: sonarcloud: name: SonarCloud runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: - fetch-depth: 0 # Shallow clones should be disabled for a better relevancy of analysis + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 9 + run_install: false + + - name: Install Dependencies (Electron) + run: | + cd electron + pnpm install + cd .. + + - name: Run Electron Tests with Coverage + run: | + cd electron + pnpm coverage + cd .. + + - name: Install Dependencies (Client) + run: | + cd client + pnpm install + cd .. + + - name: Run Client Tests with Coverage + run: | + cd client + pnpm coverage + cd .. + - name: SonarCloud Scan Electron uses: SonarSource/sonarcloud-github-action@master with: projectBaseDir: electron env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + - name: SonarCloud Scan Client uses: SonarSource/sonarcloud-github-action@master with: projectBaseDir: client env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Needed to get PR information, if any + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} + + build: + name: Build (${{ matrix.os }}-${{ matrix.arch }}) + needs: [sonarcloud] + runs-on: ${{ matrix.os }} + timeout-minutes: 60 # Set maximum job runtime + strategy: + matrix: + include: + - os: ubuntu-latest + node-version: 22.x + arch: x64 + - os: windows-latest + node-version: 22.x + arch: x64 + - os: macos-13 + node-version: 22.x + arch: x64 + - os: macos-latest + node-version: 22.x + arch: arm64 + + steps: + - uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: 9 + run_install: false + + - name: Get Package Version + id: package_version + shell: bash + run: echo "PACKAGE_VERSION=$(node -p -e "require('./electron/package.json').version")" >> $GITHUB_ENV + + - name: Setup Sentry Release + if: matrix.os == 'ubuntu-latest' + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + run: | + pnpm dlx @sentry/cli releases set-commits "${{ env.PACKAGE_VERSION }}" --commit "${{ github.repository }}@${{ github.sha }}" + pnpm dlx @sentry/cli releases new "${{ env.PACKAGE_VERSION }}" + + - name: Install Python Setuptools on Ubuntu + if: matrix.os == 'ubuntu-latest' + run: | + sudo apt-get update + sudo apt-get install -y python3-setuptools + + - name: Install Python Setuptools on MacOS-13 + if: matrix.os == 'macos-13' + run: | + # Python 2 is no longer available in Homebrew + # Install setuptools which provides distutils for Python 3 + python3 -m pip install setuptools + # Set environment variables to use Python 3 + echo "PYTHON=$(which python3)" >> $GITHUB_ENV + echo "npm_config_python=$(which python3)" >> $GITHUB_ENV + + - name: Install Python Setuptools on other macOS + if: startsWith(matrix.os, 'macos') && matrix.os != 'macos-13' + run: brew install python-setuptools + + - name: Install Python Setuptools on Windows + if: matrix.os == 'windows-latest' + run: | + python -m pip install --upgrade pip + pip install setuptools + + - name: Configure node-gyp for MacOS-13 + if: matrix.os == 'macos-13' + run: | + cd electron + # Configure node-gyp to use Python 3 + echo "node-gyp-binary=python3" >> .npmrc + echo "python=python3" >> .npmrc + echo "npm_config_python=python3" >> .npmrc + cd .. + + - name: Install Dependencies (Electron) + shell: bash + run: | + cd electron + if [[ "${{ matrix.os }}" == "macos-13" ]]; then + PYTHON=$(which python3) pnpm install + else + pnpm install + fi + cd .. + + - name: Install Dependencies (Client) + run: | + cd client + pnpm install + cd .. + + - name: Build Client + env: + VITE_TEMPLATE_ID: ${{ secrets.VITE_TEMPLATE_ID }} + VITE_SERVICE_ID: ${{ secrets.VITE_SERVICE_ID }} + VITE_USER_ID: ${{ secrets.VITE_USER_ID }} + run: | + cd client + pnpm build + cd .. + + - name: Create .env file + shell: bash + run: | + cd electron + echo "SENTRY_DSN=${{ secrets.SENTRY_DSN }}" >> .env + cd .. + + - name: Build and Release Electron App + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + CSC_LINK: ${{ secrets.CSC_LINK }} + CSC_KEY_PASSWORD: ${{ secrets.CSC_KEY_PASSWORD }} + APPLE_ID: ${{ secrets.APPLE_ID }} + APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }} + APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + CSC_IDENTITY_AUTO_DISCOVERY: ${{ matrix.os != 'windows-latest' }} + + run: | + cd electron + # Add flag to reduce console output + export ELECTRON_BUILDER_SILENT=true + pnpm build + pnpm prepare_client + if [[ "${{ matrix.os }}" == "macos-"* ]]; then + pnpm release -- --mac --arch=${{ matrix.arch }} + elif [[ "${{ matrix.os }}" == "windows-latest" ]]; then + pnpm release -- --win + elif [[ "${{ matrix.os }}" == "ubuntu-latest" ]]; then + pnpm release -- --linux + fi + cd .. + + - name: Upload Sentry Sourcemaps + if: matrix.os == 'ubuntu-latest' + env: + SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} + SENTRY_ORG: ${{ secrets.SENTRY_ORG }} + run: | + pnpm dlx @sentry/cli releases files "${{ env.PACKAGE_VERSION }}" upload-sourcemaps ./client/dist/assets/ --rewrite --url-prefix "~/dist/assets" + pnpm dlx @sentry/cli releases files "${{ env.PACKAGE_VERSION }}" list + pnpm dlx @sentry/cli releases finalize "${{ env.PACKAGE_VERSION }}" + + - name: Upload Artifacts + uses: actions/upload-artifact@v4 + with: + name: ${{ matrix.os }}-build + path: | + electron/packaged/*.dmg + electron/packaged/*.AppImage + electron/packaged/*.deb + electron/packaged/*.rpm + electron/packaged/*.exe + electron/packaged/*.msi diff --git a/.gitignore b/.gitignore index c67519a3..25d01914 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,7 @@ dist/ !scripts/ .eslintcache .env +packaged +electron/packaged +!.github/FUNDING.yml +client/.env.development diff --git a/.prettierrc b/.prettierrc index 1605b425..f9fa77cd 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { - "printWidth": 100, + "printWidth": 120, "tabWidth": 4, "singleQuote": true, "trailingComma": "all", diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a1b66d09..00000000 --- a/.travis.yml +++ /dev/null @@ -1,61 +0,0 @@ -matrix: - include: - - os: osx - osx_image: xcode11 - - os: linux - env: CC=clang CXX=clang++ npm_config_clang=1 - compiler: clang - -addons: - apt: - packages: - - libgnome-keyring-dev - - icnsutils - - graphicsmagick - -sudo: true - -language: node_js -node_js: - - '13' - -cache: - timeout: 600 - directories: - - node_modules - - electron/node_modules - - client/node_modules - - $HOME/.electron - -before_script: - - echo "SENTRY_DSN=$SENTRY_DSN" >> ./electron/.env - - sentry-cli releases set-commits "$PACKAGE_VERSION" --commit "$TRAVIS_REPO_SLUG@$TRAVIS_COMMIT" - - sentry-cli releases new "$PACKAGE_VERSION" -after_success: - - sentry-cli releases files "$PACKAGE_VERSION" upload-sourcemaps ./client/build/static/js/ --rewrite --url-prefix "~/dist/static/js" - - sentry-cli releases files "$PACKAGE_VERSION" list - - sentry-cli releases finalize "$PACKAGE_VERSION" - -install: - - npm install -g sentry-cli-binary - - cd electron - - PACKAGE_VERSION=$(node -p -e "require('./package.json').version") - - npm install - - cd .. - - cd client - - npm install - - cd .. - -script: - - cd client - - npm run build - - cd .. - - cd electron - - npm run build - - npm run prepare_client - - travis_wait 80 npm run release - - cd .. - -branches: - only: - - master diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ffb0a0e..8438ddbd 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,5 +1,3 @@ { - "cSpell.words": [ - "reflexbox" - ] -} \ No newline at end of file + "cSpell.words": [] +} diff --git a/BACKEND.md b/BACKEND.md new file mode 100644 index 00000000..c6df545e --- /dev/null +++ b/BACKEND.md @@ -0,0 +1,177 @@ +# Tockler Backend Documentation + +## Overview + +Tockler's backend is built on Electron and provides core functionality for tracking computer usage, application activities, and system state changes. The backend handles data collection, storage, analysis, and maintains the application state. + +## Architecture + +Tockler's backend is structured into several key components: + +### Core Components + +1. **Main Process (`index.ts`)** - Entry point that initializes the application, sets up windows, and manages power monitor events. +2. **Window Manager (`window-manager.ts`)** - Handles the creation and management of application windows. +3. **State Manager (`state-manager.ts`)** - Maintains the current state of tracking items and system state. +4. **Background Service (`background-service.ts`)** - Core service for handling track item creation, updates, and system state transitions. +5. **App Manager (`app-manager.ts`)** - Manages application lifecycle and initialization. + +### Data Models + +1. **TrackItem** - The primary data model representing a tracked activity with the following properties: + - `id`: Unique identifier + - `app`: Application name + - `taskName`: Type of track item (LogTrackItem, AppTrackItem, StatusTrackItem) + - `title`: Window title or description + - `url`: URL (if applicable) + - `color`: Color for visualization + - `beginDate`: Start time of the tracked item + - `endDate`: End time of the tracked item + +### Tracking Jobs + +Tockler has three main tracking jobs that run at regular intervals: + +1. **AppTrackItemJob** - Tracks active applications and window titles + + - Captures the current active window + - Creates or updates AppTrackItem records + - Analyzes window titles for task identification + +2. **StatusTrackItemJob** - Monitors system status + + - Tracks whether the system is Online, Offline, or Idle + - Manages transitions between different states + - Creates StatusTrackItem records + +3. **LogTrackItemJob** - Handles manual time logging + - Manages user-defined tracking items + - Records intentional activities logged by the user + +### Services + +1. **TrackItemService** - Handles CRUD operations for track items + + - Creating new track items + - Querying track items for various time ranges + - Exporting track items + - Updating and deleting track items + +2. **AppSettingService** - Manages application settings + + - Storing and retrieving app colors + - Managing app-specific settings + +3. **SettingsService** - Handles global application settings + - Timer settings + - UI preferences + - Background job intervals + +### State Management + +The application tracks three main states: + +- **ONLINE** - Computer is active and being used +- **IDLE** - Computer is on but not being used (idle timeout) +- **OFFLINE** - Computer is sleeping or powered off + +### Tracking Types + +Three primary tracking types are defined: + +- **AppTrackItem** - Records application usage (which apps were open and active) +- **StatusTrackItem** - Records system status (online, idle, offline) +- **LogTrackItem** - Records manual time entries created by the user + +## Core Functionality + +### Application Tracking + +The AppTrackItemJob runs at regular intervals (default: every few seconds) and: + +1. Queries the OS for the currently active window +2. Creates a new AppTrackItem or updates an existing one +3. Stores details like app name, window title, start time, and end time + +### System State Tracking + +The StatusTrackItemJob: + +1. Monitors for system idle state +2. Creates StatusTrackItem records when state changes +3. Handles transitions between Online, Idle, and Offline states + +### Sleep/Wake Handling + +The backend responds to system sleep and wake events: + +1. When the system sleeps, the current state is saved +2. When the system wakes, an Offline period is recorded for the sleep duration +3. Tracking resumes with the current state + +### Task Analysis + +The TaskAnalyzer: + +1. Examines window titles and application names +2. Identifies potential tasks based on patterns +3. Can notify users about recognized tasks + +## Database + +Tockler uses an Objection.js ORM with SQL database to store: + +1. Track items (application usage, system state, manual logs) +2. Application settings (colors, preferences) +3. Global settings + +## Implementation Details + +### Handling Day Boundaries + +The backend has special handling for activities that span midnight: + +1. TrackItems that cross midnight are split into separate day chunks +2. This ensures accurate daily reporting + +### Error Handling + +The backend implements robust error handling: + +1. Logging errors with detailed context +2. Graceful degradation when tracking encounters issues +3. Recovery mechanisms after system sleep or crashes + +### Background Job Management + +Background jobs are managed with: + +1. Configurable intervals +2. Automatic retries +3. Error logging and recovery + +## Integration Points + +The backend exposes functionality to the frontend through: + +1. IPC (Inter-Process Communication) channels +2. Shared data models +3. Event emitters for real-time updates + +## Configuration + +The backend can be configured through: + +1. Environment variables +2. User settings (stored in the database) +3. Default configurations in code + +This document provides an overview of Tockler's backend architecture and main components. For specific implementation details, refer to the corresponding source files. + +# New backend + +There should be system state events. Online, Offline, Idle. There is a thread that checks for Idle state. If state changes event is fired. + +Other parts are listening to those events. + +In active application tracking, there is a thread that in every 3 seconds checks the active window. If system is Idle or Offline, the thread is ended. It will start if it gets event Online. It keeps current state in memory, and changes endDate if needed or saves state to sqllite db diff --git a/LICENCE.txt b/LICENCE.txt old mode 100755 new mode 100644 diff --git a/README.md b/README.md old mode 100755 new mode 100644 index 69625875..65773023 --- a/README.md +++ b/README.md @@ -1,132 +1,212 @@ - +

+ + Tockler logo + + + Tockler logo + +

+ +

+ + Release + + + Total downloads + + + Latest downloads + +

+ +## Overview + +Tockler is a free application that automatically tracks your computer usage and working time. It provides detailed insights into: + +- Application usage and window titles +- Computer state (idle, offline, online) +- Interactive timeline visualization +- Daily, weekly, and monthly usage statistics +- Calendar views and charts + +## Features + +- **Time Tracking**: Go back in time and see what you were working on +- **Application Monitoring**: Track which apps were used and their window titles +- **Usage Analytics**: View total online time, application usage patterns, and trends +- **Interactive Timeline**: Visualize your computer usage with an interactive chart +- **Cross-Platform**: Available for Windows, macOS, and Linux + +## Support Tockler + +Tockler is free and open-source software. If you find it useful, please consider supporting its development: + +

+ + Sponsor on GitHub + + + Support on Open Collective + + + Support on Patreon + + + Support on Ko-fi + + + Donate via PayPal + +

+ +## Download + +

+ + View all releases + +

+ +### Windows + +

+ + Download Windows Universal Setup + + + Download Windows x64 Setup + + + Download Windows ARM64 Setup + + + Download Windows 32-bit Setup + +

+

+ + Download Windows Universal Portable + + + Download Windows x64 Portable + + + Download Windows ARM64 Portable + + + Download Windows 32-bit Portable + +

+ +### macOS + +

+ + Download macOS Universal DMG + + + Download macOS Apple Silicon DMG + +

+ +### Linux + +

+ + Download Linux AppImage + +

+ +## Screenshots + +### Light Theme + +![Timeline](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-timeline.png 'Timeline') +![Settings](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-settings.png 'Settings') +![Summary](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-summary-calendar.png 'Summary') +![Summary](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-summary-chart.png 'Summary') +![Search](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-search.png 'Search') +![Tray window](https://github.com/MayGo/tockler/raw/master/screenshots/light/tockler-tray.png 'Tray window') + +### Dark Theme + +![Timeline](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-timeline.png 'Timeline') +![Settings](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-settings.png 'Settings') +![Summary](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-summary-calendar.png 'Summary') +![Summary](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-summary-chart.png 'Summary') +![Search](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-search.png 'Search') +![Tray window](https://github.com/MayGo/tockler/raw/master/screenshots/dark/tockler-tray.png 'Tray window') + +## Technologies + +Tockler is built with modern web technologies: + +- **Framework**: [Electron](https://electron.atom.io/) with [Webpack](https://webpack.github.io/) and [TypeScript](https://www.typescriptlang.org/) +- **Frontend**: [React](https://reactjs.org/) with [Chakra UI](https://chakra-ui.com/) +- **Data Visualization**: [D3.js](https://d3js.org/) and [Victory Chart](http://formidable.com/open-source/victory/docs/victory-chart/) +- **Package Manager**: [pnpm](https://pnpm.io/) -[![Donate using PayPal](https://github.com/MayGo/tockler/raw/master/badges/Donate-PayPal-green.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=JAHHBZZCZVDMA) -[![Sponsor on GitHub](https://github.com/MayGo/tockler/raw/master/badges/GitHub-Badge.svg)](https://github.com/sponsors/maygo/) -[![Become a patron](https://github.com/MayGo/tockler/raw/master/badges/Patreon-Badge.svg)](https://www.patreon.com/Tockler) - - - -## [![Release](https://img.shields.io/github/v/release/MayGo/tockler)](https://github.com/MayGo/tockler/releases/latest) - -## ![Tockler](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-logo.png 'Tockler') - -**Automatically track applications usage and working time.** - -> With Tockler you can go back in time and see what you were working on. You can get information on what apps were used - exactly at what time - and what title the application had at that moment. This is enough to determine how much you did something. - -**Track how you spent your time on a computer.** - -> Tockler tracks active applications usage and computer state. It records active application titles. It tracks idle, offline, and online state. You can see this data with a nice interactive timeline chart. - -**Analyze your computer usage** - -> See you total online time today, yesterday, or any other day. In monthly calendar views and with charts. - -# Applications installer download - -| Operating System | Download | -| ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Windows (32 and 64-bit) | Get it on Windows | -| macOS | Get it on macOS | -| Linux | Get it on Linux | - -# Feedback - -Feel free to make feature requests by creating a issue and 'Star' this project. - -# Donations - -This project needs your support! - -If you find this app useful then feel free to donate. Anything helps to keep this app up to date and always improving. - -Thank you! - -# Made with - -- [Electron](https://electron.atom.io/) with [Webpack](https://webpack.github.io/) and [Typescript](https://www.typescriptlang.org/) -- [React](https://reactjs.org/) -- [D3 v4](https://d3js.org/) and [Victory Chart](http://formidable.com/open-source/victory/docs/victory-chart/) -- [Ant Design](https://ant.design/) - -# Screenshots - -![Timeline](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-timeline.png 'Timeline') -![Changing items color](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-change_color.png 'Changing items color') -![Settings](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-settings.png 'Settings') -![Summary](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-summary.png 'Summary') -![Search](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-search.png 'Search') -![Tray window](https://github.com/MayGo/tockler/raw/master/screenshots/tockler-tray.png 'Tray window') -![Edit log item](https://github.com/MayGo/tockler/raw/master/screenshots/editing-log-item.gif 'Edit log item') - -# Debugging - -## Logs - -By default, tockler writes logs to the following locations: - -on Linux: `~/.config/tockler/logs/main.log` - -on macOS: `~/Library/Logs/tockler/main.log` +## Development -on Windows: `%USERPROFILE%\AppData\Roaming\tockler\logs\main.log` +### Prerequisites -## Development +- Node.js +- Git +- pnpm ### Quick Start -> Prerequisites: [Node](https://nodejs.org/), [Git](https://git-scm.com/). +1. Clone the repository: ```bash -git clone https://github.com/Maygo/tockler.git # Download this project - -npm install yarn -g # install yarn or binary from https://yarnpkg.com +git clone https://github.com/Maygo/tockler.git +cd tockler ``` -### Start application +2. Enable pnpm: -Renderer and main process builds have been separated. It's easier to boilerplate this project and switch client framework. +```bash +corepack enable pnpm +``` -#### React client (renderer) +3. Install dependencies and start the application: -``` +For the React client (renderer): + +```bash cd client/ -yarn install # Install dependencies -npm start +pnpm install +pnpm start ``` -#### Electron (main) +For the Electron main process: -``` +```bash cd electron/ -yarn install # Install dependencies -yarn start +pnpm install +pnpm start ``` -Build scripts samples are in travis/appveyor files. - -# Signing +### Logs -https://4sysops.com/archives/sign-your-powershell-scripts-to-increase-security/' -in powershell as admin +Logs are stored in the following locations: -``` -$cert = Get-ChildItem -Path Cert:\CurrentUser\My -CodeSigningCert -Set-AuthenticodeSignature -FilePath '.\app\get-foreground-window-title.ps1' -Certificate $cert -``` +- Linux: `~/.config/tockler/logs/main.log` +- macOS: `~/Library/Logs/tockler/main.log` +- Windows: `%USERPROFILE%\AppData\Roaming\tockler\logs\main.log` -# License +## Feedback -GNU General Public License v2.0 -2021 MayGo (https://github.com/MayGo) +Feel free to: -# Functionality +- Create issues for feature requests +- Star this project +- Share your feedback -- On app launch only tray window runs. Main window does not open. -- Main window opens from tray windows arrow or by reopening application. +## License -# Errors +Tockler is licensed under the GNU General Public License v2.0. See the [LICENSE](LICENSE) file for details. -## while installing electron deps: electron-builder Error: Unresolved node modules: ref +MayGo (https://github.com/MayGo) -Quick fix: ELECTRON_BUILDER_ALLOW_UNRESOLVED_DEPENDENCIES=true yarn +Created by Maigo Erit @ trimatech.dev diff --git a/appveyor.before-build.ps1 b/appveyor.before-build.ps1 deleted file mode 100644 index 90730c8b..00000000 --- a/appveyor.before-build.ps1 +++ /dev/null @@ -1,7 +0,0 @@ -# Get build path -$path = $env:APPVEYOR_BUILD_FOLDER; - -$certSelfSigned = New-SelfSignedCertificate -DnsName trimatech.ee -CertStoreLocation Cert:\CurrentUser\My -KeyExportPolicy Exportable -Type CodeSigningCert -KeySpec Signature -Set-AuthenticodeSignature -FilePath "$path\electron\scripts\get-foreground-window-title.ps1" -Certificate $certSelfSigned - -exit diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index df771f54..00000000 --- a/appveyor.yml +++ /dev/null @@ -1,36 +0,0 @@ -os: Visual Studio 2019 - -platform: - - x64 - -environment: - nodejs_version: '12' - SIGNTOOL: C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe - -branches: - only: - - master - -skip_tags: true - -version: '{build}' - -install: - - ps: Install-Product node $env:nodejs_version x64 - - ps: .\appveyor.before-build.ps1 - - node --version - - npm --version - - echo SENTRY_DSN=%SENTRY_DSN% > .\electron\.env - - cd electron - - npm install - - cd .. - - cd client - - npm install - -build_script: - - npm run build - - cd .. - - cd electron - - npm run build - - npm run prepare_client - - npm run release diff --git a/client/.env.example b/client/.env.example new file mode 100644 index 00000000..c7370037 --- /dev/null +++ b/client/.env.example @@ -0,0 +1,4 @@ +# https://dashboard.emailjs.com/ +VITE_TEMPLATE_ID= +VITE_SERVICE_ID= +VITE_USER_ID= diff --git a/client/.gitignore b/client/.gitignore index d30f40ef..a547bf36 100644 --- a/client/.gitignore +++ b/client/.gitignore @@ -1,21 +1,24 @@ -# See https://help.github.com/ignore-files/ for more about ignoring files. - -# dependencies -/node_modules - -# testing -/coverage - -# production -/build - -# misc -.DS_Store -.env.local -.env.development.local -.env.test.local -.env.production.local - +# Logs +logs +*.log npm-debug.log* yarn-debug.log* yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/client/README.md b/client/README.md index 64e343e1..74872fd4 100644 --- a/client/README.md +++ b/client/README.md @@ -1,44 +1,50 @@ -This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). - -## Available Scripts - -In the project directory, you can run: - -### `yarn start` - -Runs the app in the development mode.
-Open [http://localhost:3000](http://localhost:3000) to view it in the browser. - -The page will reload if you make edits.
-You will also see any lint errors in the console. - -### `yarn test` - -Launches the test runner in the interactive watch mode.
-See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. - -### `yarn build` - -Builds the app for production to the `build` folder.
-It correctly bundles React in production mode and optimizes the build for the best performance. - -The build is minified and the filenames include the hashes.
-Your app is ready to be deployed! - -See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. - -### `yarn eject` - -**Note: this is a one-way operation. Once you `eject`, you can’t go back!** - -If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. - -Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. - -You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. - -## Learn More - -You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). - -To learn React, check out the [React documentation](https://reactjs.org/). +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type aware lint rules: + +- Configure the top-level `parserOptions` property like this: + +```js +export default tseslint.config({ + languageOptions: { + // other options... + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + }, +}) +``` + +- Replace `tseslint.configs.recommended` to `tseslint.configs.recommendedTypeChecked` or `tseslint.configs.strictTypeChecked` +- Optionally add `...tseslint.configs.stylisticTypeChecked` +- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and update the config: + +```js +// eslint.config.js +import react from 'eslint-plugin-react' + +export default tseslint.config({ + // Set the react version + settings: { react: { version: '18.3' } }, + plugins: { + // Add the react plugin + react, + }, + rules: { + // other rules... + // Enable its recommended rules + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + }, +}) +``` diff --git a/client/config-overrides.js b/client/config-overrides.js deleted file mode 100644 index 71076c54..00000000 --- a/client/config-overrides.js +++ /dev/null @@ -1,51 +0,0 @@ -const path = require('path'); -const fs = require('fs'); -const { override, fixBabelImports, addLessLoader, addWebpackPlugin } = require('customize-cra'); - -const AntDesignThemePlugin = require('antd-theme-webpack-plugin'); -const { getLessVars } = require('antd-theme-generator'); - -const themeVariables = getLessVars(path.join(__dirname, './src/styles/vars.less')); -const defaultVars = getLessVars('./node_modules/antd/lib/style/themes/default.less'); -const darkVars = { - ...getLessVars('./node_modules/antd/lib/style/themes/dark.less'), - '@primary-color': defaultVars['@primary-color'], - '@picker-basic-cell-active-with-range-color': 'darken(@primary-color, 20%)', -}; -const lightVars = { - ...getLessVars('./node_modules/antd/lib/style/themes/compact.less'), - '@primary-color': defaultVars['@primary-color'], -}; -fs.writeFileSync('./src/dark.json', JSON.stringify(darkVars)); -fs.writeFileSync('./src/light.json', JSON.stringify(lightVars)); -fs.writeFileSync('./src/theme.json', JSON.stringify(themeVariables)); - -const options = { - stylesDir: path.join(__dirname, './src'), - antDir: path.join(__dirname, './node_modules/antd'), - varFile: path.join(__dirname, './src/styles/vars.less'), - themeVariables: Array.from( - new Set([ - ...Object.keys(darkVars), - ...Object.keys(lightVars), - ...Object.keys(themeVariables), - ]), - ), - publicPath: process.env.PUBLIC_URL || './', - lessUrl: `${process.env.PUBLIC_URL || './'}less.min.js`, - generateOnce: false, // generate color.less on each compilation -}; - -module.exports = override( - fixBabelImports('import', { - libraryName: 'antd', - libraryDirectory: 'es', - style: true, - }), - addLessLoader({ - lessOptions: { - javascriptEnabled: true, - }, - }), - addWebpackPlugin(new AntDesignThemePlugin(options)), -); diff --git a/client/env.sample b/client/env.sample deleted file mode 100644 index c79d09ea..00000000 --- a/client/env.sample +++ /dev/null @@ -1,5 +0,0 @@ - -# Email JS -# REACT_APP_TEMPLATE_ID= -# REACT_APP_SERVICE_ID= -# REACT_APP_USER_ID= \ No newline at end of file diff --git a/client/eslint.config.js b/client/eslint.config.js new file mode 100644 index 00000000..21cb7b61 --- /dev/null +++ b/client/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 reactCompiler from 'eslint-plugin-react-compiler'; +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, + 'react-compiler': reactCompiler, + }, + rules: { + ...reactHooks.configs.recommended.rules, + 'react-compiler/react-compiler': 'warn', + 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], + }, + }, +); diff --git a/client/index.html b/client/index.html new file mode 100644 index 00000000..aee19bb9 --- /dev/null +++ b/client/index.html @@ -0,0 +1,15 @@ + + + + + + + Tockler + + + + +
+ + + diff --git a/client/jest.config.js b/client/jest.config.js deleted file mode 100644 index 91a2d2c0..00000000 --- a/client/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: 'ts-jest', - testEnvironment: 'node', -}; \ No newline at end of file diff --git a/client/package.json b/client/package.json index 28d4fe73..4be32c3d 100644 --- a/client/package.json +++ b/client/package.json @@ -1,83 +1,72 @@ { "name": "tockler", - "version": "3.18.4", "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "test": "TZ=Europe/Tallinn vitest --run", + "coverage": "TZ=Europe/Tallinn vitest run --coverage", + "preview": "vite preview" + }, "dependencies": { - "@analytics/google-analytics": "^0.5.2", - "@react-hook/window-size": "^1.0.12", - "@welldone-software/why-did-you-render": "^3.5.0", - "analytics": "^0.7.5", - "antd": "^4.9.4", - "antd-theme-generator": "^1.2.8", - "antd-theme-webpack-plugin": "^1.3.7", - "babel-plugin-import": "^1.13.3", - "cross-env": "6.0.3", + "@chakra-ui/icons": "^2.2.4", + "@chakra-ui/react": "^2.3.7", + "@chakra-ui/theme-tools": "^2.2.6", + "@datepicker-react/hooks": "^2.8.4", + "@emotion/react": "^11.10.5", + "@emotion/styled": "^11.10.5", + "@fontsource/inter": "^4.5.14", + "@hookform/resolvers": "^2.9.10", + "@react-hook/window-size": "^3.1.1", + "@tanstack/react-table": "^8.21.2", + "@testing-library/jest-dom": "^6.6.3", + "@testing-library/react": "^16.2.0", + "@uidotdev/usehooks": "^2.4.1", + "@vitest/coverage-v8": "^3.0.4", + "date-fns": "^4.1.0", "debounce-promise": "^3.1.2", - "easy-peasy": "^4.0.1", - "eiphop": "^1.0.13", - "electron-store": "5.2.0", - "emailjs-com": "^2.6.4", - "fast-deep-equal": "^3.1.1", - "less": "^3.13.1", - "less-loader": "^6.2.0", - "lodash": "4.17.19", - "loglevel": "^1.6.6", - "moment": "^2.24.0", - "moment-duration-format": "2.3.2", + "easy-peasy": "^5.1.0", + "electron-log": "^5.3.2", + "fast-deep-equal": "^3.1.3", + "framer-motion": "^7", + "humanize-duration": "^3.32.1", + "lodash": "4.17.21", + "luxon": "^3.5.0", + "match-sorter": "^8.0.0", "randomcolor": "^0.6.2", - "react": "^16.13.1", - "react-color": "2.19.3", - "react-component-queries": "2.3.0", - "react-dev-utils": "^10.0.0", - "react-dom": "^16.13.1", - "react-moment": "0.9.7", - "react-portal": "^4.2.0", - "react-router": "^5.1.2", - "react-router-dom": "^5.1.2", - "react-scripts": "^4.0.1", - "react-sizeme": "2.6.12", - "react-timeago": "4.4.0", - "react-use-form-state": "^0.13.2", - "reactcss": "^1.2.3", - "reflexbox": "^4.0.6", - "styled-components": "5.2.1", - "typeface-berkshire-swash": "0.0.72", - "use-react-router": "^1.0.7", - "victory": "^35.4.3" - }, - "scripts": { - "start": "cross-env ELECTRON_ENABLE_SECURITY_WARNINGS=false BROWSER=none LOG_LEVEL=debug react-app-rewired start", - "build": "cross-env GENERATE_SOURCEMAP=false PUBLIC_URL=./ react-app-rewired build", - "test": "yarn jest", - "eject": "react-app-rewired eject", - "lint": "eslint 'src/**/*{.ts,.tsx}' --fix" + "react": "^19.0.0", + "react-color-palette": "^6.2.0", + "react-dom": "^19.0.0", + "react-hook-form": "^7.54.2", + "react-icons": "^5.4.0", + "react-moment": "1.1.3", + "react-portal": "^4.3.0", + "react-router-dom": "6.4.3", + "react-scripts": "^5.0.1", + "use-debounce": "^10.0.4", + "victory": "^37.3.6", + "vitest": "^3.0.4", + "yup": "^0.32.11" }, "devDependencies": { - "@testing-library/jest-dom": "^4.2.4", - "@testing-library/react": "^9.3.2", - "@testing-library/user-event": "^7.1.2", - "@types/jest": "^24.0.0", - "@types/lodash.throttle": "^4.1.6", - "@types/node": "^12.0.0", - "@types/react": "^16.9.0", - "@types/react-dom": "^16.9.0", - "@types/webpack-env": "1.15.0", - "customize-cra": "^1.0.0", - "prettier": "^1.19.1", - "react-app-rewired": "^2.1.8", - "react-hot-loader": "4.12.19", - "ts-jest": "^26.0.0", - "typescript": "~3.7.2" - }, - "eslintConfig": { - "extends": "react-app" - }, - "browserslist": { - "production": [ - "last 1 chrome version" - ], - "development": [ - "last 1 chrome version" - ] + "@eslint/js": "^9.17.0", + "@types/lodash": "^4.17.16", + "@types/luxon": "^3.4.2", + "@types/match-sorter": "^6.0.0", + "@types/react": "^19.0.10", + "@types/react-dom": "^19.0.4", + "@vitejs/plugin-react": "^4.3.4", + "babel-plugin-react-compiler": "19.0.0-beta-27714ef-20250124", + "eslint": "^9.17.0", + "eslint-plugin-react-compiler": "19.0.0-beta-27714ef-20250124", + "eslint-plugin-react-hooks": "^5.0.0", + "eslint-plugin-react-refresh": "^0.4.16", + "globals": "^15.14.0", + "typescript": "~5.8.2", + "typescript-eslint": "^8.25.0", + "vite": "^6.2.0" } } diff --git a/client/pnpm-lock.yaml b/client/pnpm-lock.yaml new file mode 100644 index 00000000..24bc5200 --- /dev/null +++ b/client/pnpm-lock.yaml @@ -0,0 +1,14977 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + dependencies: + '@chakra-ui/icons': + specifier: ^2.2.4 + version: 2.2.4(@chakra-ui/react@2.10.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0) + '@chakra-ui/react': + specifier: ^2.3.7 + version: 2.10.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@chakra-ui/theme-tools': + specifier: ^2.2.6 + version: 2.2.6(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0) + '@datepicker-react/hooks': + specifier: ^2.8.4 + version: 2.8.4(react@19.0.0) + '@emotion/react': + specifier: ^11.10.5 + version: 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/styled': + specifier: ^11.10.5 + version: 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@fontsource/inter': + specifier: ^4.5.14 + version: 4.5.15 + '@hookform/resolvers': + specifier: ^2.9.10 + version: 2.9.11(react-hook-form@7.54.2(react@19.0.0)) + '@react-hook/window-size': + specifier: ^3.1.1 + version: 3.1.1(react@19.0.0) + '@tanstack/react-table': + specifier: ^8.21.2 + version: 8.21.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@testing-library/jest-dom': + specifier: ^6.6.3 + version: 6.6.3 + '@testing-library/react': + specifier: ^16.2.0 + version: 16.2.0(@testing-library/dom@10.4.0)(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@uidotdev/usehooks': + specifier: ^2.4.1 + version: 2.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@vitest/coverage-v8': + specifier: ^3.0.4 + version: 3.0.8(vitest@3.0.8(@types/node@22.13.9)(jiti@1.21.7)(jsdom@16.7.0)(terser@5.39.0)(yaml@2.7.0)) + date-fns: + specifier: ^4.1.0 + version: 4.1.0 + debounce-promise: + specifier: ^3.1.2 + version: 3.1.2 + easy-peasy: + specifier: ^5.1.0 + version: 5.2.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + electron-log: + specifier: ^5.3.2 + version: 5.3.2 + fast-deep-equal: + specifier: ^3.1.3 + version: 3.1.3 + framer-motion: + specifier: ^7 + version: 7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + humanize-duration: + specifier: ^3.32.1 + version: 3.32.1 + lodash: + specifier: 4.17.21 + version: 4.17.21 + luxon: + specifier: ^3.5.0 + version: 3.5.0 + match-sorter: + specifier: ^8.0.0 + version: 8.0.0 + randomcolor: + specifier: ^0.6.2 + version: 0.6.2 + react: + specifier: ^19.0.0 + version: 19.0.0 + react-color-palette: + specifier: ^6.2.0 + version: 6.2.0(react@19.0.0) + react-dom: + specifier: ^19.0.0 + version: 19.0.0(react@19.0.0) + react-hook-form: + specifier: ^7.54.2 + version: 7.54.2(react@19.0.0) + react-icons: + specifier: ^5.4.0 + version: 5.5.0(react@19.0.0) + react-moment: + specifier: 1.1.3 + version: 1.1.3(moment@2.30.1)(prop-types@15.8.1)(react@19.0.0) + react-portal: + specifier: ^4.3.0 + version: 4.3.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-router-dom: + specifier: 6.4.3 + version: 6.4.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react-scripts: + specifier: ^5.0.1 + version: 5.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(@types/babel__core@7.20.5)(eslint@9.21.0(jiti@1.21.7))(react@19.0.0)(type-fest@0.21.3)(typescript@5.8.2) + use-debounce: + specifier: ^10.0.4 + version: 10.0.4(react@19.0.0) + victory: + specifier: ^37.3.6 + version: 37.3.6(react@19.0.0) + vitest: + specifier: ^3.0.4 + version: 3.0.8(@types/node@22.13.9)(jiti@1.21.7)(jsdom@16.7.0)(terser@5.39.0)(yaml@2.7.0) + yup: + specifier: ^0.32.11 + version: 0.32.11 + devDependencies: + '@eslint/js': + specifier: ^9.17.0 + version: 9.21.0 + '@types/lodash': + specifier: ^4.17.16 + version: 4.17.16 + '@types/luxon': + specifier: ^3.4.2 + version: 3.4.2 + '@types/match-sorter': + specifier: ^6.0.0 + version: 6.0.0 + '@types/react': + specifier: ^19.0.10 + version: 19.0.10 + '@types/react-dom': + specifier: ^19.0.4 + version: 19.0.4(@types/react@19.0.10) + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.3.4(vite@6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0)) + babel-plugin-react-compiler: + specifier: 19.0.0-beta-27714ef-20250124 + version: 19.0.0-beta-27714ef-20250124 + eslint: + specifier: ^9.17.0 + version: 9.21.0(jiti@1.21.7) + eslint-plugin-react-compiler: + specifier: 19.0.0-beta-27714ef-20250124 + version: 19.0.0-beta-27714ef-20250124(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-react-hooks: + specifier: ^5.0.0 + version: 5.2.0(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-react-refresh: + specifier: ^0.4.16 + version: 0.4.19(eslint@9.21.0(jiti@1.21.7)) + globals: + specifier: ^15.14.0 + version: 15.15.0 + typescript: + specifier: ~5.8.2 + version: 5.8.2 + typescript-eslint: + specifier: ^8.25.0 + version: 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + vite: + specifier: ^6.2.0 + version: 6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + +packages: + + '@adobe/css-tools@4.4.2': + resolution: {integrity: sha512-baYZExFpsdkBNuvGKTKWCwKH57HRZLVtycZS05WTQNVOiXVSeAki3nU35zlRbToeMW8aHlJfyS+1C4BOv27q0A==} + + '@alloc/quick-lru@5.2.0': + resolution: {integrity: sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==} + engines: {node: '>=10'} + + '@ampproject/remapping@2.3.0': + resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} + engines: {node: '>=6.0.0'} + + '@apideck/better-ajv-errors@0.3.6': + resolution: {integrity: sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==} + engines: {node: '>=10'} + peerDependencies: + ajv: '>=8' + + '@babel/code-frame@7.26.2': + resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} + engines: {node: '>=6.9.0'} + + '@babel/compat-data@7.26.8': + resolution: {integrity: sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==} + engines: {node: '>=6.9.0'} + + '@babel/core@7.26.9': + resolution: {integrity: sha512-lWBYIrF7qK5+GjY5Uy+/hEgp8OJWOD/rpy74GplYRhEauvbHDeFB8t5hPOZxCZ0Oxf4Cc36tK51/l3ymJysrKw==} + engines: {node: '>=6.9.0'} + + '@babel/eslint-parser@7.26.8': + resolution: {integrity: sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg==} + engines: {node: ^10.13.0 || ^12.13.0 || >=14.0.0} + peerDependencies: + '@babel/core': ^7.11.0 + eslint: ^7.5.0 || ^8.0.0 || ^9.0.0 + + '@babel/generator@7.26.9': + resolution: {integrity: sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-annotate-as-pure@7.25.9': + resolution: {integrity: sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==} + engines: {node: '>=6.9.0'} + + '@babel/helper-compilation-targets@7.26.5': + resolution: {integrity: sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-create-class-features-plugin@7.26.9': + resolution: {integrity: sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-create-regexp-features-plugin@7.26.3': + resolution: {integrity: sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-define-polyfill-provider@0.6.3': + resolution: {integrity: sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + '@babel/helper-member-expression-to-functions@7.25.9': + resolution: {integrity: sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-imports@7.25.9': + resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-module-transforms@7.26.0': + resolution: {integrity: sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-optimise-call-expression@7.25.9': + resolution: {integrity: sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-plugin-utils@7.26.5': + resolution: {integrity: sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==} + engines: {node: '>=6.9.0'} + + '@babel/helper-remap-async-to-generator@7.25.9': + resolution: {integrity: sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-replace-supers@7.26.5': + resolution: {integrity: sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + resolution: {integrity: sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-string-parser@7.25.9': + resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-identifier@7.25.9': + resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} + engines: {node: '>=6.9.0'} + + '@babel/helper-validator-option@7.25.9': + resolution: {integrity: sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==} + engines: {node: '>=6.9.0'} + + '@babel/helper-wrap-function@7.25.9': + resolution: {integrity: sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==} + engines: {node: '>=6.9.0'} + + '@babel/helpers@7.26.9': + resolution: {integrity: sha512-Mz/4+y8udxBKdmzt/UjPACs4G3j5SshJJEFFKxlCGPydG4JAHXxjWjAwjd09tf6oINvl1VfMJo+nB7H2YKQ0dA==} + engines: {node: '>=6.9.0'} + + '@babel/parser@7.26.9': + resolution: {integrity: sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==} + engines: {node: '>=6.0.0'} + hasBin: true + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9': + resolution: {integrity: sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9': + resolution: {integrity: sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9': + resolution: {integrity: sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9': + resolution: {integrity: sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9': + resolution: {integrity: sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-proposal-class-properties@7.18.6': + resolution: {integrity: sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-decorators@7.25.9': + resolution: {integrity: sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6': + resolution: {integrity: sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-numeric-separator@7.18.6': + resolution: {integrity: sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-optional-chaining@7.21.0': + resolution: {integrity: sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-methods@7.18.6': + resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2': + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-proposal-private-property-in-object@7.21.11': + resolution: {integrity: sha512-0QZ8qP/3RLDVBwBFoWAwCtgcDZJVwA5LUJRZU8x2YFfKNuFq161wK3cuGrALu5yiPu+vzwTAg/sMWVNeWeNyaw==} + engines: {node: '>=6.9.0'} + deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead. + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-async-generators@7.8.4': + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-bigint@7.8.3': + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-properties@7.12.13': + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-class-static-block@7.14.5': + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-decorators@7.25.9': + resolution: {integrity: sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-flow@7.26.0': + resolution: {integrity: sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-assertions@7.26.0': + resolution: {integrity: sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-attributes@7.26.0': + resolution: {integrity: sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-import-meta@7.10.4': + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-json-strings@7.8.3': + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-jsx@7.25.9': + resolution: {integrity: sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4': + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3': + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-numeric-separator@7.10.4': + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-object-rest-spread@7.8.3': + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3': + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-optional-chaining@7.8.3': + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-private-property-in-object@7.14.5': + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-top-level-await@7.14.5': + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-typescript@7.25.9': + resolution: {integrity: sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6': + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-arrow-functions@7.25.9': + resolution: {integrity: sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-generator-functions@7.26.8': + resolution: {integrity: sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-async-to-generator@7.25.9': + resolution: {integrity: sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoped-functions@7.26.5': + resolution: {integrity: sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-block-scoping@7.25.9': + resolution: {integrity: sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-properties@7.25.9': + resolution: {integrity: sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-class-static-block@7.26.0': + resolution: {integrity: sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + + '@babel/plugin-transform-classes@7.25.9': + resolution: {integrity: sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-computed-properties@7.25.9': + resolution: {integrity: sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-destructuring@7.25.9': + resolution: {integrity: sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-dotall-regex@7.25.9': + resolution: {integrity: sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-keys@7.25.9': + resolution: {integrity: sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-dynamic-import@7.25.9': + resolution: {integrity: sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-exponentiation-operator@7.26.3': + resolution: {integrity: sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-export-namespace-from@7.25.9': + resolution: {integrity: sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-flow-strip-types@7.26.5': + resolution: {integrity: sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-for-of@7.26.9': + resolution: {integrity: sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-function-name@7.25.9': + resolution: {integrity: sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-json-strings@7.25.9': + resolution: {integrity: sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-literals@7.25.9': + resolution: {integrity: sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-logical-assignment-operators@7.25.9': + resolution: {integrity: sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-member-expression-literals@7.25.9': + resolution: {integrity: sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-amd@7.25.9': + resolution: {integrity: sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-commonjs@7.26.3': + resolution: {integrity: sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-systemjs@7.25.9': + resolution: {integrity: sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-modules-umd@7.25.9': + resolution: {integrity: sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9': + resolution: {integrity: sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-new-target@7.25.9': + resolution: {integrity: sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6': + resolution: {integrity: sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-numeric-separator@7.25.9': + resolution: {integrity: sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-rest-spread@7.25.9': + resolution: {integrity: sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-object-super@7.25.9': + resolution: {integrity: sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-catch-binding@7.25.9': + resolution: {integrity: sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-optional-chaining@7.25.9': + resolution: {integrity: sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-parameters@7.25.9': + resolution: {integrity: sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-methods@7.25.9': + resolution: {integrity: sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-private-property-in-object@7.25.9': + resolution: {integrity: sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-property-literals@7.25.9': + resolution: {integrity: sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-constant-elements@7.25.9': + resolution: {integrity: sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-display-name@7.25.9': + resolution: {integrity: sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-development@7.25.9': + resolution: {integrity: sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-self@7.25.9': + resolution: {integrity: sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.25.9': + resolution: {integrity: sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx@7.25.9': + resolution: {integrity: sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-pure-annotations@7.25.9': + resolution: {integrity: sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regenerator@7.25.9': + resolution: {integrity: sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-regexp-modifiers@7.26.0': + resolution: {integrity: sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/plugin-transform-reserved-words@7.25.9': + resolution: {integrity: sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-runtime@7.26.9': + resolution: {integrity: sha512-Jf+8y9wXQbbxvVYTM8gO5oEF2POdNji0NMltEkG7FtmzD9PVz7/lxpqSdTvwsjTMU5HIHuDVNf2SOxLkWi+wPQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-shorthand-properties@7.25.9': + resolution: {integrity: sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-spread@7.25.9': + resolution: {integrity: sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-sticky-regex@7.25.9': + resolution: {integrity: sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-template-literals@7.26.8': + resolution: {integrity: sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typeof-symbol@7.26.7': + resolution: {integrity: sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-typescript@7.26.8': + resolution: {integrity: sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-escapes@7.25.9': + resolution: {integrity: sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-property-regex@7.25.9': + resolution: {integrity: sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-regex@7.25.9': + resolution: {integrity: sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9': + resolution: {integrity: sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + + '@babel/preset-env@7.26.9': + resolution: {integrity: sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-modules@0.1.6-no-external-plugins': + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + + '@babel/preset-react@7.26.3': + resolution: {integrity: sha512-Nl03d6T9ky516DGK2YMxrTqvnpUW63TnJMOMonj+Zae0JiPC5BC9xPMSL6L8fiSpA5vP88qfygavVQvnLp+6Cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/preset-typescript@7.26.0': + resolution: {integrity: sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/runtime@7.26.9': + resolution: {integrity: sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==} + engines: {node: '>=6.9.0'} + + '@babel/template@7.26.9': + resolution: {integrity: sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==} + engines: {node: '>=6.9.0'} + + '@babel/traverse@7.26.9': + resolution: {integrity: sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==} + engines: {node: '>=6.9.0'} + + '@babel/types@7.26.9': + resolution: {integrity: sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==} + engines: {node: '>=6.9.0'} + + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + + '@bcoe/v8-coverage@1.0.2': + resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==} + engines: {node: '>=18'} + + '@chakra-ui/anatomy@2.3.4': + resolution: {integrity: sha512-fFIYN7L276gw0Q7/ikMMlZxP7mvnjRaWJ7f3Jsf9VtDOi6eAYIBRrhQe6+SZ0PGmoOkRaBc7gSE5oeIbgFFyrw==} + + '@chakra-ui/anatomy@2.3.6': + resolution: {integrity: sha512-TjmjyQouIZzha/l8JxdBZN1pKZTj7sLpJ0YkFnQFyqHcbfWggW9jKWzY1E0VBnhtFz/xF3KC6UAVuZVSJx+y0g==} + + '@chakra-ui/hooks@2.4.4': + resolution: {integrity: sha512-+gMwLIkabtddIL/GICU7JmnYtvfONP+fNiTfdYLV9/I1eyCz8igKgLmFJOGM6F+BpUev6hh+/+DX5ezGQ9VTbQ==} + peerDependencies: + react: '>=18' + + '@chakra-ui/icons@2.2.4': + resolution: {integrity: sha512-l5QdBgwrAg3Sc2BRqtNkJpfuLw/pWRDwwT58J6c4PqQT6wzXxyNa8Q0PForu1ltB5qEiFb1kxr/F/HO1EwNa6g==} + peerDependencies: + '@chakra-ui/react': '>=2.0.0' + react: '>=18' + + '@chakra-ui/react@2.10.6': + resolution: {integrity: sha512-9cdzcUR3LV3E2as0QhZhHAH5qjbyspV12kU1E1Ibcv6/uKUi6bIfPfMSC6R/Tw8Beqhn2ClJFPqjtXzL+C0knQ==} + peerDependencies: + '@emotion/react': '>=11' + '@emotion/styled': '>=11' + framer-motion: '>=4.0.0' + react: '>=18' + react-dom: '>=18' + + '@chakra-ui/styled-system@2.12.2': + resolution: {integrity: sha512-BlQ7i3+GYC0S0c72B+paa0sYo+QeNSMfz6fwQRFsc8A5Aax9i9lSdRL+vwJVC+k6r/0HWfRwk016R2RD2ihEwQ==} + + '@chakra-ui/theme-tools@2.2.6': + resolution: {integrity: sha512-3UhKPyzKbV3l/bg1iQN9PBvffYp+EBOoYMUaeTUdieQRPFzo2jbYR0lNCxqv8h5aGM/k54nCHU2M/GStyi9F2A==} + peerDependencies: + '@chakra-ui/styled-system': '>=2.0.0' + + '@chakra-ui/theme-tools@2.2.8': + resolution: {integrity: sha512-X2i2qgkG+k3DQfh/adn3zzM4Ty8QrGobVPjMl9rMrEYq3ac+pur6KVdVHy/SwwoPvB6S4i84uq7y35+KbJan9g==} + peerDependencies: + '@chakra-ui/styled-system': '>=2.0.0' + + '@chakra-ui/theme@3.4.8': + resolution: {integrity: sha512-ZLMP2Gek38ZTIlj+sMZLsd1TW27yVdmUKMfBmjsr1psAeOa5bDBLKDszICjhEqk7gAbiWB7jr1/HzBXid4kduQ==} + peerDependencies: + '@chakra-ui/styled-system': '>=2.8.0' + + '@chakra-ui/utils@2.2.2': + resolution: {integrity: sha512-jUPLT0JzRMWxpdzH6c+t0YMJYrvc5CLericgITV3zDSXblkfx3DsYXqU11DJTSGZI9dUKzM1Wd0Wswn4eJwvFQ==} + peerDependencies: + react: '>=16.8.0' + + '@chakra-ui/utils@2.2.4': + resolution: {integrity: sha512-nRpR9SnX7aLcJx7lKu8kgQWxdJso1oR/78HcBI+mzidvWdTykbTGdm5Q2R7S0PVH1IFBzBTgi6TiAjHvu96auA==} + peerDependencies: + react: '>=16.8.0' + + '@csstools/normalize.css@12.1.1': + resolution: {integrity: sha512-YAYeJ+Xqh7fUou1d1j9XHl44BmsuThiTr4iNrgCQ3J27IbhXsxXDGZ1cXv8Qvs99d4rBbLiSKy3+WZiet32PcQ==} + + '@csstools/postcss-cascade-layers@1.1.1': + resolution: {integrity: sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-color-function@1.1.1': + resolution: {integrity: sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-font-format-keywords@1.0.1': + resolution: {integrity: sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-hwb-function@1.0.2': + resolution: {integrity: sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-ic-unit@1.0.1': + resolution: {integrity: sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-is-pseudo-class@2.0.7': + resolution: {integrity: sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-nested-calc@1.0.0': + resolution: {integrity: sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-normalize-display-values@1.0.1': + resolution: {integrity: sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-oklab-function@1.1.1': + resolution: {integrity: sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-progressive-custom-properties@1.3.0': + resolution: {integrity: sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + '@csstools/postcss-stepped-value-functions@1.0.1': + resolution: {integrity: sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-text-decoration-shorthand@1.0.0': + resolution: {integrity: sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-trigonometric-functions@1.0.2': + resolution: {integrity: sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==} + engines: {node: ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/postcss-unset-value@1.0.2': + resolution: {integrity: sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + '@csstools/selector-specificity@2.2.0': + resolution: {integrity: sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==} + engines: {node: ^14 || ^16 || >=18} + peerDependencies: + postcss-selector-parser: ^6.0.10 + + '@datepicker-react/hooks@2.8.4': + resolution: {integrity: sha512-qaYJKK5sOSdqcL/OnCtyv3/Q6fRRljfeAyl5ISTPgEO0CM5xZzkGmTx40+6wvqjH5lEZH4ysS95nPyLwZS2tlw==} + peerDependencies: + react: '>= 16.8.5' + + '@emotion/babel-plugin@11.13.5': + resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} + + '@emotion/cache@11.14.0': + resolution: {integrity: sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==} + + '@emotion/hash@0.9.2': + resolution: {integrity: sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==} + + '@emotion/is-prop-valid@0.8.8': + resolution: {integrity: sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==} + + '@emotion/is-prop-valid@1.3.1': + resolution: {integrity: sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==} + + '@emotion/memoize@0.7.4': + resolution: {integrity: sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==} + + '@emotion/memoize@0.9.0': + resolution: {integrity: sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==} + + '@emotion/react@11.14.0': + resolution: {integrity: sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==} + peerDependencies: + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@emotion/serialize@1.3.3': + resolution: {integrity: sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==} + + '@emotion/sheet@1.4.0': + resolution: {integrity: sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==} + + '@emotion/styled@11.14.0': + resolution: {integrity: sha512-XxfOnXFffatap2IyCeJyNov3kiDQWoR08gPUQxvbL7fxKryGBKUZUkG6Hz48DZwVrJSVh9sJboyV1Ds4OW6SgA==} + peerDependencies: + '@emotion/react': ^11.0.0-rc.0 + '@types/react': '*' + react: '>=16.8.0' + peerDependenciesMeta: + '@types/react': + optional: true + + '@emotion/unitless@0.10.0': + resolution: {integrity: sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0': + resolution: {integrity: sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==} + peerDependencies: + react: '>=16.8.0' + + '@emotion/utils@1.4.2': + resolution: {integrity: sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==} + + '@emotion/weak-memoize@0.4.0': + resolution: {integrity: sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==} + + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@eslint-community/eslint-utils@4.4.1': + resolution: {integrity: sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + + '@eslint-community/regexpp@4.12.1': + resolution: {integrity: sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + + '@eslint/config-array@0.19.2': + resolution: {integrity: sha512-GNKqxfHG2ySmJOBSHg7LxeUx4xpuCoFjacmlCoYWEbaPXLwvfIjixRI12xCQZeULksQb23uiA8F40w5TojpV7w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/core@0.12.0': + resolution: {integrity: sha512-cmrR6pytBuSMTaBweKoGMwu3EiHiEC+DoyupPmlZ0HxBJBtIxwe+j/E4XPIKNx+Q74c8lXKPwYawBf5glsTkHg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/eslintrc@3.3.0': + resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/js@9.21.0': + resolution: {integrity: sha512-BqStZ3HX8Yz6LvsF5ByXYrtigrV5AXADWLAGc7PH/1SxOb7/FIYYMszZZWiUou/GB9P2lXWk2SV4d+Z8h0nknw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/object-schema@2.1.6': + resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@eslint/plugin-kit@0.2.7': + resolution: {integrity: sha512-JubJ5B2pJ4k4yGxaNLdbjrnk9d/iDz6/q8wOilpIowd6PJPgaxCuHBnBszq7Ce2TyMrywm5r4PnKm6V3iiZF+g==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@fontsource/inter@4.5.15': + resolution: {integrity: sha512-FzleM9AxZQK2nqsTDtBiY0PMEVWvnKnuu2i09+p6DHvrHsuucoV2j0tmw+kAT3L4hvsLdAIDv6MdGehsPIdT+Q==} + + '@hookform/resolvers@2.9.11': + resolution: {integrity: sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ==} + peerDependencies: + react-hook-form: ^7.0.0 + + '@humanfs/core@0.19.1': + resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==} + engines: {node: '>=18.18.0'} + + '@humanfs/node@0.16.6': + resolution: {integrity: sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==} + engines: {node: '>=18.18.0'} + + '@humanwhocodes/module-importer@1.0.1': + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + + '@humanwhocodes/retry@0.3.1': + resolution: {integrity: sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==} + engines: {node: '>=18.18'} + + '@humanwhocodes/retry@0.4.2': + resolution: {integrity: sha512-xeO57FpIu4p1Ri3Jq/EXq4ClRm86dVF2z/+kvFnyqVYRavTZmaFaUBbWCOuuTh0o/g7DSsk6kc2vrS4Vl5oPOQ==} + engines: {node: '>=18.18'} + + '@isaacs/cliui@8.0.2': + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + + '@istanbuljs/load-nyc-config@1.1.0': + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jest/console@27.5.1': + resolution: {integrity: sha512-kZ/tNpS3NXn0mlXXXPNuDZnb4c0oZ20r4K5eemM2k30ZC3G0T02nXUvyhf5YdbXWHPEJLc9qGLxEZ216MdL+Zg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/console@28.1.3': + resolution: {integrity: sha512-QPAkP5EwKdK/bxIr6C1I4Vs0rm2nHiANzj/Z5X2JQkrZo6IqvC4ldZ9K95tF0HdidhA8Bo6egxSzUFPYKcEXLw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/core@27.5.1': + resolution: {integrity: sha512-AK6/UTrvQD0Cd24NSqmIA6rKsu0tKIxfiCducZvqxYdmMisOYAsdItspT+fQDQYARPf8XgjAFZi0ogW2agH5nQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/environment@27.5.1': + resolution: {integrity: sha512-/WQjhPJe3/ghaol/4Bq480JKXV/Rfw8nQdN7f41fM8VDHLcxKXou6QyXAh3EFr9/bVG3x74z1NWDkP87EiY8gA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/fake-timers@27.5.1': + resolution: {integrity: sha512-/aPowoolwa07k7/oM3aASneNeBGCmGQsc3ugN4u6s4C/+s5M64MFo/+djTdiwcbQlRfFElGuDXWzaWj6QgKObQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/globals@27.5.1': + resolution: {integrity: sha512-ZEJNB41OBQQgGzgyInAv0UUfDDj3upmHydjieSxFvTRuZElrx7tXg/uVQ5hYVEwiXs3+aMsAeEc9X7xiSKCm4Q==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/reporters@27.5.1': + resolution: {integrity: sha512-cPXh9hWIlVJMQkVk84aIvXuBB4uQQmFqZiacloFuGiP3ah1sbCxCosidXFDfqG8+6fO1oR2dTJTlsOy4VFmUfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + '@jest/schemas@28.1.3': + resolution: {integrity: sha512-/l/VWsdt/aBXgjshLWOFyFt3IVdYypu5y2Wn2rOO1un6nkqIn8SLXzgIMYXFyYsRWDyF5EthmKJMIdJvk08grg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/source-map@27.5.1': + resolution: {integrity: sha512-y9NIHUYF3PJRlHk98NdC/N1gl88BL08aQQgu4k4ZopQkCw9t9cV8mtl3TV8b/YCB8XaVTFrmUTAJvjsntDireg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-result@27.5.1': + resolution: {integrity: sha512-EW35l2RYFUcUQxFJz5Cv5MTOxlJIQs4I7gxzi2zVU7PJhOwfYq1MdC5nhSmYjX1gmMmLPvB3sIaC+BkcHRBfag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/test-result@28.1.3': + resolution: {integrity: sha512-kZAkxnSE+FqE8YjW8gNuoVkkC9I7S1qmenl8sGcDOLropASP+BkcGKwhXoyqQuGOGeYY0y/ixjrd/iERpEXHNg==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jest/test-sequencer@27.5.1': + resolution: {integrity: sha512-LCheJF7WB2+9JuCS7VB/EmGIdQuhtqjRNI9A43idHv3E4KltCTsPsLxvdaubFHSYwY/fNjMWjl6vNRhDiN7vpQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/transform@27.5.1': + resolution: {integrity: sha512-ipON6WtYgl/1329g5AIJVbUuEh0wZVbdpGwC99Jw4LwuoBNS95MVphU6zOeD9pDkon+LLbFL7lOQRapbB8SCHw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/types@27.5.1': + resolution: {integrity: sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + '@jest/types@28.1.3': + resolution: {integrity: sha512-RyjiyMUZrKz/c+zlMFO1pm70DcIlST8AeWTkoUdZevew44wcNZQHsEVOiCVtgVnlFFD82FPaXycys58cf2muVQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + '@jridgewell/gen-mapping@0.3.8': + resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} + engines: {node: '>=6.0.0'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + + '@jridgewell/set-array@1.2.1': + resolution: {integrity: sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==} + engines: {node: '>=6.0.0'} + + '@jridgewell/source-map@0.3.6': + resolution: {integrity: sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==} + + '@jridgewell/sourcemap-codec@1.5.0': + resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + + '@leichtgewicht/ip-codec@2.0.5': + resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + + '@motionone/animation@10.18.0': + resolution: {integrity: sha512-9z2p5GFGCm0gBsZbi8rVMOAJCtw1WqBTIPw3ozk06gDvZInBPIsQcHgYogEJ4yuHJ+akuW8g1SEIOpTOvYs8hw==} + + '@motionone/dom@10.18.0': + resolution: {integrity: sha512-bKLP7E0eyO4B2UaHBBN55tnppwRnaE3KFfh3Ps9HhnAkar3Cb69kUCJY9as8LrccVYKgHA+JY5dOQqJLOPhF5A==} + + '@motionone/easing@10.18.0': + resolution: {integrity: sha512-VcjByo7XpdLS4o9T8t99JtgxkdMcNWD3yHU/n6CLEz3bkmKDRZyYQ/wmSf6daum8ZXqfUAgFeCZSpJZIMxaCzg==} + + '@motionone/generators@10.18.0': + resolution: {integrity: sha512-+qfkC2DtkDj4tHPu+AFKVfR/C30O1vYdvsGYaR13W/1cczPrrcjdvYCj0VLFuRMN+lP1xvpNZHCRNM4fBzn1jg==} + + '@motionone/types@10.17.1': + resolution: {integrity: sha512-KaC4kgiODDz8hswCrS0btrVrzyU2CSQKO7Ps90ibBVSQmjkrt2teqta6/sOG59v7+dPnKMAg13jyqtMKV2yJ7A==} + + '@motionone/utils@10.18.0': + resolution: {integrity: sha512-3XVF7sgyTSI2KWvTf6uLlBJ5iAgRgmvp3bpuOiQJvInd4nZ19ET8lX5unn30SlmRH7hXbBbH+Gxd0m0klJ3Xtw==} + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + resolution: {integrity: sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==} + + '@nodelib/fs.scandir@2.1.5': + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + + '@nodelib/fs.stat@2.0.5': + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + + '@nodelib/fs.walk@1.2.8': + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + + '@pkgjs/parseargs@0.11.0': + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + + '@pmmmwh/react-refresh-webpack-plugin@0.5.15': + resolution: {integrity: sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==} + engines: {node: '>= 10.13'} + peerDependencies: + '@types/webpack': 4.x || 5.x + react-refresh: '>=0.10.0 <1.0.0' + sockjs-client: ^1.4.0 + type-fest: '>=0.17.0 <5.0.0' + webpack: '>=4.43.0 <6.0.0' + webpack-dev-server: 3.x || 4.x || 5.x + webpack-hot-middleware: 2.x + webpack-plugin-serve: 0.x || 1.x + peerDependenciesMeta: + '@types/webpack': + optional: true + sockjs-client: + optional: true + type-fest: + optional: true + webpack-dev-server: + optional: true + webpack-hot-middleware: + optional: true + webpack-plugin-serve: + optional: true + + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@react-hook/debounce@3.0.0': + resolution: {integrity: sha512-ir/kPrSfAzY12Gre0sOHkZ2rkEmM4fS5M5zFxCi4BnCeXh2nvx9Ujd+U4IGpKCuPA+EQD0pg1eK2NGLvfWejag==} + peerDependencies: + react: '>=16.8' + + '@react-hook/event@1.2.6': + resolution: {integrity: sha512-JUL5IluaOdn5w5Afpe/puPa1rj8X6udMlQ9dt4hvMuKmTrBS1Ya6sb4sVgvfe2eU4yDuOfAhik8xhbcCekbg9Q==} + peerDependencies: + react: '>=16.8' + + '@react-hook/latest@1.0.3': + resolution: {integrity: sha512-dy6duzl+JnAZcDbNTfmaP3xHiKtbXYOaz3G51MGVljh548Y8MWzTr+PHLOfvpypEVW9zwvl+VyKjbWKEVbV1Rg==} + peerDependencies: + react: '>=16.8' + + '@react-hook/throttle@2.2.0': + resolution: {integrity: sha512-LJ5eg+yMV8lXtqK3lR+OtOZ2WH/EfWvuiEEu0M3bhR7dZRfTyEJKxH1oK9uyBxiXPtWXiQggWbZirMCXam51tg==} + peerDependencies: + react: '>=16.8' + + '@react-hook/window-size@3.1.1': + resolution: {integrity: sha512-yWnVS5LKnOUIrEsI44oz3bIIUYqflamPL27n+k/PC//PsX/YeWBky09oPeAoc9As6jSH16Wgo8plI+ECZaHk3g==} + peerDependencies: + react: '>=16.8' + + '@remix-run/router@1.0.3': + resolution: {integrity: sha512-ceuyTSs7PZ/tQqi19YZNBc5X7kj1f8p+4DIyrcIYFY9h+hd1OKm4RqtiWldR9eGEvIiJfsqwM4BsuCtRIuEw6Q==} + engines: {node: '>=14'} + + '@rollup/plugin-babel@5.3.1': + resolution: {integrity: sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==} + engines: {node: '>= 10.0.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@types/babel__core': ^7.1.9 + rollup: ^1.20.0||^2.0.0 + peerDependenciesMeta: + '@types/babel__core': + optional: true + + '@rollup/plugin-node-resolve@11.2.1': + resolution: {integrity: sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg==} + engines: {node: '>= 10.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/plugin-replace@2.4.2': + resolution: {integrity: sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==} + peerDependencies: + rollup: ^1.20.0 || ^2.0.0 + + '@rollup/pluginutils@3.1.0': + resolution: {integrity: sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==} + engines: {node: '>= 8.0.0'} + peerDependencies: + rollup: ^1.20.0||^2.0.0 + + '@rollup/rollup-android-arm-eabi@4.34.9': + resolution: {integrity: sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.34.9': + resolution: {integrity: sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.34.9': + resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.34.9': + resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.34.9': + resolution: {integrity: sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.9': + resolution: {integrity: sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + resolution: {integrity: sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.34.9': + resolution: {integrity: sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.34.9': + resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.34.9': + resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + resolution: {integrity: sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + resolution: {integrity: sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.34.9': + resolution: {integrity: sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.34.9': + resolution: {integrity: sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.34.9': + resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.34.9': + resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.34.9': + resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.34.9': + resolution: {integrity: sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.34.9': + resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==} + cpu: [x64] + os: [win32] + + '@rtsao/scc@1.1.0': + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + + '@rushstack/eslint-patch@1.10.5': + resolution: {integrity: sha512-kkKUDVlII2DQiKy7UstOR1ErJP8kUKAQ4oa+SQtM0K+lPdmmjj0YnnxBgtTVYH7mUKtbsxeFC9y0AmK7Yb78/A==} + + '@sinclair/typebox@0.24.51': + resolution: {integrity: sha512-1P1OROm/rdubP5aFDSZQILU0vrLCJ4fvHt6EoqHEM+2D/G5MK3bIaymUKLit8Js9gbns5UyJnkP/TZROLw4tUA==} + + '@sinonjs/commons@1.8.6': + resolution: {integrity: sha512-Ky+XkAkqPZSm3NLBeUng77EBQl3cmeJhITaGHdYH8kjVB+aun3S4XBRti2zt17mtt0mIUDiNxYeoJm6drVvBJQ==} + + '@sinonjs/fake-timers@8.1.0': + resolution: {integrity: sha512-OAPJUAtgeINhh/TAlUID4QTs53Njm7xzddaVlEs/SXwgtiD1tW22zAB/W1wdqfrpmikgaWQ9Fw6Ws+hsiRm5Vg==} + + '@surma/rollup-plugin-off-main-thread@2.2.3': + resolution: {integrity: sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==} + + '@svgr/babel-plugin-add-jsx-attribute@5.4.0': + resolution: {integrity: sha512-ZFf2gs/8/6B8PnSofI0inYXr2SDNTDScPXhN7k5EqD4aZ3gi6u+rbmZHVB8IM3wDyx8ntKACZbtXSm7oZGRqVg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-remove-jsx-attribute@5.4.0': + resolution: {integrity: sha512-yaS4o2PgUtwLFGTKbsiAy6D0o3ugcUhWK0Z45umJ66EPWunAz9fuFw2gJuje6wqQvQWOTJvIahUwndOXb7QCPg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-remove-jsx-empty-expression@5.0.1': + resolution: {integrity: sha512-LA72+88A11ND/yFIMzyuLRSMJ+tRKeYKeQ+mR3DcAZ5I4h5CPWN9AHyUzJbWSYp/u2u0xhmgOe0+E41+GjEueA==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-replace-jsx-attribute-value@5.0.1': + resolution: {integrity: sha512-PoiE6ZD2Eiy5mK+fjHqwGOS+IXX0wq/YDtNyIgOrc6ejFnxN4b13pRpiIPbtPwHEc+NT2KCjteAcq33/F1Y9KQ==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-svg-dynamic-title@5.4.0': + resolution: {integrity: sha512-zSOZH8PdZOpuG1ZVx/cLVePB2ibo3WPpqo7gFIjLV9a0QsuQAzJiwwqmuEdTaW2pegyBE17Uu15mOgOcgabQZg==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-svg-em-dimensions@5.4.0': + resolution: {integrity: sha512-cPzDbDA5oT/sPXDCUYoVXEmm3VIoAWAPT6mSPTJNbQaBNUuEKVKyGH93oDY4e42PYHRW67N5alJx/eEol20abw==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-transform-react-native-svg@5.4.0': + resolution: {integrity: sha512-3eYP/SaopZ41GHwXma7Rmxcv9uRslRDTY1estspeB1w1ueZWd/tPlMfEOoccYpEMZU3jD4OU7YitnXcF5hLW2Q==} + engines: {node: '>=10'} + + '@svgr/babel-plugin-transform-svg-component@5.5.0': + resolution: {integrity: sha512-q4jSH1UUvbrsOtlo/tKcgSeiCHRSBdXoIoqX1pgcKK/aU3JD27wmMKwGtpB8qRYUYoyXvfGxUVKchLuR5pB3rQ==} + engines: {node: '>=10'} + + '@svgr/babel-preset@5.5.0': + resolution: {integrity: sha512-4FiXBjvQ+z2j7yASeGPEi8VD/5rrGQk4Xrq3EdJmoZgz/tpqChpo5hgXDvmEauwtvOc52q8ghhZK4Oy7qph4ig==} + engines: {node: '>=10'} + + '@svgr/core@5.5.0': + resolution: {integrity: sha512-q52VOcsJPvV3jO1wkPtzTuKlvX7Y3xIcWRpCMtBF3MrteZJtBfQw/+u0B1BHy5ColpQc1/YVTrPEtSYIMNZlrQ==} + engines: {node: '>=10'} + + '@svgr/hast-util-to-babel-ast@5.5.0': + resolution: {integrity: sha512-cAaR/CAiZRB8GP32N+1jocovUtvlj0+e65TB50/6Lcime+EA49m/8l+P2ko+XPJ4dw3xaPS3jOL4F2X4KWxoeQ==} + engines: {node: '>=10'} + + '@svgr/plugin-jsx@5.5.0': + resolution: {integrity: sha512-V/wVh33j12hGh05IDg8GpIUXbjAPnTdPTKuP4VNLggnwaHMPNQNae2pRnyTAILWCQdz5GyMqtO488g7CKM8CBA==} + engines: {node: '>=10'} + + '@svgr/plugin-svgo@5.5.0': + resolution: {integrity: sha512-r5swKk46GuQl4RrVejVwpeeJaydoxkdwkM1mBKOgJLBUJPGaLci6ylg/IjhrRsREKDkr4kbMWdgOtbXEh0fyLQ==} + engines: {node: '>=10'} + + '@svgr/webpack@5.5.0': + resolution: {integrity: sha512-DOBOK255wfQxguUta2INKkzPj6AIS6iafZYiYmHn6W3pHlycSRRlvWKCfLDG10fXfLWqE3DJHgRUOyJYmARa7g==} + engines: {node: '>=10'} + + '@tanstack/react-table@8.21.2': + resolution: {integrity: sha512-11tNlEDTdIhMJba2RBH+ecJ9l1zgS2kjmexDPAraulc8jeNA4xocSNeyzextT0XJyASil4XsCYlJmf5jEWAtYg==} + engines: {node: '>=12'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + '@tanstack/table-core@8.21.2': + resolution: {integrity: sha512-uvXk/U4cBiFMxt+p9/G7yUWI/UbHYbyghLCjlpWZ3mLeIZiUBSKcUnw9UnKkdRz7Z/N4UBuFLWQdJCjUe7HjvA==} + engines: {node: '>=12'} + + '@testing-library/dom@10.4.0': + resolution: {integrity: sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.6.3': + resolution: {integrity: sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.2.0': + resolution: {integrity: sha512-2cSskAvA1QNtKc8Y9VJQRv0tm3hLVgxRGDB+KYhIaPQJ1I+RHbhIXcM+zClKXzMes/wshsMVzf4B9vS4IZpqDQ==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@tootallnate/once@1.1.2': + resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} + engines: {node: '>= 6'} + + '@trysound/sax@0.2.0': + resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} + engines: {node: '>=10.13.0'} + + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/bonjour@3.5.13': + resolution: {integrity: sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==} + + '@types/connect-history-api-fallback@1.5.4': + resolution: {integrity: sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/d3-array@3.2.1': + resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} + + '@types/d3-color@3.1.3': + resolution: {integrity: sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==} + + '@types/d3-ease@3.0.2': + resolution: {integrity: sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==} + + '@types/d3-interpolate@3.0.4': + resolution: {integrity: sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==} + + '@types/d3-path@3.1.1': + resolution: {integrity: sha512-VMZBYyQvbGmWyWVea0EHs/BwLgxc+MKi1zLDCONksozI4YJMcTt8ZEuIR4Sb1MMTE8MMW49v0IwI5+b7RmfWlg==} + + '@types/d3-scale@4.0.9': + resolution: {integrity: sha512-dLmtwB8zkAeO/juAMfnV+sItKjlsw2lKdZVVy6LRr0cBmegxSABiLEpGVmSJJ8O08i4+sGR6qQtb6WtuwJdvVw==} + + '@types/d3-shape@3.1.7': + resolution: {integrity: sha512-VLvUQ33C+3J+8p+Daf+nYSOsjB4GXp19/S/aGo60m9h1v6XaxjiT82lKVWJCfzhtuZ3yD7i/TPeC/fuKLLOSmg==} + + '@types/d3-time@3.0.4': + resolution: {integrity: sha512-yuzZug1nkAAaBlBBikKZTgzCeA+k1uy4ZFwWANOfKw5z5LRhV0gNA7gNkKm7HoK+HRN0wX3EkxGk0fpbWhmB7g==} + + '@types/d3-timer@3.0.2': + resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + + '@types/eslint-scope@3.7.7': + resolution: {integrity: sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==} + + '@types/eslint@8.56.12': + resolution: {integrity: sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==} + + '@types/eslint@9.6.1': + resolution: {integrity: sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==} + + '@types/estree@0.0.39': + resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + + '@types/express-serve-static-core@5.0.6': + resolution: {integrity: sha512-3xhRnjJPkULekpSzgtoNYYcTWgEZkp4myc+Saevii5JPnHNvHMRlBSHDbs7Bh1iPPoVTERHEZXyhyLbMEsExsA==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/graceful-fs@4.1.9': + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + + '@types/html-minifier-terser@6.1.0': + resolution: {integrity: sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + '@types/http-proxy@1.17.16': + resolution: {integrity: sha512-sdWoUajOB1cd0A8cRRQ1cfyWNbmFKLAqBB89Y8x5iYyG/mkJHc0YUH8pdWBy2omi9qtCpiIgGjuwO0dQST2l5w==} + + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/istanbul-lib-report@3.0.3': + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + + '@types/istanbul-reports@3.0.4': + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + + '@types/json-schema@7.0.15': + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + + '@types/json5@0.0.29': + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + + '@types/lodash.mergewith@4.6.9': + resolution: {integrity: sha512-fgkoCAOF47K7sxrQ7Mlud2TH023itugZs2bUg8h/KzT+BnZNrR2jAOmaokbLunHNnobXVWOezAeNn/lZqwxkcw==} + + '@types/lodash@4.17.16': + resolution: {integrity: sha512-HX7Em5NYQAXKW+1T+FiuG27NGwzJfCX3s1GjOa7ujxZa52kjJLOr4FUxT+giF6Tgxv1e+/czV/iTtBw27WTU9g==} + + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + + '@types/match-sorter@6.0.0': + resolution: {integrity: sha512-/B8BLck7dy+vQQedYvrTw2f+U02KghNCMLocjRSWtHhCKE1OeoAmOWiLGAPs96qacT9bSJF4HmJNyijiy5bycA==} + deprecated: This is a stub types definition. match-sorter provides its own type definitions, so you do not need this installed. + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + '@types/node-forge@1.3.11': + resolution: {integrity: sha512-FQx220y22OKNTqaByeBGqHWYz4cl94tpcxeFdvBo3wjG6XPBuZ0BNgNZRV5J5TFmmcsJ4IzsLkmGRiQbnYsBEQ==} + + '@types/node@22.13.9': + resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} + + '@types/parse-json@4.0.2': + resolution: {integrity: sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==} + + '@types/prettier@2.7.3': + resolution: {integrity: sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==} + + '@types/q@1.5.8': + resolution: {integrity: sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw==} + + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + '@types/react-dom@19.0.4': + resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==} + peerDependencies: + '@types/react': ^19.0.0 + + '@types/react@19.0.10': + resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==} + + '@types/resolve@1.17.1': + resolution: {integrity: sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==} + + '@types/retry@0.12.0': + resolution: {integrity: sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-index@1.9.4': + resolution: {integrity: sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + + '@types/sockjs@0.3.36': + resolution: {integrity: sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==} + + '@types/stack-utils@2.0.3': + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + + '@types/trusted-types@2.0.7': + resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} + + '@types/ws@8.18.0': + resolution: {integrity: sha512-8svvI3hMyvN0kKCJMvTJP/x6Y/EoQbepff882wL+Sn5QsXb3etnamgrJq4isrBxSJj5L2AuXcI0+bgkoAXGUJw==} + + '@types/yargs-parser@21.0.3': + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + + '@types/yargs@16.0.9': + resolution: {integrity: sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==} + + '@types/yargs@17.0.33': + resolution: {integrity: sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==} + + '@typescript-eslint/eslint-plugin@5.62.0': + resolution: {integrity: sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/parser': ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/eslint-plugin@8.26.0': + resolution: {integrity: sha512-cLr1J6pe56zjKYajK6SSSre6nl1Gj6xDp1TY0trpgPzjVbgDwd09v2Ws37LABxzkicmUjhEeg/fAUjPJJB1v5Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/experimental-utils@5.62.0': + resolution: {integrity: sha512-RTXpeB3eMkpoclG3ZHft6vG/Z30azNHuqY6wKPBHlVMZFuEvrtlEDe8gMqDb+SO+9hjC/pLekeSCryf9vMZlCw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@typescript-eslint/parser@5.62.0': + resolution: {integrity: sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/parser@8.26.0': + resolution: {integrity: sha512-mNtXP9LTVBy14ZF3o7JG69gRPBK/2QWtQd0j0oH26HcY/foyJJau6pNUez7QrM5UHnSvwlQcJXKsk0I99B9pOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/scope-manager@5.62.0': + resolution: {integrity: sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/scope-manager@8.26.0': + resolution: {integrity: sha512-E0ntLvsfPqnPwng8b8y4OGuzh/iIOm2z8U3S9zic2TeMLW61u5IH2Q1wu0oSTkfrSzwbDJIB/Lm8O3//8BWMPA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/type-utils@5.62.0': + resolution: {integrity: sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: '*' + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/type-utils@8.26.0': + resolution: {integrity: sha512-ruk0RNChLKz3zKGn2LwXuVoeBcUMh+jaqzN461uMMdxy5H9epZqIBtYj7UiPXRuOpaALXGbmRuZQhmwHhaS04Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/types@5.62.0': + resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/types@8.26.0': + resolution: {integrity: sha512-89B1eP3tnpr9A8L6PZlSjBvnJhWXtYfZhECqlBl1D9Lme9mHO6iWlsprBtVenQvY1HMhax1mWOjhtL3fh/u+pA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@typescript-eslint/typescript-estree@5.62.0': + resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/typescript-estree@8.26.0': + resolution: {integrity: sha512-tiJ1Hvy/V/oMVRTbEOIeemA2XoylimlDQ03CgPPNaHYZbpsc78Hmngnt+WXZfJX1pjQ711V7g0H7cSJThGYfPQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/utils@5.62.0': + resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + + '@typescript-eslint/utils@8.26.0': + resolution: {integrity: sha512-2L2tU3FVwhvU14LndnQCA2frYC8JnPDVKyQtWFPf8IYFMt/ykEN1bPolNhNbCVgOmdzTlWdusCTKA/9nKrf8Ig==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + '@typescript-eslint/visitor-keys@5.62.0': + resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + '@typescript-eslint/visitor-keys@8.26.0': + resolution: {integrity: sha512-2z8JQJWAzPdDd51dRQ/oqIJxe99/hoLIqmf8RMCAJQtYDc535W/Jt2+RTP4bP0aKeBG1F65yjIZuczOXCmbWwg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + '@uidotdev/usehooks@2.4.1': + resolution: {integrity: sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==} + engines: {node: '>=16'} + peerDependencies: + react: '>=18.0.0' + react-dom: '>=18.0.0' + + '@vitejs/plugin-react@4.3.4': + resolution: {integrity: sha512-SCCPBJtYLdE8PX/7ZQAs1QAZ8Jqwih+0VBLum1EGqmCCQal+MIUqLCzj3ZUy8ufbC0cAM4LRlSTm7IQJwWT4ug==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 || ^6.0.0 + + '@vitest/coverage-v8@3.0.8': + resolution: {integrity: sha512-y7SAKsQirsEJ2F8bulBck4DoluhI2EEgTimHd6EEUgJBGKy9tC25cpywh1MH4FvDGoG2Unt7+asVd1kj4qOSAw==} + peerDependencies: + '@vitest/browser': 3.0.8 + vitest: 3.0.8 + peerDependenciesMeta: + '@vitest/browser': + optional: true + + '@vitest/expect@3.0.8': + resolution: {integrity: sha512-Xu6TTIavTvSSS6LZaA3EebWFr6tsoXPetOWNMOlc7LO88QVVBwq2oQWBoDiLCN6YTvNYsGSjqOO8CAdjom5DCQ==} + + '@vitest/mocker@3.0.8': + resolution: {integrity: sha512-n3LjS7fcW1BCoF+zWZxG7/5XvuYH+lsFg+BDwwAz0arIwHQJFUEsKBQ0BLU49fCxuM/2HSeBPHQD8WjgrxMfow==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.0.8': + resolution: {integrity: sha512-BNqwbEyitFhzYMYHUVbIvepOyeQOSFA/NeJMIP9enMntkkxLgOcgABH6fjyXG85ipTgvero6noreavGIqfJcIg==} + + '@vitest/runner@3.0.8': + resolution: {integrity: sha512-c7UUw6gEcOzI8fih+uaAXS5DwjlBaCJUo7KJ4VvJcjL95+DSR1kova2hFuRt3w41KZEFcOEiq098KkyrjXeM5w==} + + '@vitest/snapshot@3.0.8': + resolution: {integrity: sha512-x8IlMGSEMugakInj44nUrLSILh/zy1f2/BgH0UeHpNyOocG18M9CWVIFBaXPt8TrqVZWmcPjwfG/ht5tnpba8A==} + + '@vitest/spy@3.0.8': + resolution: {integrity: sha512-MR+PzJa+22vFKYb934CejhR4BeRpMSoxkvNoDit68GQxRLSf11aT6CTj3XaqUU9rxgWJFnqicN/wxw6yBRkI1Q==} + + '@vitest/utils@3.0.8': + resolution: {integrity: sha512-nkBC3aEhfX2PdtQI/QwAWp8qZWwzASsU4Npbcd5RdMPBSSLCpkZp52P3xku3s3uA0HIEhGvEcF8rNkBsz9dQ4Q==} + + '@webassemblyjs/ast@1.14.1': + resolution: {integrity: sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==} + + '@webassemblyjs/floating-point-hex-parser@1.13.2': + resolution: {integrity: sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==} + + '@webassemblyjs/helper-api-error@1.13.2': + resolution: {integrity: sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==} + + '@webassemblyjs/helper-buffer@1.14.1': + resolution: {integrity: sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==} + + '@webassemblyjs/helper-numbers@1.13.2': + resolution: {integrity: sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==} + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': + resolution: {integrity: sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==} + + '@webassemblyjs/helper-wasm-section@1.14.1': + resolution: {integrity: sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==} + + '@webassemblyjs/ieee754@1.13.2': + resolution: {integrity: sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==} + + '@webassemblyjs/leb128@1.13.2': + resolution: {integrity: sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==} + + '@webassemblyjs/utf8@1.13.2': + resolution: {integrity: sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==} + + '@webassemblyjs/wasm-edit@1.14.1': + resolution: {integrity: sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==} + + '@webassemblyjs/wasm-gen@1.14.1': + resolution: {integrity: sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==} + + '@webassemblyjs/wasm-opt@1.14.1': + resolution: {integrity: sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==} + + '@webassemblyjs/wasm-parser@1.14.1': + resolution: {integrity: sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==} + + '@webassemblyjs/wast-printer@1.14.1': + resolution: {integrity: sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==} + + '@xtuc/ieee754@1.2.0': + resolution: {integrity: sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==} + + '@xtuc/long@4.2.2': + resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} + + '@zag-js/dom-query@0.31.1': + resolution: {integrity: sha512-oiuohEXAXhBxpzzNm9k2VHGEOLC1SXlXSbRPcfBZ9so5NRQUA++zCE7cyQJqGLTZR0t3itFLlZqDbYEXRrefwg==} + + '@zag-js/element-size@0.31.1': + resolution: {integrity: sha512-4T3yvn5NqqAjhlP326Fv+w9RqMIBbNN9H72g5q2ohwzhSgSfZzrKtjL4rs9axY/cw9UfMfXjRjEE98e5CMq7WQ==} + + '@zag-js/focus-visible@0.31.1': + resolution: {integrity: sha512-dbLksz7FEwyFoANbpIlNnd3bVm0clQSUsnP8yUVQucStZPsuWjCrhL2jlAbGNrTrahX96ntUMXHb/sM68TibFg==} + + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + + acorn-globals@6.0.0: + resolution: {integrity: sha512-ZQl7LOWaF5ePqqcX4hLuv/bLXYQNfNWw2c0/yX/TsPRKamzHcTGQnlCjHT3TsmkOUVEPS3crCxiPfdzE/Trlhg==} + + acorn-jsx@5.3.2: + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + + acorn-walk@7.2.0: + resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} + engines: {node: '>=0.4.0'} + + acorn@7.4.1: + resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} + engines: {node: '>=0.4.0'} + hasBin: true + + acorn@8.14.1: + resolution: {integrity: sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==} + engines: {node: '>=0.4.0'} + hasBin: true + + address@1.2.2: + resolution: {integrity: sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==} + engines: {node: '>= 10.0.0'} + + adjust-sourcemap-loader@4.0.0: + resolution: {integrity: sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==} + engines: {node: '>=8.9'} + + agent-base@6.0.2: + resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} + engines: {node: '>= 6.0.0'} + + ajv-formats@2.1.1: + resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} + peerDependencies: + ajv: ^8.0.0 + peerDependenciesMeta: + ajv: + optional: true + + ajv-keywords@3.5.2: + resolution: {integrity: sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==} + peerDependencies: + ajv: ^6.9.1 + + ajv-keywords@5.1.0: + resolution: {integrity: sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==} + peerDependencies: + ajv: ^8.8.2 + + ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + + ajv@8.17.1: + resolution: {integrity: sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==} + + ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + + ansi-html-community@0.0.8: + resolution: {integrity: sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-html@0.0.9: + resolution: {integrity: sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==} + engines: {'0': node >= 0.8.0} + hasBin: true + + ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + + ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + + ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + + ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + + ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + + any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + + arg@5.0.2: + resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + + argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + + aria-hidden@1.2.4: + resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} + engines: {node: '>=10'} + + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + + array-buffer-byte-length@1.0.2: + resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} + engines: {node: '>= 0.4'} + + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + + array-includes@3.1.8: + resolution: {integrity: sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==} + engines: {node: '>= 0.4'} + + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + + array.prototype.findlast@1.2.5: + resolution: {integrity: sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==} + engines: {node: '>= 0.4'} + + array.prototype.findlastindex@1.2.5: + resolution: {integrity: sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==} + engines: {node: '>= 0.4'} + + array.prototype.flat@1.3.3: + resolution: {integrity: sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==} + engines: {node: '>= 0.4'} + + array.prototype.flatmap@1.3.3: + resolution: {integrity: sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==} + engines: {node: '>= 0.4'} + + array.prototype.reduce@1.0.7: + resolution: {integrity: sha512-mzmiUCVwtiD4lgxYP8g7IYy8El8p2CSMePvIbTS7gchKir/L1fgJrk0yDKmAX6mnRQFKNADYIk8nNlTris5H1Q==} + engines: {node: '>= 0.4'} + + array.prototype.tosorted@1.1.4: + resolution: {integrity: sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==} + engines: {node: '>= 0.4'} + + arraybuffer.prototype.slice@1.0.4: + resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} + engines: {node: '>= 0.4'} + + asap@2.0.6: + resolution: {integrity: sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==} + + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + + ast-types-flow@0.0.8: + resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + + async-function@1.0.0: + resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} + engines: {node: '>= 0.4'} + + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + + at-least-node@1.0.0: + resolution: {integrity: sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==} + engines: {node: '>= 4.0.0'} + + autoprefixer@10.4.20: + resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} + engines: {node: ^10 || ^12 || >=14} + hasBin: true + peerDependencies: + postcss: ^8.1.0 + + available-typed-arrays@1.0.7: + resolution: {integrity: sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==} + engines: {node: '>= 0.4'} + + axe-core@4.10.3: + resolution: {integrity: sha512-Xm7bpRXnDSX2YE2YFfBk2FnF0ep6tmG7xPh8iHee8MIcrgq762Nkce856dYtJYLkuIoYZvGfTs/PbZhideTcEg==} + engines: {node: '>=4'} + + axobject-query@4.1.0: + resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} + engines: {node: '>= 0.4'} + + babel-jest@27.5.1: + resolution: {integrity: sha512-cdQ5dXjGRd0IBRATiQ4mZGlGlRE8kJpjPOixdNRdT+m3UcNqmYWN6rK6nvtXYfY3D76cb8s/O1Ss8ea24PIwcg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + + babel-loader@8.4.1: + resolution: {integrity: sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==} + engines: {node: '>= 8.9'} + peerDependencies: + '@babel/core': ^7.0.0 + webpack: '>=2' + + babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + + babel-plugin-jest-hoist@27.5.1: + resolution: {integrity: sha512-50wCwD5EMNW4aRpOwtqzyZHIewTYNxLA4nhB+09d8BIssfNfzBRhkBIHiaPv1Si226TQSvp8gxAJm2iY2qs2hQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + babel-plugin-macros@3.1.0: + resolution: {integrity: sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==} + engines: {node: '>=10', npm: '>=6'} + + babel-plugin-named-asset-import@0.3.8: + resolution: {integrity: sha512-WXiAc++qo7XcJ1ZnTYGtLxmBCVbddAml3CEXgWaBzNzLNoxtQ8AiGEFDMOhot9XjTCQbvP5E77Fj9Gk924f00Q==} + peerDependencies: + '@babel/core': ^7.1.0 + + babel-plugin-polyfill-corejs2@0.4.12: + resolution: {integrity: sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.10.6: + resolution: {integrity: sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-corejs3@0.11.1: + resolution: {integrity: sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-polyfill-regenerator@0.6.3: + resolution: {integrity: sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + + babel-plugin-react-compiler@19.0.0-beta-27714ef-20250124: + resolution: {integrity: sha512-1AnF/dlvbIJzAjw5jEbDx7csHx772VP9AtrEg2CgUUD6MIu24j5ShxmBZ0tpfdb2pZtLVwcsoGylfZTzUoCr9w==} + + babel-plugin-transform-react-remove-prop-types@0.4.24: + resolution: {integrity: sha512-eqj0hVcJUR57/Ug2zE1Yswsw4LhuqqHhD+8v120T1cl3kjg76QwtyBrdIk4WVwK+lAhBJVYCd/v+4nc4y+8JsA==} + + babel-preset-current-node-syntax@1.1.0: + resolution: {integrity: sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-jest@27.5.1: + resolution: {integrity: sha512-Nptf2FzlPCWYuJg41HBqXVT8ym6bXOevuCTbhxlUpjwtysGaIWFvDEjp4y+G7fl13FgOdjs7P/DmErqH7da0Ag==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + + babel-preset-react-app@10.1.0: + resolution: {integrity: sha512-f9B1xMdnkCIqe+2dHrJsoQFRz7reChaAHE/65SdaykPklQqhme2WaC08oD3is77x9ff98/9EazAKFDZv5rFEQg==} + + balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + batch@0.6.1: + resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} + + bfj@7.1.0: + resolution: {integrity: sha512-I6MMLkn+anzNdCUp9hMRyui1HaNEUCco50lxbvNS4+EyXg8lN3nJ48PjPWtbH8UVS9CuMoaKE9U2V3l29DaRQw==} + engines: {node: '>= 8.0.0'} + + big.js@5.2.2: + resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==} + + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + + bluebird@3.7.2: + resolution: {integrity: sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bonjour-service@1.3.0: + resolution: {integrity: sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==} + + boolbase@1.0.0: + resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + + brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + + brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-process-hrtime@1.0.0: + resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} + + browserslist@4.24.4: + resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + + bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + + buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + + builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bind@1.0.8: + resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + + callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + + camel-case@4.1.2: + resolution: {integrity: sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==} + + camelcase-css@2.0.1: + resolution: {integrity: sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==} + engines: {node: '>= 6'} + + camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + caniuse-api@3.0.0: + resolution: {integrity: sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==} + + caniuse-lite@1.0.30001702: + resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==} + + case-sensitive-paths-webpack-plugin@2.4.0: + resolution: {integrity: sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==} + engines: {node: '>=4'} + + chai@5.2.0: + resolution: {integrity: sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==} + engines: {node: '>=12'} + + chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + + char-regex@2.0.2: + resolution: {integrity: sha512-cbGOjAptfM2LVmWhwRFHEKTPkLwNddVmuqYZQt895yXwAsWsXObCG+YN4DGQ/JBtT4GP1a1lPPdio2z413LmTg==} + engines: {node: '>=12.20'} + + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + + check-types@11.2.3: + resolution: {integrity: sha512-+67P1GkJRaxQD6PKK0Et9DhwQB+vGg3PM5+aavopCpZT1lj9jeqfvpgTLAWErNj8qApkkmXlu/Ug74kmhagkXg==} + + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + + chrome-trace-event@1.0.4: + resolution: {integrity: sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==} + engines: {node: '>=6.0'} + + ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + + cjs-module-lexer@1.4.3: + resolution: {integrity: sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==} + + clean-css@5.3.3: + resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} + engines: {node: '>= 10.0'} + + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + + coa@2.0.2: + resolution: {integrity: sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==} + engines: {node: '>= 4.0'} + + collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + + color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + + color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + + color2k@2.0.3: + resolution: {integrity: sha512-zW190nQTIoXcGCaU08DvVNFTmQhUpnJfVuAKfWqUQkflXKpaDdpaYoM0iluLS9lgJNHyBF58KKA2FBEwkD7wog==} + + colord@2.9.3: + resolution: {integrity: sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==} + + colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + + commander@4.1.1: + resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} + engines: {node: '>= 6'} + + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + + commander@8.3.0: + resolution: {integrity: sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==} + engines: {node: '>= 12'} + + common-tags@1.8.2: + resolution: {integrity: sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==} + engines: {node: '>=4.0.0'} + + commondir@1.0.1: + resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} + + compressible@2.0.18: + resolution: {integrity: sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==} + engines: {node: '>= 0.6'} + + compression@1.8.0: + resolution: {integrity: sha512-k6WLKfunuqCYD3t6AsuPGvQWaKwuLLh2/xHNcX4qE+vIfDNXpSqnrhwA7O53R7WVQUnt8dVAIW+YHr7xTgOgGA==} + engines: {node: '>= 0.8.0'} + + concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + confusing-browser-globals@1.0.11: + resolution: {integrity: sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==} + + connect-history-api-fallback@2.0.0: + resolution: {integrity: sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==} + engines: {node: '>=0.8'} + + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + convert-source-map@1.9.0: + resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} + + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + copy-to-clipboard@3.3.3: + resolution: {integrity: sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==} + + core-js-compat@3.41.0: + resolution: {integrity: sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==} + + core-js-pure@3.41.0: + resolution: {integrity: sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==} + + core-js@3.41.0: + resolution: {integrity: sha512-SJ4/EHwS36QMJd6h/Rg+GyR4A5xE0FSI3eZ+iBVpfqf1x0eTSg1smWLHrA+2jQThZSh97fmSgFSU8B61nxosxA==} + + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cosmiconfig@6.0.0: + resolution: {integrity: sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==} + engines: {node: '>=8'} + + cosmiconfig@7.1.0: + resolution: {integrity: sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==} + engines: {node: '>=10'} + + cross-spawn@7.0.6: + resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} + engines: {node: '>= 8'} + + crypto-random-string@2.0.0: + resolution: {integrity: sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==} + engines: {node: '>=8'} + + css-blank-pseudo@3.0.3: + resolution: {integrity: sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-declaration-sorter@6.4.1: + resolution: {integrity: sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==} + engines: {node: ^10 || ^12 || >=14} + peerDependencies: + postcss: ^8.0.9 + + css-has-pseudo@3.0.4: + resolution: {integrity: sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-loader@6.11.0: + resolution: {integrity: sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.0.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + css-minimizer-webpack-plugin@3.4.1: + resolution: {integrity: sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + '@parcel/css': '*' + clean-css: '*' + csso: '*' + esbuild: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + '@parcel/css': + optional: true + clean-css: + optional: true + csso: + optional: true + esbuild: + optional: true + + css-prefers-color-scheme@6.0.3: + resolution: {integrity: sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==} + engines: {node: ^12 || ^14 || >=16} + hasBin: true + peerDependencies: + postcss: ^8.4 + + css-select-base-adapter@0.1.1: + resolution: {integrity: sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==} + + css-select@2.1.0: + resolution: {integrity: sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==} + + css-select@4.3.0: + resolution: {integrity: sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==} + + css-tree@1.0.0-alpha.37: + resolution: {integrity: sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==} + engines: {node: '>=8.0.0'} + + css-tree@1.1.3: + resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} + engines: {node: '>=8.0.0'} + + css-what@3.4.2: + resolution: {integrity: sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==} + engines: {node: '>= 6'} + + css-what@6.1.0: + resolution: {integrity: sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==} + engines: {node: '>= 6'} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssdb@7.11.2: + resolution: {integrity: sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==} + + cssesc@3.0.0: + resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==} + engines: {node: '>=4'} + hasBin: true + + cssnano-preset-default@5.2.14: + resolution: {integrity: sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano-utils@3.1.0: + resolution: {integrity: sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + cssnano@5.1.15: + resolution: {integrity: sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + csso@4.2.0: + resolution: {integrity: sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==} + engines: {node: '>=8.0.0'} + + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.4.4: + resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + + d3-array@3.2.4: + resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==} + engines: {node: '>=12'} + + d3-color@3.1.0: + resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==} + engines: {node: '>=12'} + + d3-ease@3.0.1: + resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==} + engines: {node: '>=12'} + + d3-format@3.1.0: + resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==} + engines: {node: '>=12'} + + d3-interpolate@3.0.1: + resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==} + engines: {node: '>=12'} + + d3-path@3.1.0: + resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==} + engines: {node: '>=12'} + + d3-scale@4.0.2: + resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==} + engines: {node: '>=12'} + + d3-shape@3.2.0: + resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==} + engines: {node: '>=12'} + + d3-time-format@4.1.0: + resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==} + engines: {node: '>=12'} + + d3-time@3.1.0: + resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==} + engines: {node: '>=12'} + + d3-timer@3.0.1: + resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==} + engines: {node: '>=12'} + + d3-voronoi@1.1.4: + resolution: {integrity: sha512-dArJ32hchFsrQ8uMiTBLq256MpnZjeuBtdHpaDlYuQyjU0CVzCJl/BVW+SkszaAeH95D/8gxqAhgx0ouAWAfRg==} + + damerau-levenshtein@1.0.8: + resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + + data-urls@2.0.0: + resolution: {integrity: sha512-X5eWTSXO/BJmpdIKCRuKUgSCgAN0OwliVK3yPKbwIWU1Tdw5BRajxlzMidvh+gwko9AfQ9zIj52pzF91Q3YAvQ==} + engines: {node: '>=10'} + + data-view-buffer@1.0.2: + resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} + engines: {node: '>= 0.4'} + + data-view-byte-length@1.0.2: + resolution: {integrity: sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==} + engines: {node: '>= 0.4'} + + data-view-byte-offset@1.0.1: + resolution: {integrity: sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==} + engines: {node: '>= 0.4'} + + date-fns@2.30.0: + resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} + engines: {node: '>=0.11'} + + date-fns@4.1.0: + resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + + debounce-promise@3.1.2: + resolution: {integrity: sha512-rZHcgBkbYavBeD9ej6sP56XfG53d51CD4dnaw989YX/nZ/ZJfgRx/9ePKmTNiUiyQvh4mtrMoS3OAWW+yoYtpg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@4.4.0: + resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decimal.js@10.5.0: + resolution: {integrity: sha512-8vDa8Qxvr/+d94hSh5P3IJwI5t8/c0KsMp+g8bNw9cY2icONa5aPfvKeieW1WlG0WQYwwhJ7mjui2xtiePQSXw==} + + dedent@0.7.0: + resolution: {integrity: sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==} + + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + + deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + + deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + + default-gateway@6.0.3: + resolution: {integrity: sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==} + engines: {node: '>= 10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-lazy-prop@2.0.0: + resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==} + engines: {node: '>=8'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + delaunator@4.0.1: + resolution: {integrity: sha512-WNPWi1IRKZfCt/qIDMfERkDp93+iZEmOxN2yy4Jg+Xhv8SLk2UTqqbe1sfiipn0and9QrE914/ihdx82Y/Giag==} + + delaunay-find@0.0.6: + resolution: {integrity: sha512-1+almjfrnR7ZamBk0q3Nhg6lqSe6Le4vL0WJDSMx4IDbQwTpUTXPjxC00lqLBT8MYsJpPCbI16sIkw9cPsbi7Q==} + + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@1.1.2: + resolution: {integrity: sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==} + engines: {node: '>= 0.6'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + + detect-node-es@1.1.0: + resolution: {integrity: sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + detect-port-alt@1.1.6: + resolution: {integrity: sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==} + engines: {node: '>= 4.2.1'} + hasBin: true + + didyoumean@1.2.2: + resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} + + diff-sequences@27.5.1: + resolution: {integrity: sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + + dlv@1.1.3: + resolution: {integrity: sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==} + + dns-packet@5.6.1: + resolution: {integrity: sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==} + engines: {node: '>=6'} + + doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + + dom-converter@0.2.0: + resolution: {integrity: sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==} + + dom-serializer@0.2.2: + resolution: {integrity: sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==} + + dom-serializer@1.4.1: + resolution: {integrity: sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==} + + domelementtype@1.3.1: + resolution: {integrity: sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==} + + domelementtype@2.3.0: + resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==} + + domexception@2.0.1: + resolution: {integrity: sha512-yxJ2mFy/sibVQlu5qHjOkf9J3K6zgmCxgJ94u2EdvDOV09H+32LtRswEcUsmUWN72pVLOEnTSRaIVVzVQgS0dg==} + engines: {node: '>=8'} + deprecated: Use your platform's native DOMException instead + + domhandler@4.3.1: + resolution: {integrity: sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==} + engines: {node: '>= 4'} + + domutils@1.7.0: + resolution: {integrity: sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==} + + domutils@2.8.0: + resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==} + + dot-case@3.0.4: + resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} + + dotenv-expand@5.1.0: + resolution: {integrity: sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==} + + dotenv@10.0.0: + resolution: {integrity: sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==} + engines: {node: '>=10'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + + duplexer@0.1.2: + resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} + + eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + + easy-peasy@5.2.0: + resolution: {integrity: sha512-QHRRJTsF15ZLK5vLcCLDF3A7sMrE4+7S/8ggZempfMbXX3xNsH2R3HVA+Xo5rZA65Rg8Zf5X6fflEMGuzfgwTw==} + peerDependencies: + '@types/react': ^16.8 || ^17.0 || ^18.0 + '@types/react-dom': ^16.8 || ^17.0 || ^18.0 + react: ^16.8 || ^17.0 || ^18.0 + react-dom: ^16.8 || ^17.0 || ^18.0 + react-native: '>=0.59' + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + react-dom: + optional: true + react-native: + optional: true + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + + electron-log@5.3.2: + resolution: {integrity: sha512-EFI5MFFEzFJU5gyhJNpKQhfGfrRP9IWzSu0sSxrWXasWKvVAOFgBySafX8W1pbPKa/w8/DDPu2bBBtVZJdDsnw==} + engines: {node: '>= 14'} + + electron-to-chromium@1.5.113: + resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} + + emittery@0.10.2: + resolution: {integrity: sha512-aITqOwnLanpHLNXZJENbOgjUBeHocD+xsSJmNrjovKBW5HbSpW3d1pEls7GFQPUWXiwG9+0P4GtHfEqC/4M0Iw==} + engines: {node: '>=12'} + + emittery@0.8.1: + resolution: {integrity: sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==} + engines: {node: '>=10'} + + emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + + emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + + emojis-list@3.0.0: + resolution: {integrity: sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==} + engines: {node: '>= 4'} + + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + enhanced-resolve@5.18.1: + resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} + engines: {node: '>=10.13.0'} + + entities@2.2.0: + resolution: {integrity: sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==} + + error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + + error-stack-parser@2.1.4: + resolution: {integrity: sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==} + + es-abstract@1.23.9: + resolution: {integrity: sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==} + engines: {node: '>= 0.4'} + + es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-iterator-helpers@1.2.1: + resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} + engines: {node: '>= 0.4'} + + es-module-lexer@1.6.0: + resolution: {integrity: sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + es-shim-unscopables@1.1.0: + resolution: {integrity: sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==} + engines: {node: '>= 0.4'} + + es-to-primitive@1.3.0: + resolution: {integrity: sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==} + engines: {node: '>= 0.4'} + + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + + escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + + escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + escodegen@1.14.3: + resolution: {integrity: sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==} + engines: {node: '>=4.0'} + hasBin: true + + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + + eslint-config-react-app@7.0.1: + resolution: {integrity: sha512-K6rNzvkIeHaTd8m/QEh1Zko0KI7BACWkkneSs6s9cKZC/J27X3eZR6Upt1jkmZ/4FK+XUOPPxMEN7+lbUXfSlA==} + engines: {node: '>=14.0.0'} + peerDependencies: + eslint: ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + + eslint-module-utils@2.12.0: + resolution: {integrity: sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + + eslint-plugin-flowtype@8.0.3: + resolution: {integrity: sha512-dX8l6qUL6O+fYPtpNRideCFSpmWOUVx5QcaGLVqe/vlDiBSe4vYljDWDETwnyFzpl7By/WVIu6rcrniCgH9BqQ==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@babel/plugin-syntax-flow': ^7.14.5 + '@babel/plugin-transform-react-jsx': ^7.14.9 + eslint: ^8.1.0 + + eslint-plugin-import@2.31.0: + resolution: {integrity: sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + + eslint-plugin-jest@25.7.0: + resolution: {integrity: sha512-PWLUEXeeF7C9QGKqvdSbzLOiLTx+bno7/HC9eefePfEb257QFHg7ye3dh80AZVkaa/RQsBB1Q/ORQvg2X7F0NQ==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^4.0.0 || ^5.0.0 + eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 + jest: '*' + peerDependenciesMeta: + '@typescript-eslint/eslint-plugin': + optional: true + jest: + optional: true + + eslint-plugin-jsx-a11y@6.10.2: + resolution: {integrity: sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==} + engines: {node: '>=4.0'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9 + + eslint-plugin-react-compiler@19.0.0-beta-27714ef-20250124: + resolution: {integrity: sha512-8/NaV8E+eQ+BiKGeWg5wIizuKwEXLo+n/lgiyTLmJnZj8eoFW3G7NGJf3Nke4ji3Rndy34LK5Qi5TF6BPiZlSQ==} + engines: {node: ^14.17.0 || ^16.0.0 || >= 18.0.0} + peerDependencies: + eslint: '>=7' + + eslint-plugin-react-hooks@4.6.2: + resolution: {integrity: sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==} + engines: {node: '>=10'} + peerDependencies: + eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 + + eslint-plugin-react-hooks@5.2.0: + resolution: {integrity: sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==} + 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 + + eslint-plugin-react-refresh@0.4.19: + resolution: {integrity: sha512-eyy8pcr/YxSYjBoqIFSrlbn9i/xvxUFa8CjzAYo9cFjgGXqq1hyjihcpZvxRLalpaWmueWR81xn7vuKmAFijDQ==} + peerDependencies: + eslint: '>=8.40' + + eslint-plugin-react@7.37.4: + resolution: {integrity: sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==} + engines: {node: '>=4'} + peerDependencies: + eslint: ^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7 + + eslint-plugin-testing-library@5.11.1: + resolution: {integrity: sha512-5eX9e1Kc2PqVRed3taaLnAAqPZGEX75C+M/rXzUAI3wIg/ZxzUm1OVAwfe/O+vE+6YXOLetSe9g5GKD2ecXipw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0, npm: '>=6'} + peerDependencies: + eslint: ^7.5.0 || ^8.0.0 + + eslint-scope@5.1.1: + resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==} + engines: {node: '>=8.0.0'} + + eslint-scope@8.2.0: + resolution: {integrity: sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-visitor-keys@2.1.0: + resolution: {integrity: sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==} + engines: {node: '>=10'} + + eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + + eslint-visitor-keys@4.2.0: + resolution: {integrity: sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + eslint-webpack-plugin@3.2.0: + resolution: {integrity: sha512-avrKcGncpPbPSUHX6B3stNGzkKFto3eL+DKM4+VyMrVnhPc3vRczVlCq3uhuFOdRvDHTVXuzwk1ZKUrqDQHQ9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + webpack: ^5.0.0 + + eslint@9.21.0: + resolution: {integrity: sha512-KjeihdFqTPhOMXTt7StsDxriV4n66ueuF/jfPNC3j/lduHwr/ijDwJMsF+wyMJethgiKi5wniIE243vi07d3pg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true + + espree@10.3.0: + resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + + esprima@1.2.2: + resolution: {integrity: sha512-+JpPZam9w5DuJ3Q67SqsMGtiHKENSMRVoxvArfJZK01/BfLEObtZ6orJa/MtoGNR/rfMgp5837T41PAmTwAv/A==} + engines: {node: '>=0.4.0'} + hasBin: true + + esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} + engines: {node: '>=0.10'} + + esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + + estraverse@4.3.0: + resolution: {integrity: sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==} + engines: {node: '>=4.0'} + + estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + + estree-walker@1.0.1: + resolution: {integrity: sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==} + + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + + esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + eventemitter3@4.0.7: + resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + + events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + + execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + + exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + + expect-type@1.2.0: + resolution: {integrity: sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==} + engines: {node: '>=12.0.0'} + + expect@27.5.1: + resolution: {integrity: sha512-E1q5hSUG2AmYQwQJ041nvgpkODHQvB+RKlB4IYdru6uJsyFTRyZAP463M+1lINorwbqAmUggi6+WwkD8lCS/Dw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + + fast-glob@3.3.3: + resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} + engines: {node: '>=8.6.0'} + + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + + fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + + fast-uri@3.0.6: + resolution: {integrity: sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==} + + fastq@1.19.1: + resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + + faye-websocket@0.11.4: + resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==} + engines: {node: '>=0.8.0'} + + fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + + file-entry-cache@8.0.0: + resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} + engines: {node: '>=16.0.0'} + + file-loader@6.2.0: + resolution: {integrity: sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + + filesize@8.0.7: + resolution: {integrity: sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==} + engines: {node: '>= 0.4.0'} + + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + find-cache-dir@3.3.2: + resolution: {integrity: sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==} + engines: {node: '>=8'} + + find-root@1.1.0: + resolution: {integrity: sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==} + + find-up@3.0.0: + resolution: {integrity: sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==} + engines: {node: '>=6'} + + find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat-cache@4.0.1: + resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==} + engines: {node: '>=16'} + + flatted@3.3.3: + resolution: {integrity: sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==} + + focus-lock@1.3.6: + resolution: {integrity: sha512-Ik/6OCk9RQQ0T5Xw+hKNLWrjSMtv51dD4GRmJjbD5a58TIEpI5a5iXagKVl3Z5UuyslMCA8Xwnu76jQob62Yhg==} + engines: {node: '>=10'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + + for-each@0.3.5: + resolution: {integrity: sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==} + engines: {node: '>= 0.4'} + + foreground-child@3.3.1: + resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} + engines: {node: '>=14'} + + fork-ts-checker-webpack-plugin@6.5.3: + resolution: {integrity: sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==} + engines: {node: '>=10', yarn: '>=1.0.0'} + peerDependencies: + eslint: '>= 6' + typescript: '>= 2.7' + vue-template-compiler: '*' + webpack: '>= 4' + peerDependenciesMeta: + eslint: + optional: true + vue-template-compiler: + optional: true + + form-data@3.0.3: + resolution: {integrity: sha512-q5YBMeWy6E2Un0nMGWMgI65MAKtaylxfNJGJxpGh45YDciZB4epbWpaAfImil6CPAPTYB4sh0URQNDRIZG5F2w==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + + fraction.js@4.3.7: + resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + + framer-motion@7.10.3: + resolution: {integrity: sha512-k2ccYeZNSpPg//HTaqrU+4pRq9f9ZpaaN7rr0+Rx5zA4wZLbk547wtDzge2db1sB+1mnJ6r59P4xb+aEIi/W+w==} + peerDependencies: + react: ^18.0.0 + react-dom: ^18.0.0 + + framesync@6.1.2: + resolution: {integrity: sha512-jBTqhX6KaQVDyus8muwZbBeGGP0XgujBRbQ7gM7BRdS3CadCZIHiawyzYLnafYcvZIh5j8WE7cxZKFn7dXhu9g==} + + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-extra@10.1.0: + resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} + engines: {node: '>=12'} + + fs-extra@9.1.0: + resolution: {integrity: sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==} + engines: {node: '>=10'} + + fs-monkey@1.0.6: + resolution: {integrity: sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==} + + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + + fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + + function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + + function.prototype.name@1.1.8: + resolution: {integrity: sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==} + engines: {node: '>= 0.4'} + + functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + + gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + + get-nonce@1.0.1: + resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} + engines: {node: '>=6'} + + get-own-enumerable-property-symbols@3.0.2: + resolution: {integrity: sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==} + + get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + + get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + + get-symbol-description@1.1.0: + resolution: {integrity: sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==} + engines: {node: '>= 0.4'} + + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + + glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + + glob-to-regexp@0.4.1: + resolution: {integrity: sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==} + + glob@10.4.5: + resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + hasBin: true + + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + global-modules@2.0.0: + resolution: {integrity: sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==} + engines: {node: '>=6'} + + global-prefix@3.0.0: + resolution: {integrity: sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==} + engines: {node: '>=6'} + + globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + + globals@14.0.0: + resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} + engines: {node: '>=18'} + + globals@15.15.0: + resolution: {integrity: sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg==} + engines: {node: '>=18'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + + handle-thing@2.0.1: + resolution: {integrity: sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==} + + harmony-reflect@1.6.2: + resolution: {integrity: sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==} + + has-bigints@1.1.0: + resolution: {integrity: sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==} + engines: {node: '>= 0.4'} + + has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-proto@1.2.0: + resolution: {integrity: sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==} + engines: {node: '>= 0.4'} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hasown@2.0.2: + resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} + engines: {node: '>= 0.4'} + + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + + hermes-estree@0.25.1: + resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} + + hermes-parser@0.25.1: + resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} + + hey-listen@1.0.8: + resolution: {integrity: sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + hoopy@0.1.4: + resolution: {integrity: sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==} + engines: {node: '>= 6.0.0'} + + hpack.js@2.1.6: + resolution: {integrity: sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==} + + html-encoding-sniffer@2.0.1: + resolution: {integrity: sha512-D5JbOMBIR/TVZkubHT+OyT2705QvogUW4IBn6nHd756OwieSF9aDYFj4dv6HHEVGYbHaLETa3WggZYWWMyy3ZQ==} + engines: {node: '>=10'} + + html-entities@2.5.2: + resolution: {integrity: sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==} + + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + + html-minifier-terser@6.1.0: + resolution: {integrity: sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==} + engines: {node: '>=12'} + hasBin: true + + html-webpack-plugin@5.6.3: + resolution: {integrity: sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==} + engines: {node: '>=10.13.0'} + peerDependencies: + '@rspack/core': 0.x || 1.x + webpack: ^5.20.0 + peerDependenciesMeta: + '@rspack/core': + optional: true + webpack: + optional: true + + htmlparser2@6.1.0: + resolution: {integrity: sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==} + + http-deceiver@1.2.7: + resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==} + + http-errors@1.6.3: + resolution: {integrity: sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==} + engines: {node: '>= 0.6'} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + + http-parser-js@0.5.9: + resolution: {integrity: sha512-n1XsPy3rXVxlqxVioEWdC+0+M+SQw0DpJynwtOPo1X+ZlvdzTLtDBIJJlDQTnwZIFJrZSzSGmIOUdP8tu+SgLw==} + + http-proxy-agent@4.0.1: + resolution: {integrity: sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==} + engines: {node: '>= 6'} + + http-proxy-middleware@2.0.7: + resolution: {integrity: sha512-fgVY8AV7qU7z/MmXJ/rxwbrtQH4jBQ9m7kp3llF0liB7glmFeVZFBepQb32T3y8n8k2+AEYuMPCpinYW+/CuRA==} + engines: {node: '>=12.0.0'} + peerDependencies: + '@types/express': ^4.17.13 + peerDependenciesMeta: + '@types/express': + optional: true + + http-proxy@1.18.1: + resolution: {integrity: sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==} + engines: {node: '>=8.0.0'} + + https-proxy-agent@5.0.1: + resolution: {integrity: sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==} + engines: {node: '>= 6'} + + human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + + humanize-duration@3.32.1: + resolution: {integrity: sha512-inh5wue5XdfObhu/IGEMiA1nUXigSGcaKNemcbLRKa7jXYGDZXr3LoT9pTIzq2hPEbld7w/qv9h+ikWGz8fL1g==} + + iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + + icss-utils@5.1.0: + resolution: {integrity: sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + idb@7.1.1: + resolution: {integrity: sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==} + + identity-obj-proxy@3.0.0: + resolution: {integrity: sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==} + engines: {node: '>=4'} + + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + + immer@9.0.21: + resolution: {integrity: sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==} + + import-fresh@3.3.1: + resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==} + engines: {node: '>=6'} + + import-local@3.2.0: + resolution: {integrity: sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==} + engines: {node: '>=8'} + hasBin: true + + imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + + indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + + inherits@2.0.3: + resolution: {integrity: sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==} + + inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + + ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + + internal-slot@1.1.0: + resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} + engines: {node: '>= 0.4'} + + internmap@2.0.3: + resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} + engines: {node: '>=12'} + + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + + ipaddr.js@2.2.0: + resolution: {integrity: sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==} + engines: {node: '>= 10'} + + is-array-buffer@3.0.5: + resolution: {integrity: sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==} + engines: {node: '>= 0.4'} + + is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + + is-async-function@2.1.1: + resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} + engines: {node: '>= 0.4'} + + is-bigint@1.1.0: + resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} + engines: {node: '>= 0.4'} + + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + + is-boolean-object@1.2.2: + resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} + engines: {node: '>= 0.4'} + + is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + + is-core-module@2.16.1: + resolution: {integrity: sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==} + engines: {node: '>= 0.4'} + + is-data-view@1.0.2: + resolution: {integrity: sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==} + engines: {node: '>= 0.4'} + + is-date-object@1.1.0: + resolution: {integrity: sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==} + engines: {node: '>= 0.4'} + + is-docker@2.2.1: + resolution: {integrity: sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==} + engines: {node: '>=8'} + hasBin: true + + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + + is-finalizationregistry@1.1.1: + resolution: {integrity: sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==} + engines: {node: '>= 0.4'} + + is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + + is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + + is-generator-function@1.1.0: + resolution: {integrity: sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==} + engines: {node: '>= 0.4'} + + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-map@2.0.3: + resolution: {integrity: sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==} + engines: {node: '>= 0.4'} + + is-module@1.0.0: + resolution: {integrity: sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==} + + is-number-object@1.1.1: + resolution: {integrity: sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==} + engines: {node: '>= 0.4'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-obj@1.0.1: + resolution: {integrity: sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==} + engines: {node: '>=0.10.0'} + + is-plain-obj@3.0.0: + resolution: {integrity: sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==} + engines: {node: '>=10'} + + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + + is-regex@1.2.1: + resolution: {integrity: sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==} + engines: {node: '>= 0.4'} + + is-regexp@1.0.0: + resolution: {integrity: sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==} + engines: {node: '>=0.10.0'} + + is-root@2.1.0: + resolution: {integrity: sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==} + engines: {node: '>=6'} + + is-set@2.0.3: + resolution: {integrity: sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==} + engines: {node: '>= 0.4'} + + is-shared-array-buffer@1.0.4: + resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} + engines: {node: '>= 0.4'} + + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + + is-string@1.1.1: + resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} + engines: {node: '>= 0.4'} + + is-symbol@1.1.1: + resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} + engines: {node: '>= 0.4'} + + is-typed-array@1.1.15: + resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} + engines: {node: '>= 0.4'} + + is-typedarray@1.0.0: + resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} + + is-weakmap@2.0.2: + resolution: {integrity: sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==} + engines: {node: '>= 0.4'} + + is-weakref@1.1.1: + resolution: {integrity: sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==} + engines: {node: '>= 0.4'} + + is-weakset@2.0.4: + resolution: {integrity: sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==} + engines: {node: '>= 0.4'} + + is-wsl@2.2.0: + resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} + engines: {node: '>=8'} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + + isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + + isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + + istanbul-lib-source-maps@5.0.6: + resolution: {integrity: sha512-yg2d+Em4KizZC5niWhQaIomgf5WlL4vOOjZ5xGCmF8SnPE/mDWWXgvRExdcpCgh9lLRRa1/fSYp2ymmbJ1pI+A==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + + iterator.prototype@1.1.5: + resolution: {integrity: sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==} + engines: {node: '>= 0.4'} + + jackspeak@3.4.3: + resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} + + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + + jest-changed-files@27.5.1: + resolution: {integrity: sha512-buBLMiByfWGCoMsLLzGUUSpAmIAGnbR2KJoMN10ziLhOLvP4e0SlypHnAel8iqQXTrcbmfEY9sSqae5sgUsTvw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-circus@27.5.1: + resolution: {integrity: sha512-D95R7x5UtlMA5iBYsOHFFbMD/GVA4R/Kdq15f7xYWUfWHBto9NYRsOvnSauTgdF+ogCpJ4tyKOXhUifxS65gdw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-cli@27.5.1: + resolution: {integrity: sha512-Hc6HOOwYq4/74/c62dEE3r5elx8wjYqxY0r0G/nFrLDPMFRu6RA/u8qINOIkvhxG7mMQ5EJsOGfRpI8L6eFUVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jest-config@27.5.1: + resolution: {integrity: sha512-5sAsjm6tGdsVbW9ahcChPAFCk4IlkQUknH5AvKjuLTSlcO/wCZKyFdn7Rg0EkC+OGgWODEy2hDpWB1PgzH0JNA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + peerDependencies: + ts-node: '>=9.0.0' + peerDependenciesMeta: + ts-node: + optional: true + + jest-diff@27.5.1: + resolution: {integrity: sha512-m0NvkX55LDt9T4mctTEgnZk3fmEg3NRYutvMPWM/0iPnkFj2wIeF45O1718cMSOFO1vINkqmxqD8vE37uTEbqw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-docblock@27.5.1: + resolution: {integrity: sha512-rl7hlABeTsRYxKiUfpHrQrG4e2obOiTQWfMEH3PxPjOtdsfLQO4ReWSZaQ7DETm4xu07rl4q/h4zcKXyU0/OzQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-each@27.5.1: + resolution: {integrity: sha512-1Ff6p+FbhT/bXQnEouYy00bkNSY7OUpfIcmdl8vZ31A1UUaurOLPA8a8BbJOF2RDUElwJhmeaV7LnagI+5UwNQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-jsdom@27.5.1: + resolution: {integrity: sha512-TFBvkTC1Hnnnrka/fUb56atfDtJ9VMZ94JkjTbggl1PEpwrYtUBKMezB3inLmWqQsXYLcMwNoDQwoBTAvFfsfw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-environment-node@27.5.1: + resolution: {integrity: sha512-Jt4ZUnxdOsTGwSRAfKEnE6BcwsSPNOijjwifq5sDFSA2kesnXTvNqKHYgM0hDq3549Uf/KzdXNYn4wMZJPlFLw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-get-type@27.5.1: + resolution: {integrity: sha512-2KY95ksYSaK7DMBWQn6dQz3kqAf3BB64y2udeG+hv4KfSOb9qwcYQstTJc1KCbsix+wLZWZYN8t7nwX3GOBLRw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-haste-map@27.5.1: + resolution: {integrity: sha512-7GgkZ4Fw4NFbMSDSpZwXeBiIbx+t/46nJ2QitkOjvwPYyZmqttu2TDSimMHP1EkPOi4xUZAN1doE5Vd25H4Jng==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-jasmine2@27.5.1: + resolution: {integrity: sha512-jtq7VVyG8SqAorDpApwiJJImd0V2wv1xzdheGHRGyuT7gZm6gG47QEskOlzsN1PG/6WNaCo5pmwMHDf3AkG2pQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-leak-detector@27.5.1: + resolution: {integrity: sha512-POXfWAMvfU6WMUXftV4HolnJfnPOGEu10fscNCA76KBpRRhcMN2c8d3iT2pxQS3HLbA+5X4sOUPzYO2NUyIlHQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-matcher-utils@27.5.1: + resolution: {integrity: sha512-z2uTx/T6LBaCoNWNFWwChLBKYxTMcGBRjAt+2SbP929/Fflb9aa5LGma654Rz8z9HLxsrUaYzxE9T/EFIL/PAw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-message-util@27.5.1: + resolution: {integrity: sha512-rMyFe1+jnyAAf+NHwTclDz0eAaLkVDdKVHHBFWsBWHnnh5YeJMNWWsv7AbFYXfK3oTqvL7VTWkhNLu1jX24D+g==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-message-util@28.1.3: + resolution: {integrity: sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-mock@27.5.1: + resolution: {integrity: sha512-K4jKbY1d4ENhbrG2zuPWaQBvDly+iZ2yAW+T1fATN78hc0sInwn7wZB8XtlNnvHug5RMwV897Xm4LqmPM4e2Og==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-pnp-resolver@1.2.3: + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + + jest-regex-util@27.5.1: + resolution: {integrity: sha512-4bfKq2zie+x16okqDXjXn9ql2B0dScQu+vcwe4TvFVhkVyuWLqpZrZtXxLLWoXYgn0E87I6r6GRYHF7wFZBUvg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-regex-util@28.0.2: + resolution: {integrity: sha512-4s0IgyNIy0y9FK+cjoVYoxamT7Zeo7MhzqRGx7YDYmaQn1wucY9rotiGkBzzcMXTtjrCAP/f7f+E0F7+fxPNdw==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-resolve-dependencies@27.5.1: + resolution: {integrity: sha512-QQOOdY4PE39iawDn5rzbIePNigfe5B9Z91GDD1ae/xNDlu9kaat8QQ5EKnNmVWPV54hUdxCVwwj6YMgR2O7IOg==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-resolve@27.5.1: + resolution: {integrity: sha512-FFDy8/9E6CV83IMbDpcjOhumAQPDyETnU2KZ1O98DwTnz8AOBsW/Xv3GySr1mOZdItLR+zDZ7I/UdTFbgSOVCw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runner@27.5.1: + resolution: {integrity: sha512-g4NPsM4mFCOwFKXO4p/H/kWGdJp9V8kURY2lX8Me2drgXqG7rrZAx5kv+5H7wtt/cdFIjhqYx1HrlqWHaOvDaQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-runtime@27.5.1: + resolution: {integrity: sha512-o7gxw3Gf+H2IGt8fv0RiyE1+r83FJBRruoA+FXrlHw6xEyBsU8ugA6IPfTdVyA0w8HClpbK+DGJxH59UrNMx8A==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-serializer@27.5.1: + resolution: {integrity: sha512-jZCyo6iIxO1aqUxpuBlwTDMkzOAJS4a3eYz3YzgxxVQFwLeSA7Jfq5cbqCY+JLvTDrWirgusI/0KwxKMgrdf7w==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-snapshot@27.5.1: + resolution: {integrity: sha512-yYykXI5a0I31xX67mgeLw1DZ0bJB+gpq5IpSuCAoyDi0+BhgU/RIrL+RTzDmkNTchvDFWKP8lp+w/42Z3us5sA==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-util@27.5.1: + resolution: {integrity: sha512-Kv2o/8jNvX1MQ0KGtw480E/w4fBCDOnH6+6DmeKi6LZUIlKA5kwY0YNdlzaWTiVgxqAqik11QyxDOKk543aKXw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-util@28.1.3: + resolution: {integrity: sha512-XdqfpHwpcSRko/C35uLYFM2emRAltIIKZiJ9eAmhjsj0CqZMa0p1ib0R5fWIqGhn1a103DebTbpqIaP1qCQ6tQ==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-validate@27.5.1: + resolution: {integrity: sha512-thkNli0LYTmOI1tDB3FI1S1RTp/Bqyd9pTarJwL87OIBFuqEb5Apv5EaApEudYg4g86e3CT6kM0RowkhtEnCBQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-watch-typeahead@1.1.0: + resolution: {integrity: sha512-Va5nLSJTN7YFtC2jd+7wsoe1pNe5K4ShLux/E5iHEwlB9AxaxmggY7to9KUqKojhaJw3aXqt5WAb4jGPOolpEw==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + jest: ^27.0.0 || ^28.0.0 + + jest-watcher@27.5.1: + resolution: {integrity: sha512-z676SuD6Z8o8qbmEGhoEUFOM1+jfEiL3DXHK/xgEiG2EyNYfFG60jluWcupY6dATjfEsKQuibReS1djInQnoVw==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + jest-watcher@28.1.3: + resolution: {integrity: sha512-t4qcqj9hze+jviFPUN3YAtAEeFnr/azITXQEMARf5cMwKY2SMBRnCQTXLixTl20OR6mLh9KLMrgVJgJISym+1g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest-worker@26.6.2: + resolution: {integrity: sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==} + engines: {node: '>= 10.13.0'} + + jest-worker@27.5.1: + resolution: {integrity: sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==} + engines: {node: '>= 10.13.0'} + + jest-worker@28.1.3: + resolution: {integrity: sha512-CqRA220YV/6jCo8VWvAt1KKx6eek1VIHMPeLEbpcfSfkEeWyBNppynM/o6q+Wmw+sOhos2ml34wZbSX3G13//g==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + jest@27.5.1: + resolution: {integrity: sha512-Yn0mADZB89zTtjkPJEXwrac3LHudkQMR+Paqa8uxJHCBr9agxztUifWCyiYrjhMPBoUVBjyny0I7XH6ozDr7QQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + + jiti@1.21.7: + resolution: {integrity: sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==} + hasBin: true + + js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + + js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + + jsdom@16.7.0: + resolution: {integrity: sha512-u9Smc2G1USStM+s/x1ru5Sxrl6mPYCbByG1U/hUmqaVsm4tbNyS7CicOSRyuGQYZhTu0h84qkZZQ/I+dzizSVw==} + engines: {node: '>=10'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + + jsesc@3.0.2: + resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} + engines: {node: '>=6'} + hasBin: true + + jsesc@3.1.0: + resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} + engines: {node: '>=6'} + hasBin: true + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + + json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + + json-schema-traverse@1.0.0: + resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==} + + json-schema@0.4.0: + resolution: {integrity: sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==} + + json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + + json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + + jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + + jsonpath@1.1.1: + resolution: {integrity: sha512-l6Cg7jRpixfbgoWgkrl77dgEj8RPvND0wMH6TwQmi9Qs4TFfS9u5cUFnbeKTwj5ga5Y3BTGGNI28k117LJ009w==} + + jsonpointer@5.0.1: + resolution: {integrity: sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==} + engines: {node: '>=0.10.0'} + + jsx-ast-utils@3.3.5: + resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} + engines: {node: '>=4.0'} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + + kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + + klona@2.0.6: + resolution: {integrity: sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==} + engines: {node: '>= 8'} + + language-subtag-registry@0.3.23: + resolution: {integrity: sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==} + + language-tags@1.0.9: + resolution: {integrity: sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==} + engines: {node: '>=0.10'} + + launch-editor@2.10.0: + resolution: {integrity: sha512-D7dBRJo/qcGX9xlvt/6wUYzQxjh5G1RvZPgPv8vi4KRU99DVQL/oW7tnVOCCTm2HGeo3C5HvGE5Yrh6UBoZ0vA==} + + leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + + levn@0.3.0: + resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==} + engines: {node: '>= 0.8.0'} + + levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + + lilconfig@2.1.0: + resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==} + engines: {node: '>=10'} + + lilconfig@3.1.3: + resolution: {integrity: sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==} + engines: {node: '>=14'} + + lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + + loader-runner@4.3.0: + resolution: {integrity: sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==} + engines: {node: '>=6.11.5'} + + loader-utils@2.0.4: + resolution: {integrity: sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==} + engines: {node: '>=8.9.0'} + + loader-utils@3.3.1: + resolution: {integrity: sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==} + engines: {node: '>= 12.13.0'} + + locate-path@3.0.0: + resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} + engines: {node: '>=6'} + + locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + + lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + + lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + + lodash.memoize@4.1.2: + resolution: {integrity: sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==} + + lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + + lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + + loupe@3.1.3: + resolution: {integrity: sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==} + + lower-case@2.0.2: + resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==} + + lru-cache@10.4.3: + resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + + lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + + magic-string@0.25.9: + resolution: {integrity: sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==} + + magic-string@0.30.17: + resolution: {integrity: sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==} + + magicast@0.3.5: + resolution: {integrity: sha512-L0WhttDl+2BOsybvEOLK7fW3UA0OQ0IQ2d6Zl2x/a6vVRs3bAY0ECOSHHeL5jD+SbOpOCUEi0y1DgHEn9Qn1AQ==} + + make-dir@3.1.0: + resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} + engines: {node: '>=8'} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + + makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + + match-sorter@8.0.0: + resolution: {integrity: sha512-bGJ6Zb+OhzXe+ptP5d80OLVx7AkqfRbtGEh30vNSfjNwllu+hHI+tcbMIT/fbkx/FKN1PmKuDb65+Oofg+XUxw==} + + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + mdn-data@2.0.14: + resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} + + mdn-data@2.0.4: + resolution: {integrity: sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + memfs@3.5.3: + resolution: {integrity: sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==} + engines: {node: '>= 4.0.0'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + + merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + + merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + + micromatch@4.0.8: + resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} + engines: {node: '>=8.6'} + + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-db@1.53.0: + resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + + mini-css-extract-plugin@2.9.2: + resolution: {integrity: sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} + engines: {node: '>=16 || 14 >=14.17'} + + minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + + minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + + mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + + moment@2.30.1: + resolution: {integrity: sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + multicast-dns@7.2.5: + resolution: {integrity: sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==} + hasBin: true + + mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + + nanoclone@0.2.1: + resolution: {integrity: sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==} + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} + engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} + hasBin: true + + natural-compare-lite@1.4.0: + resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} + + natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + + negotiator@0.6.4: + resolution: {integrity: sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==} + engines: {node: '>= 0.6'} + + neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + + no-case@3.0.4: + resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + + node-forge@1.3.1: + resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==} + engines: {node: '>= 6.13.0'} + + node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + + node-releases@2.0.19: + resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + + normalize-range@0.1.2: + resolution: {integrity: sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==} + engines: {node: '>=0.10.0'} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + + nth-check@1.0.2: + resolution: {integrity: sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==} + + nth-check@2.1.1: + resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} + + nwsapi@2.2.18: + resolution: {integrity: sha512-p1TRH/edngVEHVbwqWnxUViEmq5znDvyB+Sik5cmuLpGOIfDf/39zLiq3swPF8Vakqn+gvNiOQAZu8djYlQILA==} + + object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + + object-hash@3.0.0: + resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} + engines: {node: '>= 6'} + + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + object.assign@4.1.7: + resolution: {integrity: sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==} + engines: {node: '>= 0.4'} + + object.entries@1.1.8: + resolution: {integrity: sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==} + engines: {node: '>= 0.4'} + + object.fromentries@2.0.8: + resolution: {integrity: sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==} + engines: {node: '>= 0.4'} + + object.getownpropertydescriptors@2.1.8: + resolution: {integrity: sha512-qkHIGe4q0lSYMv0XI4SsBTJz3WaURhLvd0lKSgtVuOsJ2krg4SgMw3PIRQFMp07yi++UR3se2mkcLqsBNpBb/A==} + engines: {node: '>= 0.8'} + + object.groupby@1.0.3: + resolution: {integrity: sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==} + engines: {node: '>= 0.4'} + + object.values@1.2.1: + resolution: {integrity: sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==} + engines: {node: '>= 0.4'} + + obuf@1.1.2: + resolution: {integrity: sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + + open@8.4.2: + resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} + engines: {node: '>=12'} + + optionator@0.8.3: + resolution: {integrity: sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==} + engines: {node: '>= 0.8.0'} + + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} + engines: {node: '>= 0.8.0'} + + own-keys@1.0.1: + resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} + engines: {node: '>= 0.4'} + + p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@3.0.0: + resolution: {integrity: sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==} + engines: {node: '>=6'} + + p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + + p-retry@4.6.2: + resolution: {integrity: sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==} + engines: {node: '>=8'} + + p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + + package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + + param-case@3.0.4: + resolution: {integrity: sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==} + + parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + + parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + + parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + + pascal-case@3.1.2: + resolution: {integrity: sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==} + + path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + + path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + + path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + + path-scurry@1.11.1: + resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} + engines: {node: '>=16 || 14 >=14.18'} + + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + + pathe@2.0.3: + resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + + pathval@2.0.0: + resolution: {integrity: sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==} + engines: {node: '>= 14.16'} + + performance-now@2.1.0: + resolution: {integrity: sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==} + + picocolors@0.2.1: + resolution: {integrity: sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==} + + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} + + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + + pify@2.3.0: + resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} + engines: {node: '>=0.10.0'} + + pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + + pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + + pkg-up@3.1.0: + resolution: {integrity: sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==} + engines: {node: '>=8'} + + possible-typed-array-names@1.1.0: + resolution: {integrity: sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==} + engines: {node: '>= 0.4'} + + postcss-attribute-case-insensitive@5.0.2: + resolution: {integrity: sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-browser-comments@4.0.0: + resolution: {integrity: sha512-X9X9/WN3KIvY9+hNERUqX9gncsgBA25XaeR+jshHz2j8+sYyHktHw1JdKuMjeLpGktXidqDhA7b/qm1mrBDmgg==} + engines: {node: '>=8'} + peerDependencies: + browserslist: '>=4' + postcss: '>=8' + + postcss-calc@8.2.4: + resolution: {integrity: sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==} + peerDependencies: + postcss: ^8.2.2 + + postcss-clamp@4.1.0: + resolution: {integrity: sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==} + engines: {node: '>=7.6.0'} + peerDependencies: + postcss: ^8.4.6 + + postcss-color-functional-notation@4.2.4: + resolution: {integrity: sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-color-hex-alpha@8.0.4: + resolution: {integrity: sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-color-rebeccapurple@7.1.1: + resolution: {integrity: sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-colormin@5.3.1: + resolution: {integrity: sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-convert-values@5.1.3: + resolution: {integrity: sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-custom-media@8.0.2: + resolution: {integrity: sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + postcss-custom-properties@12.1.11: + resolution: {integrity: sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-custom-selectors@6.0.3: + resolution: {integrity: sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.3 + + postcss-dir-pseudo-class@6.0.5: + resolution: {integrity: sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-discard-comments@5.1.2: + resolution: {integrity: sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-duplicates@5.1.0: + resolution: {integrity: sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-empty@5.1.1: + resolution: {integrity: sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-discard-overridden@5.1.0: + resolution: {integrity: sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-double-position-gradients@3.1.2: + resolution: {integrity: sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-env-function@4.0.6: + resolution: {integrity: sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-flexbugs-fixes@5.0.2: + resolution: {integrity: sha512-18f9voByak7bTktR2QgDveglpn9DTbBWPUzSOe9g0N4WR/2eSt6Vrcbf0hmspvMI6YWGywz6B9f7jzpFNJJgnQ==} + peerDependencies: + postcss: ^8.1.4 + + postcss-focus-visible@6.0.4: + resolution: {integrity: sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-focus-within@5.0.4: + resolution: {integrity: sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-font-variant@5.0.0: + resolution: {integrity: sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==} + peerDependencies: + postcss: ^8.1.0 + + postcss-gap-properties@3.0.5: + resolution: {integrity: sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-image-set-function@4.0.7: + resolution: {integrity: sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-import@15.1.0: + resolution: {integrity: sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==} + engines: {node: '>=14.0.0'} + peerDependencies: + postcss: ^8.0.0 + + postcss-initial@4.0.1: + resolution: {integrity: sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==} + peerDependencies: + postcss: ^8.0.0 + + postcss-js@4.0.1: + resolution: {integrity: sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==} + engines: {node: ^12 || ^14 || >= 16} + peerDependencies: + postcss: ^8.4.21 + + postcss-lab-function@4.2.1: + resolution: {integrity: sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-load-config@4.0.2: + resolution: {integrity: sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==} + engines: {node: '>= 14'} + peerDependencies: + postcss: '>=8.0.9' + ts-node: '>=9.0.0' + peerDependenciesMeta: + postcss: + optional: true + ts-node: + optional: true + + postcss-loader@6.2.1: + resolution: {integrity: sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + postcss: ^7.0.0 || ^8.0.1 + webpack: ^5.0.0 + + postcss-logical@5.0.4: + resolution: {integrity: sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.4 + + postcss-media-minmax@5.0.0: + resolution: {integrity: sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + postcss: ^8.1.0 + + postcss-merge-longhand@5.1.7: + resolution: {integrity: sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-merge-rules@5.1.4: + resolution: {integrity: sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-font-values@5.1.0: + resolution: {integrity: sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-gradients@5.1.1: + resolution: {integrity: sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-params@5.1.4: + resolution: {integrity: sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-minify-selectors@5.2.1: + resolution: {integrity: sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-modules-extract-imports@3.1.0: + resolution: {integrity: sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-local-by-default@4.2.0: + resolution: {integrity: sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-scope@3.2.1: + resolution: {integrity: sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-modules-values@4.0.0: + resolution: {integrity: sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==} + engines: {node: ^10 || ^12 || >= 14} + peerDependencies: + postcss: ^8.1.0 + + postcss-nested@6.2.0: + resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} + engines: {node: '>=12.0'} + peerDependencies: + postcss: ^8.2.14 + + postcss-nesting@10.2.0: + resolution: {integrity: sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-normalize-charset@5.1.0: + resolution: {integrity: sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-display-values@5.1.0: + resolution: {integrity: sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-positions@5.1.1: + resolution: {integrity: sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-repeat-style@5.1.1: + resolution: {integrity: sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-string@5.1.0: + resolution: {integrity: sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-timing-functions@5.1.0: + resolution: {integrity: sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-unicode@5.1.1: + resolution: {integrity: sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-url@5.1.0: + resolution: {integrity: sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize-whitespace@5.1.1: + resolution: {integrity: sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-normalize@10.0.1: + resolution: {integrity: sha512-+5w18/rDev5mqERcG3W5GZNMJa1eoYYNGo8gB7tEwaos0ajk3ZXAI4mHGcNT47NE+ZnZD1pEpUOFLvltIwmeJA==} + engines: {node: '>= 12'} + peerDependencies: + browserslist: '>= 4' + postcss: '>= 8' + + postcss-opacity-percentage@1.1.3: + resolution: {integrity: sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-ordered-values@5.1.3: + resolution: {integrity: sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-overflow-shorthand@3.0.4: + resolution: {integrity: sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-page-break@3.0.4: + resolution: {integrity: sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==} + peerDependencies: + postcss: ^8 + + postcss-place@7.0.5: + resolution: {integrity: sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-preset-env@7.8.3: + resolution: {integrity: sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-pseudo-class-any-link@7.1.6: + resolution: {integrity: sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-reduce-initial@5.1.2: + resolution: {integrity: sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-reduce-transforms@5.1.0: + resolution: {integrity: sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-replace-overflow-wrap@4.0.0: + resolution: {integrity: sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==} + peerDependencies: + postcss: ^8.0.3 + + postcss-selector-not@6.0.1: + resolution: {integrity: sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==} + engines: {node: ^12 || ^14 || >=16} + peerDependencies: + postcss: ^8.2 + + postcss-selector-parser@6.1.2: + resolution: {integrity: sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==} + engines: {node: '>=4'} + + postcss-selector-parser@7.1.0: + resolution: {integrity: sha512-8sLjZwK0R+JlxlYcTuVnyT2v+htpdrjDOKuMcOVdYjt52Lh8hWRYpxBPoKx/Zg+bcjc3wx6fmQevMmUztS/ccA==} + engines: {node: '>=4'} + + postcss-svgo@5.1.0: + resolution: {integrity: sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-unique-selectors@5.1.1: + resolution: {integrity: sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + postcss-value-parser@4.2.0: + resolution: {integrity: sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==} + + postcss@7.0.39: + resolution: {integrity: sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==} + engines: {node: '>=6.0.0'} + + postcss@8.5.3: + resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} + engines: {node: ^10 || ^12 || >=14} + + prelude-ls@1.1.2: + resolution: {integrity: sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==} + engines: {node: '>= 0.8.0'} + + prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + + pretty-bytes@5.6.0: + resolution: {integrity: sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==} + engines: {node: '>=6'} + + pretty-error@4.0.0: + resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} + + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + + pretty-format@28.1.3: + resolution: {integrity: sha512-8gFb/To0OmxHR9+ZTb14Df2vNxdGCX8g1xWGUTqUw5TiZvcQf5sHKObd5UcPyLLyowNwDAMTF3XWOG1B6mxl1Q==} + engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + promise@8.3.0: + resolution: {integrity: sha512-rZPNPKTOYVNEEKFaq1HqTgOwZD+4/YHS5ukLzQCypkj+OkYx7iv0mA91lJlpPPZ8vMau3IIGj5Qlwrx+8iiSmg==} + + prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + + prop-types@15.8.1: + resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + + property-expr@2.0.6: + resolution: {integrity: sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==} + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + q@1.5.1: + resolution: {integrity: sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==} + engines: {node: '>=0.6.0', teleport: '>=0.2.0'} + deprecated: |- + You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other. + + (For a CapTP with native promises, see @endo/eventual-send and @endo/captp) + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + + queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + + raf@3.4.1: + resolution: {integrity: sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + randomcolor@0.6.2: + resolution: {integrity: sha512-Mn6TbyYpFgwFuQ8KJKqf3bqqY9O1y37/0jgSK/61PUxV4QfIMv0+K2ioq8DfOjkBslcjwSzRfIDEXfzA9aCx7A==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + + react-app-polyfill@3.0.0: + resolution: {integrity: sha512-sZ41cxiU5llIB003yxxQBYrARBqe0repqPTTYBTmMqTz9szeBbE37BehCE891NZsmdZqqP+xWKdT3eo3vOzN8w==} + engines: {node: '>=14'} + + react-clientside-effect@1.2.7: + resolution: {integrity: sha512-gce9m0Pk/xYYMEojRI9bgvqQAkl6hm7ozQvqWPyQx+kULiatdHgkNM1QG4DQRx5N9BAzWSCJmt9mMV8/KsdgVg==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + + react-color-palette@6.2.0: + resolution: {integrity: sha512-9rIboaRJNoeF8aCI2f3J8wgMyhl74SnGmZLDjor3bKf0iDBhP2EBv0/jGmm0hrj6OackGCqtWl5ZvM89XUc3sg==} + engines: {node: '>=10'} + peerDependencies: + react: '>=16.8.0' + + react-dev-utils@12.0.1: + resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=2.7' + webpack: '>=4' + peerDependenciesMeta: + typescript: + optional: true + + react-dom@19.0.0: + resolution: {integrity: sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==} + peerDependencies: + react: ^19.0.0 + + react-error-overlay@6.1.0: + resolution: {integrity: sha512-SN/U6Ytxf1QGkw/9ve5Y+NxBbZM6Ht95tuXNMKs8EJyFa/Vy/+Co3stop3KBHARfn/giv+Lj1uUnTfOJ3moFEQ==} + + react-fast-compare@3.2.2: + resolution: {integrity: sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==} + + react-focus-lock@2.13.6: + resolution: {integrity: sha512-ehylFFWyYtBKXjAO9+3v8d0i+cnc1trGS0vlTGhzFW1vbFXVUTmR8s2tt/ZQG8x5hElg6rhENlLG1H3EZK0Llg==} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-hook-form@7.54.2: + resolution: {integrity: sha512-eHpAUgUjWbZocoQYUHposymRb4ZP6d0uwUnooL2uOybA9/3tPUvoAKqEWK1WaSiTxxOfTpffNZP7QwlnM3/gEg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: ^16.8.0 || ^17 || ^18 || ^19 + + react-icons@5.5.0: + resolution: {integrity: sha512-MEFcXdkP3dLo8uumGI5xN3lDFNsRtrjbOEKDLD7yv76v4wpnEq2Lt2qeHaQOr34I/wPN3s3+N08WkQ+CW37Xiw==} + peerDependencies: + react: '*' + + react-is@16.13.1: + resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + + react-is@18.3.1: + resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + + react-moment@1.1.3: + resolution: {integrity: sha512-8EPvlUL8u6EknPp1ISF5MQ3wx2OHJVXIP/iZc4wRh3iV3XozftZERDv9ANZeAtMlhNNQHdFoqcZHFUkBSTONfA==} + peerDependencies: + moment: ^2.29.0 + prop-types: ^15.7.0 + react: ^16.0 || ^17.0.0 || ^18.0.0 + + react-portal@4.3.0: + resolution: {integrity: sha512-qs/2uKq1ifB3J1+K8ExfgUvCDZqlqCkfOEhqTELEDTfosloKiuzOzc7hl7IQ/7nohiFZD41BUYU0boAsIsGYHw==} + peerDependencies: + react: ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0 + react-dom: ^16.0.0-0 || ^17.0.0-0 || ^18.0.0-0 || ^19.0.0 + + react-refresh@0.11.0: + resolution: {integrity: sha512-F27qZr8uUqwhWZboondsPx8tnC3Ct3SxZA3V5WyEvujRyyNv0VYPhoBg1gZ8/MV5tubQp76Trw8lTv9hzRBa+A==} + engines: {node: '>=0.10.0'} + + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react-remove-scroll-bar@2.3.8: + resolution: {integrity: sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + + react-remove-scroll@2.6.3: + resolution: {integrity: sha512-pnAi91oOk8g8ABQKGF5/M9qxmmOPxaAnopyTHYfqYEwJhyFrbbBtHuSgtKEoH0jpcxx5o3hXqH1mNd9/Oi+8iQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react-router-dom@6.4.3: + resolution: {integrity: sha512-MiaYQU8CwVCaOfJdYvt84KQNjT78VF0TJrA17SIQgNHRvLnXDJO6qsFqq8F/zzB1BWZjCFIrQpu4QxcshitziQ==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + react-dom: '>=16.8' + + react-router@6.4.3: + resolution: {integrity: sha512-BT6DoGn6aV1FVP5yfODMOiieakp3z46P1Fk0RNzJMACzE7C339sFuHebfvWtnB4pzBvXXkHP2vscJzWRuUjTtA==} + engines: {node: '>=14'} + peerDependencies: + react: '>=16.8' + + react-scripts@5.0.1: + resolution: {integrity: sha512-8VAmEm/ZAwQzJ+GOMLbBsTdDKOpuZh7RPs0UymvBR2vRk4iZWCskjbFnxqjrzoIvlNNRZ3QJFx6/qDSi6zSnaQ==} + engines: {node: '>=14.0.0'} + hasBin: true + peerDependencies: + eslint: '*' + react: '>= 16' + typescript: ^3.2.1 || ^4 + peerDependenciesMeta: + typescript: + optional: true + + react-style-singleton@2.2.3: + resolution: {integrity: sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + react@19.0.0: + resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==} + engines: {node: '>=0.10.0'} + + read-cache@1.0.0: + resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + + recursive-readdir@2.2.3: + resolution: {integrity: sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==} + engines: {node: '>=6.0.0'} + + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + + redux-thunk@2.4.2: + resolution: {integrity: sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==} + peerDependencies: + redux: ^4 + + redux@4.2.1: + resolution: {integrity: sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==} + + reflect.getprototypeof@1.0.10: + resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} + engines: {node: '>= 0.4'} + + regenerate-unicode-properties@10.2.0: + resolution: {integrity: sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==} + engines: {node: '>=4'} + + regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + + regenerator-runtime@0.13.11: + resolution: {integrity: sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==} + + regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + + regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + + regex-parser@2.3.1: + resolution: {integrity: sha512-yXLRqatcCuKtVHsWrNg0JL3l1zGfdXeEvDa0bdu4tCDQw0RpMDZsqbkyRTUnKMR0tXF627V2oEWjBEaEdqTwtQ==} + + regexp.prototype.flags@1.5.4: + resolution: {integrity: sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==} + engines: {node: '>= 0.4'} + + regexpu-core@6.2.0: + resolution: {integrity: sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==} + engines: {node: '>=4'} + + regjsgen@0.8.0: + resolution: {integrity: sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==} + + regjsparser@0.12.0: + resolution: {integrity: sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==} + hasBin: true + + relateurl@0.2.7: + resolution: {integrity: sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==} + engines: {node: '>= 0.10'} + + remove-accents@0.5.0: + resolution: {integrity: sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==} + + renderkid@3.0.0: + resolution: {integrity: sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==} + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + require-from-string@2.0.2: + resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==} + engines: {node: '>=0.10.0'} + + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + + resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + + resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + + resolve-url-loader@4.0.0: + resolution: {integrity: sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==} + engines: {node: '>=8.9'} + peerDependencies: + rework: 1.0.1 + rework-visit: 1.0.0 + peerDependenciesMeta: + rework: + optional: true + rework-visit: + optional: true + + resolve.exports@1.1.1: + resolution: {integrity: sha512-/NtpHNDN7jWhAaQ9BvBUYZ6YTXsRBgfqWFWP7BZBaoMJO/I3G5OFzvTuWNlZC3aPjins1F+TNrLKsGbH4rfsRQ==} + engines: {node: '>=10'} + + resolve@1.22.10: + resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} + engines: {node: '>= 0.4'} + hasBin: true + + resolve@2.0.0-next.5: + resolution: {integrity: sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==} + hasBin: true + + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + + reusify@1.1.0: + resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + + rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + deprecated: Rimraf versions prior to v4 are no longer supported + hasBin: true + + rollup-plugin-terser@7.0.2: + resolution: {integrity: sha512-w3iIaU4OxcF52UUXiZNsNeuXIMDvFrr+ZXK6bFZ0Q60qyVfq4uLptoS4bbq3paG3x216eQllFZX7zt6TIImguQ==} + deprecated: This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser + peerDependencies: + rollup: ^2.0.0 + + rollup@2.79.2: + resolution: {integrity: sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==} + engines: {node: '>=10.0.0'} + hasBin: true + + rollup@4.34.9: + resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + + run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + + safe-array-concat@1.1.3: + resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} + engines: {node: '>=0.4'} + + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-push-apply@1.0.0: + resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} + engines: {node: '>= 0.4'} + + safe-regex-test@1.1.0: + resolution: {integrity: sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==} + engines: {node: '>= 0.4'} + + safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + + sanitize.css@13.0.0: + resolution: {integrity: sha512-ZRwKbh/eQ6w9vmTjkuG0Ioi3HBwPFce0O+v//ve+aOq1oeCy7jMV2qzzAlpsNuqpqCBjjriM1lbtZbF/Q8jVyA==} + + sass-loader@12.6.0: + resolution: {integrity: sha512-oLTaH0YCtX4cfnJZxKSLAyglED0naiYfNG1iXfU5w1LNZ+ukoA5DtyDIN5zmKVZwYNJP4KRc5Y3hkWga+7tYfA==} + engines: {node: '>= 12.13.0'} + peerDependencies: + fibers: '>= 3.1.0' + node-sass: ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + sass: ^1.3.0 + sass-embedded: '*' + webpack: ^5.0.0 + peerDependenciesMeta: + fibers: + optional: true + node-sass: + optional: true + sass: + optional: true + sass-embedded: + optional: true + + sax@1.2.4: + resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} + + saxes@5.0.1: + resolution: {integrity: sha512-5LBh1Tls8c9xgGjw3QrMwETmTMVk0oFgvrFSvWx62llR2hcEInrKNZ2GZCCuuy2lvWrdl5jhbpeqc5hRYKFOcw==} + engines: {node: '>=10'} + + scheduler@0.25.0: + resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + + schema-utils@2.7.0: + resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} + engines: {node: '>= 8.9.0'} + + schema-utils@2.7.1: + resolution: {integrity: sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==} + engines: {node: '>= 8.9.0'} + + schema-utils@3.3.0: + resolution: {integrity: sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==} + engines: {node: '>= 10.13.0'} + + schema-utils@4.3.0: + resolution: {integrity: sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==} + engines: {node: '>= 10.13.0'} + + select-hose@2.0.0: + resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==} + + selfsigned@2.4.1: + resolution: {integrity: sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==} + engines: {node: '>=10'} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.7.1: + resolution: {integrity: sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==} + engines: {node: '>=10'} + hasBin: true + + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + + serialize-javascript@4.0.0: + resolution: {integrity: sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==} + + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + + serve-index@1.9.1: + resolution: {integrity: sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==} + engines: {node: '>= 0.8.0'} + + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + + set-function-length@1.2.2: + resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} + engines: {node: '>= 0.4'} + + set-function-name@2.0.2: + resolution: {integrity: sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==} + engines: {node: '>= 0.4'} + + set-proto@1.0.0: + resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==} + engines: {node: '>= 0.4'} + + setprototypeof@1.1.0: + resolution: {integrity: sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + + shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + + shell-quote@1.8.2: + resolution: {integrity: sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==} + engines: {node: '>= 0.4'} + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + + signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + + sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + + slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + + slash@4.0.0: + resolution: {integrity: sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==} + engines: {node: '>=12'} + + sockjs@0.3.24: + resolution: {integrity: sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==} + + source-list-map@2.0.1: + resolution: {integrity: sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==} + + source-map-js@1.2.1: + resolution: {integrity: sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==} + engines: {node: '>=0.10.0'} + + source-map-loader@3.0.2: + resolution: {integrity: sha512-BokxPoLjyl3iOrgkWaakaxqnelAJSS+0V+De0kKIq6lyWrXuiPgYTGp6z3iHmqljKAaLXwZa+ctD8GccRJeVvg==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + + source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + + source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + + source-map@0.7.4: + resolution: {integrity: sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==} + engines: {node: '>= 8'} + + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + + sourcemap-codec@1.4.8: + resolution: {integrity: sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==} + deprecated: Please use @jridgewell/sourcemap-codec instead + + spdy-transport@3.0.0: + resolution: {integrity: sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==} + + spdy@4.0.2: + resolution: {integrity: sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==} + engines: {node: '>=6.0.0'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + + stable@0.1.8: + resolution: {integrity: sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==} + deprecated: 'Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility' + + stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + stackframe@1.3.4: + resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==} + + static-eval@2.0.2: + resolution: {integrity: sha512-N/D219Hcr2bPjLxPiV+TQE++Tsmrady7TqAJugLy7Xk1EumfDWS/f5dtBbkRCGE7wKKXuYockQoj8Rm2/pVKyg==} + + statuses@1.5.0: + resolution: {integrity: sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==} + engines: {node: '>= 0.6'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + + std-env@3.8.1: + resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} + + string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + + string-length@5.0.1: + resolution: {integrity: sha512-9Ep08KAMUn0OadnVaBuRdE2l615CQ508kr0XMadjClfYpdCyvrbFp6Taebo8yyxokQ4viUd/xPPUA4FGgUa0ow==} + engines: {node: '>=12.20'} + + string-natural-compare@3.0.1: + resolution: {integrity: sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==} + + string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + + string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + + string.prototype.includes@2.0.1: + resolution: {integrity: sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==} + engines: {node: '>= 0.4'} + + string.prototype.matchall@4.0.12: + resolution: {integrity: sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==} + engines: {node: '>= 0.4'} + + string.prototype.repeat@1.0.0: + resolution: {integrity: sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==} + + string.prototype.trim@1.2.10: + resolution: {integrity: sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==} + engines: {node: '>= 0.4'} + + string.prototype.trimend@1.0.9: + resolution: {integrity: sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==} + engines: {node: '>= 0.4'} + + string.prototype.trimstart@1.0.8: + resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} + engines: {node: '>= 0.4'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + + stringify-object@3.3.0: + resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} + engines: {node: '>=4'} + + strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + + strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + + strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + + strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + + strip-comments@2.0.1: + resolution: {integrity: sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==} + engines: {node: '>=10'} + + strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + + style-loader@3.3.4: + resolution: {integrity: sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^5.0.0 + + stylehacks@5.1.1: + resolution: {integrity: sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==} + engines: {node: ^10 || ^12 || >=14.0} + peerDependencies: + postcss: ^8.2.15 + + stylis@4.2.0: + resolution: {integrity: sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==} + + sucrase@3.35.0: + resolution: {integrity: sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + + supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-hyperlinks@2.3.0: + resolution: {integrity: sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==} + engines: {node: '>=8'} + + supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + + svg-parser@2.0.4: + resolution: {integrity: sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==} + + svgo@1.3.2: + resolution: {integrity: sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==} + engines: {node: '>=4.0.0'} + deprecated: This SVGO version is no longer supported. Upgrade to v2.x.x. + hasBin: true + + svgo@2.8.0: + resolution: {integrity: sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==} + engines: {node: '>=10.13.0'} + hasBin: true + + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + + tailwindcss@3.4.17: + resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==} + engines: {node: '>=14.0.0'} + hasBin: true + + tapable@1.1.3: + resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} + engines: {node: '>=6'} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + + temp-dir@2.0.0: + resolution: {integrity: sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==} + engines: {node: '>=8'} + + tempy@0.6.0: + resolution: {integrity: sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==} + engines: {node: '>=10'} + + terminal-link@2.1.1: + resolution: {integrity: sha512-un0FmiRUQNr5PJqy9kP7c40F5BOfpGlYTrxonDChEZB7pzZxRNp/bt+ymiy9/npwXya9KH99nJ/GXFIiUkYGFQ==} + engines: {node: '>=8'} + + terser-webpack-plugin@5.3.14: + resolution: {integrity: sha512-vkZjpUjb6OMS7dhV+tILUW6BhpDR7P2L/aQSAv+Uwk+m8KATX9EccViHTJR2qDtACKPIYndLGCyl3FMo+r2LMw==} + engines: {node: '>= 10.13.0'} + peerDependencies: + '@swc/core': '*' + esbuild: '*' + uglify-js: '*' + webpack: ^5.1.0 + peerDependenciesMeta: + '@swc/core': + optional: true + esbuild: + optional: true + uglify-js: + optional: true + + terser@5.39.0: + resolution: {integrity: sha512-LBAhFyLho16harJoWMg/nZsQYgTrg5jXOn2nCYjRUcZZEdE3qa2zb8QEDRUGVZBW4rlazf2fxkg8tztybTaqWw==} + engines: {node: '>=10'} + hasBin: true + + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + + test-exclude@7.0.1: + resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + engines: {node: '>=18'} + + text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + + thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + + thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + + throat@6.0.2: + resolution: {integrity: sha512-WKexMoJj3vEuK0yFEapj8y64V0A6xcuPuK9Gt1d0R+dzCSJc0lHqQytAbSB4cDAK0dWh4T0E2ETkoLE2WZ41OQ==} + + thunky@1.1.0: + resolution: {integrity: sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==} + + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@3.0.2: + resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} + engines: {node: '>=14.0.0'} + + tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + + toggle-selection@1.0.6: + resolution: {integrity: sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==} + + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toposort@2.0.2: + resolution: {integrity: sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==} + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + tr46@2.1.0: + resolution: {integrity: sha512-15Ih7phfcdP5YxqiB+iDtLoaTz4Nd35+IiAv0kQ5FNKHzXgdWqPoTIqEDDJmXceQt4JZk6lVPT8lnDlPpGDppw==} + engines: {node: '>=8'} + + tryer@1.0.1: + resolution: {integrity: sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==} + + ts-api-utils@2.0.1: + resolution: {integrity: sha512-dnlgjFSVetynI8nzgJ+qF62efpglpWRk8isUEWZGWlJYySCTD6aKvbUDu+zbPeDakk3bg5H4XpitHukgfL1m9w==} + engines: {node: '>=18.12'} + peerDependencies: + typescript: '>=4.8.4' + + ts-interface-checker@0.1.13: + resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + + ts-toolbelt@9.6.0: + resolution: {integrity: sha512-nsZd8ZeNUzukXPlJmTBwUAuABDe/9qtVDelJeT/qW0ow3ZS3BsQJtNkan1802aM9Uf68/Y8ljw86Hu0h5IUW3w==} + + tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + + tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + + tsutils@3.21.0: + resolution: {integrity: sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==} + engines: {node: '>= 6'} + peerDependencies: + typescript: '>=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta' + + type-check@0.3.2: + resolution: {integrity: sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==} + engines: {node: '>= 0.8.0'} + + type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + + type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + + type-fest@0.16.0: + resolution: {integrity: sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==} + engines: {node: '>=10'} + + type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typed-array-buffer@1.0.3: + resolution: {integrity: sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==} + engines: {node: '>= 0.4'} + + typed-array-byte-length@1.0.3: + resolution: {integrity: sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==} + engines: {node: '>= 0.4'} + + typed-array-byte-offset@1.0.4: + resolution: {integrity: sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==} + engines: {node: '>= 0.4'} + + typed-array-length@1.0.7: + resolution: {integrity: sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==} + engines: {node: '>= 0.4'} + + typedarray-to-buffer@3.1.5: + resolution: {integrity: sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==} + + typescript-eslint@8.26.0: + resolution: {integrity: sha512-PtVz9nAnuNJuAVeUFvwztjuUgSnJInODAUx47VDwWPXzd5vismPOtPtt83tzNXyOjVQbPRp786D6WFW/M2koIA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + typescript: '>=4.8.4 <5.9.0' + + typescript@5.8.2: + resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} + engines: {node: '>=14.17'} + hasBin: true + + unbox-primitive@1.1.0: + resolution: {integrity: sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==} + engines: {node: '>= 0.4'} + + underscore@1.12.1: + resolution: {integrity: sha512-hEQt0+ZLDVUMhebKxL4x1BTtDY7bavVofhZ9KZ4aI26X9SRaE+Y3m83XUL1UP2jn8ynjndwCCpEHdUG+9pP1Tw==} + + undici-types@6.20.0: + resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + + unicode-canonical-property-names-ecmascript@2.0.1: + resolution: {integrity: sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==} + engines: {node: '>=4'} + + unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + + unicode-match-property-value-ecmascript@2.2.0: + resolution: {integrity: sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==} + engines: {node: '>=4'} + + unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + + unique-string@2.0.0: + resolution: {integrity: sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==} + engines: {node: '>=8'} + + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + + universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + unquote@1.1.1: + resolution: {integrity: sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==} + + upath@1.2.0: + resolution: {integrity: sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==} + engines: {node: '>=4'} + + update-browserslist-db@1.1.3: + resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + + uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + + use-callback-ref@1.3.3: + resolution: {integrity: sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-debounce@10.0.4: + resolution: {integrity: sha512-6Cf7Yr7Wk7Kdv77nnJMf6de4HuDE4dTxKij+RqE9rufDsI6zsbjyAxcH5y2ueJCQAnfgKbzXbZHYlkFwmBlWkw==} + engines: {node: '>= 16.0.0'} + peerDependencies: + react: '*' + + use-sidecar@1.1.3: + resolution: {integrity: sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==} + engines: {node: '>=10'} + peerDependencies: + '@types/react': '*' + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc + peerDependenciesMeta: + '@types/react': + optional: true + + use-sync-external-store@1.4.0: + resolution: {integrity: sha512-9WXSPC5fMv61vaupRkCKCxsPxBocVnwakBEkMIHHpkTTg6icbJtg6jzgtLDm4bl3cSHAca52rYWih0k4K3PfHw==} + peerDependencies: + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + + util.promisify@1.0.1: + resolution: {integrity: sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA==} + + utila@0.4.0: + resolution: {integrity: sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==} + + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + + v8-to-istanbul@8.1.1: + resolution: {integrity: sha512-FGtKtv3xIpR6BYhvgH8MI/y78oT7d8Au3ww4QIxymrCtZEh5b8gCw2siywE+puhEmuWKDtmfrvF5UlB298ut3w==} + engines: {node: '>=10.12.0'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + + victory-area@37.3.6: + resolution: {integrity: sha512-wVC8LKrZJLiSySNuJLRCB449qZTsPiRyzLlNoJwe21y+XA/a2HJbmJSeywmo8P153aX8viKe1H8ygDsTFXQhHw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-axis@37.3.6: + resolution: {integrity: sha512-Vi0dZvgmXmnCdoqc49WckeG5cMXnl7FTtqVhXu9JweA9cgCnkZabBd5mRvAjblb3Lo4j0HZCSPKHYWUPW70qZg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-bar@37.3.6: + resolution: {integrity: sha512-jdATFRWL1LUW/yEpKWx/aId2BiU2o1pPF9+Kh1TFISBduJoI4ZqvZD90H1QK4f/z50PikqiqiDECaKoKM1jfOQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-box-plot@37.3.6: + resolution: {integrity: sha512-GOucnD63h14ScBuISC/nd1GBTEx6gIZfLE+0P0gyeH1poBKq0trTTvpQDvAMuGR8zICfEETG3ltmUMCwRrFyUg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-brush-container@37.3.6: + resolution: {integrity: sha512-LfZ2CgX1cYAqCtYxcSB68OfZS2v0T2VLXoEArd0lCXfRBY1Gya7GacCUcuo7GoK9XOXeslx7S/U95aVutt1VLg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-brush-line@37.3.6: + resolution: {integrity: sha512-zsZJfF1fUj4F7mUoIMV+h73qoTClPA4bKM1terlYrDBD8l/c/f0KBbEotu3E1X+n4QMmDRruswaB/YUdqK5QLA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-candlestick@37.3.6: + resolution: {integrity: sha512-h/mOmkCrsWrirn4dFnpLxJPXpxT+uHxuYxnXGrAyH+YUOrVj3iKaDJlEiVlz5vy30syE5j5hzTQCMsZ/hzHNdg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-canvas@37.3.6: + resolution: {integrity: sha512-1CD4S0uZ92sUGGSIEQferEfSqd/z9EXw9G6zkzPIoJeTKFshpfqCjUkNRx9Iu9Upxt3fUpId8Qwl1YfchmbrFg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-chart@37.3.6: + resolution: {integrity: sha512-IkPo/W4AJ7bPu902TGER09OseR9ODm+FQAKfOBw4JsdEhZZ7BiG9zgd/25+x0r5EsTLu81CYGQVkBa+ZazcOlA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-core@37.3.6: + resolution: {integrity: sha512-aFgO6KokxPbUCPznZP5UPhOdI22pMuwDXKDt6eoQOnkVim66Ia+K95TQar2nwVKGYV5j26aKVf/n9blwphGJRw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-create-container@37.3.6: + resolution: {integrity: sha512-Uf5bFQvqUsXCjqpvBW4LhrdrHkM6dBqxYgub6FCsBb86f84xZQ3vY7jFkg/JfvF0oGKMoWXYYrYLC1sk+fcWVA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-cursor-container@37.3.6: + resolution: {integrity: sha512-+Oiw57d5nE+iq8As8RvepknzmNtKq1Gsc50u1X3IRd4jXtX8zqZrgXGlVZ+BP/tkLsWnGYVjKulwKBf2oaEUuw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-errorbar@37.3.6: + resolution: {integrity: sha512-WGAv/qizOlfmwKv+Yfxr4q6pDgTfloNQwi3Z3M0h8povjMZt74tHYkvi/TASSRYr3zv5kjUqUJ28qAyGMWwryQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-group@37.3.6: + resolution: {integrity: sha512-kgy/Azl5BxwlJAV0KDPGypv35TMrOD1J2ZxnJW2Wyyq+e8i0GGBIv5MoBzou64BRsDlS9V0CYRIjnkHgrBpB5w==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-histogram@37.3.6: + resolution: {integrity: sha512-K4d43MpXHYnGCLEMzfRpJ+lCRRDKALPi/juxfMGVzBPzSMgjC8h9x6hKdxaejiTd/E04UdzNO7J24plL3Uz8rA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-legend@37.3.6: + resolution: {integrity: sha512-vRRrhj3/ENqKVLdaBMzEmR83N6BOjox1bthYT1eJjN2H5SIK35bxn30IkiV/Pz3y627EqZe4TAWaxc0jiJlCiA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-line@37.3.6: + resolution: {integrity: sha512-Ke817uf/qFbN9jU7Dba7CrcHXYO5wAZuKKnyeHJmLDeQeFST0773xejnIuC+dBgZipjFr4KIbSd+VcUafFNE1g==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-pie@37.3.6: + resolution: {integrity: sha512-tvdgAZ/HQWlo3KDDe0XAVbizHuaNMbgkkiF7zfA7Ww+3bHSs+0P9dsDtK2xP365D8gBCOv8pWmuzvKRhzNbqeA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-polar-axis@37.3.6: + resolution: {integrity: sha512-RpFsCkzHezJq5P+C/wtVdjEHX25JIFsSgs6qYSnfr/hayaFbWgK5HhRFpriQm5hg61cx47WxAOLyHvzf0nasvw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-scatter@37.3.6: + resolution: {integrity: sha512-fp95zMTPXgW1cmTowzDXhn+KxePMVDrzU0lotsHQMdBV7eB+ioXdu9hORlx4VHmMYg2ihsGwRTF+VAZ7rGxphA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-selection-container@37.3.6: + resolution: {integrity: sha512-gd3qODDlBtLEJM7+2jCXk2YcLBUmIpYEEHswytMhwc6zihxXipGBUHRulhLj/I05mKay2gaOAg5ewiJHd4Awgw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-shared-events@37.3.6: + resolution: {integrity: sha512-ygrbOtzLUTbtKebacZKyQRekhSAROnAvMkVI/PKsAGsz0ClY9P7qDEJG7eTUUygjO6ax0tI6WNE6JogQzeD1gw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-stack@37.3.6: + resolution: {integrity: sha512-ldod04RdqGJGH5p5eWXCofdTkbhZqIp3iwW7NpxSbMDLs8zPQIVvDFVtuJgMwQiC5vnIpbhMmxVeFbr8m64ZKA==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-tooltip@37.3.6: + resolution: {integrity: sha512-vqaJS9noauOqDDBBAV9Ln9duOY/i17h1DCfCPAqhwPFyvFbwKvAub9zPTeYWAm/14VvWX5O/0yekFCVbcC7hjg==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-vendor@37.3.6: + resolution: {integrity: sha512-SbPDPdDBYp+5MJHhBCAyI7wKM3d5ivekigc2Dk2s7pgbZ9wIgIBYGVw4zGHBml/qTFbexrofXW6Gu4noGxrOwQ==} + + victory-voronoi-container@37.3.6: + resolution: {integrity: sha512-qAAG0rMuK7A4EoJ4cyUk5wNdOW+HuCXNKPOko+hYK6wWOYXJvFhiglYyA85a695YyAXECc6JyJS/crm4IOEFag==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-voronoi@37.3.6: + resolution: {integrity: sha512-Q+1FWHp8IAbmDL9pGWS0y0N4Cb5qmD9OOgxoxCfIDsLlhGvd6LddhRoknWsN7WnreaK+XiwjSfQkdMTCZ4hdhQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory-zoom-container@37.3.6: + resolution: {integrity: sha512-AGL+k20mI44OL5b0VgIxlmnNSefIoFmbbim5NraPmIxbtns9qQW/56ivIncJcYomBungIx99gUpsEpcQaMNHgQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + victory@37.3.6: + resolution: {integrity: sha512-CZ1vjvra0R1U3T2dMI4EsjI8Ng+JmQ2ox/EweSzjkTnHfW/Vn5ylryadawDiYjDMcBvABjO3uODsIlSEm4d/Sw==} + engines: {node: '>=18.0.0'} + peerDependencies: + react: '>=16.6.0' + + vite-node@3.0.8: + resolution: {integrity: sha512-6PhR4H9VGlcwXZ+KWCdMqbtG649xCPZqfI9j2PsK1FcXgEzro5bGHcVKFCTqPLaNKZES8Evqv4LwvZARsq5qlg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + + vite@6.2.1: + resolution: {integrity: sha512-n2GnqDb6XPhlt9B8olZPrgMD/es/Nd1RdChF6CBD/fHW6pUyUTt2sQW2fPRX5GiD9XEa6+8A6A4f2vT6pSsE7Q==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + jiti: '>=1.21.0' + less: '*' + lightningcss: ^1.21.0 + sass: '*' + sass-embedded: '*' + stylus: '*' + sugarss: '*' + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + '@types/node': + optional: true + jiti: + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + + vitest@3.0.8: + resolution: {integrity: sha512-dfqAsNqRGUc8hB9OVR2P0w8PZPEckti2+5rdZip0WIz9WW0MnImJ8XiR61QhqLa92EQzKP2uPkzenKOAHyEIbA==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.0.8 + '@vitest/ui': 3.0.8 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + + w3c-hr-time@1.0.2: + resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} + deprecated: Use your platform's native performance.now() and performance.timeOrigin. + + w3c-xmlserializer@2.0.0: + resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} + engines: {node: '>=10'} + + walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + + watchpack@2.4.2: + resolution: {integrity: sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==} + engines: {node: '>=10.13.0'} + + wbuf@1.7.3: + resolution: {integrity: sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + webidl-conversions@5.0.0: + resolution: {integrity: sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==} + engines: {node: '>=8'} + + webidl-conversions@6.1.0: + resolution: {integrity: sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w==} + engines: {node: '>=10.4'} + + webpack-dev-middleware@5.3.4: + resolution: {integrity: sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==} + engines: {node: '>= 12.13.0'} + peerDependencies: + webpack: ^4.0.0 || ^5.0.0 + + webpack-dev-server@4.15.2: + resolution: {integrity: sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==} + engines: {node: '>= 12.13.0'} + hasBin: true + peerDependencies: + webpack: ^4.37.0 || ^5.0.0 + webpack-cli: '*' + peerDependenciesMeta: + webpack: + optional: true + webpack-cli: + optional: true + + webpack-manifest-plugin@4.1.1: + resolution: {integrity: sha512-YXUAwxtfKIJIKkhg03MKuiFAD72PlrqCiwdwO4VEXdRO5V0ORCNwaOwAZawPZalCbmH9kBDmXnNeQOw+BIEiow==} + engines: {node: '>=12.22.0'} + peerDependencies: + webpack: ^4.44.2 || ^5.47.0 + + webpack-sources@1.4.3: + resolution: {integrity: sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==} + + webpack-sources@2.3.1: + resolution: {integrity: sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==} + engines: {node: '>=10.13.0'} + + webpack-sources@3.2.3: + resolution: {integrity: sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==} + engines: {node: '>=10.13.0'} + + webpack@5.98.0: + resolution: {integrity: sha512-UFynvx+gM44Gv9qFgj0acCQK2VE1CtdfwFdimkapco3hlPCJ/zeq73n2yVKimVbtm+TnApIugGhLJnkU6gjYXA==} + engines: {node: '>=10.13.0'} + hasBin: true + peerDependencies: + webpack-cli: '*' + peerDependenciesMeta: + webpack-cli: + optional: true + + websocket-driver@0.7.4: + resolution: {integrity: sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==} + engines: {node: '>=0.8.0'} + + websocket-extensions@0.1.4: + resolution: {integrity: sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==} + engines: {node: '>=0.8.0'} + + whatwg-encoding@1.0.5: + resolution: {integrity: sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==} + + whatwg-fetch@3.6.20: + resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + + whatwg-mimetype@2.3.0: + resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + + whatwg-url@8.7.0: + resolution: {integrity: sha512-gAojqb/m9Q8a5IV96E3fHJM70AzCkgt4uXYX2O7EmuyOnLrViCQlsEBmF9UQIu3/aeAIp2U17rtbpZWNntQqdg==} + engines: {node: '>=10'} + + which-boxed-primitive@1.1.1: + resolution: {integrity: sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==} + engines: {node: '>= 0.4'} + + which-builtin-type@1.2.1: + resolution: {integrity: sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==} + engines: {node: '>= 0.4'} + + which-collection@1.0.2: + resolution: {integrity: sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==} + engines: {node: '>= 0.4'} + + which-typed-array@1.1.18: + resolution: {integrity: sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==} + engines: {node: '>= 0.4'} + + which@1.3.1: + resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} + hasBin: true + + which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + + workbox-background-sync@6.6.0: + resolution: {integrity: sha512-jkf4ZdgOJxC9u2vztxLuPT/UjlH7m/nWRQ/MgGL0v8BJHoZdVGJd18Kck+a0e55wGXdqyHO+4IQTk0685g4MUw==} + + workbox-broadcast-update@6.6.0: + resolution: {integrity: sha512-nm+v6QmrIFaB/yokJmQ/93qIJ7n72NICxIwQwe5xsZiV2aI93MGGyEyzOzDPVz5THEr5rC3FJSsO3346cId64Q==} + + workbox-build@6.6.0: + resolution: {integrity: sha512-Tjf+gBwOTuGyZwMz2Nk/B13Fuyeo0Q84W++bebbVsfr9iLkDSo6j6PST8tET9HYA58mlRXwlMGpyWO8ETJiXdQ==} + engines: {node: '>=10.0.0'} + + workbox-cacheable-response@6.6.0: + resolution: {integrity: sha512-JfhJUSQDwsF1Xv3EV1vWzSsCOZn4mQ38bWEBR3LdvOxSPgB65gAM6cS2CX8rkkKHRgiLrN7Wxoyu+TuH67kHrw==} + deprecated: workbox-background-sync@6.6.0 + + workbox-core@6.6.0: + resolution: {integrity: sha512-GDtFRF7Yg3DD859PMbPAYPeJyg5gJYXuBQAC+wyrWuuXgpfoOrIQIvFRZnQ7+czTIQjIr1DhLEGFzZanAT/3bQ==} + + workbox-expiration@6.6.0: + resolution: {integrity: sha512-baplYXcDHbe8vAo7GYvyAmlS4f6998Jff513L4XvlzAOxcl8F620O91guoJ5EOf5qeXG4cGdNZHkkVAPouFCpw==} + + workbox-google-analytics@6.6.0: + resolution: {integrity: sha512-p4DJa6OldXWd6M9zRl0H6vB9lkrmqYFkRQ2xEiNdBFp9U0LhsGO7hsBscVEyH9H2/3eZZt8c97NB2FD9U2NJ+Q==} + deprecated: It is not compatible with newer versions of GA starting with v4, as long as you are using GAv3 it should be ok, but the package is not longer being maintained + + workbox-navigation-preload@6.6.0: + resolution: {integrity: sha512-utNEWG+uOfXdaZmvhshrh7KzhDu/1iMHyQOV6Aqup8Mm78D286ugu5k9MFD9SzBT5TcwgwSORVvInaXWbvKz9Q==} + + workbox-precaching@6.6.0: + resolution: {integrity: sha512-eYu/7MqtRZN1IDttl/UQcSZFkHP7dnvr/X3Vn6Iw6OsPMruQHiVjjomDFCNtd8k2RdjLs0xiz9nq+t3YVBcWPw==} + + workbox-range-requests@6.6.0: + resolution: {integrity: sha512-V3aICz5fLGq5DpSYEU8LxeXvsT//mRWzKrfBOIxzIdQnV/Wj7R+LyJVTczi4CQ4NwKhAaBVaSujI1cEjXW+hTw==} + + workbox-recipes@6.6.0: + resolution: {integrity: sha512-TFi3kTgYw73t5tg73yPVqQC8QQjxJSeqjXRO4ouE/CeypmP2O/xqmB/ZFBBQazLTPxILUQ0b8aeh0IuxVn9a6A==} + + workbox-routing@6.6.0: + resolution: {integrity: sha512-x8gdN7VDBiLC03izAZRfU+WKUXJnbqt6PG9Uh0XuPRzJPpZGLKce/FkOX95dWHRpOHWLEq8RXzjW0O+POSkKvw==} + + workbox-strategies@6.6.0: + resolution: {integrity: sha512-eC07XGuINAKUWDnZeIPdRdVja4JQtTuc35TZ8SwMb1ztjp7Ddq2CJ4yqLvWzFWGlYI7CG/YGqaETntTxBGdKgQ==} + + workbox-streams@6.6.0: + resolution: {integrity: sha512-rfMJLVvwuED09CnH1RnIep7L9+mj4ufkTyDPVaXPKlhi9+0czCu+SJggWCIFbPpJaAZmp2iyVGLqS3RUmY3fxg==} + + workbox-sw@6.6.0: + resolution: {integrity: sha512-R2IkwDokbtHUE4Kus8pKO5+VkPHD2oqTgl+XJwh4zbF1HyjAbgNmK/FneZHVU7p03XUt9ICfuGDYISWG9qV/CQ==} + + workbox-webpack-plugin@6.6.0: + resolution: {integrity: sha512-xNZIZHalboZU66Wa7x1YkjIqEy1gTR+zPM+kjrYJzqN7iurYZBctBLISyScjhkJKYuRrZUP0iqViZTh8rS0+3A==} + engines: {node: '>=10.0.0'} + peerDependencies: + webpack: ^4.4.0 || ^5.9.0 + + workbox-window@6.6.0: + resolution: {integrity: sha512-L4N9+vka17d16geaJXXRjENLFldvkWy7JyGxElRD0JvBxvFEd8LOhr+uXCcar/NzAmIBRv9EZ+M+Qr4mOoBITw==} + + wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + + wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + write-file-atomic@3.0.3: + resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} + + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.1: + resolution: {integrity: sha512-RKW2aJZMXeMxVpnZ6bck+RswznaxmzdULiBr6KY7XkTnW8uvt0iT9H5DkHUChXrc+uurzwa0rVI16n/Xzjdz1w==} + 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 + + xml-name-validator@3.0.0: + resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + + yaml@1.10.2: + resolution: {integrity: sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==} + engines: {node: '>= 6'} + + yaml@2.7.0: + resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} + engines: {node: '>= 14'} + hasBin: true + + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + + yup@0.32.11: + resolution: {integrity: sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==} + engines: {node: '>=10'} + + zod-validation-error@3.4.0: + resolution: {integrity: sha512-ZOPR9SVY6Pb2qqO5XHt+MkkTRxGXb4EVtnjc9JpXUOtUB1T9Ru7mZOT361AN3MsetVe7R0a1KZshJDZdgp9miQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + zod: ^3.18.0 + + zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + +snapshots: + + '@adobe/css-tools@4.4.2': {} + + '@alloc/quick-lru@5.2.0': {} + + '@ampproject/remapping@2.3.0': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@apideck/better-ajv-errors@0.3.6(ajv@8.17.1)': + dependencies: + ajv: 8.17.1 + json-schema: 0.4.0 + jsonpointer: 5.0.1 + leven: 3.1.0 + + '@babel/code-frame@7.26.2': + dependencies: + '@babel/helper-validator-identifier': 7.25.9 + js-tokens: 4.0.0 + picocolors: 1.1.1 + + '@babel/compat-data@7.26.8': {} + + '@babel/core@7.26.9': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helpers': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + convert-source-map: 2.0.0 + debug: 4.4.0 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/eslint-parser@7.26.8(@babel/core@7.26.9)(eslint@9.21.0(jiti@1.21.7))': + dependencies: + '@babel/core': 7.26.9 + '@nicolo-ribaudo/eslint-scope-5-internals': 5.1.1-v1 + eslint: 9.21.0(jiti@1.21.7) + eslint-visitor-keys: 2.1.0 + semver: 6.3.1 + + '@babel/generator@7.26.9': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 3.1.0 + + '@babel/helper-annotate-as-pure@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-compilation-targets@7.26.5': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/helper-validator-option': 7.25.9 + browserslist: 4.24.4 + lru-cache: 5.1.1 + semver: 6.3.1 + + '@babel/helper-create-class-features-plugin@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/traverse': 7.26.9 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/helper-create-regexp-features-plugin@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + regexpu-core: 6.2.0 + semver: 6.3.1 + + '@babel/helper-define-polyfill-provider@0.6.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + debug: 4.4.0 + lodash.debounce: 4.0.8 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + '@babel/helper-member-expression-to-functions@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-imports@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-module-transforms@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-optimise-call-expression@7.25.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/helper-plugin-utils@7.26.5': {} + + '@babel/helper-remap-async-to-generator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-wrap-function': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-replace-supers@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-member-expression-to-functions': 7.25.9 + '@babel/helper-optimise-call-expression': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-skip-transparent-expression-wrappers@7.25.9': + dependencies: + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helper-string-parser@7.25.9': {} + + '@babel/helper-validator-identifier@7.25.9': {} + + '@babel/helper-validator-option@7.25.9': {} + + '@babel/helper-wrap-function@7.25.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/helpers@7.26.9': + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/parser@7.26.9': + dependencies: + '@babel/types': 7.26.9 + + '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-class-properties@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-decorators@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-decorators': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-nullish-coalescing-operator@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.9) + + '@babel/plugin-proposal-numeric-separator@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.9) + + '@babel/plugin-proposal-optional-chaining@7.21.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + + '@babel/plugin-proposal-private-property-in-object@7.21.11(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-decorators@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-assertions@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-attributes@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-jsx@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-typescript@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-arrow-functions@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-async-generator-functions@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-async-to-generator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-remap-async-to-generator': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-block-scoped-functions@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-block-scoping@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-class-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-class-static-block@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-classes@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-computed-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/template': 7.26.9 + + '@babel/plugin-transform-destructuring@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dotall-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-keys@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-dynamic-import@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-exponentiation-operator@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-export-namespace-from@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-flow-strip-types@7.26.5(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.9) + + '@babel/plugin-transform-for-of@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-function-name@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-json-strings@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-logical-assignment-operators@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-member-expression-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-modules-amd@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-commonjs@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-systemjs@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-identifier': 7.25.9 + '@babel/traverse': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-modules-umd@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-named-capturing-groups-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-new-target@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-nullish-coalescing-operator@7.26.6(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-numeric-separator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-object-rest-spread@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) + + '@babel/plugin-transform-object-super@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-replace-supers': 7.26.5(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-optional-catch-binding@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-optional-chaining@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-parameters@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-private-methods@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-private-property-in-object@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-property-literals@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-constant-elements@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-display-name@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-jsx-development@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-jsx-self@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-jsx-source@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/types': 7.26.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-react-pure-annotations@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-regenerator@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + regenerator-transform: 0.15.2 + + '@babel/plugin-transform-regexp-modifiers@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-reserved-words@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-runtime@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@babel/helper-plugin-utils': 7.26.5 + babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.9) + babel-plugin-polyfill-corejs3: 0.10.6(@babel/core@7.26.9) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-shorthand-properties@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-spread@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-sticky-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-template-literals@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typeof-symbol@7.26.7(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-typescript@7.26.8(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-annotate-as-pure': 7.25.9 + '@babel/helper-create-class-features-plugin': 7.26.9(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.25.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/plugin-transform-unicode-escapes@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-property-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/plugin-transform-unicode-sets-regex@7.25.9(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-create-regexp-features-plugin': 7.26.3(@babel/core@7.26.9) + '@babel/helper-plugin-utils': 7.26.5 + + '@babel/preset-env@7.26.9(@babel/core@7.26.9)': + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-compilation-targets': 7.26.5 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.26.9) + '@babel/plugin-syntax-import-assertions': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-transform-arrow-functions': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-async-generator-functions': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-async-to-generator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoped-functions': 7.26.5(@babel/core@7.26.9) + '@babel/plugin-transform-block-scoping': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-class-static-block': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-classes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-computed-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-destructuring': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dotall-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-keys': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-duplicate-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-dynamic-import': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-exponentiation-operator': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-export-namespace-from': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-for-of': 7.26.9(@babel/core@7.26.9) + '@babel/plugin-transform-function-name': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-json-strings': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-logical-assignment-operators': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-member-expression-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-amd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-modules-systemjs': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-umd': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-named-capturing-groups-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-new-target': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-nullish-coalescing-operator': 7.26.6(@babel/core@7.26.9) + '@babel/plugin-transform-numeric-separator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-rest-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-object-super': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-catch-binding': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-optional-chaining': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-parameters': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-methods': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-private-property-in-object': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-property-literals': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regenerator': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-regexp-modifiers': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-reserved-words': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-shorthand-properties': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-spread': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-sticky-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-template-literals': 7.26.8(@babel/core@7.26.9) + '@babel/plugin-transform-typeof-symbol': 7.26.7(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-escapes': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-property-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-regex': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-unicode-sets-regex': 7.25.9(@babel/core@7.26.9) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.26.9) + babel-plugin-polyfill-corejs2: 0.4.12(@babel/core@7.26.9) + babel-plugin-polyfill-corejs3: 0.11.1(@babel/core@7.26.9) + babel-plugin-polyfill-regenerator: 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/types': 7.26.9 + esutils: 2.0.3 + + '@babel/preset-react@7.26.3(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-react-jsx-development': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-react-pure-annotations': 7.25.9(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/preset-typescript@7.26.0(@babel/core@7.26.9)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-plugin-utils': 7.26.5 + '@babel/helper-validator-option': 7.25.9 + '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-modules-commonjs': 7.26.3(@babel/core@7.26.9) + '@babel/plugin-transform-typescript': 7.26.8(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + '@babel/runtime@7.26.9': + dependencies: + regenerator-runtime: 0.14.1 + + '@babel/template@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@babel/traverse@7.26.9': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/generator': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + debug: 4.4.0 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + + '@babel/types@7.26.9': + dependencies: + '@babel/helper-string-parser': 7.25.9 + '@babel/helper-validator-identifier': 7.25.9 + + '@bcoe/v8-coverage@0.2.3': {} + + '@bcoe/v8-coverage@1.0.2': {} + + '@chakra-ui/anatomy@2.3.4': {} + + '@chakra-ui/anatomy@2.3.6': {} + + '@chakra-ui/hooks@2.4.4(react@19.0.0)': + dependencies: + '@chakra-ui/utils': 2.2.4(react@19.0.0) + '@zag-js/element-size': 0.31.1 + copy-to-clipboard: 3.3.3 + framesync: 6.1.2 + react: 19.0.0 + + '@chakra-ui/icons@2.2.4(@chakra-ui/react@2.10.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react@19.0.0)': + dependencies: + '@chakra-ui/react': 2.10.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + + '@chakra-ui/react@2.10.6(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0))(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@chakra-ui/hooks': 2.4.4(react@19.0.0) + '@chakra-ui/styled-system': 2.12.2(react@19.0.0) + '@chakra-ui/theme': 3.4.8(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0) + '@chakra-ui/utils': 2.2.4(react@19.0.0) + '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/styled': 11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0) + '@popperjs/core': 2.11.8 + '@zag-js/focus-visible': 0.31.1 + aria-hidden: 1.2.4 + framer-motion: 7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-fast-compare: 3.2.2 + react-focus-lock: 2.13.6(@types/react@19.0.10)(react@19.0.0) + react-remove-scroll: 2.6.3(@types/react@19.0.10)(react@19.0.0) + transitivePeerDependencies: + - '@types/react' + + '@chakra-ui/styled-system@2.12.2(react@19.0.0)': + dependencies: + '@chakra-ui/utils': 2.2.4(react@19.0.0) + csstype: 3.1.3 + transitivePeerDependencies: + - react + + '@chakra-ui/theme-tools@2.2.6(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0)': + dependencies: + '@chakra-ui/anatomy': 2.3.4 + '@chakra-ui/styled-system': 2.12.2(react@19.0.0) + '@chakra-ui/utils': 2.2.2(react@19.0.0) + color2k: 2.0.3 + transitivePeerDependencies: + - react + + '@chakra-ui/theme-tools@2.2.8(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0)': + dependencies: + '@chakra-ui/anatomy': 2.3.6 + '@chakra-ui/styled-system': 2.12.2(react@19.0.0) + '@chakra-ui/utils': 2.2.4(react@19.0.0) + color2k: 2.0.3 + transitivePeerDependencies: + - react + + '@chakra-ui/theme@3.4.8(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0)': + dependencies: + '@chakra-ui/anatomy': 2.3.6 + '@chakra-ui/styled-system': 2.12.2(react@19.0.0) + '@chakra-ui/theme-tools': 2.2.8(@chakra-ui/styled-system@2.12.2(react@19.0.0))(react@19.0.0) + '@chakra-ui/utils': 2.2.4(react@19.0.0) + transitivePeerDependencies: + - react + + '@chakra-ui/utils@2.2.2(react@19.0.0)': + dependencies: + '@types/lodash.mergewith': 4.6.9 + lodash.mergewith: 4.6.2 + react: 19.0.0 + + '@chakra-ui/utils@2.2.4(react@19.0.0)': + dependencies: + '@types/lodash.mergewith': 4.6.9 + lodash.mergewith: 4.6.2 + react: 19.0.0 + + '@csstools/normalize.css@12.1.1': {} + + '@csstools/postcss-cascade-layers@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + '@csstools/postcss-color-function@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-font-format-keywords@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-hwb-function@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-ic-unit@1.0.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-is-pseudo-class@2.0.7(postcss@8.5.3)': + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + '@csstools/postcss-nested-calc@1.0.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-normalize-display-values@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-oklab-function@1.1.1(postcss@8.5.3)': + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-progressive-custom-properties@1.3.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-stepped-value-functions@1.0.1(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-text-decoration-shorthand@1.0.0(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-trigonometric-functions@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + '@csstools/postcss-unset-value@1.0.2(postcss@8.5.3)': + dependencies: + postcss: 8.5.3 + + '@csstools/selector-specificity@2.2.0(postcss-selector-parser@6.1.2)': + dependencies: + postcss-selector-parser: 6.1.2 + + '@datepicker-react/hooks@2.8.4(react@19.0.0)': + dependencies: + date-fns: 2.30.0 + react: 19.0.0 + + '@emotion/babel-plugin@11.13.5': + dependencies: + '@babel/helper-module-imports': 7.25.9 + '@babel/runtime': 7.26.9 + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/serialize': 1.3.3 + babel-plugin-macros: 3.1.0 + convert-source-map: 1.9.0 + escape-string-regexp: 4.0.0 + find-root: 1.1.0 + source-map: 0.5.7 + stylis: 4.2.0 + transitivePeerDependencies: + - supports-color + + '@emotion/cache@11.14.0': + dependencies: + '@emotion/memoize': 0.9.0 + '@emotion/sheet': 1.4.0 + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + stylis: 4.2.0 + + '@emotion/hash@0.9.2': {} + + '@emotion/is-prop-valid@0.8.8': + dependencies: + '@emotion/memoize': 0.7.4 + optional: true + + '@emotion/is-prop-valid@1.3.1': + dependencies: + '@emotion/memoize': 0.9.0 + + '@emotion/memoize@0.7.4': + optional: true + + '@emotion/memoize@0.9.0': {} + + '@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.9 + '@emotion/babel-plugin': 11.13.5 + '@emotion/cache': 11.14.0 + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.0.0) + '@emotion/utils': 1.4.2 + '@emotion/weak-memoize': 0.4.0 + hoist-non-react-statics: 3.3.2 + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.10 + transitivePeerDependencies: + - supports-color + + '@emotion/serialize@1.3.3': + dependencies: + '@emotion/hash': 0.9.2 + '@emotion/memoize': 0.9.0 + '@emotion/unitless': 0.10.0 + '@emotion/utils': 1.4.2 + csstype: 3.1.3 + + '@emotion/sheet@1.4.0': {} + + '@emotion/styled@11.14.0(@emotion/react@11.14.0(@types/react@19.0.10)(react@19.0.0))(@types/react@19.0.10)(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.9 + '@emotion/babel-plugin': 11.13.5 + '@emotion/is-prop-valid': 1.3.1 + '@emotion/react': 11.14.0(@types/react@19.0.10)(react@19.0.0) + '@emotion/serialize': 1.3.3 + '@emotion/use-insertion-effect-with-fallbacks': 1.2.0(react@19.0.0) + '@emotion/utils': 1.4.2 + react: 19.0.0 + optionalDependencies: + '@types/react': 19.0.10 + transitivePeerDependencies: + - supports-color + + '@emotion/unitless@0.10.0': {} + + '@emotion/use-insertion-effect-with-fallbacks@1.2.0(react@19.0.0)': + dependencies: + react: 19.0.0 + + '@emotion/utils@1.4.2': {} + + '@emotion/weak-memoize@0.4.0': {} + + '@esbuild/aix-ppc64@0.25.0': + optional: true + + '@esbuild/android-arm64@0.25.0': + optional: true + + '@esbuild/android-arm@0.25.0': + optional: true + + '@esbuild/android-x64@0.25.0': + optional: true + + '@esbuild/darwin-arm64@0.25.0': + optional: true + + '@esbuild/darwin-x64@0.25.0': + optional: true + + '@esbuild/freebsd-arm64@0.25.0': + optional: true + + '@esbuild/freebsd-x64@0.25.0': + optional: true + + '@esbuild/linux-arm64@0.25.0': + optional: true + + '@esbuild/linux-arm@0.25.0': + optional: true + + '@esbuild/linux-ia32@0.25.0': + optional: true + + '@esbuild/linux-loong64@0.25.0': + optional: true + + '@esbuild/linux-mips64el@0.25.0': + optional: true + + '@esbuild/linux-ppc64@0.25.0': + optional: true + + '@esbuild/linux-riscv64@0.25.0': + optional: true + + '@esbuild/linux-s390x@0.25.0': + optional: true + + '@esbuild/linux-x64@0.25.0': + optional: true + + '@esbuild/netbsd-arm64@0.25.0': + optional: true + + '@esbuild/netbsd-x64@0.25.0': + optional: true + + '@esbuild/openbsd-arm64@0.25.0': + optional: true + + '@esbuild/openbsd-x64@0.25.0': + optional: true + + '@esbuild/sunos-x64@0.25.0': + optional: true + + '@esbuild/win32-arm64@0.25.0': + optional: true + + '@esbuild/win32-ia32@0.25.0': + optional: true + + '@esbuild/win32-x64@0.25.0': + optional: true + + '@eslint-community/eslint-utils@4.4.1(eslint@9.21.0(jiti@1.21.7))': + dependencies: + eslint: 9.21.0(jiti@1.21.7) + eslint-visitor-keys: 3.4.3 + + '@eslint-community/regexpp@4.12.1': {} + + '@eslint/config-array@0.19.2': + dependencies: + '@eslint/object-schema': 2.1.6 + debug: 4.4.0 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + + '@eslint/core@0.12.0': + dependencies: + '@types/json-schema': 7.0.15 + + '@eslint/eslintrc@3.3.0': + dependencies: + ajv: 6.12.6 + debug: 4.4.0 + espree: 10.3.0 + globals: 14.0.0 + ignore: 5.3.2 + import-fresh: 3.3.1 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + + '@eslint/js@9.21.0': {} + + '@eslint/object-schema@2.1.6': {} + + '@eslint/plugin-kit@0.2.7': + dependencies: + '@eslint/core': 0.12.0 + levn: 0.4.1 + + '@fontsource/inter@4.5.15': {} + + '@hookform/resolvers@2.9.11(react-hook-form@7.54.2(react@19.0.0))': + dependencies: + react-hook-form: 7.54.2(react@19.0.0) + + '@humanfs/core@0.19.1': {} + + '@humanfs/node@0.16.6': + dependencies: + '@humanfs/core': 0.19.1 + '@humanwhocodes/retry': 0.3.1 + + '@humanwhocodes/module-importer@1.0.1': {} + + '@humanwhocodes/retry@0.3.1': {} + + '@humanwhocodes/retry@0.4.2': {} + + '@isaacs/cliui@8.0.2': + dependencies: + string-width: 5.1.2 + string-width-cjs: string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: wrap-ansi@7.0.0 + + '@istanbuljs/load-nyc-config@1.1.0': + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + + '@istanbuljs/schema@0.1.3': {} + + '@jest/console@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + + '@jest/console@28.1.3': + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.13.9 + chalk: 4.1.2 + jest-message-util: 28.1.3 + jest-util: 28.1.3 + slash: 3.0.0 + + '@jest/core@27.5.1': + dependencies: + '@jest/console': 27.5.1 + '@jest/reporters': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.8.1 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 27.5.1 + jest-config: 27.5.1 + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-resolve-dependencies: 27.5.1 + jest-runner: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + jest-watcher: 27.5.1 + micromatch: 4.0.8 + rimraf: 3.0.2 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + '@jest/environment@27.5.1': + dependencies: + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + jest-mock: 27.5.1 + + '@jest/fake-timers@27.5.1': + dependencies: + '@jest/types': 27.5.1 + '@sinonjs/fake-timers': 8.1.0 + '@types/node': 22.13.9 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + '@jest/globals@27.5.1': + dependencies: + '@jest/environment': 27.5.1 + '@jest/types': 27.5.1 + expect: 27.5.1 + + '@jest/reporters@27.5.1': + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 5.2.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.7 + jest-haste-map: 27.5.1 + jest-resolve: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + slash: 3.0.0 + source-map: 0.6.1 + string-length: 4.0.2 + terminal-link: 2.1.1 + v8-to-istanbul: 8.1.1 + transitivePeerDependencies: + - supports-color + + '@jest/schemas@28.1.3': + dependencies: + '@sinclair/typebox': 0.24.51 + + '@jest/source-map@27.5.1': + dependencies: + callsites: 3.1.0 + graceful-fs: 4.2.11 + source-map: 0.6.1 + + '@jest/test-result@27.5.1': + dependencies: + '@jest/console': 27.5.1 + '@jest/types': 27.5.1 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-result@28.1.3': + dependencies: + '@jest/console': 28.1.3 + '@jest/types': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + + '@jest/test-sequencer@27.5.1': + dependencies: + '@jest/test-result': 27.5.1 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-runtime: 27.5.1 + transitivePeerDependencies: + - supports-color + + '@jest/transform@27.5.1': + dependencies: + '@babel/core': 7.26.9 + '@jest/types': 27.5.1 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 1.9.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-regex-util: 27.5.1 + jest-util: 27.5.1 + micromatch: 4.0.8 + pirates: 4.0.6 + slash: 3.0.0 + source-map: 0.6.1 + write-file-atomic: 3.0.3 + transitivePeerDependencies: + - supports-color + + '@jest/types@27.5.1': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.9 + '@types/yargs': 16.0.9 + chalk: 4.1.2 + + '@jest/types@28.1.3': + dependencies: + '@jest/schemas': 28.1.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 22.13.9 + '@types/yargs': 17.0.33 + chalk: 4.1.2 + + '@jridgewell/gen-mapping@0.3.8': + dependencies: + '@jridgewell/set-array': 1.2.1 + '@jridgewell/sourcemap-codec': 1.5.0 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/resolve-uri@3.1.2': {} + + '@jridgewell/set-array@1.2.1': {} + + '@jridgewell/source-map@0.3.6': + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + '@jridgewell/trace-mapping': 0.3.25 + + '@jridgewell/sourcemap-codec@1.5.0': {} + + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + + '@leichtgewicht/ip-codec@2.0.5': {} + + '@motionone/animation@10.18.0': + dependencies: + '@motionone/easing': 10.18.0 + '@motionone/types': 10.17.1 + '@motionone/utils': 10.18.0 + tslib: 2.4.0 + + '@motionone/dom@10.18.0': + dependencies: + '@motionone/animation': 10.18.0 + '@motionone/generators': 10.18.0 + '@motionone/types': 10.17.1 + '@motionone/utils': 10.18.0 + hey-listen: 1.0.8 + tslib: 2.4.0 + + '@motionone/easing@10.18.0': + dependencies: + '@motionone/utils': 10.18.0 + tslib: 2.4.0 + + '@motionone/generators@10.18.0': + dependencies: + '@motionone/types': 10.17.1 + '@motionone/utils': 10.18.0 + tslib: 2.4.0 + + '@motionone/types@10.17.1': {} + + '@motionone/utils@10.18.0': + dependencies: + '@motionone/types': 10.17.1 + hey-listen: 1.0.8 + tslib: 2.4.0 + + '@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1': + dependencies: + eslint-scope: 5.1.1 + + '@nodelib/fs.scandir@2.1.5': + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + + '@nodelib/fs.stat@2.0.5': {} + + '@nodelib/fs.walk@1.2.8': + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.19.1 + + '@pkgjs/parseargs@0.11.0': + optional: true + + '@pmmmwh/react-refresh-webpack-plugin@0.5.15(react-refresh@0.11.0)(type-fest@0.21.3)(webpack-dev-server@4.15.2(webpack@5.98.0))(webpack@5.98.0)': + dependencies: + ansi-html: 0.0.9 + core-js-pure: 3.41.0 + error-stack-parser: 2.1.4 + html-entities: 2.5.2 + loader-utils: 2.0.4 + react-refresh: 0.11.0 + schema-utils: 4.3.0 + source-map: 0.7.4 + webpack: 5.98.0 + optionalDependencies: + type-fest: 0.21.3 + webpack-dev-server: 4.15.2(webpack@5.98.0) + + '@popperjs/core@2.11.8': {} + + '@react-hook/debounce@3.0.0(react@19.0.0)': + dependencies: + '@react-hook/latest': 1.0.3(react@19.0.0) + react: 19.0.0 + + '@react-hook/event@1.2.6(react@19.0.0)': + dependencies: + react: 19.0.0 + + '@react-hook/latest@1.0.3(react@19.0.0)': + dependencies: + react: 19.0.0 + + '@react-hook/throttle@2.2.0(react@19.0.0)': + dependencies: + '@react-hook/latest': 1.0.3(react@19.0.0) + react: 19.0.0 + + '@react-hook/window-size@3.1.1(react@19.0.0)': + dependencies: + '@react-hook/debounce': 3.0.0(react@19.0.0) + '@react-hook/event': 1.2.6(react@19.0.0) + '@react-hook/throttle': 2.2.0(react@19.0.0) + react: 19.0.0 + + '@remix-run/router@1.0.3': {} + + '@rollup/plugin-babel@5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2)': + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-module-imports': 7.25.9 + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + rollup: 2.79.2 + optionalDependencies: + '@types/babel__core': 7.20.5 + transitivePeerDependencies: + - supports-color + + '@rollup/plugin-node-resolve@11.2.1(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + '@types/resolve': 1.17.1 + builtin-modules: 3.3.0 + deepmerge: 4.3.1 + is-module: 1.0.0 + resolve: 1.22.10 + rollup: 2.79.2 + + '@rollup/plugin-replace@2.4.2(rollup@2.79.2)': + dependencies: + '@rollup/pluginutils': 3.1.0(rollup@2.79.2) + magic-string: 0.25.9 + rollup: 2.79.2 + + '@rollup/pluginutils@3.1.0(rollup@2.79.2)': + dependencies: + '@types/estree': 0.0.39 + estree-walker: 1.0.1 + picomatch: 2.3.1 + rollup: 2.79.2 + + '@rollup/rollup-android-arm-eabi@4.34.9': + optional: true + + '@rollup/rollup-android-arm64@4.34.9': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.9': + optional: true + + '@rollup/rollup-darwin-x64@4.34.9': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.9': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.9': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.9': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.9': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.9': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.9': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.9': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.9': + optional: true + + '@rtsao/scc@1.1.0': {} + + '@rushstack/eslint-patch@1.10.5': {} + + '@sinclair/typebox@0.24.51': {} + + '@sinonjs/commons@1.8.6': + dependencies: + type-detect: 4.0.8 + + '@sinonjs/fake-timers@8.1.0': + dependencies: + '@sinonjs/commons': 1.8.6 + + '@surma/rollup-plugin-off-main-thread@2.2.3': + dependencies: + ejs: 3.1.10 + json5: 2.2.3 + magic-string: 0.25.9 + string.prototype.matchall: 4.0.12 + + '@svgr/babel-plugin-add-jsx-attribute@5.4.0': {} + + '@svgr/babel-plugin-remove-jsx-attribute@5.4.0': {} + + '@svgr/babel-plugin-remove-jsx-empty-expression@5.0.1': {} + + '@svgr/babel-plugin-replace-jsx-attribute-value@5.0.1': {} + + '@svgr/babel-plugin-svg-dynamic-title@5.4.0': {} + + '@svgr/babel-plugin-svg-em-dimensions@5.4.0': {} + + '@svgr/babel-plugin-transform-react-native-svg@5.4.0': {} + + '@svgr/babel-plugin-transform-svg-component@5.5.0': {} + + '@svgr/babel-preset@5.5.0': + dependencies: + '@svgr/babel-plugin-add-jsx-attribute': 5.4.0 + '@svgr/babel-plugin-remove-jsx-attribute': 5.4.0 + '@svgr/babel-plugin-remove-jsx-empty-expression': 5.0.1 + '@svgr/babel-plugin-replace-jsx-attribute-value': 5.0.1 + '@svgr/babel-plugin-svg-dynamic-title': 5.4.0 + '@svgr/babel-plugin-svg-em-dimensions': 5.4.0 + '@svgr/babel-plugin-transform-react-native-svg': 5.4.0 + '@svgr/babel-plugin-transform-svg-component': 5.5.0 + + '@svgr/core@5.5.0': + dependencies: + '@svgr/plugin-jsx': 5.5.0 + camelcase: 6.3.0 + cosmiconfig: 7.1.0 + transitivePeerDependencies: + - supports-color + + '@svgr/hast-util-to-babel-ast@5.5.0': + dependencies: + '@babel/types': 7.26.9 + + '@svgr/plugin-jsx@5.5.0': + dependencies: + '@babel/core': 7.26.9 + '@svgr/babel-preset': 5.5.0 + '@svgr/hast-util-to-babel-ast': 5.5.0 + svg-parser: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@svgr/plugin-svgo@5.5.0': + dependencies: + cosmiconfig: 7.1.0 + deepmerge: 4.3.1 + svgo: 1.3.2 + + '@svgr/webpack@5.5.0': + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-transform-react-constant-elements': 7.25.9(@babel/core@7.26.9) + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/preset-react': 7.26.3(@babel/core@7.26.9) + '@svgr/core': 5.5.0 + '@svgr/plugin-jsx': 5.5.0 + '@svgr/plugin-svgo': 5.5.0 + loader-utils: 2.0.4 + transitivePeerDependencies: + - supports-color + + '@tanstack/react-table@8.21.2(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@tanstack/table-core': 8.21.2 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@tanstack/table-core@8.21.2': {} + + '@testing-library/dom@10.4.0': + dependencies: + '@babel/code-frame': 7.26.2 + '@babel/runtime': 7.26.9 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.6.3': + dependencies: + '@adobe/css-tools': 4.4.2 + aria-query: 5.3.2 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + + '@testing-library/react@16.2.0(@testing-library/dom@10.4.0)(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@babel/runtime': 7.26.9 + '@testing-library/dom': 10.4.0 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.10 + '@types/react-dom': 19.0.4(@types/react@19.0.10) + + '@tootallnate/once@1.1.2': {} + + '@trysound/sax@0.2.0': {} + + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.26.9 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.26.9 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 22.13.9 + + '@types/bonjour@3.5.13': + dependencies: + '@types/node': 22.13.9 + + '@types/connect-history-api-fallback@1.5.4': + dependencies: + '@types/express-serve-static-core': 5.0.6 + '@types/node': 22.13.9 + + '@types/connect@3.4.38': + dependencies: + '@types/node': 22.13.9 + + '@types/d3-array@3.2.1': {} + + '@types/d3-color@3.1.3': {} + + '@types/d3-ease@3.0.2': {} + + '@types/d3-interpolate@3.0.4': + dependencies: + '@types/d3-color': 3.1.3 + + '@types/d3-path@3.1.1': {} + + '@types/d3-scale@4.0.9': + dependencies: + '@types/d3-time': 3.0.4 + + '@types/d3-shape@3.1.7': + dependencies: + '@types/d3-path': 3.1.1 + + '@types/d3-time@3.0.4': {} + + '@types/d3-timer@3.0.2': {} + + '@types/eslint-scope@3.7.7': + dependencies: + '@types/eslint': 9.6.1 + '@types/estree': 1.0.6 + + '@types/eslint@8.56.12': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + + '@types/eslint@9.6.1': + dependencies: + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + + '@types/estree@0.0.39': {} + + '@types/estree@1.0.6': {} + + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 22.13.9 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express-serve-static-core@5.0.6': + dependencies: + '@types/node': 22.13.9 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.18 + '@types/serve-static': 1.15.7 + + '@types/graceful-fs@4.1.9': + dependencies: + '@types/node': 22.13.9 + + '@types/html-minifier-terser@6.1.0': {} + + '@types/http-errors@2.0.4': {} + + '@types/http-proxy@1.17.16': + dependencies: + '@types/node': 22.13.9 + + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/istanbul-lib-report@3.0.3': + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + + '@types/istanbul-reports@3.0.4': + dependencies: + '@types/istanbul-lib-report': 3.0.3 + + '@types/json-schema@7.0.15': {} + + '@types/json5@0.0.29': {} + + '@types/lodash.mergewith@4.6.9': + dependencies: + '@types/lodash': 4.17.16 + + '@types/lodash@4.17.16': {} + + '@types/luxon@3.4.2': {} + + '@types/match-sorter@6.0.0': + dependencies: + match-sorter: 8.0.0 + + '@types/mime@1.3.5': {} + + '@types/node-forge@1.3.11': + dependencies: + '@types/node': 22.13.9 + + '@types/node@22.13.9': + dependencies: + undici-types: 6.20.0 + + '@types/parse-json@4.0.2': {} + + '@types/prettier@2.7.3': {} + + '@types/q@1.5.8': {} + + '@types/qs@6.9.18': {} + + '@types/range-parser@1.2.7': {} + + '@types/react-dom@19.0.4(@types/react@19.0.10)': + dependencies: + '@types/react': 19.0.10 + + '@types/react@19.0.10': + dependencies: + csstype: 3.1.3 + + '@types/resolve@1.17.1': + dependencies: + '@types/node': 22.13.9 + + '@types/retry@0.12.0': {} + + '@types/semver@7.5.8': {} + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 22.13.9 + + '@types/serve-index@1.9.4': + dependencies: + '@types/express': 4.17.21 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 22.13.9 + '@types/send': 0.17.4 + + '@types/sockjs@0.3.36': + dependencies: + '@types/node': 22.13.9 + + '@types/stack-utils@2.0.3': {} + + '@types/trusted-types@2.0.7': {} + + '@types/ws@8.18.0': + dependencies: + '@types/node': 22.13.9 + + '@types/yargs-parser@21.0.3': {} + + '@types/yargs@16.0.9': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@types/yargs@17.0.33': + dependencies: + '@types/yargs-parser': 21.0.3 + + '@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/type-utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + debug: 4.4.0 + eslint: 9.21.0(jiti@1.21.7) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare-lite: 1.4.0 + semver: 7.7.1 + tsutils: 3.21.0(typescript@5.8.2) + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/eslint-plugin@8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@eslint-community/regexpp': 4.12.1 + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/type-utils': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.26.0 + eslint: 9.21.0(jiti@1.21.7) + graphemer: 1.4.0 + ignore: 5.3.2 + natural-compare: 1.4.0 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/experimental-utils@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2) + debug: 4.4.0 + eslint: 9.21.0(jiti@1.21.7) + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) + '@typescript-eslint/visitor-keys': 8.26.0 + debug: 4.4.0 + eslint: 9.21.0(jiti@1.21.7) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/scope-manager@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + + '@typescript-eslint/scope-manager@8.26.0': + dependencies: + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 + + '@typescript-eslint/type-utils@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2) + '@typescript-eslint/utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + debug: 4.4.0 + eslint: 9.21.0(jiti@1.21.7) + tsutils: 3.21.0(typescript@5.8.2) + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/type-utils@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + debug: 4.4.0 + eslint: 9.21.0(jiti@1.21.7) + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/types@5.62.0': {} + + '@typescript-eslint/types@8.26.0': {} + + '@typescript-eslint/typescript-estree@5.62.0(typescript@5.8.2)': + dependencies: + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/visitor-keys': 5.62.0 + debug: 4.4.0 + globby: 11.1.0 + is-glob: 4.0.3 + semver: 7.7.1 + tsutils: 3.21.0(typescript@5.8.2) + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/typescript-estree@8.26.0(typescript@5.8.2)': + dependencies: + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/visitor-keys': 8.26.0 + debug: 4.4.0 + fast-glob: 3.3.3 + is-glob: 4.0.3 + minimatch: 9.0.5 + semver: 7.7.1 + ts-api-utils: 2.0.1(typescript@5.8.2) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/utils@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@1.21.7)) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.8 + '@typescript-eslint/scope-manager': 5.62.0 + '@typescript-eslint/types': 5.62.0 + '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + eslint-scope: 5.1.1 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + - typescript + + '@typescript-eslint/utils@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)': + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@1.21.7)) + '@typescript-eslint/scope-manager': 8.26.0 + '@typescript-eslint/types': 8.26.0 + '@typescript-eslint/typescript-estree': 8.26.0(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + '@typescript-eslint/visitor-keys@5.62.0': + dependencies: + '@typescript-eslint/types': 5.62.0 + eslint-visitor-keys: 3.4.3 + + '@typescript-eslint/visitor-keys@8.26.0': + dependencies: + '@typescript-eslint/types': 8.26.0 + eslint-visitor-keys: 4.2.0 + + '@uidotdev/usehooks@2.4.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + '@vitejs/plugin-react@4.3.4(vite@6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0))': + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-transform-react-jsx-self': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-react-jsx-source': 7.25.9(@babel/core@7.26.9) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + '@vitest/coverage-v8@3.0.8(vitest@3.0.8(@types/node@22.13.9)(jiti@1.21.7)(jsdom@16.7.0)(terser@5.39.0)(yaml@2.7.0))': + dependencies: + '@ampproject/remapping': 2.3.0 + '@bcoe/v8-coverage': 1.0.2 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 5.0.6 + istanbul-reports: 3.1.7 + magic-string: 0.30.17 + magicast: 0.3.5 + std-env: 3.8.1 + test-exclude: 7.0.1 + tinyrainbow: 2.0.0 + vitest: 3.0.8(@types/node@22.13.9)(jiti@1.21.7)(jsdom@16.7.0)(terser@5.39.0)(yaml@2.7.0) + transitivePeerDependencies: + - supports-color + + '@vitest/expect@3.0.8': + dependencies: + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.0.8(vite@6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0))': + dependencies: + '@vitest/spy': 3.0.8 + estree-walker: 3.0.3 + magic-string: 0.30.17 + optionalDependencies: + vite: 6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + + '@vitest/pretty-format@3.0.8': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.0.8': + dependencies: + '@vitest/utils': 3.0.8 + pathe: 2.0.3 + + '@vitest/snapshot@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + magic-string: 0.30.17 + pathe: 2.0.3 + + '@vitest/spy@3.0.8': + dependencies: + tinyspy: 3.0.2 + + '@vitest/utils@3.0.8': + dependencies: + '@vitest/pretty-format': 3.0.8 + loupe: 3.1.3 + tinyrainbow: 2.0.0 + + '@webassemblyjs/ast@1.14.1': + dependencies: + '@webassemblyjs/helper-numbers': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + + '@webassemblyjs/floating-point-hex-parser@1.13.2': {} + + '@webassemblyjs/helper-api-error@1.13.2': {} + + '@webassemblyjs/helper-buffer@1.14.1': {} + + '@webassemblyjs/helper-numbers@1.13.2': + dependencies: + '@webassemblyjs/floating-point-hex-parser': 1.13.2 + '@webassemblyjs/helper-api-error': 1.13.2 + '@xtuc/long': 4.2.2 + + '@webassemblyjs/helper-wasm-bytecode@1.13.2': {} + + '@webassemblyjs/helper-wasm-section@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/wasm-gen': 1.14.1 + + '@webassemblyjs/ieee754@1.13.2': + dependencies: + '@xtuc/ieee754': 1.2.0 + + '@webassemblyjs/leb128@1.13.2': + dependencies: + '@xtuc/long': 4.2.2 + + '@webassemblyjs/utf8@1.13.2': {} + + '@webassemblyjs/wasm-edit@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/helper-wasm-section': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-opt': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + '@webassemblyjs/wast-printer': 1.14.1 + + '@webassemblyjs/wasm-gen@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wasm-opt@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-buffer': 1.14.1 + '@webassemblyjs/wasm-gen': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + + '@webassemblyjs/wasm-parser@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/helper-api-error': 1.13.2 + '@webassemblyjs/helper-wasm-bytecode': 1.13.2 + '@webassemblyjs/ieee754': 1.13.2 + '@webassemblyjs/leb128': 1.13.2 + '@webassemblyjs/utf8': 1.13.2 + + '@webassemblyjs/wast-printer@1.14.1': + dependencies: + '@webassemblyjs/ast': 1.14.1 + '@xtuc/long': 4.2.2 + + '@xtuc/ieee754@1.2.0': {} + + '@xtuc/long@4.2.2': {} + + '@zag-js/dom-query@0.31.1': {} + + '@zag-js/element-size@0.31.1': {} + + '@zag-js/focus-visible@0.31.1': + dependencies: + '@zag-js/dom-query': 0.31.1 + + abab@2.0.6: {} + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + + acorn-globals@6.0.0: + dependencies: + acorn: 7.4.1 + acorn-walk: 7.2.0 + + acorn-jsx@5.3.2(acorn@8.14.1): + dependencies: + acorn: 8.14.1 + + acorn-walk@7.2.0: {} + + acorn@7.4.1: {} + + acorn@8.14.1: {} + + address@1.2.2: {} + + adjust-sourcemap-loader@4.0.0: + dependencies: + loader-utils: 2.0.4 + regex-parser: 2.3.1 + + agent-base@6.0.2: + dependencies: + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + ajv-formats@2.1.1(ajv@8.17.1): + optionalDependencies: + ajv: 8.17.1 + + ajv-keywords@3.5.2(ajv@6.12.6): + dependencies: + ajv: 6.12.6 + + ajv-keywords@5.1.0(ajv@8.17.1): + dependencies: + ajv: 8.17.1 + fast-deep-equal: 3.1.3 + + ajv@6.12.6: + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + + ajv@8.17.1: + dependencies: + fast-deep-equal: 3.1.3 + fast-uri: 3.0.6 + json-schema-traverse: 1.0.0 + require-from-string: 2.0.2 + + ansi-escapes@4.3.2: + dependencies: + type-fest: 0.21.3 + + ansi-html-community@0.0.8: {} + + ansi-html@0.0.9: {} + + ansi-regex@5.0.1: {} + + ansi-regex@6.1.0: {} + + ansi-styles@3.2.1: + dependencies: + color-convert: 1.9.3 + + ansi-styles@4.3.0: + dependencies: + color-convert: 2.0.1 + + ansi-styles@5.2.0: {} + + ansi-styles@6.2.1: {} + + any-promise@1.3.0: {} + + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + + arg@5.0.2: {} + + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + + argparse@2.0.1: {} + + aria-hidden@1.2.4: + dependencies: + tslib: 2.8.1 + + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + + array-buffer-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + is-array-buffer: 3.0.5 + + array-flatten@1.1.1: {} + + array-includes@3.1.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + is-string: 1.1.1 + + array-union@2.1.0: {} + + array.prototype.findlast@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.findlastindex@1.2.5: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-shim-unscopables: 1.1.0 + + array.prototype.flat@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.flatmap@1.3.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-shim-unscopables: 1.1.0 + + array.prototype.reduce@1.0.7: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-array-method-boxes-properly: 1.0.0 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + is-string: 1.1.1 + + array.prototype.tosorted@1.1.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-shim-unscopables: 1.1.0 + + arraybuffer.prototype.slice@1.0.4: + dependencies: + array-buffer-byte-length: 1.0.2 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + is-array-buffer: 3.0.5 + + asap@2.0.6: {} + + assertion-error@2.0.1: {} + + ast-types-flow@0.0.8: {} + + async-function@1.0.0: {} + + async@3.2.6: {} + + asynckit@0.4.0: {} + + at-least-node@1.0.0: {} + + autoprefixer@10.4.20(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001702 + fraction.js: 4.3.7 + normalize-range: 0.1.2 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + available-typed-arrays@1.0.7: + dependencies: + possible-typed-array-names: 1.1.0 + + axe-core@4.10.3: {} + + axobject-query@4.1.0: {} + + babel-jest@27.5.1(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 27.5.1(@babel/core@7.26.9) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + + babel-loader@8.4.1(@babel/core@7.26.9)(webpack@5.98.0): + dependencies: + '@babel/core': 7.26.9 + find-cache-dir: 3.3.2 + loader-utils: 2.0.4 + make-dir: 3.1.0 + schema-utils: 2.7.1 + webpack: 5.98.0 + + babel-plugin-istanbul@6.1.1: + dependencies: + '@babel/helper-plugin-utils': 7.26.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-jest-hoist@27.5.1: + dependencies: + '@babel/template': 7.26.9 + '@babel/types': 7.26.9 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.6 + + babel-plugin-macros@3.1.0: + dependencies: + '@babel/runtime': 7.26.9 + cosmiconfig: 7.1.0 + resolve: 1.22.10 + + babel-plugin-named-asset-import@0.3.8(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + + babel-plugin-polyfill-corejs2@0.4.12(@babel/core@7.26.9): + dependencies: + '@babel/compat-data': 7.26.8 + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.10.6(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-corejs3@0.11.1(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + core-js-compat: 3.41.0 + transitivePeerDependencies: + - supports-color + + babel-plugin-polyfill-regenerator@0.6.3(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/helper-define-polyfill-provider': 0.6.3(@babel/core@7.26.9) + transitivePeerDependencies: + - supports-color + + babel-plugin-react-compiler@19.0.0-beta-27714ef-20250124: + dependencies: + '@babel/types': 7.26.9 + + babel-plugin-transform-react-remove-prop-types@0.4.24: {} + + babel-preset-current-node-syntax@1.1.0(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.26.9) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.26.9) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-import-attributes': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.26.9) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.26.9) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.26.9) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.26.9) + + babel-preset-jest@27.5.1(@babel/core@7.26.9): + dependencies: + '@babel/core': 7.26.9 + babel-plugin-jest-hoist: 27.5.1 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.9) + + babel-preset-react-app@10.1.0: + dependencies: + '@babel/core': 7.26.9 + '@babel/plugin-proposal-class-properties': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-proposal-decorators': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-proposal-nullish-coalescing-operator': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-proposal-numeric-separator': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-proposal-optional-chaining': 7.21.0(@babel/core@7.26.9) + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.9) + '@babel/plugin-proposal-private-property-in-object': 7.21.11(@babel/core@7.26.9) + '@babel/plugin-transform-flow-strip-types': 7.26.5(@babel/core@7.26.9) + '@babel/plugin-transform-react-display-name': 7.25.9(@babel/core@7.26.9) + '@babel/plugin-transform-runtime': 7.26.9(@babel/core@7.26.9) + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/preset-react': 7.26.3(@babel/core@7.26.9) + '@babel/preset-typescript': 7.26.0(@babel/core@7.26.9) + '@babel/runtime': 7.26.9 + babel-plugin-macros: 3.1.0 + babel-plugin-transform-react-remove-prop-types: 0.4.24 + transitivePeerDependencies: + - supports-color + + balanced-match@1.0.2: {} + + batch@0.6.1: {} + + bfj@7.1.0: + dependencies: + bluebird: 3.7.2 + check-types: 11.2.3 + hoopy: 0.1.4 + jsonpath: 1.1.1 + tryer: 1.0.1 + + big.js@5.2.2: {} + + binary-extensions@2.3.0: {} + + bluebird@3.7.2: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + on-finished: 2.4.1 + qs: 6.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bonjour-service@1.3.0: + dependencies: + fast-deep-equal: 3.1.3 + multicast-dns: 7.2.5 + + boolbase@1.0.0: {} + + brace-expansion@1.1.11: + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + brace-expansion@2.0.1: + dependencies: + balanced-match: 1.0.2 + + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-process-hrtime@1.0.0: {} + + browserslist@4.24.4: + dependencies: + caniuse-lite: 1.0.30001702 + electron-to-chromium: 1.5.113 + node-releases: 2.0.19 + update-browserslist-db: 1.1.3(browserslist@4.24.4) + + bser@2.1.1: + dependencies: + node-int64: 0.4.0 + + buffer-from@1.1.2: {} + + builtin-modules@3.3.0: {} + + bytes@3.1.2: {} + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bind@1.0.8: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + get-intrinsic: 1.3.0 + set-function-length: 1.2.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + + callsites@3.1.0: {} + + camel-case@4.1.2: + dependencies: + pascal-case: 3.1.2 + tslib: 2.8.1 + + camelcase-css@2.0.1: {} + + camelcase@5.3.1: {} + + camelcase@6.3.0: {} + + caniuse-api@3.0.0: + dependencies: + browserslist: 4.24.4 + caniuse-lite: 1.0.30001702 + lodash.memoize: 4.1.2 + lodash.uniq: 4.5.0 + + caniuse-lite@1.0.30001702: {} + + case-sensitive-paths-webpack-plugin@2.4.0: {} + + chai@5.2.0: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.1.3 + pathval: 2.0.0 + + chalk@2.4.2: + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + char-regex@1.0.2: {} + + char-regex@2.0.2: {} + + check-error@2.1.1: {} + + check-types@11.2.3: {} + + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + + chrome-trace-event@1.0.4: {} + + ci-info@3.9.0: {} + + cjs-module-lexer@1.4.3: {} + + clean-css@5.3.3: + dependencies: + source-map: 0.6.1 + + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + co@4.6.0: {} + + coa@2.0.2: + dependencies: + '@types/q': 1.5.8 + chalk: 2.4.2 + q: 1.5.1 + + collect-v8-coverage@1.0.2: {} + + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + + color-convert@2.0.1: + dependencies: + color-name: 1.1.4 + + color-name@1.1.3: {} + + color-name@1.1.4: {} + + color2k@2.0.3: {} + + colord@2.9.3: {} + + colorette@2.0.20: {} + + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + + commander@2.20.3: {} + + commander@4.1.1: {} + + commander@7.2.0: {} + + commander@8.3.0: {} + + common-tags@1.8.2: {} + + commondir@1.0.1: {} + + compressible@2.0.18: + dependencies: + mime-db: 1.53.0 + + compression@1.8.0: + dependencies: + bytes: 3.1.2 + compressible: 2.0.18 + debug: 2.6.9 + negotiator: 0.6.4 + on-headers: 1.0.2 + safe-buffer: 5.2.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + concat-map@0.0.1: {} + + confusing-browser-globals@1.0.11: {} + + connect-history-api-fallback@2.0.0: {} + + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + convert-source-map@1.9.0: {} + + convert-source-map@2.0.0: {} + + cookie-signature@1.0.6: {} + + cookie@0.7.1: {} + + copy-to-clipboard@3.3.3: + dependencies: + toggle-selection: 1.0.6 + + core-js-compat@3.41.0: + dependencies: + browserslist: 4.24.4 + + core-js-pure@3.41.0: {} + + core-js@3.41.0: {} + + core-util-is@1.0.3: {} + + cosmiconfig@6.0.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cosmiconfig@7.1.0: + dependencies: + '@types/parse-json': 4.0.2 + import-fresh: 3.3.1 + parse-json: 5.2.0 + path-type: 4.0.0 + yaml: 1.10.2 + + cross-spawn@7.0.6: + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + + crypto-random-string@2.0.0: {} + + css-blank-pseudo@3.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + css-declaration-sorter@6.4.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + css-has-pseudo@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + css-loader@6.11.0(webpack@5.98.0): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-modules-extract-imports: 3.1.0(postcss@8.5.3) + postcss-modules-local-by-default: 4.2.0(postcss@8.5.3) + postcss-modules-scope: 3.2.1(postcss@8.5.3) + postcss-modules-values: 4.0.0(postcss@8.5.3) + postcss-value-parser: 4.2.0 + semver: 7.7.1 + optionalDependencies: + webpack: 5.98.0 + + css-minimizer-webpack-plugin@3.4.1(webpack@5.98.0): + dependencies: + cssnano: 5.1.15(postcss@8.5.3) + jest-worker: 27.5.1 + postcss: 8.5.3 + schema-utils: 4.3.0 + serialize-javascript: 6.0.2 + source-map: 0.6.1 + webpack: 5.98.0 + + css-prefers-color-scheme@6.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + css-select-base-adapter@0.1.1: {} + + css-select@2.1.0: + dependencies: + boolbase: 1.0.0 + css-what: 3.4.2 + domutils: 1.7.0 + nth-check: 1.0.2 + + css-select@4.3.0: + dependencies: + boolbase: 1.0.0 + css-what: 6.1.0 + domhandler: 4.3.1 + domutils: 2.8.0 + nth-check: 2.1.1 + + css-tree@1.0.0-alpha.37: + dependencies: + mdn-data: 2.0.4 + source-map: 0.6.1 + + css-tree@1.1.3: + dependencies: + mdn-data: 2.0.14 + source-map: 0.6.1 + + css-what@3.4.2: {} + + css-what@6.1.0: {} + + css.escape@1.5.1: {} + + cssdb@7.11.2: {} + + cssesc@3.0.0: {} + + cssnano-preset-default@5.2.14(postcss@8.5.3): + dependencies: + css-declaration-sorter: 6.4.1(postcss@8.5.3) + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-calc: 8.2.4(postcss@8.5.3) + postcss-colormin: 5.3.1(postcss@8.5.3) + postcss-convert-values: 5.1.3(postcss@8.5.3) + postcss-discard-comments: 5.1.2(postcss@8.5.3) + postcss-discard-duplicates: 5.1.0(postcss@8.5.3) + postcss-discard-empty: 5.1.1(postcss@8.5.3) + postcss-discard-overridden: 5.1.0(postcss@8.5.3) + postcss-merge-longhand: 5.1.7(postcss@8.5.3) + postcss-merge-rules: 5.1.4(postcss@8.5.3) + postcss-minify-font-values: 5.1.0(postcss@8.5.3) + postcss-minify-gradients: 5.1.1(postcss@8.5.3) + postcss-minify-params: 5.1.4(postcss@8.5.3) + postcss-minify-selectors: 5.2.1(postcss@8.5.3) + postcss-normalize-charset: 5.1.0(postcss@8.5.3) + postcss-normalize-display-values: 5.1.0(postcss@8.5.3) + postcss-normalize-positions: 5.1.1(postcss@8.5.3) + postcss-normalize-repeat-style: 5.1.1(postcss@8.5.3) + postcss-normalize-string: 5.1.0(postcss@8.5.3) + postcss-normalize-timing-functions: 5.1.0(postcss@8.5.3) + postcss-normalize-unicode: 5.1.1(postcss@8.5.3) + postcss-normalize-url: 5.1.0(postcss@8.5.3) + postcss-normalize-whitespace: 5.1.1(postcss@8.5.3) + postcss-ordered-values: 5.1.3(postcss@8.5.3) + postcss-reduce-initial: 5.1.2(postcss@8.5.3) + postcss-reduce-transforms: 5.1.0(postcss@8.5.3) + postcss-svgo: 5.1.0(postcss@8.5.3) + postcss-unique-selectors: 5.1.1(postcss@8.5.3) + + cssnano-utils@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + cssnano@5.1.15(postcss@8.5.3): + dependencies: + cssnano-preset-default: 5.2.14(postcss@8.5.3) + lilconfig: 2.1.0 + postcss: 8.5.3 + yaml: 1.10.2 + + csso@4.2.0: + dependencies: + css-tree: 1.1.3 + + cssom@0.3.8: {} + + cssom@0.4.4: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + + csstype@3.1.3: {} + + d3-array@3.2.4: + dependencies: + internmap: 2.0.3 + + d3-color@3.1.0: {} + + d3-ease@3.0.1: {} + + d3-format@3.1.0: {} + + d3-interpolate@3.0.1: + dependencies: + d3-color: 3.1.0 + + d3-path@3.1.0: {} + + d3-scale@4.0.2: + dependencies: + d3-array: 3.2.4 + d3-format: 3.1.0 + d3-interpolate: 3.0.1 + d3-time: 3.1.0 + d3-time-format: 4.1.0 + + d3-shape@3.2.0: + dependencies: + d3-path: 3.1.0 + + d3-time-format@4.1.0: + dependencies: + d3-time: 3.1.0 + + d3-time@3.1.0: + dependencies: + d3-array: 3.2.4 + + d3-timer@3.0.1: {} + + d3-voronoi@1.1.4: {} + + damerau-levenshtein@1.0.8: {} + + data-urls@2.0.0: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + + data-view-buffer@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-length@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + data-view-byte-offset@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-data-view: 1.0.2 + + date-fns@2.30.0: + dependencies: + '@babel/runtime': 7.26.9 + + date-fns@4.1.0: {} + + debounce-promise@3.1.2: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + + debug@4.4.0: + dependencies: + ms: 2.1.3 + + decimal.js@10.5.0: {} + + dedent@0.7.0: {} + + deep-eql@5.0.2: {} + + deep-is@0.1.4: {} + + deepmerge@4.3.1: {} + + default-gateway@6.0.3: + dependencies: + execa: 5.1.1 + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-lazy-prop@2.0.0: {} + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + + delaunator@4.0.1: {} + + delaunay-find@0.0.6: + dependencies: + delaunator: 4.0.1 + + delayed-stream@1.0.0: {} + + depd@1.1.2: {} + + depd@2.0.0: {} + + dequal@2.0.3: {} + + destroy@1.2.0: {} + + detect-newline@3.1.0: {} + + detect-node-es@1.1.0: {} + + detect-node@2.1.0: {} + + detect-port-alt@1.1.6: + dependencies: + address: 1.2.2 + debug: 2.6.9 + transitivePeerDependencies: + - supports-color + + didyoumean@1.2.2: {} + + diff-sequences@27.5.1: {} + + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + + dlv@1.1.3: {} + + dns-packet@5.6.1: + dependencies: + '@leichtgewicht/ip-codec': 2.0.5 + + doctrine@2.1.0: + dependencies: + esutils: 2.0.3 + + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + + dom-converter@0.2.0: + dependencies: + utila: 0.4.0 + + dom-serializer@0.2.2: + dependencies: + domelementtype: 2.3.0 + entities: 2.2.0 + + dom-serializer@1.4.1: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + entities: 2.2.0 + + domelementtype@1.3.1: {} + + domelementtype@2.3.0: {} + + domexception@2.0.1: + dependencies: + webidl-conversions: 5.0.0 + + domhandler@4.3.1: + dependencies: + domelementtype: 2.3.0 + + domutils@1.7.0: + dependencies: + dom-serializer: 0.2.2 + domelementtype: 1.3.1 + + domutils@2.8.0: + dependencies: + dom-serializer: 1.4.1 + domelementtype: 2.3.0 + domhandler: 4.3.1 + + dot-case@3.0.4: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + dotenv-expand@5.1.0: {} + + dotenv@10.0.0: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + + duplexer@0.1.2: {} + + eastasianwidth@0.2.0: {} + + easy-peasy@5.2.0(@types/react-dom@19.0.4(@types/react@19.0.10))(@types/react@19.0.10)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@babel/runtime': 7.26.9 + fast-deep-equal: 3.1.3 + immer: 9.0.21 + react: 19.0.0 + redux: 4.2.1 + redux-thunk: 2.4.2(redux@4.2.1) + ts-toolbelt: 9.6.0 + use-sync-external-store: 1.4.0(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.10 + '@types/react-dom': 19.0.4(@types/react@19.0.10) + react-dom: 19.0.0(react@19.0.0) + + ee-first@1.1.1: {} + + ejs@3.1.10: + dependencies: + jake: 10.9.2 + + electron-log@5.3.2: {} + + electron-to-chromium@1.5.113: {} + + emittery@0.10.2: {} + + emittery@0.8.1: {} + + emoji-regex@8.0.0: {} + + emoji-regex@9.2.2: {} + + emojis-list@3.0.0: {} + + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + enhanced-resolve@5.18.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + + entities@2.2.0: {} + + error-ex@1.3.2: + dependencies: + is-arrayish: 0.2.1 + + error-stack-parser@2.1.4: + dependencies: + stackframe: 1.3.4 + + es-abstract@1.23.9: + dependencies: + array-buffer-byte-length: 1.0.2 + arraybuffer.prototype.slice: 1.0.4 + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + data-view-buffer: 1.0.2 + data-view-byte-length: 1.0.2 + data-view-byte-offset: 1.0.1 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + es-set-tostringtag: 2.1.0 + es-to-primitive: 1.3.0 + function.prototype.name: 1.1.8 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + get-symbol-description: 1.1.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + internal-slot: 1.1.0 + is-array-buffer: 3.0.5 + is-callable: 1.2.7 + is-data-view: 1.0.2 + is-regex: 1.2.1 + is-shared-array-buffer: 1.0.4 + is-string: 1.1.1 + is-typed-array: 1.1.15 + is-weakref: 1.1.1 + math-intrinsics: 1.1.0 + object-inspect: 1.13.4 + object-keys: 1.1.1 + object.assign: 4.1.7 + own-keys: 1.0.1 + regexp.prototype.flags: 1.5.4 + safe-array-concat: 1.1.3 + safe-push-apply: 1.0.0 + safe-regex-test: 1.1.0 + set-proto: 1.0.0 + string.prototype.trim: 1.2.10 + string.prototype.trimend: 1.0.9 + string.prototype.trimstart: 1.0.8 + typed-array-buffer: 1.0.3 + typed-array-byte-length: 1.0.3 + typed-array-byte-offset: 1.0.4 + typed-array-length: 1.0.7 + unbox-primitive: 1.1.0 + which-typed-array: 1.1.18 + + es-array-method-boxes-properly@1.0.0: {} + + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-iterator-helpers@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-set-tostringtag: 2.1.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + globalthis: 1.0.4 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + has-proto: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + iterator.prototype: 1.1.5 + safe-array-concat: 1.1.3 + + es-module-lexer@1.6.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + es-shim-unscopables@1.1.0: + dependencies: + hasown: 2.0.2 + + es-to-primitive@1.3.0: + dependencies: + is-callable: 1.2.7 + is-date-object: 1.1.0 + is-symbol: 1.1.1 + + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + + escalade@3.2.0: {} + + escape-html@1.0.3: {} + + escape-string-regexp@1.0.5: {} + + escape-string-regexp@2.0.0: {} + + escape-string-regexp@4.0.0: {} + + escodegen@1.14.3: + dependencies: + esprima: 4.0.1 + estraverse: 4.3.0 + esutils: 2.0.3 + optionator: 0.8.3 + optionalDependencies: + source-map: 0.6.1 + + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + + eslint-config-react-app@7.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(eslint@9.21.0(jiti@1.21.7))(jest@27.5.1)(typescript@5.8.2): + dependencies: + '@babel/core': 7.26.9 + '@babel/eslint-parser': 7.26.8(@babel/core@7.26.9)(eslint@9.21.0(jiti@1.21.7)) + '@rushstack/eslint-patch': 1.10.5 + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/parser': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + babel-preset-react-app: 10.1.0 + confusing-browser-globals: 1.0.11 + eslint: 9.21.0(jiti@1.21.7) + eslint-plugin-flowtype: 8.0.3(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-import: 2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-jest: 25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(jest@27.5.1)(typescript@5.8.2) + eslint-plugin-jsx-a11y: 6.10.2(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-react: 7.37.4(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-react-hooks: 4.6.2(eslint@9.21.0(jiti@1.21.7)) + eslint-plugin-testing-library: 5.11.1(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - '@babel/plugin-syntax-flow' + - '@babel/plugin-transform-react-jsx' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - jest + - supports-color + + eslint-import-resolver-node@0.3.9: + dependencies: + debug: 3.2.7 + is-core-module: 2.16.1 + resolve: 1.22.10 + transitivePeerDependencies: + - supports-color + + eslint-module-utils@2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@1.21.7)): + dependencies: + debug: 3.2.7 + optionalDependencies: + '@typescript-eslint/parser': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + + eslint-plugin-flowtype@8.0.3(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(eslint@9.21.0(jiti@1.21.7)): + dependencies: + '@babel/plugin-syntax-flow': 7.26.0(@babel/core@7.26.9) + '@babel/plugin-transform-react-jsx': 7.25.9(@babel/core@7.26.9) + eslint: 9.21.0(jiti@1.21.7) + lodash: 4.17.21 + string-natural-compare: 3.0.1 + + eslint-plugin-import@2.31.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7)): + dependencies: + '@rtsao/scc': 1.1.0 + array-includes: 3.1.8 + array.prototype.findlastindex: 1.2.5 + array.prototype.flat: 1.3.3 + array.prototype.flatmap: 1.3.3 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 9.21.0(jiti@1.21.7) + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.12.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint-import-resolver-node@0.3.9)(eslint@9.21.0(jiti@1.21.7)) + hasown: 2.0.2 + is-core-module: 2.16.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + object.groupby: 1.0.3 + object.values: 1.2.1 + semver: 6.3.1 + string.prototype.trimend: 1.0.9 + tsconfig-paths: 3.15.0 + optionalDependencies: + '@typescript-eslint/parser': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + + eslint-plugin-jest@25.7.0(@typescript-eslint/eslint-plugin@5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(jest@27.5.1)(typescript@5.8.2): + dependencies: + '@typescript-eslint/experimental-utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + optionalDependencies: + '@typescript-eslint/eslint-plugin': 5.62.0(@typescript-eslint/parser@5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + jest: 27.5.1 + transitivePeerDependencies: + - supports-color + - typescript + + eslint-plugin-jsx-a11y@6.10.2(eslint@9.21.0(jiti@1.21.7)): + dependencies: + aria-query: 5.3.2 + array-includes: 3.1.8 + array.prototype.flatmap: 1.3.3 + ast-types-flow: 0.0.8 + axe-core: 4.10.3 + axobject-query: 4.1.0 + damerau-levenshtein: 1.0.8 + emoji-regex: 9.2.2 + eslint: 9.21.0(jiti@1.21.7) + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + language-tags: 1.0.9 + minimatch: 3.1.2 + object.fromentries: 2.0.8 + safe-regex-test: 1.1.0 + string.prototype.includes: 2.0.1 + + eslint-plugin-react-compiler@19.0.0-beta-27714ef-20250124(eslint@9.21.0(jiti@1.21.7)): + dependencies: + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.26.9) + eslint: 9.21.0(jiti@1.21.7) + hermes-parser: 0.25.1 + zod: 3.24.2 + zod-validation-error: 3.4.0(zod@3.24.2) + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-hooks@4.6.2(eslint@9.21.0(jiti@1.21.7)): + dependencies: + eslint: 9.21.0(jiti@1.21.7) + + eslint-plugin-react-hooks@5.2.0(eslint@9.21.0(jiti@1.21.7)): + dependencies: + eslint: 9.21.0(jiti@1.21.7) + + eslint-plugin-react-refresh@0.4.19(eslint@9.21.0(jiti@1.21.7)): + dependencies: + eslint: 9.21.0(jiti@1.21.7) + + eslint-plugin-react@7.37.4(eslint@9.21.0(jiti@1.21.7)): + dependencies: + array-includes: 3.1.8 + array.prototype.findlast: 1.2.5 + array.prototype.flatmap: 1.3.3 + array.prototype.tosorted: 1.1.4 + doctrine: 2.1.0 + es-iterator-helpers: 1.2.1 + eslint: 9.21.0(jiti@1.21.7) + estraverse: 5.3.0 + hasown: 2.0.2 + jsx-ast-utils: 3.3.5 + minimatch: 3.1.2 + object.entries: 1.1.8 + object.fromentries: 2.0.8 + object.values: 1.2.1 + prop-types: 15.8.1 + resolve: 2.0.0-next.5 + semver: 6.3.1 + string.prototype.matchall: 4.0.12 + string.prototype.repeat: 1.0.0 + + eslint-plugin-testing-library@5.11.1(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2): + dependencies: + '@typescript-eslint/utils': 5.62.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + transitivePeerDependencies: + - supports-color + - typescript + + eslint-scope@5.1.1: + dependencies: + esrecurse: 4.3.0 + estraverse: 4.3.0 + + eslint-scope@8.2.0: + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + + eslint-visitor-keys@2.1.0: {} + + eslint-visitor-keys@3.4.3: {} + + eslint-visitor-keys@4.2.0: {} + + eslint-webpack-plugin@3.2.0(eslint@9.21.0(jiti@1.21.7))(webpack@5.98.0): + dependencies: + '@types/eslint': 8.56.12 + eslint: 9.21.0(jiti@1.21.7) + jest-worker: 28.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + schema-utils: 4.3.0 + webpack: 5.98.0 + + eslint@9.21.0(jiti@1.21.7): + dependencies: + '@eslint-community/eslint-utils': 4.4.1(eslint@9.21.0(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.1 + '@eslint/config-array': 0.19.2 + '@eslint/core': 0.12.0 + '@eslint/eslintrc': 3.3.0 + '@eslint/js': 9.21.0 + '@eslint/plugin-kit': 0.2.7 + '@humanfs/node': 0.16.6 + '@humanwhocodes/module-importer': 1.0.1 + '@humanwhocodes/retry': 0.4.2 + '@types/estree': 1.0.6 + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.6 + debug: 4.4.0 + escape-string-regexp: 4.0.0 + eslint-scope: 8.2.0 + eslint-visitor-keys: 4.2.0 + espree: 10.3.0 + esquery: 1.6.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 8.0.0 + find-up: 5.0.0 + glob-parent: 6.0.2 + ignore: 5.3.2 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + 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.4 + optionalDependencies: + jiti: 1.21.7 + transitivePeerDependencies: + - supports-color + + espree@10.3.0: + dependencies: + acorn: 8.14.1 + acorn-jsx: 5.3.2(acorn@8.14.1) + eslint-visitor-keys: 4.2.0 + + esprima@1.2.2: {} + + esprima@4.0.1: {} + + esquery@1.6.0: + dependencies: + estraverse: 5.3.0 + + esrecurse@4.3.0: + dependencies: + estraverse: 5.3.0 + + estraverse@4.3.0: {} + + estraverse@5.3.0: {} + + estree-walker@1.0.1: {} + + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.6 + + esutils@2.0.3: {} + + etag@1.8.1: {} + + eventemitter3@4.0.7: {} + + events@3.3.0: {} + + execa@5.1.1: + dependencies: + cross-spawn: 7.0.6 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + + exit@0.1.2: {} + + expect-type@1.2.0: {} + + expect@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-get-type: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + + fast-deep-equal@3.1.3: {} + + fast-glob@3.3.3: + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.8 + + fast-json-stable-stringify@2.1.0: {} + + fast-levenshtein@2.0.6: {} + + fast-uri@3.0.6: {} + + fastq@1.19.1: + dependencies: + reusify: 1.1.0 + + faye-websocket@0.11.4: + dependencies: + websocket-driver: 0.7.4 + + fb-watchman@2.0.2: + dependencies: + bser: 2.1.1 + + file-entry-cache@8.0.0: + dependencies: + flat-cache: 4.0.1 + + file-loader@6.2.0(webpack@5.98.0): + dependencies: + loader-utils: 2.0.4 + schema-utils: 3.3.0 + webpack: 5.98.0 + + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + + filesize@8.0.7: {} + + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + find-cache-dir@3.3.2: + dependencies: + commondir: 1.0.1 + make-dir: 3.1.0 + pkg-dir: 4.2.0 + + find-root@1.1.0: {} + + find-up@3.0.0: + dependencies: + locate-path: 3.0.0 + + find-up@4.1.0: + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat-cache@4.0.1: + dependencies: + flatted: 3.3.3 + keyv: 4.5.4 + + flatted@3.3.3: {} + + focus-lock@1.3.6: + dependencies: + tslib: 2.8.1 + + follow-redirects@1.15.9: {} + + for-each@0.3.5: + dependencies: + is-callable: 1.2.7 + + foreground-child@3.3.1: + dependencies: + cross-spawn: 7.0.6 + signal-exit: 4.1.0 + + fork-ts-checker-webpack-plugin@6.5.3(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)(webpack@5.98.0): + dependencies: + '@babel/code-frame': 7.26.2 + '@types/json-schema': 7.0.15 + chalk: 4.1.2 + chokidar: 3.6.0 + cosmiconfig: 6.0.0 + deepmerge: 4.3.1 + fs-extra: 9.1.0 + glob: 7.2.3 + memfs: 3.5.3 + minimatch: 3.1.2 + schema-utils: 2.7.0 + semver: 7.7.1 + tapable: 1.1.3 + typescript: 5.8.2 + webpack: 5.98.0 + optionalDependencies: + eslint: 9.21.0(jiti@1.21.7) + + form-data@3.0.3: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + + fraction.js@4.3.7: {} + + framer-motion@7.10.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@motionone/dom': 10.18.0 + hey-listen: 1.0.8 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + tslib: 2.4.0 + optionalDependencies: + '@emotion/is-prop-valid': 0.8.8 + + framesync@6.1.2: + dependencies: + tslib: 2.4.0 + + fresh@0.5.2: {} + + fs-extra@10.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-extra@9.1.0: + dependencies: + at-least-node: 1.0.0 + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + + fs-monkey@1.0.6: {} + + fs.realpath@1.0.0: {} + + fsevents@2.3.3: + optional: true + + function-bind@1.1.2: {} + + function.prototype.name@1.1.8: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + functions-have-names: 1.2.3 + hasown: 2.0.2 + is-callable: 1.2.7 + + functions-have-names@1.2.3: {} + + gensync@1.0.0-beta.2: {} + + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + + get-nonce@1.0.1: {} + + get-own-enumerable-property-symbols@3.0.2: {} + + get-package-type@0.1.0: {} + + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + + get-stream@6.0.1: {} + + get-symbol-description@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + + glob-parent@6.0.2: + dependencies: + is-glob: 4.0.3 + + glob-to-regexp@0.4.1: {} + + glob@10.4.5: + dependencies: + foreground-child: 3.3.1 + jackspeak: 3.4.3 + minimatch: 9.0.5 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 1.11.1 + + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + global-modules@2.0.0: + dependencies: + global-prefix: 3.0.0 + + global-prefix@3.0.0: + dependencies: + ini: 1.3.8 + kind-of: 6.0.3 + which: 1.3.1 + + globals@11.12.0: {} + + globals@14.0.0: {} + + globals@15.15.0: {} + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.3 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + + gopd@1.2.0: {} + + graceful-fs@4.2.11: {} + + graphemer@1.4.0: {} + + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + + handle-thing@2.0.1: {} + + harmony-reflect@1.6.2: {} + + has-bigints@1.1.0: {} + + has-flag@3.0.0: {} + + has-flag@4.0.0: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-proto@1.2.0: + dependencies: + dunder-proto: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hasown@2.0.2: + dependencies: + function-bind: 1.1.2 + + he@1.2.0: {} + + hermes-estree@0.25.1: {} + + hermes-parser@0.25.1: + dependencies: + hermes-estree: 0.25.1 + + hey-listen@1.0.8: {} + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + hoopy@0.1.4: {} + + hpack.js@2.1.6: + dependencies: + inherits: 2.0.4 + obuf: 1.1.2 + readable-stream: 2.3.8 + wbuf: 1.7.3 + + html-encoding-sniffer@2.0.1: + dependencies: + whatwg-encoding: 1.0.5 + + html-entities@2.5.2: {} + + html-escaper@2.0.2: {} + + html-minifier-terser@6.1.0: + dependencies: + camel-case: 4.1.2 + clean-css: 5.3.3 + commander: 8.3.0 + he: 1.2.0 + param-case: 3.0.4 + relateurl: 0.2.7 + terser: 5.39.0 + + html-webpack-plugin@5.6.3(webpack@5.98.0): + dependencies: + '@types/html-minifier-terser': 6.1.0 + html-minifier-terser: 6.1.0 + lodash: 4.17.21 + pretty-error: 4.0.0 + tapable: 2.2.1 + optionalDependencies: + webpack: 5.98.0 + + htmlparser2@6.1.0: + dependencies: + domelementtype: 2.3.0 + domhandler: 4.3.1 + domutils: 2.8.0 + entities: 2.2.0 + + http-deceiver@1.2.7: {} + + http-errors@1.6.3: + dependencies: + depd: 1.1.2 + inherits: 2.0.3 + setprototypeof: 1.1.0 + statuses: 1.5.0 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + + http-parser-js@0.5.9: {} + + http-proxy-agent@4.0.1: + dependencies: + '@tootallnate/once': 1.1.2 + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + http-proxy-middleware@2.0.7(@types/express@4.17.21): + dependencies: + '@types/http-proxy': 1.17.16 + http-proxy: 1.18.1 + is-glob: 4.0.3 + is-plain-obj: 3.0.0 + micromatch: 4.0.8 + optionalDependencies: + '@types/express': 4.17.21 + transitivePeerDependencies: + - debug + + http-proxy@1.18.1: + dependencies: + eventemitter3: 4.0.7 + follow-redirects: 1.15.9 + requires-port: 1.0.0 + transitivePeerDependencies: + - debug + + https-proxy-agent@5.0.1: + dependencies: + agent-base: 6.0.2 + debug: 4.4.0 + transitivePeerDependencies: + - supports-color + + human-signals@2.1.0: {} + + humanize-duration@3.32.1: {} + + iconv-lite@0.4.24: + dependencies: + safer-buffer: 2.1.2 + + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + + icss-utils@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + idb@7.1.1: {} + + identity-obj-proxy@3.0.0: + dependencies: + harmony-reflect: 1.6.2 + + ignore@5.3.2: {} + + immer@9.0.21: {} + + import-fresh@3.3.1: + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + + import-local@3.2.0: + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + + imurmurhash@0.1.4: {} + + indent-string@4.0.0: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + + inherits@2.0.3: {} + + inherits@2.0.4: {} + + ini@1.3.8: {} + + internal-slot@1.1.0: + dependencies: + es-errors: 1.3.0 + hasown: 2.0.2 + side-channel: 1.1.0 + + internmap@2.0.3: {} + + ipaddr.js@1.9.1: {} + + ipaddr.js@2.2.0: {} + + is-array-buffer@3.0.5: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-arrayish@0.2.1: {} + + is-async-function@2.1.1: + dependencies: + async-function: 1.0.0 + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-bigint@1.1.0: + dependencies: + has-bigints: 1.1.0 + + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + + is-boolean-object@1.2.2: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-callable@1.2.7: {} + + is-core-module@2.16.1: + dependencies: + hasown: 2.0.2 + + is-data-view@1.0.2: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + is-typed-array: 1.1.15 + + is-date-object@1.1.0: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-docker@2.2.1: {} + + is-extglob@2.1.1: {} + + is-finalizationregistry@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-fullwidth-code-point@3.0.0: {} + + is-generator-fn@2.1.0: {} + + is-generator-function@1.1.0: + dependencies: + call-bound: 1.0.4 + get-proto: 1.0.1 + has-tostringtag: 1.0.2 + safe-regex-test: 1.1.0 + + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-map@2.0.3: {} + + is-module@1.0.0: {} + + is-number-object@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-number@7.0.0: {} + + is-obj@1.0.1: {} + + is-plain-obj@3.0.0: {} + + is-potential-custom-element-name@1.0.1: {} + + is-regex@1.2.1: + dependencies: + call-bound: 1.0.4 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + is-regexp@1.0.0: {} + + is-root@2.1.0: {} + + is-set@2.0.3: {} + + is-shared-array-buffer@1.0.4: + dependencies: + call-bound: 1.0.4 + + is-stream@2.0.1: {} + + is-string@1.1.1: + dependencies: + call-bound: 1.0.4 + has-tostringtag: 1.0.2 + + is-symbol@1.1.1: + dependencies: + call-bound: 1.0.4 + has-symbols: 1.1.0 + safe-regex-test: 1.1.0 + + is-typed-array@1.1.15: + dependencies: + which-typed-array: 1.1.18 + + is-typedarray@1.0.0: {} + + is-weakmap@2.0.2: {} + + is-weakref@1.1.1: + dependencies: + call-bound: 1.0.4 + + is-weakset@2.0.4: + dependencies: + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + + is-wsl@2.2.0: + dependencies: + is-docker: 2.2.1 + + isarray@1.0.0: {} + + isarray@2.0.5: {} + + isexe@2.0.0: {} + + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-instrument@5.2.1: + dependencies: + '@babel/core': 7.26.9 + '@babel/parser': 7.26.9 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-lib-source-maps@4.0.1: + dependencies: + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + + istanbul-lib-source-maps@5.0.6: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + debug: 4.4.0 + istanbul-lib-coverage: 3.2.2 + transitivePeerDependencies: + - supports-color + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + + iterator.prototype@1.1.5: + dependencies: + define-data-property: 1.1.4 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + has-symbols: 1.1.0 + set-function-name: 2.0.2 + + jackspeak@3.4.3: + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + + jake@10.9.2: + dependencies: + async: 3.2.6 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + + jest-changed-files@27.5.1: + dependencies: + '@jest/types': 27.5.1 + execa: 5.1.1 + throat: 6.0.2 + + jest-circus@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + co: 4.6.0 + dedent: 0.7.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-cli@27.5.1: + dependencies: + '@jest/core': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + import-local: 3.2.0 + jest-config: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + prompts: 2.4.2 + yargs: 16.2.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jest-config@27.5.1: + dependencies: + '@babel/core': 7.26.9 + '@jest/test-sequencer': 27.5.1 + '@jest/types': 27.5.1 + babel-jest: 27.5.1(@babel/core@7.26.9) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-get-type: 27.5.1 + jest-jasmine2: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runner: 27.5.1 + jest-util: 27.5.1 + jest-validate: 27.5.1 + micromatch: 4.0.8 + parse-json: 5.2.0 + pretty-format: 27.5.1 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-diff@27.5.1: + dependencies: + chalk: 4.1.2 + diff-sequences: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-docblock@27.5.1: + dependencies: + detect-newline: 3.1.0 + + jest-each@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + jest-get-type: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + + jest-environment-jsdom@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + jest-mock: 27.5.1 + jest-util: 27.5.1 + jsdom: 16.7.0 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-environment-node@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + jest-mock: 27.5.1 + jest-util: 27.5.1 + + jest-get-type@27.5.1: {} + + jest-haste-map@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/graceful-fs': 4.1.9 + '@types/node': 22.13.9 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 27.5.1 + jest-serializer: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + micromatch: 4.0.8 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + + jest-jasmine2@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + co: 4.6.0 + expect: 27.5.1 + is-generator-fn: 2.1.0 + jest-each: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-runtime: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + pretty-format: 27.5.1 + throat: 6.0.2 + transitivePeerDependencies: + - supports-color + + jest-leak-detector@27.5.1: + dependencies: + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-matcher-utils@27.5.1: + dependencies: + chalk: 4.1.2 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + pretty-format: 27.5.1 + + jest-message-util@27.5.1: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 27.5.1 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 27.5.1 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-message-util@28.1.3: + dependencies: + '@babel/code-frame': 7.26.2 + '@jest/types': 28.1.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.8 + pretty-format: 28.1.3 + slash: 3.0.0 + stack-utils: 2.0.6 + + jest-mock@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + + jest-pnp-resolver@1.2.3(jest-resolve@27.5.1): + optionalDependencies: + jest-resolve: 27.5.1 + + jest-regex-util@27.5.1: {} + + jest-regex-util@28.0.2: {} + + jest-resolve-dependencies@27.5.1: + dependencies: + '@jest/types': 27.5.1 + jest-regex-util: 27.5.1 + jest-snapshot: 27.5.1 + transitivePeerDependencies: + - supports-color + + jest-resolve@27.5.1: + dependencies: + '@jest/types': 27.5.1 + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-pnp-resolver: 1.2.3(jest-resolve@27.5.1) + jest-util: 27.5.1 + jest-validate: 27.5.1 + resolve: 1.22.10 + resolve.exports: 1.1.1 + slash: 3.0.0 + + jest-runner@27.5.1: + dependencies: + '@jest/console': 27.5.1 + '@jest/environment': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + emittery: 0.8.1 + graceful-fs: 4.2.11 + jest-docblock: 27.5.1 + jest-environment-jsdom: 27.5.1 + jest-environment-node: 27.5.1 + jest-haste-map: 27.5.1 + jest-leak-detector: 27.5.1 + jest-message-util: 27.5.1 + jest-resolve: 27.5.1 + jest-runtime: 27.5.1 + jest-util: 27.5.1 + jest-worker: 27.5.1 + source-map-support: 0.5.21 + throat: 6.0.2 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - utf-8-validate + + jest-runtime@27.5.1: + dependencies: + '@jest/environment': 27.5.1 + '@jest/fake-timers': 27.5.1 + '@jest/globals': 27.5.1 + '@jest/source-map': 27.5.1 + '@jest/test-result': 27.5.1 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + chalk: 4.1.2 + cjs-module-lexer: 1.4.3 + collect-v8-coverage: 1.0.2 + execa: 5.1.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 27.5.1 + jest-message-util: 27.5.1 + jest-mock: 27.5.1 + jest-regex-util: 27.5.1 + jest-resolve: 27.5.1 + jest-snapshot: 27.5.1 + jest-util: 27.5.1 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + + jest-serializer@27.5.1: + dependencies: + '@types/node': 22.13.9 + graceful-fs: 4.2.11 + + jest-snapshot@27.5.1: + dependencies: + '@babel/core': 7.26.9 + '@babel/generator': 7.26.9 + '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.9) + '@babel/traverse': 7.26.9 + '@babel/types': 7.26.9 + '@jest/transform': 27.5.1 + '@jest/types': 27.5.1 + '@types/babel__traverse': 7.20.6 + '@types/prettier': 2.7.3 + babel-preset-current-node-syntax: 1.1.0(@babel/core@7.26.9) + chalk: 4.1.2 + expect: 27.5.1 + graceful-fs: 4.2.11 + jest-diff: 27.5.1 + jest-get-type: 27.5.1 + jest-haste-map: 27.5.1 + jest-matcher-utils: 27.5.1 + jest-message-util: 27.5.1 + jest-util: 27.5.1 + natural-compare: 1.4.0 + pretty-format: 27.5.1 + semver: 7.7.1 + transitivePeerDependencies: + - supports-color + + jest-util@27.5.1: + dependencies: + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-util@28.1.3: + dependencies: + '@jest/types': 28.1.3 + '@types/node': 22.13.9 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + + jest-validate@27.5.1: + dependencies: + '@jest/types': 27.5.1 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 27.5.1 + leven: 3.1.0 + pretty-format: 27.5.1 + + jest-watch-typeahead@1.1.0(jest@27.5.1): + dependencies: + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest: 27.5.1 + jest-regex-util: 28.0.2 + jest-watcher: 28.1.3 + slash: 4.0.0 + string-length: 5.0.1 + strip-ansi: 7.1.0 + + jest-watcher@27.5.1: + dependencies: + '@jest/test-result': 27.5.1 + '@jest/types': 27.5.1 + '@types/node': 22.13.9 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + jest-util: 27.5.1 + string-length: 4.0.2 + + jest-watcher@28.1.3: + dependencies: + '@jest/test-result': 28.1.3 + '@jest/types': 28.1.3 + '@types/node': 22.13.9 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.10.2 + jest-util: 28.1.3 + string-length: 4.0.2 + + jest-worker@26.6.2: + dependencies: + '@types/node': 22.13.9 + merge-stream: 2.0.0 + supports-color: 7.2.0 + + jest-worker@27.5.1: + dependencies: + '@types/node': 22.13.9 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest-worker@28.1.3: + dependencies: + '@types/node': 22.13.9 + merge-stream: 2.0.0 + supports-color: 8.1.1 + + jest@27.5.1: + dependencies: + '@jest/core': 27.5.1 + import-local: 3.2.0 + jest-cli: 27.5.1 + transitivePeerDependencies: + - bufferutil + - canvas + - supports-color + - ts-node + - utf-8-validate + + jiti@1.21.7: {} + + js-tokens@4.0.0: {} + + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + + js-yaml@4.1.0: + dependencies: + argparse: 2.0.1 + + jsdom@16.7.0: + dependencies: + abab: 2.0.6 + acorn: 8.14.1 + acorn-globals: 6.0.0 + cssom: 0.4.4 + cssstyle: 2.3.0 + data-urls: 2.0.0 + decimal.js: 10.5.0 + domexception: 2.0.1 + escodegen: 2.1.0 + form-data: 3.0.3 + html-encoding-sniffer: 2.0.1 + http-proxy-agent: 4.0.1 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.18 + parse5: 6.0.1 + saxes: 5.0.1 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-hr-time: 1.0.2 + w3c-xmlserializer: 2.0.0 + webidl-conversions: 6.1.0 + whatwg-encoding: 1.0.5 + whatwg-mimetype: 2.3.0 + whatwg-url: 8.7.0 + ws: 7.5.10 + xml-name-validator: 3.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + + jsesc@3.0.2: {} + + jsesc@3.1.0: {} + + json-buffer@3.0.1: {} + + json-parse-even-better-errors@2.3.1: {} + + json-schema-traverse@0.4.1: {} + + json-schema-traverse@1.0.0: {} + + json-schema@0.4.0: {} + + json-stable-stringify-without-jsonify@1.0.1: {} + + json-stringify-safe@5.0.1: {} + + json5@1.0.2: + dependencies: + minimist: 1.2.8 + + json5@2.2.3: {} + + jsonfile@6.1.0: + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + + jsonpath@1.1.1: + dependencies: + esprima: 1.2.2 + static-eval: 2.0.2 + underscore: 1.12.1 + + jsonpointer@5.0.1: {} + + jsx-ast-utils@3.3.5: + dependencies: + array-includes: 3.1.8 + array.prototype.flat: 1.3.3 + object.assign: 4.1.7 + object.values: 1.2.1 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + kind-of@6.0.3: {} + + kleur@3.0.3: {} + + klona@2.0.6: {} + + language-subtag-registry@0.3.23: {} + + language-tags@1.0.9: + dependencies: + language-subtag-registry: 0.3.23 + + launch-editor@2.10.0: + dependencies: + picocolors: 1.1.1 + shell-quote: 1.8.2 + + leven@3.1.0: {} + + levn@0.3.0: + dependencies: + prelude-ls: 1.1.2 + type-check: 0.3.2 + + levn@0.4.1: + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + + lilconfig@2.1.0: {} + + lilconfig@3.1.3: {} + + lines-and-columns@1.2.4: {} + + loader-runner@4.3.0: {} + + loader-utils@2.0.4: + dependencies: + big.js: 5.2.2 + emojis-list: 3.0.0 + json5: 2.2.3 + + loader-utils@3.3.1: {} + + locate-path@3.0.0: + dependencies: + p-locate: 3.0.0 + path-exists: 3.0.0 + + locate-path@5.0.0: + dependencies: + p-locate: 4.1.0 + + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + + lodash-es@4.17.21: {} + + lodash.debounce@4.0.8: {} + + lodash.memoize@4.1.2: {} + + lodash.merge@4.6.2: {} + + lodash.mergewith@4.6.2: {} + + lodash.sortby@4.7.0: {} + + lodash.uniq@4.5.0: {} + + lodash@4.17.21: {} + + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + + loupe@3.1.3: {} + + lower-case@2.0.2: + dependencies: + tslib: 2.8.1 + + lru-cache@10.4.3: {} + + lru-cache@5.1.1: + dependencies: + yallist: 3.1.1 + + luxon@3.5.0: {} + + lz-string@1.5.0: {} + + magic-string@0.25.9: + dependencies: + sourcemap-codec: 1.4.8 + + magic-string@0.30.17: + dependencies: + '@jridgewell/sourcemap-codec': 1.5.0 + + magicast@0.3.5: + dependencies: + '@babel/parser': 7.26.9 + '@babel/types': 7.26.9 + source-map-js: 1.2.1 + + make-dir@3.1.0: + dependencies: + semver: 6.3.1 + + make-dir@4.0.0: + dependencies: + semver: 7.7.1 + + makeerror@1.0.12: + dependencies: + tmpl: 1.0.5 + + match-sorter@8.0.0: + dependencies: + '@babel/runtime': 7.26.9 + remove-accents: 0.5.0 + + math-intrinsics@1.1.0: {} + + mdn-data@2.0.14: {} + + mdn-data@2.0.4: {} + + media-typer@0.3.0: {} + + memfs@3.5.3: + dependencies: + fs-monkey: 1.0.6 + + merge-descriptors@1.0.3: {} + + merge-stream@2.0.0: {} + + merge2@1.4.1: {} + + methods@1.1.2: {} + + micromatch@4.0.8: + dependencies: + braces: 3.0.3 + picomatch: 2.3.1 + + mime-db@1.52.0: {} + + mime-db@1.53.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + + mimic-fn@2.1.0: {} + + min-indent@1.0.1: {} + + mini-css-extract-plugin@2.9.2(webpack@5.98.0): + dependencies: + schema-utils: 4.3.0 + tapable: 2.2.1 + webpack: 5.98.0 + + minimalistic-assert@1.0.1: {} + + minimatch@3.1.2: + dependencies: + brace-expansion: 1.1.11 + + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + + minimatch@9.0.5: + dependencies: + brace-expansion: 2.0.1 + + minimist@1.2.8: {} + + minipass@7.1.2: {} + + mkdirp@0.5.6: + dependencies: + minimist: 1.2.8 + + moment@2.30.1: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + multicast-dns@7.2.5: + dependencies: + dns-packet: 5.6.1 + thunky: 1.1.0 + + mz@2.7.0: + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + + nanoclone@0.2.1: {} + + nanoid@3.3.8: {} + + natural-compare-lite@1.4.0: {} + + natural-compare@1.4.0: {} + + negotiator@0.6.3: {} + + negotiator@0.6.4: {} + + neo-async@2.6.2: {} + + no-case@3.0.4: + dependencies: + lower-case: 2.0.2 + tslib: 2.8.1 + + node-forge@1.3.1: {} + + node-int64@0.4.0: {} + + node-releases@2.0.19: {} + + normalize-path@3.0.0: {} + + normalize-range@0.1.2: {} + + normalize-url@6.1.0: {} + + npm-run-path@4.0.1: + dependencies: + path-key: 3.1.1 + + nth-check@1.0.2: + dependencies: + boolbase: 1.0.0 + + nth-check@2.1.1: + dependencies: + boolbase: 1.0.0 + + nwsapi@2.2.18: {} + + object-assign@4.1.1: {} + + object-hash@3.0.0: {} + + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + object.assign@4.1.7: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + has-symbols: 1.1.0 + object-keys: 1.1.1 + + object.entries@1.1.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + object.fromentries@2.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + + object.getownpropertydescriptors@2.1.8: + dependencies: + array.prototype.reduce: 1.0.7 + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + gopd: 1.2.0 + safe-array-concat: 1.1.3 + + object.groupby@1.0.3: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + + object.values@1.2.1: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + obuf@1.1.2: {} + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 + + open@8.4.2: + dependencies: + define-lazy-prop: 2.0.0 + is-docker: 2.2.1 + is-wsl: 2.2.0 + + optionator@0.8.3: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.3.0 + prelude-ls: 1.1.2 + type-check: 0.3.2 + word-wrap: 1.2.5 + + optionator@0.9.4: + dependencies: + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + word-wrap: 1.2.5 + + own-keys@1.0.1: + dependencies: + get-intrinsic: 1.3.0 + object-keys: 1.1.1 + safe-push-apply: 1.0.0 + + p-limit@2.3.0: + dependencies: + p-try: 2.2.0 + + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@3.0.0: + dependencies: + p-limit: 2.3.0 + + p-locate@4.1.0: + dependencies: + p-limit: 2.3.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + + p-retry@4.6.2: + dependencies: + '@types/retry': 0.12.0 + retry: 0.13.1 + + p-try@2.2.0: {} + + package-json-from-dist@1.0.1: {} + + param-case@3.0.4: + dependencies: + dot-case: 3.0.4 + tslib: 2.8.1 + + parent-module@1.0.1: + dependencies: + callsites: 3.1.0 + + parse-json@5.2.0: + dependencies: + '@babel/code-frame': 7.26.2 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + + parse5@6.0.1: {} + + parseurl@1.3.3: {} + + pascal-case@3.1.2: + dependencies: + no-case: 3.0.4 + tslib: 2.8.1 + + path-exists@3.0.0: {} + + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + + path-key@3.1.1: {} + + path-parse@1.0.7: {} + + path-scurry@1.11.1: + dependencies: + lru-cache: 10.4.3 + minipass: 7.1.2 + + path-to-regexp@0.1.12: {} + + path-type@4.0.0: {} + + pathe@2.0.3: {} + + pathval@2.0.0: {} + + performance-now@2.1.0: {} + + picocolors@0.2.1: {} + + picocolors@1.1.1: {} + + picomatch@2.3.1: {} + + pify@2.3.0: {} + + pirates@4.0.6: {} + + pkg-dir@4.2.0: + dependencies: + find-up: 4.1.0 + + pkg-up@3.1.0: + dependencies: + find-up: 3.0.0 + + possible-typed-array-names@1.1.0: {} + + postcss-attribute-case-insensitive@5.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-browser-comments@4.0.0(browserslist@4.24.4)(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + + postcss-calc@8.2.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + postcss-value-parser: 4.2.0 + + postcss-clamp@4.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-functional-notation@4.2.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-hex-alpha@8.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-color-rebeccapurple@7.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-colormin@5.3.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + colord: 2.9.3 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-convert-values@5.1.3(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-media@8.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-properties@12.1.11(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-custom-selectors@6.0.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-dir-pseudo-class@6.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-discard-comments@5.1.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-duplicates@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-empty@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-discard-overridden@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-double-position-gradients@3.1.2(postcss@8.5.3): + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-env-function@4.0.6(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-flexbugs-fixes@5.0.2(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-focus-visible@6.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-focus-within@5.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-font-variant@5.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-gap-properties@3.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-image-set-function@4.0.7(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-import@15.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + read-cache: 1.0.0 + resolve: 1.22.10 + + postcss-initial@4.0.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-js@4.0.1(postcss@8.5.3): + dependencies: + camelcase-css: 2.0.1 + postcss: 8.5.3 + + postcss-lab-function@4.2.1(postcss@8.5.3): + dependencies: + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-load-config@4.0.2(postcss@8.5.3): + dependencies: + lilconfig: 3.1.3 + yaml: 2.7.0 + optionalDependencies: + postcss: 8.5.3 + + postcss-loader@6.2.1(postcss@8.5.3)(webpack@5.98.0): + dependencies: + cosmiconfig: 7.1.0 + klona: 2.0.6 + postcss: 8.5.3 + semver: 7.7.1 + webpack: 5.98.0 + + postcss-logical@5.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-media-minmax@5.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-merge-longhand@5.1.7(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + stylehacks: 5.1.1(postcss@8.5.3) + + postcss-merge-rules@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-minify-font-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-gradients@5.1.1(postcss@8.5.3): + dependencies: + colord: 2.9.3 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-params@5.1.4(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-minify-selectors@5.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-modules-extract-imports@3.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-modules-local-by-default@4.2.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + postcss-value-parser: 4.2.0 + + postcss-modules-scope@3.2.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 7.1.0 + + postcss-modules-values@4.0.0(postcss@8.5.3): + dependencies: + icss-utils: 5.1.0(postcss@8.5.3) + postcss: 8.5.3 + + postcss-nested@6.2.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-nesting@10.2.0(postcss@8.5.3): + dependencies: + '@csstools/selector-specificity': 2.2.0(postcss-selector-parser@6.1.2) + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-normalize-charset@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-normalize-display-values@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-positions@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-repeat-style@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-string@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-timing-functions@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-unicode@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-url@5.1.0(postcss@8.5.3): + dependencies: + normalize-url: 6.1.0 + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize-whitespace@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-normalize@10.0.1(browserslist@4.24.4)(postcss@8.5.3): + dependencies: + '@csstools/normalize.css': 12.1.1 + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-browser-comments: 4.0.0(browserslist@4.24.4)(postcss@8.5.3) + sanitize.css: 13.0.0 + + postcss-opacity-percentage@1.1.3(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-ordered-values@5.1.3(postcss@8.5.3): + dependencies: + cssnano-utils: 3.1.0(postcss@8.5.3) + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-overflow-shorthand@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-page-break@3.0.4(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-place@7.0.5(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-preset-env@7.8.3(postcss@8.5.3): + dependencies: + '@csstools/postcss-cascade-layers': 1.1.1(postcss@8.5.3) + '@csstools/postcss-color-function': 1.1.1(postcss@8.5.3) + '@csstools/postcss-font-format-keywords': 1.0.1(postcss@8.5.3) + '@csstools/postcss-hwb-function': 1.0.2(postcss@8.5.3) + '@csstools/postcss-ic-unit': 1.0.1(postcss@8.5.3) + '@csstools/postcss-is-pseudo-class': 2.0.7(postcss@8.5.3) + '@csstools/postcss-nested-calc': 1.0.0(postcss@8.5.3) + '@csstools/postcss-normalize-display-values': 1.0.1(postcss@8.5.3) + '@csstools/postcss-oklab-function': 1.1.1(postcss@8.5.3) + '@csstools/postcss-progressive-custom-properties': 1.3.0(postcss@8.5.3) + '@csstools/postcss-stepped-value-functions': 1.0.1(postcss@8.5.3) + '@csstools/postcss-text-decoration-shorthand': 1.0.0(postcss@8.5.3) + '@csstools/postcss-trigonometric-functions': 1.0.2(postcss@8.5.3) + '@csstools/postcss-unset-value': 1.0.2(postcss@8.5.3) + autoprefixer: 10.4.20(postcss@8.5.3) + browserslist: 4.24.4 + css-blank-pseudo: 3.0.3(postcss@8.5.3) + css-has-pseudo: 3.0.4(postcss@8.5.3) + css-prefers-color-scheme: 6.0.3(postcss@8.5.3) + cssdb: 7.11.2 + postcss: 8.5.3 + postcss-attribute-case-insensitive: 5.0.2(postcss@8.5.3) + postcss-clamp: 4.1.0(postcss@8.5.3) + postcss-color-functional-notation: 4.2.4(postcss@8.5.3) + postcss-color-hex-alpha: 8.0.4(postcss@8.5.3) + postcss-color-rebeccapurple: 7.1.1(postcss@8.5.3) + postcss-custom-media: 8.0.2(postcss@8.5.3) + postcss-custom-properties: 12.1.11(postcss@8.5.3) + postcss-custom-selectors: 6.0.3(postcss@8.5.3) + postcss-dir-pseudo-class: 6.0.5(postcss@8.5.3) + postcss-double-position-gradients: 3.1.2(postcss@8.5.3) + postcss-env-function: 4.0.6(postcss@8.5.3) + postcss-focus-visible: 6.0.4(postcss@8.5.3) + postcss-focus-within: 5.0.4(postcss@8.5.3) + postcss-font-variant: 5.0.0(postcss@8.5.3) + postcss-gap-properties: 3.0.5(postcss@8.5.3) + postcss-image-set-function: 4.0.7(postcss@8.5.3) + postcss-initial: 4.0.1(postcss@8.5.3) + postcss-lab-function: 4.2.1(postcss@8.5.3) + postcss-logical: 5.0.4(postcss@8.5.3) + postcss-media-minmax: 5.0.0(postcss@8.5.3) + postcss-nesting: 10.2.0(postcss@8.5.3) + postcss-opacity-percentage: 1.1.3(postcss@8.5.3) + postcss-overflow-shorthand: 3.0.4(postcss@8.5.3) + postcss-page-break: 3.0.4(postcss@8.5.3) + postcss-place: 7.0.5(postcss@8.5.3) + postcss-pseudo-class-any-link: 7.1.6(postcss@8.5.3) + postcss-replace-overflow-wrap: 4.0.0(postcss@8.5.3) + postcss-selector-not: 6.0.1(postcss@8.5.3) + postcss-value-parser: 4.2.0 + + postcss-pseudo-class-any-link@7.1.6(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-reduce-initial@5.1.2(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + caniuse-api: 3.0.0 + postcss: 8.5.3 + + postcss-reduce-transforms@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + + postcss-replace-overflow-wrap@4.0.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + + postcss-selector-not@6.0.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-selector-parser@6.1.2: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-selector-parser@7.1.0: + dependencies: + cssesc: 3.0.0 + util-deprecate: 1.0.2 + + postcss-svgo@5.1.0(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-value-parser: 4.2.0 + svgo: 2.8.0 + + postcss-unique-selectors@5.1.1(postcss@8.5.3): + dependencies: + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + postcss-value-parser@4.2.0: {} + + postcss@7.0.39: + dependencies: + picocolors: 0.2.1 + source-map: 0.6.1 + + postcss@8.5.3: + dependencies: + nanoid: 3.3.8 + picocolors: 1.1.1 + source-map-js: 1.2.1 + + prelude-ls@1.1.2: {} + + prelude-ls@1.2.1: {} + + pretty-bytes@5.6.0: {} + + pretty-error@4.0.0: + dependencies: + lodash: 4.17.21 + renderkid: 3.0.0 + + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + + pretty-format@28.1.3: + dependencies: + '@jest/schemas': 28.1.3 + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 18.3.1 + + process-nextick-args@2.0.1: {} + + promise@8.3.0: + dependencies: + asap: 2.0.6 + + prompts@2.4.2: + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + + prop-types@15.8.1: + dependencies: + loose-envify: 1.4.0 + object-assign: 4.1.1 + react-is: 16.13.1 + + property-expr@2.0.6: {} + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + + psl@1.15.0: + dependencies: + punycode: 2.3.1 + + punycode@2.3.1: {} + + q@1.5.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + + querystringify@2.2.0: {} + + queue-microtask@1.2.3: {} + + raf@3.4.1: + dependencies: + performance-now: 2.1.0 + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + randomcolor@0.6.2: {} + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + + react-app-polyfill@3.0.0: + dependencies: + core-js: 3.41.0 + object-assign: 4.1.1 + promise: 8.3.0 + raf: 3.4.1 + regenerator-runtime: 0.13.11 + whatwg-fetch: 3.6.20 + + react-clientside-effect@1.2.7(react@19.0.0): + dependencies: + '@babel/runtime': 7.26.9 + react: 19.0.0 + + react-color-palette@6.2.0(react@19.0.0): + dependencies: + react: 19.0.0 + + react-dev-utils@12.0.1(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)(webpack@5.98.0): + dependencies: + '@babel/code-frame': 7.26.2 + address: 1.2.2 + browserslist: 4.24.4 + chalk: 4.1.2 + cross-spawn: 7.0.6 + detect-port-alt: 1.1.6 + escape-string-regexp: 4.0.0 + filesize: 8.0.7 + find-up: 5.0.0 + fork-ts-checker-webpack-plugin: 6.5.3(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)(webpack@5.98.0) + global-modules: 2.0.0 + globby: 11.1.0 + gzip-size: 6.0.0 + immer: 9.0.21 + is-root: 2.1.0 + loader-utils: 3.3.1 + open: 8.4.2 + pkg-up: 3.1.0 + prompts: 2.4.2 + react-error-overlay: 6.1.0 + recursive-readdir: 2.2.3 + shell-quote: 1.8.2 + strip-ansi: 6.0.1 + text-table: 0.2.0 + webpack: 5.98.0 + optionalDependencies: + typescript: 5.8.2 + transitivePeerDependencies: + - eslint + - supports-color + - vue-template-compiler + + react-dom@19.0.0(react@19.0.0): + dependencies: + react: 19.0.0 + scheduler: 0.25.0 + + react-error-overlay@6.1.0: {} + + react-fast-compare@3.2.2: {} + + react-focus-lock@2.13.6(@types/react@19.0.10)(react@19.0.0): + dependencies: + '@babel/runtime': 7.26.9 + focus-lock: 1.3.6 + prop-types: 15.8.1 + react: 19.0.0 + react-clientside-effect: 1.2.7(react@19.0.0) + use-callback-ref: 1.3.3(@types/react@19.0.10)(react@19.0.0) + use-sidecar: 1.1.3(@types/react@19.0.10)(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.10 + + react-hook-form@7.54.2(react@19.0.0): + dependencies: + react: 19.0.0 + + react-icons@5.5.0(react@19.0.0): + dependencies: + react: 19.0.0 + + react-is@16.13.1: {} + + react-is@17.0.2: {} + + react-is@18.3.1: {} + + react-moment@1.1.3(moment@2.30.1)(prop-types@15.8.1)(react@19.0.0): + dependencies: + moment: 2.30.1 + prop-types: 15.8.1 + react: 19.0.0 + + react-portal@4.3.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + prop-types: 15.8.1 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + + react-refresh@0.11.0: {} + + react-refresh@0.14.2: {} + + react-remove-scroll-bar@2.3.8(@types/react@19.0.10)(react@19.0.0): + dependencies: + react: 19.0.0 + react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.0.10 + + react-remove-scroll@2.6.3(@types/react@19.0.10)(react@19.0.0): + dependencies: + react: 19.0.0 + react-remove-scroll-bar: 2.3.8(@types/react@19.0.10)(react@19.0.0) + react-style-singleton: 2.2.3(@types/react@19.0.10)(react@19.0.0) + tslib: 2.8.1 + use-callback-ref: 1.3.3(@types/react@19.0.10)(react@19.0.0) + use-sidecar: 1.1.3(@types/react@19.0.10)(react@19.0.0) + optionalDependencies: + '@types/react': 19.0.10 + + react-router-dom@6.4.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0): + dependencies: + '@remix-run/router': 1.0.3 + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + react-router: 6.4.3(react@19.0.0) + + react-router@6.4.3(react@19.0.0): + dependencies: + '@remix-run/router': 1.0.3 + react: 19.0.0 + + react-scripts@5.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(@types/babel__core@7.20.5)(eslint@9.21.0(jiti@1.21.7))(react@19.0.0)(type-fest@0.21.3)(typescript@5.8.2): + dependencies: + '@babel/core': 7.26.9 + '@pmmmwh/react-refresh-webpack-plugin': 0.5.15(react-refresh@0.11.0)(type-fest@0.21.3)(webpack-dev-server@4.15.2(webpack@5.98.0))(webpack@5.98.0) + '@svgr/webpack': 5.5.0 + babel-jest: 27.5.1(@babel/core@7.26.9) + babel-loader: 8.4.1(@babel/core@7.26.9)(webpack@5.98.0) + babel-plugin-named-asset-import: 0.3.8(@babel/core@7.26.9) + babel-preset-react-app: 10.1.0 + bfj: 7.1.0 + browserslist: 4.24.4 + camelcase: 6.3.0 + case-sensitive-paths-webpack-plugin: 2.4.0 + css-loader: 6.11.0(webpack@5.98.0) + css-minimizer-webpack-plugin: 3.4.1(webpack@5.98.0) + dotenv: 10.0.0 + dotenv-expand: 5.1.0 + eslint: 9.21.0(jiti@1.21.7) + eslint-config-react-app: 7.0.1(@babel/plugin-syntax-flow@7.26.0(@babel/core@7.26.9))(@babel/plugin-transform-react-jsx@7.25.9(@babel/core@7.26.9))(eslint@9.21.0(jiti@1.21.7))(jest@27.5.1)(typescript@5.8.2) + eslint-webpack-plugin: 3.2.0(eslint@9.21.0(jiti@1.21.7))(webpack@5.98.0) + file-loader: 6.2.0(webpack@5.98.0) + fs-extra: 10.1.0 + html-webpack-plugin: 5.6.3(webpack@5.98.0) + identity-obj-proxy: 3.0.0 + jest: 27.5.1 + jest-resolve: 27.5.1 + jest-watch-typeahead: 1.1.0(jest@27.5.1) + mini-css-extract-plugin: 2.9.2(webpack@5.98.0) + postcss: 8.5.3 + postcss-flexbugs-fixes: 5.0.2(postcss@8.5.3) + postcss-loader: 6.2.1(postcss@8.5.3)(webpack@5.98.0) + postcss-normalize: 10.0.1(browserslist@4.24.4)(postcss@8.5.3) + postcss-preset-env: 7.8.3(postcss@8.5.3) + prompts: 2.4.2 + react: 19.0.0 + react-app-polyfill: 3.0.0 + react-dev-utils: 12.0.1(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2)(webpack@5.98.0) + react-refresh: 0.11.0 + resolve: 1.22.10 + resolve-url-loader: 4.0.0 + sass-loader: 12.6.0(webpack@5.98.0) + semver: 7.7.1 + source-map-loader: 3.0.2(webpack@5.98.0) + style-loader: 3.3.4(webpack@5.98.0) + tailwindcss: 3.4.17 + terser-webpack-plugin: 5.3.14(webpack@5.98.0) + webpack: 5.98.0 + webpack-dev-server: 4.15.2(webpack@5.98.0) + webpack-manifest-plugin: 4.1.1(webpack@5.98.0) + workbox-webpack-plugin: 6.6.0(@types/babel__core@7.20.5)(webpack@5.98.0) + optionalDependencies: + fsevents: 2.3.3 + typescript: 5.8.2 + transitivePeerDependencies: + - '@babel/plugin-syntax-flow' + - '@babel/plugin-transform-react-jsx' + - '@parcel/css' + - '@rspack/core' + - '@swc/core' + - '@types/babel__core' + - '@types/webpack' + - bufferutil + - canvas + - clean-css + - csso + - debug + - esbuild + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - fibers + - node-notifier + - node-sass + - rework + - rework-visit + - sass + - sass-embedded + - sockjs-client + - supports-color + - ts-node + - type-fest + - uglify-js + - utf-8-validate + - vue-template-compiler + - webpack-cli + - webpack-hot-middleware + - webpack-plugin-serve + + react-style-singleton@2.2.3(@types/react@19.0.10)(react@19.0.0): + dependencies: + get-nonce: 1.0.1 + react: 19.0.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.0.10 + + react@19.0.0: {} + + read-cache@1.0.0: + dependencies: + pify: 2.3.0 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + + recursive-readdir@2.2.3: + dependencies: + minimatch: 3.1.2 + + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + + redux-thunk@2.4.2(redux@4.2.1): + dependencies: + redux: 4.2.1 + + redux@4.2.1: + dependencies: + '@babel/runtime': 7.26.9 + + reflect.getprototypeof@1.0.10: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + get-proto: 1.0.1 + which-builtin-type: 1.2.1 + + regenerate-unicode-properties@10.2.0: + dependencies: + regenerate: 1.4.2 + + regenerate@1.4.2: {} + + regenerator-runtime@0.13.11: {} + + regenerator-runtime@0.14.1: {} + + regenerator-transform@0.15.2: + dependencies: + '@babel/runtime': 7.26.9 + + regex-parser@2.3.1: {} + + regexp.prototype.flags@1.5.4: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-errors: 1.3.0 + get-proto: 1.0.1 + gopd: 1.2.0 + set-function-name: 2.0.2 + + regexpu-core@6.2.0: + dependencies: + regenerate: 1.4.2 + regenerate-unicode-properties: 10.2.0 + regjsgen: 0.8.0 + regjsparser: 0.12.0 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.2.0 + + regjsgen@0.8.0: {} + + regjsparser@0.12.0: + dependencies: + jsesc: 3.0.2 + + relateurl@0.2.7: {} + + remove-accents@0.5.0: {} + + renderkid@3.0.0: + dependencies: + css-select: 4.3.0 + dom-converter: 0.2.0 + htmlparser2: 6.1.0 + lodash: 4.17.21 + strip-ansi: 6.0.1 + + require-directory@2.1.1: {} + + require-from-string@2.0.2: {} + + requires-port@1.0.0: {} + + resolve-cwd@3.0.0: + dependencies: + resolve-from: 5.0.0 + + resolve-from@4.0.0: {} + + resolve-from@5.0.0: {} + + resolve-url-loader@4.0.0: + dependencies: + adjust-sourcemap-loader: 4.0.0 + convert-source-map: 1.9.0 + loader-utils: 2.0.4 + postcss: 7.0.39 + source-map: 0.6.1 + + resolve.exports@1.1.1: {} + + resolve@1.22.10: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + resolve@2.0.0-next.5: + dependencies: + is-core-module: 2.16.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + + retry@0.13.1: {} + + reusify@1.1.0: {} + + rimraf@3.0.2: + dependencies: + glob: 7.2.3 + + rollup-plugin-terser@7.0.2(rollup@2.79.2): + dependencies: + '@babel/code-frame': 7.26.2 + jest-worker: 26.6.2 + rollup: 2.79.2 + serialize-javascript: 4.0.0 + terser: 5.39.0 + + rollup@2.79.2: + optionalDependencies: + fsevents: 2.3.3 + + rollup@4.34.9: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.9 + '@rollup/rollup-android-arm64': 4.34.9 + '@rollup/rollup-darwin-arm64': 4.34.9 + '@rollup/rollup-darwin-x64': 4.34.9 + '@rollup/rollup-freebsd-arm64': 4.34.9 + '@rollup/rollup-freebsd-x64': 4.34.9 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.9 + '@rollup/rollup-linux-arm-musleabihf': 4.34.9 + '@rollup/rollup-linux-arm64-gnu': 4.34.9 + '@rollup/rollup-linux-arm64-musl': 4.34.9 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.9 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.9 + '@rollup/rollup-linux-riscv64-gnu': 4.34.9 + '@rollup/rollup-linux-s390x-gnu': 4.34.9 + '@rollup/rollup-linux-x64-gnu': 4.34.9 + '@rollup/rollup-linux-x64-musl': 4.34.9 + '@rollup/rollup-win32-arm64-msvc': 4.34.9 + '@rollup/rollup-win32-ia32-msvc': 4.34.9 + '@rollup/rollup-win32-x64-msvc': 4.34.9 + fsevents: 2.3.3 + + run-parallel@1.2.0: + dependencies: + queue-microtask: 1.2.3 + + safe-array-concat@1.1.3: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + get-intrinsic: 1.3.0 + has-symbols: 1.1.0 + isarray: 2.0.5 + + safe-buffer@5.1.2: {} + + safe-buffer@5.2.1: {} + + safe-push-apply@1.0.0: + dependencies: + es-errors: 1.3.0 + isarray: 2.0.5 + + safe-regex-test@1.1.0: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-regex: 1.2.1 + + safer-buffer@2.1.2: {} + + sanitize.css@13.0.0: {} + + sass-loader@12.6.0(webpack@5.98.0): + dependencies: + klona: 2.0.6 + neo-async: 2.6.2 + webpack: 5.98.0 + + sax@1.2.4: {} + + saxes@5.0.1: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.25.0: {} + + schema-utils@2.7.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@2.7.1: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@3.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 6.12.6 + ajv-keywords: 3.5.2(ajv@6.12.6) + + schema-utils@4.3.0: + dependencies: + '@types/json-schema': 7.0.15 + ajv: 8.17.1 + ajv-formats: 2.1.1(ajv@8.17.1) + ajv-keywords: 5.1.0(ajv@8.17.1) + + select-hose@2.0.0: {} + + selfsigned@2.4.1: + dependencies: + '@types/node-forge': 1.3.11 + node-forge: 1.3.1 + + semver@6.3.1: {} + + semver@7.7.1: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color + + serialize-javascript@4.0.0: + dependencies: + randombytes: 2.1.0 + + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + + serve-index@1.9.1: + dependencies: + accepts: 1.3.8 + batch: 0.6.1 + debug: 2.6.9 + escape-html: 1.0.3 + http-errors: 1.6.3 + mime-types: 2.1.35 + parseurl: 1.3.3 + transitivePeerDependencies: + - supports-color + + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + + set-function-length@1.2.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + function-bind: 1.1.2 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-property-descriptors: 1.0.2 + + set-function-name@2.0.2: + dependencies: + define-data-property: 1.1.4 + es-errors: 1.3.0 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.2 + + set-proto@1.0.0: + dependencies: + dunder-proto: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + + setprototypeof@1.1.0: {} + + setprototypeof@1.2.0: {} + + shebang-command@2.0.0: + dependencies: + shebang-regex: 3.0.0 + + shebang-regex@3.0.0: {} + + shell-quote@1.8.2: {} + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + + siginfo@2.0.0: {} + + signal-exit@3.0.7: {} + + signal-exit@4.1.0: {} + + sisteransi@1.0.5: {} + + slash@3.0.0: {} + + slash@4.0.0: {} + + sockjs@0.3.24: + dependencies: + faye-websocket: 0.11.4 + uuid: 8.3.2 + websocket-driver: 0.7.4 + + source-list-map@2.0.1: {} + + source-map-js@1.2.1: {} + + source-map-loader@3.0.2(webpack@5.98.0): + dependencies: + abab: 2.0.6 + iconv-lite: 0.6.3 + source-map-js: 1.2.1 + webpack: 5.98.0 + + source-map-support@0.5.21: + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + + source-map@0.5.7: {} + + source-map@0.6.1: {} + + source-map@0.7.4: {} + + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sourcemap-codec@1.4.8: {} + + spdy-transport@3.0.0: + dependencies: + debug: 4.4.0 + detect-node: 2.1.0 + hpack.js: 2.1.6 + obuf: 1.1.2 + readable-stream: 3.6.2 + wbuf: 1.7.3 + transitivePeerDependencies: + - supports-color + + spdy@4.0.2: + dependencies: + debug: 4.4.0 + handle-thing: 2.0.1 + http-deceiver: 1.2.7 + select-hose: 2.0.0 + spdy-transport: 3.0.0 + transitivePeerDependencies: + - supports-color + + sprintf-js@1.0.3: {} + + stable@0.1.8: {} + + stack-utils@2.0.6: + dependencies: + escape-string-regexp: 2.0.0 + + stackback@0.0.2: {} + + stackframe@1.3.4: {} + + static-eval@2.0.2: + dependencies: + escodegen: 1.14.3 + + statuses@1.5.0: {} + + statuses@2.0.1: {} + + std-env@3.8.1: {} + + string-length@4.0.2: + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + + string-length@5.0.1: + dependencies: + char-regex: 2.0.2 + strip-ansi: 7.1.0 + + string-natural-compare@3.0.1: {} + + string-width@4.2.3: + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + + string-width@5.1.2: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + + string.prototype.includes@2.0.1: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-abstract: 1.23.9 + + string.prototype.matchall@4.0.12: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + get-intrinsic: 1.3.0 + gopd: 1.2.0 + has-symbols: 1.1.0 + internal-slot: 1.1.0 + regexp.prototype.flags: 1.5.4 + set-function-name: 2.0.2 + side-channel: 1.1.0 + + string.prototype.repeat@1.0.0: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + + string.prototype.trim@1.2.10: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-data-property: 1.1.4 + define-properties: 1.2.1 + es-abstract: 1.23.9 + es-object-atoms: 1.1.1 + has-property-descriptors: 1.0.2 + + string.prototype.trimend@1.0.9: + dependencies: + call-bind: 1.0.8 + call-bound: 1.0.4 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string.prototype.trimstart@1.0.8: + dependencies: + call-bind: 1.0.8 + define-properties: 1.2.1 + es-object-atoms: 1.1.1 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + + stringify-object@3.3.0: + dependencies: + get-own-enumerable-property-symbols: 3.0.2 + is-obj: 1.0.1 + is-regexp: 1.0.0 + + strip-ansi@6.0.1: + dependencies: + ansi-regex: 5.0.1 + + strip-ansi@7.1.0: + dependencies: + ansi-regex: 6.1.0 + + strip-bom@3.0.0: {} + + strip-bom@4.0.0: {} + + strip-comments@2.0.1: {} + + strip-final-newline@2.0.0: {} + + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + + strip-json-comments@3.1.1: {} + + style-loader@3.3.4(webpack@5.98.0): + dependencies: + webpack: 5.98.0 + + stylehacks@5.1.1(postcss@8.5.3): + dependencies: + browserslist: 4.24.4 + postcss: 8.5.3 + postcss-selector-parser: 6.1.2 + + stylis@4.2.0: {} + + sucrase@3.35.0: + dependencies: + '@jridgewell/gen-mapping': 0.3.8 + commander: 4.1.1 + glob: 10.4.5 + lines-and-columns: 1.2.4 + mz: 2.7.0 + pirates: 4.0.6 + ts-interface-checker: 0.1.13 + + supports-color@5.5.0: + dependencies: + has-flag: 3.0.0 + + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-hyperlinks@2.3.0: + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + + supports-preserve-symlinks-flag@1.0.0: {} + + svg-parser@2.0.4: {} + + svgo@1.3.2: + dependencies: + chalk: 2.4.2 + coa: 2.0.2 + css-select: 2.1.0 + css-select-base-adapter: 0.1.1 + css-tree: 1.0.0-alpha.37 + csso: 4.2.0 + js-yaml: 3.14.1 + mkdirp: 0.5.6 + object.values: 1.2.1 + sax: 1.2.4 + stable: 0.1.8 + unquote: 1.1.1 + util.promisify: 1.0.1 + + svgo@2.8.0: + dependencies: + '@trysound/sax': 0.2.0 + commander: 7.2.0 + css-select: 4.3.0 + css-tree: 1.1.3 + csso: 4.2.0 + picocolors: 1.1.1 + stable: 0.1.8 + + symbol-tree@3.2.4: {} + + tailwindcss@3.4.17: + 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.3 + glob-parent: 6.0.2 + is-glob: 4.0.3 + jiti: 1.21.7 + lilconfig: 3.1.3 + micromatch: 4.0.8 + normalize-path: 3.0.0 + object-hash: 3.0.0 + picocolors: 1.1.1 + postcss: 8.5.3 + postcss-import: 15.1.0(postcss@8.5.3) + postcss-js: 4.0.1(postcss@8.5.3) + postcss-load-config: 4.0.2(postcss@8.5.3) + postcss-nested: 6.2.0(postcss@8.5.3) + postcss-selector-parser: 6.1.2 + resolve: 1.22.10 + sucrase: 3.35.0 + transitivePeerDependencies: + - ts-node + + tapable@1.1.3: {} + + tapable@2.2.1: {} + + temp-dir@2.0.0: {} + + tempy@0.6.0: + dependencies: + is-stream: 2.0.1 + temp-dir: 2.0.0 + type-fest: 0.16.0 + unique-string: 2.0.0 + + terminal-link@2.1.1: + dependencies: + ansi-escapes: 4.3.2 + supports-hyperlinks: 2.3.0 + + terser-webpack-plugin@5.3.14(webpack@5.98.0): + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + jest-worker: 27.5.1 + schema-utils: 4.3.0 + serialize-javascript: 6.0.2 + terser: 5.39.0 + webpack: 5.98.0 + + terser@5.39.0: + dependencies: + '@jridgewell/source-map': 0.3.6 + acorn: 8.14.1 + commander: 2.20.3 + source-map-support: 0.5.21 + + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + + test-exclude@7.0.1: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 10.4.5 + minimatch: 9.0.5 + + text-table@0.2.0: {} + + thenify-all@1.6.0: + dependencies: + thenify: 3.3.1 + + thenify@3.3.1: + dependencies: + any-promise: 1.3.0 + + throat@6.0.2: {} + + thunky@1.1.0: {} + + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + + tinypool@1.0.2: {} + + tinyrainbow@2.0.0: {} + + tinyspy@3.0.2: {} + + tmpl@1.0.5: {} + + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + + toggle-selection@1.0.6: {} + + toidentifier@1.0.1: {} + + toposort@2.0.2: {} + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tr46@2.1.0: + dependencies: + punycode: 2.3.1 + + tryer@1.0.1: {} + + ts-api-utils@2.0.1(typescript@5.8.2): + dependencies: + typescript: 5.8.2 + + ts-interface-checker@0.1.13: {} + + ts-toolbelt@9.6.0: {} + + tsconfig-paths@3.15.0: + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + + tslib@1.14.1: {} + + tslib@2.4.0: {} + + tslib@2.8.1: {} + + tsutils@3.21.0(typescript@5.8.2): + dependencies: + tslib: 1.14.1 + typescript: 5.8.2 + + type-check@0.3.2: + dependencies: + prelude-ls: 1.1.2 + + type-check@0.4.0: + dependencies: + prelude-ls: 1.2.1 + + type-detect@4.0.8: {} + + type-fest@0.16.0: {} + + type-fest@0.21.3: {} + + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typed-array-buffer@1.0.3: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + is-typed-array: 1.1.15 + + typed-array-byte-length@1.0.3: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + + typed-array-byte-offset@1.0.4: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + has-proto: 1.2.0 + is-typed-array: 1.1.15 + reflect.getprototypeof: 1.0.10 + + typed-array-length@1.0.7: + dependencies: + call-bind: 1.0.8 + for-each: 0.3.5 + gopd: 1.2.0 + is-typed-array: 1.1.15 + possible-typed-array-names: 1.1.0 + reflect.getprototypeof: 1.0.10 + + typedarray-to-buffer@3.1.5: + dependencies: + is-typedarray: 1.0.0 + + typescript-eslint@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2): + dependencies: + '@typescript-eslint/eslint-plugin': 8.26.0(@typescript-eslint/parser@8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2))(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/parser': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + '@typescript-eslint/utils': 8.26.0(eslint@9.21.0(jiti@1.21.7))(typescript@5.8.2) + eslint: 9.21.0(jiti@1.21.7) + typescript: 5.8.2 + transitivePeerDependencies: + - supports-color + + typescript@5.8.2: {} + + unbox-primitive@1.1.0: + dependencies: + call-bound: 1.0.4 + has-bigints: 1.1.0 + has-symbols: 1.1.0 + which-boxed-primitive: 1.1.1 + + underscore@1.12.1: {} + + undici-types@6.20.0: {} + + unicode-canonical-property-names-ecmascript@2.0.1: {} + + unicode-match-property-ecmascript@2.0.0: + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.1 + unicode-property-aliases-ecmascript: 2.1.0 + + unicode-match-property-value-ecmascript@2.2.0: {} + + unicode-property-aliases-ecmascript@2.1.0: {} + + unique-string@2.0.0: + dependencies: + crypto-random-string: 2.0.0 + + universalify@0.2.0: {} + + universalify@2.0.1: {} + + unpipe@1.0.0: {} + + unquote@1.1.1: {} + + upath@1.2.0: {} + + update-browserslist-db@1.1.3(browserslist@4.24.4): + dependencies: + browserslist: 4.24.4 + escalade: 3.2.0 + picocolors: 1.1.1 + + uri-js@4.4.1: + dependencies: + punycode: 2.3.1 + + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + + use-callback-ref@1.3.3(@types/react@19.0.10)(react@19.0.0): + dependencies: + react: 19.0.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.0.10 + + use-debounce@10.0.4(react@19.0.0): + dependencies: + react: 19.0.0 + + use-sidecar@1.1.3(@types/react@19.0.10)(react@19.0.0): + dependencies: + detect-node-es: 1.1.0 + react: 19.0.0 + tslib: 2.8.1 + optionalDependencies: + '@types/react': 19.0.10 + + use-sync-external-store@1.4.0(react@19.0.0): + dependencies: + react: 19.0.0 + + util-deprecate@1.0.2: {} + + util.promisify@1.0.1: + dependencies: + define-properties: 1.2.1 + es-abstract: 1.23.9 + has-symbols: 1.1.0 + object.getownpropertydescriptors: 2.1.8 + + utila@0.4.0: {} + + utils-merge@1.0.1: {} + + uuid@8.3.2: {} + + v8-to-istanbul@8.1.1: + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 1.9.0 + source-map: 0.7.4 + + vary@1.1.2: {} + + victory-area@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-axis@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-bar@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-box-plot@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-brush-container@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + + victory-brush-line@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + + victory-candlestick@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-canvas@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-bar: 37.3.6(react@19.0.0) + victory-core: 37.3.6(react@19.0.0) + + victory-chart@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-axis: 37.3.6(react@19.0.0) + victory-core: 37.3.6(react@19.0.0) + victory-polar-axis: 37.3.6(react@19.0.0) + victory-shared-events: 37.3.6(react@19.0.0) + + victory-core@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-vendor: 37.3.6 + + victory-create-container@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-brush-container: 37.3.6(react@19.0.0) + victory-core: 37.3.6(react@19.0.0) + victory-cursor-container: 37.3.6(react@19.0.0) + victory-selection-container: 37.3.6(react@19.0.0) + victory-voronoi-container: 37.3.6(react@19.0.0) + victory-zoom-container: 37.3.6(react@19.0.0) + + victory-cursor-container@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-errorbar@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-group@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + victory-shared-events: 37.3.6(react@19.0.0) + + victory-histogram@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-bar: 37.3.6(react@19.0.0) + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-legend@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-line@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-pie@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + victory-vendor: 37.3.6 + + victory-polar-axis@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-scatter@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-selection-container@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-shared-events@37.3.6(react@19.0.0): + dependencies: + json-stringify-safe: 5.0.1 + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + + victory-stack@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + victory-shared-events: 37.3.6(react@19.0.0) + + victory-tooltip@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-vendor@37.3.6: + dependencies: + '@types/d3-array': 3.2.1 + '@types/d3-ease': 3.0.2 + '@types/d3-interpolate': 3.0.4 + '@types/d3-scale': 4.0.9 + '@types/d3-shape': 3.1.7 + '@types/d3-time': 3.0.4 + '@types/d3-timer': 3.0.2 + d3-array: 3.2.4 + d3-ease: 3.0.1 + d3-interpolate: 3.0.1 + d3-scale: 4.0.2 + d3-shape: 3.2.0 + d3-time: 3.1.0 + d3-timer: 3.0.1 + + victory-voronoi-container@37.3.6(react@19.0.0): + dependencies: + delaunay-find: 0.0.6 + lodash: 4.17.21 + react: 19.0.0 + react-fast-compare: 3.2.2 + victory-core: 37.3.6(react@19.0.0) + victory-tooltip: 37.3.6(react@19.0.0) + + victory-voronoi@37.3.6(react@19.0.0): + dependencies: + d3-voronoi: 1.1.4 + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory-zoom-container@37.3.6(react@19.0.0): + dependencies: + lodash: 4.17.21 + react: 19.0.0 + victory-core: 37.3.6(react@19.0.0) + + victory@37.3.6(react@19.0.0): + dependencies: + react: 19.0.0 + victory-area: 37.3.6(react@19.0.0) + victory-axis: 37.3.6(react@19.0.0) + victory-bar: 37.3.6(react@19.0.0) + victory-box-plot: 37.3.6(react@19.0.0) + victory-brush-container: 37.3.6(react@19.0.0) + victory-brush-line: 37.3.6(react@19.0.0) + victory-candlestick: 37.3.6(react@19.0.0) + victory-canvas: 37.3.6(react@19.0.0) + victory-chart: 37.3.6(react@19.0.0) + victory-core: 37.3.6(react@19.0.0) + victory-create-container: 37.3.6(react@19.0.0) + victory-cursor-container: 37.3.6(react@19.0.0) + victory-errorbar: 37.3.6(react@19.0.0) + victory-group: 37.3.6(react@19.0.0) + victory-histogram: 37.3.6(react@19.0.0) + victory-legend: 37.3.6(react@19.0.0) + victory-line: 37.3.6(react@19.0.0) + victory-pie: 37.3.6(react@19.0.0) + victory-polar-axis: 37.3.6(react@19.0.0) + victory-scatter: 37.3.6(react@19.0.0) + victory-selection-container: 37.3.6(react@19.0.0) + victory-shared-events: 37.3.6(react@19.0.0) + victory-stack: 37.3.6(react@19.0.0) + victory-tooltip: 37.3.6(react@19.0.0) + victory-voronoi: 37.3.6(react@19.0.0) + victory-voronoi-container: 37.3.6(react@19.0.0) + victory-zoom-container: 37.3.6(react@19.0.0) + + vite-node@3.0.8(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0): + dependencies: + cac: 6.7.14 + debug: 4.4.0 + es-module-lexer: 1.6.0 + pathe: 2.0.3 + vite: 6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite@6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0): + dependencies: + esbuild: 0.25.0 + postcss: 8.5.3 + rollup: 4.34.9 + optionalDependencies: + '@types/node': 22.13.9 + fsevents: 2.3.3 + jiti: 1.21.7 + terser: 5.39.0 + yaml: 2.7.0 + + vitest@3.0.8(@types/node@22.13.9)(jiti@1.21.7)(jsdom@16.7.0)(terser@5.39.0)(yaml@2.7.0): + dependencies: + '@vitest/expect': 3.0.8 + '@vitest/mocker': 3.0.8(vite@6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0)) + '@vitest/pretty-format': 3.0.8 + '@vitest/runner': 3.0.8 + '@vitest/snapshot': 3.0.8 + '@vitest/spy': 3.0.8 + '@vitest/utils': 3.0.8 + chai: 5.2.0 + debug: 4.4.0 + expect-type: 1.2.0 + magic-string: 0.30.17 + pathe: 2.0.3 + std-env: 3.8.1 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinypool: 1.0.2 + tinyrainbow: 2.0.0 + vite: 6.2.1(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + vite-node: 3.0.8(@types/node@22.13.9)(jiti@1.21.7)(terser@5.39.0)(yaml@2.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 22.13.9 + jsdom: 16.7.0 + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + w3c-hr-time@1.0.2: + dependencies: + browser-process-hrtime: 1.0.0 + + w3c-xmlserializer@2.0.0: + dependencies: + xml-name-validator: 3.0.0 + + walker@1.0.8: + dependencies: + makeerror: 1.0.12 + + watchpack@2.4.2: + dependencies: + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + + wbuf@1.7.3: + dependencies: + minimalistic-assert: 1.0.1 + + webidl-conversions@4.0.2: {} + + webidl-conversions@5.0.0: {} + + webidl-conversions@6.1.0: {} + + webpack-dev-middleware@5.3.4(webpack@5.98.0): + dependencies: + colorette: 2.0.20 + memfs: 3.5.3 + mime-types: 2.1.35 + range-parser: 1.2.1 + schema-utils: 4.3.0 + webpack: 5.98.0 + + webpack-dev-server@4.15.2(webpack@5.98.0): + dependencies: + '@types/bonjour': 3.5.13 + '@types/connect-history-api-fallback': 1.5.4 + '@types/express': 4.17.21 + '@types/serve-index': 1.9.4 + '@types/serve-static': 1.15.7 + '@types/sockjs': 0.3.36 + '@types/ws': 8.18.0 + ansi-html-community: 0.0.8 + bonjour-service: 1.3.0 + chokidar: 3.6.0 + colorette: 2.0.20 + compression: 1.8.0 + connect-history-api-fallback: 2.0.0 + default-gateway: 6.0.3 + express: 4.21.2 + graceful-fs: 4.2.11 + html-entities: 2.5.2 + http-proxy-middleware: 2.0.7(@types/express@4.17.21) + ipaddr.js: 2.2.0 + launch-editor: 2.10.0 + open: 8.4.2 + p-retry: 4.6.2 + rimraf: 3.0.2 + schema-utils: 4.3.0 + selfsigned: 2.4.1 + serve-index: 1.9.1 + sockjs: 0.3.24 + spdy: 4.0.2 + webpack-dev-middleware: 5.3.4(webpack@5.98.0) + ws: 8.18.1 + optionalDependencies: + webpack: 5.98.0 + transitivePeerDependencies: + - bufferutil + - debug + - supports-color + - utf-8-validate + + webpack-manifest-plugin@4.1.1(webpack@5.98.0): + dependencies: + tapable: 2.2.1 + webpack: 5.98.0 + webpack-sources: 2.3.1 + + webpack-sources@1.4.3: + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + + webpack-sources@2.3.1: + dependencies: + source-list-map: 2.0.1 + source-map: 0.6.1 + + webpack-sources@3.2.3: {} + + webpack@5.98.0: + dependencies: + '@types/eslint-scope': 3.7.7 + '@types/estree': 1.0.6 + '@webassemblyjs/ast': 1.14.1 + '@webassemblyjs/wasm-edit': 1.14.1 + '@webassemblyjs/wasm-parser': 1.14.1 + acorn: 8.14.1 + browserslist: 4.24.4 + chrome-trace-event: 1.0.4 + enhanced-resolve: 5.18.1 + es-module-lexer: 1.6.0 + eslint-scope: 5.1.1 + events: 3.3.0 + glob-to-regexp: 0.4.1 + graceful-fs: 4.2.11 + json-parse-even-better-errors: 2.3.1 + loader-runner: 4.3.0 + mime-types: 2.1.35 + neo-async: 2.6.2 + schema-utils: 4.3.0 + tapable: 2.2.1 + terser-webpack-plugin: 5.3.14(webpack@5.98.0) + watchpack: 2.4.2 + webpack-sources: 3.2.3 + transitivePeerDependencies: + - '@swc/core' + - esbuild + - uglify-js + + websocket-driver@0.7.4: + dependencies: + http-parser-js: 0.5.9 + safe-buffer: 5.2.1 + websocket-extensions: 0.1.4 + + websocket-extensions@0.1.4: {} + + whatwg-encoding@1.0.5: + dependencies: + iconv-lite: 0.4.24 + + whatwg-fetch@3.6.20: {} + + whatwg-mimetype@2.3.0: {} + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + + whatwg-url@8.7.0: + dependencies: + lodash: 4.17.21 + tr46: 2.1.0 + webidl-conversions: 6.1.0 + + which-boxed-primitive@1.1.1: + dependencies: + is-bigint: 1.1.0 + is-boolean-object: 1.2.2 + is-number-object: 1.1.1 + is-string: 1.1.1 + is-symbol: 1.1.1 + + which-builtin-type@1.2.1: + dependencies: + call-bound: 1.0.4 + function.prototype.name: 1.1.8 + has-tostringtag: 1.0.2 + is-async-function: 2.1.1 + is-date-object: 1.1.0 + is-finalizationregistry: 1.1.1 + is-generator-function: 1.1.0 + is-regex: 1.2.1 + is-weakref: 1.1.1 + isarray: 2.0.5 + which-boxed-primitive: 1.1.1 + which-collection: 1.0.2 + which-typed-array: 1.1.18 + + which-collection@1.0.2: + dependencies: + is-map: 2.0.3 + is-set: 2.0.3 + is-weakmap: 2.0.2 + is-weakset: 2.0.4 + + which-typed-array@1.1.18: + dependencies: + available-typed-arrays: 1.0.7 + call-bind: 1.0.8 + call-bound: 1.0.4 + for-each: 0.3.5 + gopd: 1.2.0 + has-tostringtag: 1.0.2 + + which@1.3.1: + dependencies: + isexe: 2.0.0 + + which@2.0.2: + dependencies: + isexe: 2.0.0 + + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + + word-wrap@1.2.5: {} + + workbox-background-sync@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-broadcast-update@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-build@6.6.0(@types/babel__core@7.20.5): + dependencies: + '@apideck/better-ajv-errors': 0.3.6(ajv@8.17.1) + '@babel/core': 7.26.9 + '@babel/preset-env': 7.26.9(@babel/core@7.26.9) + '@babel/runtime': 7.26.9 + '@rollup/plugin-babel': 5.3.1(@babel/core@7.26.9)(@types/babel__core@7.20.5)(rollup@2.79.2) + '@rollup/plugin-node-resolve': 11.2.1(rollup@2.79.2) + '@rollup/plugin-replace': 2.4.2(rollup@2.79.2) + '@surma/rollup-plugin-off-main-thread': 2.2.3 + ajv: 8.17.1 + common-tags: 1.8.2 + fast-json-stable-stringify: 2.1.0 + fs-extra: 9.1.0 + glob: 7.2.3 + lodash: 4.17.21 + pretty-bytes: 5.6.0 + rollup: 2.79.2 + rollup-plugin-terser: 7.0.2(rollup@2.79.2) + source-map: 0.8.0-beta.0 + stringify-object: 3.3.0 + strip-comments: 2.0.1 + tempy: 0.6.0 + upath: 1.2.0 + workbox-background-sync: 6.6.0 + workbox-broadcast-update: 6.6.0 + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-google-analytics: 6.6.0 + workbox-navigation-preload: 6.6.0 + workbox-precaching: 6.6.0 + workbox-range-requests: 6.6.0 + workbox-recipes: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + workbox-streams: 6.6.0 + workbox-sw: 6.6.0 + workbox-window: 6.6.0 + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-cacheable-response@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-core@6.6.0: {} + + workbox-expiration@6.6.0: + dependencies: + idb: 7.1.1 + workbox-core: 6.6.0 + + workbox-google-analytics@6.6.0: + dependencies: + workbox-background-sync: 6.6.0 + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-navigation-preload@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-precaching@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-range-requests@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-recipes@6.6.0: + dependencies: + workbox-cacheable-response: 6.6.0 + workbox-core: 6.6.0 + workbox-expiration: 6.6.0 + workbox-precaching: 6.6.0 + workbox-routing: 6.6.0 + workbox-strategies: 6.6.0 + + workbox-routing@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-strategies@6.6.0: + dependencies: + workbox-core: 6.6.0 + + workbox-streams@6.6.0: + dependencies: + workbox-core: 6.6.0 + workbox-routing: 6.6.0 + + workbox-sw@6.6.0: {} + + workbox-webpack-plugin@6.6.0(@types/babel__core@7.20.5)(webpack@5.98.0): + dependencies: + fast-json-stable-stringify: 2.1.0 + pretty-bytes: 5.6.0 + upath: 1.2.0 + webpack: 5.98.0 + webpack-sources: 1.4.3 + workbox-build: 6.6.0(@types/babel__core@7.20.5) + transitivePeerDependencies: + - '@types/babel__core' + - supports-color + + workbox-window@6.6.0: + dependencies: + '@types/trusted-types': 2.0.7 + workbox-core: 6.6.0 + + wrap-ansi@7.0.0: + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + + wrap-ansi@8.1.0: + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + + wrappy@1.0.2: {} + + write-file-atomic@3.0.3: + dependencies: + imurmurhash: 0.1.4 + is-typedarray: 1.0.0 + signal-exit: 3.0.7 + typedarray-to-buffer: 3.1.5 + + ws@7.5.10: {} + + ws@8.18.1: {} + + xml-name-validator@3.0.0: {} + + xmlchars@2.2.0: {} + + y18n@5.0.8: {} + + yallist@3.1.1: {} + + yaml@1.10.2: {} + + yaml@2.7.0: {} + + yargs-parser@20.2.9: {} + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yocto-queue@0.1.0: {} + + yup@0.32.11: + dependencies: + '@babel/runtime': 7.26.9 + '@types/lodash': 4.17.16 + lodash: 4.17.21 + lodash-es: 4.17.21 + nanoclone: 0.2.1 + property-expr: 2.0.6 + toposort: 2.0.2 + + zod-validation-error@3.4.0(zod@3.24.2): + dependencies: + zod: 3.24.2 + + zod@3.24.2: {} diff --git a/client/public/index.html b/client/public/index.html deleted file mode 100644 index d62bd172..00000000 --- a/client/public/index.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - Tockler - - - -
- - diff --git a/client/public/less.min.js b/client/public/less.min.js deleted file mode 100644 index 6319704f..00000000 --- a/client/public/less.min.js +++ /dev/null @@ -1,17 +0,0 @@ -/*! - * Less - Leaner CSS v2.7.2 - * http://lesscss.org - * - * Copyright (c) 2009-2017, Alexis Sellier - * Licensed under the Apache-2.0 License. - * - */ - - /** * @license Apache-2.0 - */ - -!function(a){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=a();else if("function"==typeof define&&define.amd)define([],a);else{var b;b="undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this,b.less=a()}}(function(){return function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g0||b.isFileProtocol?"development":"production");var c=/!dumpLineNumbers:(comments|mediaquery|all)/.exec(a.location.hash);c&&(b.dumpLineNumbers=c[1]),void 0===b.useFileCache&&(b.useFileCache=!0),void 0===b.onReady&&(b.onReady=!0)}},{"./browser":3,"./utils":10}],2:[function(a,b,c){function d(a){a.filename&&console.warn(a),e.async||h.removeChild(i)}a("promise/polyfill.js");var e=window.less||{};a("./add-default-options")(window,e);var f=b.exports=a("./index")(window,e);window.less=f;var g,h,i;e.onReady&&(/!watch/.test(window.location.hash)&&f.watch(),e.async||(g="body { display: none !important }",h=document.head||document.getElementsByTagName("head")[0],i=document.createElement("style"),i.type="text/css",i.styleSheet?i.styleSheet.cssText=g:i.appendChild(document.createTextNode(g)),h.appendChild(i)),f.registerStylesheetsImmediately(),f.pageLoadFinished=f.refresh("development"===f.env).then(d,d))},{"./add-default-options":1,"./index":8,"promise/polyfill.js":97}],3:[function(a,b,c){var d=a("./utils");b.exports={createCSS:function(a,b,c){var e=c.href||"",f="less:"+(c.title||d.extractId(e)),g=a.getElementById(f),h=!1,i=a.createElement("style");i.setAttribute("type","text/css"),c.media&&i.setAttribute("media",c.media),i.id=f,i.styleSheet||(i.appendChild(a.createTextNode(b)),h=null!==g&&g.childNodes.length>0&&i.childNodes.length>0&&g.firstChild.nodeValue===i.firstChild.nodeValue);var j=a.getElementsByTagName("head")[0];if(null===g||h===!1){var k=c&&c.nextSibling||null;k?k.parentNode.insertBefore(i,k):j.appendChild(i)}if(g&&h===!1&&g.parentNode.removeChild(g),i.styleSheet)try{i.styleSheet.cssText=b}catch(l){throw new Error("Couldn't reassign styleSheet.cssText.")}},currentScript:function(a){var b=a.document;return b.currentScript||function(){var a=b.getElementsByTagName("script");return a[a.length-1]}()}}},{"./utils":10}],4:[function(a,b,c){b.exports=function(a,b,c){var d=null;if("development"!==b.env)try{d="undefined"==typeof a.localStorage?null:a.localStorage}catch(e){}return{setCSS:function(a,b,e,f){if(d){c.info("saving "+a+" to cache.");try{d.setItem(a,f),d.setItem(a+":timestamp",b),e&&d.setItem(a+":vars",JSON.stringify(e))}catch(g){c.error('failed to save "'+a+'" to local storage for caching.')}}},getCSS:function(a,b,c){var e=d&&d.getItem(a),f=d&&d.getItem(a+":timestamp"),g=d&&d.getItem(a+":vars");if(c=c||{},f&&b.lastModified&&new Date(b.lastModified).valueOf()===new Date(f).valueOf()&&(!c&&!g||JSON.stringify(c)===g))return e}}}},{}],5:[function(a,b,c){var d=a("./utils"),e=a("./browser");b.exports=function(a,b,c){function f(b,f){var g,h,i="less-error-message:"+d.extractId(f||""),j='
  • {content}
  • ',k=a.document.createElement("div"),l=[],m=b.filename||f,n=m.match(/([^\/]+(\?.*)?)$/)[1];k.id=i,k.className="less-error-message",h="

    "+(b.type||"Syntax")+"Error: "+(b.message||"There is an error in your .less file")+'

    in '+n+" ";var o=function(a,b,c){void 0!==a.extract[b]&&l.push(j.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};b.extract&&(o(b,0,""),o(b,1,"line"),o(b,2,""),h+="on line "+b.line+", column "+(b.column+1)+":

    "),b.stack&&(b.extract||c.logLevel>=4)&&(h+="
    Stack Trace
    "+b.stack.split("\n").slice(1).join("
    ")),k.innerHTML=h,e.createCSS(a.document,[".less-error-message ul, .less-error-message li {","list-style-type: none;","margin-right: 15px;","padding: 4px 0;","margin: 0;","}",".less-error-message label {","font-size: 12px;","margin-right: 15px;","padding: 4px 0;","color: #cc7777;","}",".less-error-message pre {","color: #dd6666;","padding: 4px 0;","margin: 0;","display: inline-block;","}",".less-error-message pre.line {","color: #ff0000;","}",".less-error-message h3 {","font-size: 20px;","font-weight: bold;","padding: 15px 0 5px 0;","margin: 0;","}",".less-error-message a {","color: #10a","}",".less-error-message .error {","color: red;","font-weight: bold;","padding-bottom: 2px;","border-bottom: 1px dashed red;","}"].join("\n"),{title:"error-message"}),k.style.cssText=["font-family: Arial, sans-serif","border: 1px solid #e00","background-color: #eee","border-radius: 5px","-webkit-border-radius: 5px","-moz-border-radius: 5px","color: #e00","padding: 15px","margin-bottom: 15px"].join(";"),"development"===c.env&&(g=setInterval(function(){var b=a.document,c=b.body;c&&(b.getElementById(i)?c.replaceChild(k,b.getElementById(i)):c.insertBefore(k,c.firstChild),clearInterval(g))},10))}function g(b){var c=a.document.getElementById("less-error-message:"+d.extractId(b));c&&c.parentNode.removeChild(c)}function h(a){}function i(a){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?h(a):"function"==typeof c.errorReporting&&c.errorReporting("remove",a):g(a)}function j(a,d){var e="{line} {content}",f=a.filename||d,g=[],h=(a.type||"Syntax")+"Error: "+(a.message||"There is an error in your .less file")+" in "+f+" ",i=function(a,b,c){void 0!==a.extract[b]&&g.push(e.replace(/\{line\}/,(parseInt(a.line,10)||0)+(b-1)).replace(/\{class\}/,c).replace(/\{content\}/,a.extract[b]))};a.extract&&(i(a,0,""),i(a,1,"line"),i(a,2,""),h+="on line "+a.line+", column "+(a.column+1)+":\n"+g.join("\n")),a.stack&&(a.extract||c.logLevel>=4)&&(h+="\nStack Trace\n"+a.stack),b.logger.error(h)}function k(a,b){c.errorReporting&&"html"!==c.errorReporting?"console"===c.errorReporting?j(a,b):"function"==typeof c.errorReporting&&c.errorReporting("add",a,b):f(a,b)}return{add:k,remove:i}}},{"./browser":3,"./utils":10}],6:[function(a,b,c){b.exports=function(b,c){function d(){if(window.XMLHttpRequest&&!("file:"===window.location.protocol&&"ActiveXObject"in window))return new XMLHttpRequest;try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(a){return c.error("browser doesn't support AJAX."),null}}var e=a("../less/environment/abstract-file-manager.js"),f={},g=function(){};return g.prototype=new e,g.prototype.alwaysMakePathsAbsolute=function(){return!0},g.prototype.join=function(a,b){return a?this.extractUrlParts(b,a).path:b},g.prototype.doXHR=function(a,e,f,g){function h(b,c,d){b.status>=200&&b.status<300?c(b.responseText,b.getResponseHeader("Last-Modified")):"function"==typeof d&&d(b.status,a)}var i=d(),j=!b.isFileProtocol||b.fileAsync;"function"==typeof i.overrideMimeType&&i.overrideMimeType("text/css"),c.debug("XHR: Getting '"+a+"'"),i.open("GET",a,j),i.setRequestHeader("Accept",e||"text/x-less, text/css; q=0.9, */*; q=0.5"),i.send(null),b.isFileProtocol&&!b.fileAsync?0===i.status||i.status>=200&&i.status<300?f(i.responseText):g(i.status,a):j?i.onreadystatechange=function(){4==i.readyState&&h(i,f,g)}:h(i,f,g)},g.prototype.supports=function(a,b,c,d){return!0},g.prototype.clearFileCache=function(){f={}},g.prototype.loadFile=function(a,b,c,d,e){b&&!this.isPathAbsolute(a)&&(a=b+a),c=c||{};var g=this.extractUrlParts(a,window.location.href),h=g.url;if(c.useFileCache&&f[h])try{var i=f[h];e(null,{contents:i,filename:h,webInfo:{lastModified:new Date}})}catch(j){e({filename:h,message:"Error loading file "+h+" error was "+j.message})}else this.doXHR(h,c.mime,function(a,b){f[h]=a,e(null,{contents:a,filename:h,webInfo:{lastModified:b}})},function(a,b){e({type:"File",message:"'"+b+"' wasn't found ("+a+")",href:h})})},g}},{"../less/environment/abstract-file-manager.js":15}],7:[function(a,b,c){b.exports=function(){function b(){throw{type:"Runtime",message:"Image size functions are not supported in browser version of less"}}var c=a("./../less/functions/function-registry"),d={"image-size":function(a){return b(this,a),-1},"image-width":function(a){return b(this,a),-1},"image-height":function(a){return b(this,a),-1}};c.addMultiple(d)}},{"./../less/functions/function-registry":22}],8:[function(a,b,c){var d=a("./utils").addDataAttr,e=a("./browser");b.exports=function(b,c){function f(a){return c.postProcessor&&"function"==typeof c.postProcessor&&(a=c.postProcessor.call(a,a)||a),a}function g(a){var b={};for(var c in a)a.hasOwnProperty(c)&&(b[c]=a[c]);return b}function h(a,b){var c=Array.prototype.slice.call(arguments,2);return function(){var d=c.concat(Array.prototype.slice.call(arguments,0));return a.apply(b,d)}}function i(a){for(var b,d=m.getElementsByTagName("style"),e=0;e=c&&console.log(a)},info:function(a){b.logLevel>=d&&console.log(a)},warn:function(a){b.logLevel>=e&&console.warn(a)},error:function(a){b.logLevel>=f&&console.error(a)}}]);for(var g=0;g0&&(a=a.slice(0,b)),b=a.lastIndexOf("/"),b<0&&(b=a.lastIndexOf("\\")),b<0?"":a.slice(0,b+1)},d.prototype.tryAppendExtension=function(a,b){return/(\.[a-z]*$)|([\?;].*)$/.test(a)?a:a+b},d.prototype.tryAppendLessExtension=function(a){return this.tryAppendExtension(a,".less")},d.prototype.supportsSync=function(){return!1},d.prototype.alwaysMakePathsAbsolute=function(){return!1},d.prototype.isPathAbsolute=function(a){return/^(?:[a-z-]+:|\/|\\|#)/i.test(a)},d.prototype.join=function(a,b){return a?a+b:b},d.prototype.pathDiff=function(a,b){var c,d,e,f,g=this.extractUrlParts(a),h=this.extractUrlParts(b),i="";if(g.hostPart!==h.hostPart)return"";for(d=Math.max(h.directories.length,g.directories.length),c=0;c0&&(h.splice(c-1,2),c-=2)}return g.hostPart=f[1],g.directories=h,g.path=(f[1]||"")+h.join("/"),g.fileUrl=g.path+(f[4]||""),g.url=g.fileUrl+(f[5]||""),g},b.exports=d},{}],16:[function(a,b,c){var d=a("../logger"),e=function(a,b){this.fileManagers=b||[],a=a||{};for(var c=["encodeBase64","mimeLookup","charsetLookup","getSourceMapGenerator"],d=[],e=d.concat(c),f=0;f=0;h--){var i=g[h];if(i[f?"supportsSync":"supports"](a,b,c,e))return i}return null},e.prototype.addFileManager=function(a){this.fileManagers.push(a)},e.prototype.clearFileManagers=function(){this.fileManagers=[]},b.exports=e},{"../logger":33}],17:[function(a,b,c){function d(a,b,c){var d,f,g,h,i=b.alpha,j=c.alpha,k=[];g=j+i*(1-j);for(var l=0;l<3;l++)d=b.rgb[l]/255,f=c.rgb[l]/255,h=a(d,f),g&&(h=(j*f+i*(d-j*(d+f-h)))/g),k[l]=255*h;return new e(k,g)}var e=a("../tree/color"),f=a("./function-registry"),g={multiply:function(a,b){return a*b},screen:function(a,b){return a+b-a*b},overlay:function(a,b){return a*=2,a<=1?g.multiply(a,b):g.screen(a-1,b)},softlight:function(a,b){var c=1,d=a;return b>.5&&(d=1,c=a>.25?Math.sqrt(a):((16*a-12)*a+4)*a),a-(1-2*b)*d*(c-a)},hardlight:function(a,b){return g.overlay(b,a)},difference:function(a,b){return Math.abs(a-b)},exclusion:function(a,b){return a+b-2*a*b},average:function(a,b){return(a+b)/2},negation:function(a,b){return 1-Math.abs(a+b-1)}};for(var h in g)g.hasOwnProperty(h)&&(d[h]=d.bind(null,g[h]));f.addMultiple(d)},{"../tree/color":50,"./function-registry":22}],18:[function(a,b,c){function d(a){return Math.min(1,Math.max(0,a))}function e(a){return h.hsla(a.h,a.s,a.l,a.a)}function f(a){if(a instanceof i)return parseFloat(a.unit.is("%")?a.value/100:a.value);if("number"==typeof a)return a;throw{type:"Argument",message:"color functions take numbers as parameters"}}function g(a,b){return a instanceof i&&a.unit.is("%")?parseFloat(a.value*b/100):f(a)}var h,i=a("../tree/dimension"),j=a("../tree/color"),k=a("../tree/quoted"),l=a("../tree/anonymous"),m=a("./function-registry");h={rgb:function(a,b,c){return h.rgba(a,b,c,1)},rgba:function(a,b,c,d){var e=[a,b,c].map(function(a){return g(a,255)});return d=f(d),new j(e,d)},hsl:function(a,b,c){return h.hsla(a,b,c,1)},hsla:function(a,b,c,e){function g(a){return a=a<0?a+1:a>1?a-1:a,6*a<1?i+(j-i)*a*6:2*a<1?j:3*a<2?i+(j-i)*(2/3-a)*6:i}var i,j;return a=f(a)%360/360,b=d(f(b)),c=d(f(c)),e=d(f(e)),j=c<=.5?c*(b+1):c+b-c*b,i=2*c-j,h.rgba(255*g(a+1/3),255*g(a),255*g(a-1/3),e)},hsv:function(a,b,c){return h.hsva(a,b,c,1)},hsva:function(a,b,c,d){a=f(a)%360/360*360,b=f(b),c=f(c),d=f(d);var e,g;e=Math.floor(a/60%6),g=a/60-e;var i=[c,c*(1-b),c*(1-g*b),c*(1-(1-g)*b)],j=[[0,3,1],[2,0,1],[1,0,3],[1,2,0],[3,1,0],[0,1,2]];return h.rgba(255*i[j[e][0]],255*i[j[e][1]],255*i[j[e][2]],d)},hue:function(a){return new i(a.toHSL().h)},saturation:function(a){return new i(100*a.toHSL().s,"%")},lightness:function(a){return new i(100*a.toHSL().l,"%")},hsvhue:function(a){return new i(a.toHSV().h)},hsvsaturation:function(a){return new i(100*a.toHSV().s,"%")},hsvvalue:function(a){return new i(100*a.toHSV().v,"%")},red:function(a){return new i(a.rgb[0])},green:function(a){return new i(a.rgb[1])},blue:function(a){return new i(a.rgb[2])},alpha:function(a){return new i(a.toHSL().a)},luma:function(a){return new i(a.luma()*a.alpha*100,"%")},luminance:function(a){var b=.2126*a.rgb[0]/255+.7152*a.rgb[1]/255+.0722*a.rgb[2]/255;return new i(b*a.alpha*100,"%")},saturate:function(a,b,c){if(!a.rgb)return null;var f=a.toHSL();return f.s+="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},desaturate:function(a,b,c){var f=a.toHSL();return f.s-="undefined"!=typeof c&&"relative"===c.value?f.s*b.value/100:b.value/100,f.s=d(f.s),e(f)},lighten:function(a,b,c){var f=a.toHSL();return f.l+="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},darken:function(a,b,c){var f=a.toHSL();return f.l-="undefined"!=typeof c&&"relative"===c.value?f.l*b.value/100:b.value/100,f.l=d(f.l),e(f)},fadein:function(a,b,c){var f=a.toHSL();return f.a+="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fadeout:function(a,b,c){var f=a.toHSL();return f.a-="undefined"!=typeof c&&"relative"===c.value?f.a*b.value/100:b.value/100,f.a=d(f.a),e(f)},fade:function(a,b){var c=a.toHSL();return c.a=b.value/100,c.a=d(c.a),e(c)},spin:function(a,b){var c=a.toHSL(),d=(c.h+b.value)%360;return c.h=d<0?360+d:d,e(c)},mix:function(a,b,c){a.toHSL&&b.toHSL||(console.log(b.type),console.dir(b)),c||(c=new i(50));var d=c.value/100,e=2*d-1,f=a.toHSL().a-b.toHSL().a,g=((e*f==-1?e:(e+f)/(1+e*f))+1)/2,h=1-g,k=[a.rgb[0]*g+b.rgb[0]*h,a.rgb[1]*g+b.rgb[1]*h,a.rgb[2]*g+b.rgb[2]*h],l=a.alpha*d+b.alpha*(1-d);return new j(k,l)},greyscale:function(a){return h.desaturate(a,new i(100))},contrast:function(a,b,c,d){if(!a.rgb)return null;if("undefined"==typeof c&&(c=h.rgba(255,255,255,1)),"undefined"==typeof b&&(b=h.rgba(0,0,0,1)),b.luma()>c.luma()){var e=c;c=b,b=e}return d="undefined"==typeof d?.43:f(d),a.luma()=t&&this.context.ieCompat!==!1?(g.warn("Skipped data-uri embedding of "+i+" because its size ("+s.length+" characters) exceeds IE8-safe "+t+" characters!"),f(this,e||a)):new d(new c('"'+s+'"',s,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../logger":33,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],20:[function(a,b,c){var d=a("../tree/keyword"),e=a("./function-registry"),f={eval:function(){var a=this.value_,b=this.error_;if(b)throw b;if(null!=a)return a?d.True:d.False},value:function(a){this.value_=a},error:function(a){this.error_=a},reset:function(){this.value_=this.error_=null}};e.add("default",f.eval.bind(f)),b.exports=f},{"../tree/keyword":65,"./function-registry":22}],21:[function(a,b,c){var d=a("../tree/expression"),e=function(a,b,c,d){this.name=a.toLowerCase(),this.index=c,this.context=b,this.currentFileInfo=d,this.func=b.frames[0].functionRegistry.get(this.name)};e.prototype.isValid=function(){return Boolean(this.func)},e.prototype.call=function(a){return Array.isArray(a)&&(a=a.filter(function(a){return"Comment"!==a.type}).map(function(a){if("Expression"===a.type){var b=a.value.filter(function(a){return"Comment"!==a.type});return 1===b.length?b[0]:new d(b)}return a})),this.func.apply(this,a)},b.exports=e},{"../tree/expression":59}],22:[function(a,b,c){function d(a){return{_data:{},add:function(a,b){a=a.toLowerCase(),this._data.hasOwnProperty(a),this._data[a]=b},addMultiple:function(a){Object.keys(a).forEach(function(b){this.add(b,a[b])}.bind(this))},get:function(b){return this._data[b]||a&&a.get(b)},inherit:function(){return d(this)}}}b.exports=d(null)},{}],23:[function(a,b,c){b.exports=function(b){var c={functionRegistry:a("./function-registry"),functionCaller:a("./function-caller")};return a("./default"),a("./color"),a("./color-blending"),a("./data-uri")(b),a("./math"),a("./number"),a("./string"),a("./svg")(b),a("./types"),c}},{"./color":18,"./color-blending":17,"./data-uri":19,"./default":20,"./function-caller":21,"./function-registry":22,"./math":25,"./number":26,"./string":27,"./svg":28,"./types":29}],24:[function(a,b,c){var d=a("../tree/dimension"),e=function(){};e._math=function(a,b,c){if(!(c instanceof d))throw{type:"Argument",message:"argument must be a number"};return null==b?b=c.unit:c=c.unify(),new d(a(parseFloat(c.value)),b)},b.exports=e},{"../tree/dimension":56}],25:[function(a,b,c){var d=a("./function-registry"),e=a("./math-helper.js"),f={ceil:null,floor:null,sqrt:null,abs:null,tan:"",sin:"",cos:"",atan:"rad",asin:"rad",acos:"rad"};for(var g in f)f.hasOwnProperty(g)&&(f[g]=e._math.bind(null,Math[g],f[g]));f.round=function(a,b){var c="undefined"==typeof b?0:b.value;return e._math(function(a){return a.toFixed(c)},null,a)},d.addMultiple(f)},{"./function-registry":22,"./math-helper.js":24}],26:[function(a,b,c){var d=a("../tree/dimension"),e=a("../tree/anonymous"),f=a("./function-registry"),g=a("./math-helper.js"),h=function(a,b){switch(b=Array.prototype.slice.call(b),b.length){case 0:throw{type:"Argument",message:"one or more arguments required"}}var c,f,g,h,i,j,k,l,m=[],n={};for(c=0;ci.value)&&(m[f]=g);else{if(void 0!==k&&j!==k)throw{type:"Argument",message:"incompatible types"};n[j]=m.length,m.push(g)}else Array.isArray(b[c].value)&&Array.prototype.push.apply(b,Array.prototype.slice.call(b[c].value));return 1==m.length?m[0]:(b=m.map(function(a){return a.toCSS(this.context)}).join(this.context.compress?",":", "),new e((a?"min":"max")+"("+b+")"))};f.addMultiple({min:function(){return h(!0,arguments)},max:function(){return h(!1,arguments)},convert:function(a,b){return a.convertTo(b.value)},pi:function(){return new d(Math.PI)},mod:function(a,b){return new d(a.value%b.value,a.unit)},pow:function(a,b){if("number"==typeof a&&"number"==typeof b)a=new d(a),b=new d(b);else if(!(a instanceof d&&b instanceof d))throw{type:"Argument",message:"arguments must be numbers"};return new d(Math.pow(a.value,b.value),a.unit)},percentage:function(a){var b=g._math(function(a){return 100*a},"%",a);return b}})},{"../tree/anonymous":46,"../tree/dimension":56,"./function-registry":22,"./math-helper.js":24}],27:[function(a,b,c){var d=a("../tree/quoted"),e=a("../tree/anonymous"),f=a("../tree/javascript"),g=a("./function-registry");g.addMultiple({e:function(a){return new e(a instanceof f?a.evaluated:a.value)},escape:function(a){return new e(encodeURI(a.value).replace(/=/g,"%3D").replace(/:/g,"%3A").replace(/#/g,"%23").replace(/;/g,"%3B").replace(/\(/g,"%28").replace(/\)/g,"%29"))},replace:function(a,b,c,e){var f=a.value;return c="Quoted"===c.type?c.value:c.toCSS(),f=f.replace(new RegExp(b.value,e?e.value:""),c),new d(a.quote||"",f,a.escaped)},"%":function(a){for(var b=Array.prototype.slice.call(arguments,1),c=a.value,e=0;e",k=0;k";return j+="',j=encodeURIComponent(j),j="data:image/svg+xml,"+j,new g(new f("'"+j+"'",j,(!1),this.index,this.currentFileInfo),this.index,this.currentFileInfo)})}},{"../tree/color":50,"../tree/dimension":56,"../tree/expression":59,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],29:[function(a,b,c){var d=a("../tree/keyword"),e=a("../tree/detached-ruleset"),f=a("../tree/dimension"),g=a("../tree/color"),h=a("../tree/quoted"),i=a("../tree/anonymous"),j=a("../tree/url"),k=a("../tree/operation"),l=a("./function-registry"),m=function(a,b){return a instanceof b?d.True:d.False},n=function(a,b){if(void 0===b)throw{type:"Argument",message:"missing the required second argument to isunit."};if(b="string"==typeof b.value?b.value:b,"string"!=typeof b)throw{type:"Argument",message:"Second argument to isunit should be a unit or a string."};return a instanceof f&&a.unit.is(b)?d.True:d.False},o=function(a){var b=Array.isArray(a.value)?a.value:Array(a);return b};l.addMultiple({isruleset:function(a){return m(a,e)},iscolor:function(a){return m(a,g)},isnumber:function(a){return m(a,f)},isstring:function(a){return m(a,h)},iskeyword:function(a){return m(a,d)},isurl:function(a){return m(a,j)},ispixel:function(a){return n(a,"px")},ispercentage:function(a){return n(a,"%")},isem:function(a){return n(a,"em")},isunit:n,unit:function(a,b){if(!(a instanceof f))throw{type:"Argument",message:"the first argument to unit must be a number"+(a instanceof k?". Have you forgotten parenthesis?":"")};return b=b?b instanceof d?b.value:b.toCSS():"",new f(a.value,b)},"get-unit":function(a){return new i(a.unit)},extract:function(a,b){return b=b.value-1,o(a)[b]},length:function(a){return new f(o(a).length)}})},{"../tree/anonymous":46,"../tree/color":50,"../tree/detached-ruleset":55,"../tree/dimension":56,"../tree/keyword":65,"../tree/operation":71,"../tree/quoted":73,"../tree/url":80,"./function-registry":22}],30:[function(a,b,c){var d=a("./contexts"),e=a("./parser/parser"),f=a("./plugins/function-importer");b.exports=function(a){var b=function(a,b){this.rootFilename=b.filename,this.paths=a.paths||[],this.contents={},this.contentsIgnoredChars={},this.mime=a.mime,this.error=null,this.context=a,this.queue=[],this.files={}};return b.prototype.push=function(b,c,g,h,i){var j=this;this.queue.push(b);var k=function(a,c,d){j.queue.splice(j.queue.indexOf(b),1);var e=d===j.rootFilename;h.optional&&a?i(null,{rules:[]},!1,null):(j.files[d]=c,a&&!j.error&&(j.error=a),i(a,c,e,d))},l={relativeUrls:this.context.relativeUrls,entryPath:g.entryPath,rootpath:g.rootpath,rootFilename:g.rootFilename},m=a.getFileManager(b,g.currentDirectory,this.context,a);if(!m)return void k({message:"Could not find a file-manager for "+b});c&&(b=m.tryAppendExtension(b,h.plugin?".js":".less"));var n=function(a){var b=a.filename,c=a.contents.replace(/^\uFEFF/,"");l.currentDirectory=m.getPath(b),l.relativeUrls&&(l.rootpath=m.join(j.context.rootpath||"",m.pathDiff(l.currentDirectory,l.entryPath)),!m.isPathAbsolute(l.rootpath)&&m.alwaysMakePathsAbsolute()&&(l.rootpath=m.join(l.entryPath,l.rootpath))),l.filename=b;var i=new d.Parse(j.context);i.processImports=!1,j.contents[b]=c,(g.reference||h.reference)&&(l.reference=!0),h.plugin?new f(i,l).eval(c,function(a,c){k(a,c,b)}):h.inline?k(null,c,b):new e(i,j,l).parse(c,function(a,c){k(a,c,b)})},o=m.loadFile(b,g.currentDirectory,this.context,a,function(a,b){a?k(a):n(b)});o&&o.then(n,k)},b}},{"./contexts":11,"./parser/parser":38,"./plugins/function-importer":40}],31:[function(a,b,c){b.exports=function(b,c){var d,e,f,g,h,i={version:[2,7,2],data:a("./data"),tree:a("./tree"),Environment:h=a("./environment/environment"),AbstractFileManager:a("./environment/abstract-file-manager"),environment:b=new h(b,c),visitors:a("./visitors"),Parser:a("./parser/parser"),functions:a("./functions")(b),contexts:a("./contexts"),SourceMapOutput:d=a("./source-map-output")(b),SourceMapBuilder:e=a("./source-map-builder")(d,b),ParseTree:f=a("./parse-tree")(e),ImportManager:g=a("./import-manager")(b),render:a("./render")(b,f,g),parse:a("./parse")(b,f,g),LessError:a("./less-error"),transformTree:a("./transform-tree"),utils:a("./utils"),PluginManager:a("./plugin-manager"),logger:a("./logger")};return i}},{"./contexts":11,"./data":13,"./environment/abstract-file-manager":15,"./environment/environment":16,"./functions":23,"./import-manager":30,"./less-error":32,"./logger":33,"./parse":35,"./parse-tree":34,"./parser/parser":38,"./plugin-manager":39,"./render":41,"./source-map-builder":42,"./source-map-output":43,"./transform-tree":44,"./tree":62,"./utils":83,"./visitors":87}],32:[function(a,b,c){var d=a("./utils"),e=b.exports=function(a,b,c){Error.call(this);var e=a.filename||c;if(b&&e){var f=b.contents[e],g=d.getLocation(a.index,f),h=g.line,i=g.column,j=a.call&&d.getLocation(a.call,f).line,k=f.split("\n");this.type=a.type||"Syntax",this.filename=e,this.index=a.index,this.line="number"==typeof h?h+1:null,this.callLine=j+1,this.callExtract=k[j],this.column=i,this.extract=[k[h-1],k[h],k[h+1]]}this.message=a.message,this.stack=a.stack};if("undefined"==typeof Object.create){var f=function(){};f.prototype=Error.prototype,e.prototype=new f}else e.prototype=Object.create(Error.prototype);e.prototype.constructor=e},{"./utils":83}],33:[function(a,b,c){b.exports={error:function(a){this._fireEvent("error",a)},warn:function(a){this._fireEvent("warn",a)},info:function(a){this._fireEvent("info",a)},debug:function(a){this._fireEvent("debug",a)},addListener:function(a){this._listeners.push(a)},removeListener:function(a){for(var b=0;b=97&&j<=122||j<34))switch(j){case 40:o++,e=h;continue;case 41:if(--o<0)return b("missing opening `(`",h);continue;case 59:o||c();continue;case 123:n++,d=h;continue;case 125:if(--n<0)return b("missing opening `{`",h);n||o||c();continue;case 92:if(h96)){if(k==j){l=1;break}if(92==k){if(h==m-1)return b("unescaped `\\`",h);h++}}if(l)continue;return b("unmatched `"+String.fromCharCode(j)+"`",i);case 47:if(o||h==m-1)continue;if(k=a.charCodeAt(h+1),47==k)for(h+=2;hd&&g>f?b("missing closing `}` or `*/`",d):b("missing closing `}`",d):0!==o?b("missing closing `)`",e):(c(!0),p)}},{}],37:[function(a,b,c){var d=a("./chunker");b.exports=function(){function a(d){for(var e,f,j,p=k.i,q=c,s=k.i-i,t=k.i+h.length-s,u=k.i+=d,v=b;k.i=0){j={index:k.i,text:v.substr(k.i,x+2-k.i),isLineComment:!1},k.i+=j.text.length-1,k.commentStore.push(j);continue}}break}if(e!==l&&e!==n&&e!==m&&e!==o)break}if(h=h.slice(d+k.i-u+s),i=k.i,!h.length){if(ce||k.i===e&&a&&!f)&&(e=k.i,f=a);var b=j.pop();h=b.current,i=k.i=b.i,c=b.j},k.forget=function(){j.pop()},k.isWhitespace=function(a){var c=k.i+(a||0),d=b.charCodeAt(c);return d===l||d===o||d===m||d===n},k.$re=function(b){k.i>i&&(h=h.slice(k.i-i),i=k.i);var c=b.exec(h);return c?(a(c[0].length),"string"==typeof c?c:1===c.length?c[0]:c):null},k.$char=function(c){return b.charAt(k.i)!==c?null:(a(1),c)},k.$str=function(c){for(var d=c.length,e=0;es||a=b.length;return k.i=b.length-1,furthestChar:b[k.i]}},k}},{"./chunker":36}],38:[function(a,b,c){var d=a("../less-error"),e=a("../tree"),f=a("../visitors"),g=a("./parser-input"),h=a("../utils"),i=function j(a,b,c){function i(a,e){throw new d({index:o.i,filename:c.filename,type:e||"Syntax",message:a},b)}function k(a,b,c){var d=a instanceof Function?a.call(n):o.$re(a);return d?d:void i(b||("string"==typeof a?"expected '"+a+"' got '"+o.currentChar()+"'":"unexpected token"))}function l(a,b){return o.$char(a)?a:void i(b||"expected '"+a+"' got '"+o.currentChar()+"'")}function m(a){var b=c.filename;return{lineNumber:h.getLocation(a,o.getInput()).line+1,fileName:b}}var n,o=g();return{parse:function(g,h,i){var k,l,m,n,p=null,q="";if(l=i&&i.globalVars?j.serializeVars(i.globalVars)+"\n":"",m=i&&i.modifyVars?"\n"+j.serializeVars(i.modifyVars):"",a.pluginManager)for(var r=a.pluginManager.getPreProcessors(),s=0;s1&&(b=new e.Value(g)),d.push(b),g=[])}return o.forget(),a?d:f},literal:function(){return this.dimension()||this.color()||this.quoted()||this.unicodeDescriptor()},assignment:function(){var a,b;return o.save(),(a=o.$re(/^\w+(?=\s?=)/i))&&o.$char("=")&&(b=n.entity())?(o.forget(),new e.Assignment(a,b)):void o.restore()},url:function(){var a,b=o.i;return o.autoCommentAbsorb=!1,o.$str("url(")?(a=this.quoted()||this.variable()||o.$re(/^(?:(?:\\[\(\)'"])|[^\(\)'"])+/)||"",o.autoCommentAbsorb=!0,l(")"),new e.URL(null!=a.value||a instanceof e.Variable?a:new e.Anonymous(a),b,c)):void(o.autoCommentAbsorb=!0)},variable:function(){var a,b=o.i;if("@"===o.currentChar()&&(a=o.$re(/^@@?[\w-]+/)))return new e.Variable(a,b,c)},variableCurly:function(){var a,b=o.i;if("@"===o.currentChar()&&(a=o.$re(/^@\{([\w-]+)\}/)))return new e.Variable("@"+a[1],b,c)},color:function(){var a;if("#"===o.currentChar()&&(a=o.$re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))){var b=a.input.match(/^#([\w]+).*/);return b=b[1],b.match(/^[A-Fa-f0-9]+$/)||i("Invalid HEX color code"),new e.Color(a[1],(void 0),"#"+b)}},colorKeyword:function(){o.save();var a=o.autoCommentAbsorb;o.autoCommentAbsorb=!1;var b=o.$re(/^[_A-Za-z-][_A-Za-z0-9-]+/);if(o.autoCommentAbsorb=a,!b)return void o.forget();o.restore();var c=e.Color.fromKeyword(b);return c?(o.$str(b),c):void 0},dimension:function(){if(!o.peekNotNumeric()){var a=o.$re(/^([+-]?\d*\.?\d+)(%|[a-z_]+)?/i);return a?new e.Dimension(a[1],a[2]):void 0}},unicodeDescriptor:function(){var a;if(a=o.$re(/^U\+[0-9a-fA-F?]+(\-[0-9a-fA-F?]+)?/))return new e.UnicodeDescriptor(a[0])},javascript:function(){var a,b=o.i;o.save();var d=o.$char("~"),f=o.$char("`");return f?(a=o.$re(/^[^`]*`/))?(o.forget(),new e.JavaScript(a.substr(0,a.length-1),Boolean(d),b,c)):void o.restore("invalid javascript definition"):void o.restore()}},variable:function(){var a;if("@"===o.currentChar()&&(a=o.$re(/^(@[\w-]+)\s*:/)))return a[1]},rulesetCall:function(){var a;if("@"===o.currentChar()&&(a=o.$re(/^(@[\w-]+)\(\s*\)\s*;/)))return new e.RulesetCall(a[1])},extend:function(a){var b,d,f,g,h,j=o.i;if(o.$str(a?"&:extend(":":extend(")){do{for(f=null,b=null;!(f=o.$re(/^(all)(?=\s*(\)|,))/))&&(d=this.element());)b?b.push(d):b=[d];f=f&&f[1],b||i("Missing target selector for :extend()."),h=new e.Extend(new e.Selector(b),f,j,c),g?g.push(h):g=[h]}while(o.$char(","));return k(/^\)/),a&&k(/^;/),g}},extendRule:function(){return this.extend(!0)},mixin:{call:function(){var a,b,d,f,g,h,i=o.currentChar(),j=!1,k=o.i;if("."===i||"#"===i){for(o.save();;){if(a=o.i,f=o.$re(/^[#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/),!f)break;d=new e.Element(g,f,a,c),b?b.push(d):b=[d],g=o.$char(">")}return b&&(o.$char("(")&&(h=this.args(!0).args,l(")")),n.important()&&(j=!0),n.end())?(o.forget(),new e.mixin.Call(b,h,k,c,j)):void o.restore()}},args:function(a){var b,c,d,f,g,h,j,k=n.entities,l={args:null,variadic:!1},m=[],p=[],q=[];for(o.save();;){if(a)h=n.detachedRuleset()||n.expression();else{if(o.commentStore.length=0,o.$str("...")){l.variadic=!0,o.$char(";")&&!b&&(b=!0),(b?p:q).push({variadic:!0});break}h=k.variable()||k.literal()||k.keyword()}if(!h)break;f=null,h.throwAwayComments&&h.throwAwayComments(),g=h;var r=null;if(a?h.value&&1==h.value.length&&(r=h.value[0]):r=h,r&&r instanceof e.Variable)if(o.$char(":")){if(m.length>0&&(b&&i("Cannot mix ; and , as delimiter types"),c=!0),g=n.detachedRuleset()||n.expression(),!g){if(!a)return o.restore(),l.args=[],l;i("could not understand value for named argument")}f=d=r.name}else if(o.$str("...")){if(!a){l.variadic=!0,o.$char(";")&&!b&&(b=!0),(b?p:q).push({name:h.name,variadic:!0});break}j=!0}else a||(d=f=r.name,g=null);g&&m.push(g),q.push({name:f,value:g,expand:j}),o.$char(",")||(o.$char(";")||b)&&(c&&i("Cannot mix ; and , as delimiter types"),b=!0,m.length>1&&(g=new e.Value(m)),p.push({name:d,value:g,expand:j}),d=null,m=[],c=!1)}return o.forget(),l.args=b?p:q,l},definition:function(){var a,b,c,d,f=[],g=!1;if(!("."!==o.currentChar()&&"#"!==o.currentChar()||o.peek(/^[^{]*\}/)))if(o.save(),b=o.$re(/^([#.](?:[\w-]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+)\s*\(/)){a=b[1];var h=this.args(!1);if(f=h.args,g=h.variadic,!o.$char(")"))return void o.restore("Missing closing ')'");if(o.commentStore.length=0,o.$str("when")&&(d=k(n.conditions,"expected condition")),c=n.block())return o.forget(),new e.mixin.Definition(a,f,c,d,g);o.restore()}else o.forget()}},entity:function(){var a=this.entities;return this.comment()||a.literal()||a.variable()||a.url()||a.call()||a.keyword()||a.javascript()},end:function(){return o.$char(";")||o.peek("}")},alpha:function(){var a;if(o.$re(/^opacity=/i))return a=o.$re(/^\d+/),a||(a=k(this.entities.variable,"Could not parse alpha")),l(")"),new e.Alpha(a)},element:function(){var a,b,d,f=o.i;if(b=this.combinator(),a=o.$re(/^(?:\d+\.\d+|\d+)%/)||o.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/)||o.$char("*")||o.$char("&")||this.attribute()||o.$re(/^\([^&()@]+\)/)||o.$re(/^[\.#:](?=@)/)||this.entities.variableCurly(),a||(o.save(),o.$char("(")?(d=this.selector())&&o.$char(")")?(a=new e.Paren(d),o.forget()):o.restore("Missing closing ')'"):o.forget()),a)return new e.Element(b,a,f,c)},combinator:function(){var a=o.currentChar();if("/"===a){o.save();var b=o.$re(/^\/[a-z]+\//i);if(b)return o.forget(),new e.Combinator(b);o.restore()}if(">"===a||"+"===a||"~"===a||"|"===a||"^"===a){for(o.i++,"^"===a&&"^"===o.currentChar()&&(a="^^",o.i++);o.isWhitespace();)o.i++;return new e.Combinator(a)}return new e.Combinator(o.isWhitespace(-1)?" ":null)},lessSelector:function(){return this.selector(!0)},selector:function(a){for(var b,d,f,g,h,j,l,m=o.i;(a&&(d=this.extend())||a&&(j=o.$str("when"))||(g=this.element()))&&(j?l=k(this.conditions,"expected condition"):l?i("CSS guard can only be used at the end of selector"):d?h=h?h.concat(d):d:(h&&i("Extend can only be used at the end of selector"),f=o.currentChar(),b?b.push(g):b=[g],g=null),"{"!==f&&"}"!==f&&";"!==f&&","!==f&&")"!==f););return b?new e.Selector(b,h,l,m,c):void(h&&i("Extend must be used to extend a selector, it cannot be used on its own"))},attribute:function(){if(o.$char("[")){var a,b,c,d=this.entities;return(a=d.variableCurly())||(a=k(/^(?:[_A-Za-z0-9-\*]*\|)?(?:[_A-Za-z0-9-]|\\.)+/)),c=o.$re(/^[|~*$^]?=/),c&&(b=d.quoted()||o.$re(/^[0-9]+%/)||o.$re(/^[\w-]+/)||d.variableCurly()),l("]"),new e.Attribute(a,c,b)}},block:function(){var a;if(o.$char("{")&&(a=this.primary())&&o.$char("}"))return a},blockRuleset:function(){var a=this.block();return a&&(a=new e.Ruleset(null,a)),a},detachedRuleset:function(){var a=this.blockRuleset();if(a)return new e.DetachedRuleset(a)},ruleset:function(){var b,c,d,f;for(o.save(),a.dumpLineNumbers&&(f=m(o.i));;){if(c=this.lessSelector(),!c)break;if(b?b.push(c):b=[c],o.commentStore.length=0,c.condition&&b.length>1&&i("Guards are only currently allowed on a single selector."),!o.$char(","))break;c.condition&&i("Guards are only currently allowed on a single selector."),o.commentStore.length=0}if(b&&(d=this.block())){o.forget();var g=new e.Ruleset(b,d,a.strictImports);return a.dumpLineNumbers&&(g.debugInfo=f),g}o.restore()},rule:function(b){var d,f,g,h,i,j=o.i,k=o.currentChar();if("."!==k&&"#"!==k&&"&"!==k&&":"!==k)if(o.save(),d=this.variable()||this.ruleProperty()){if(i="string"==typeof d,i&&(f=this.detachedRuleset()),o.commentStore.length=0,!f){h=!i&&d.length>1&&d.pop().value;var l=!b&&(a.compress||i);if(l&&(f=this.value()),!f&&(f=this.anonymousValue()))return o.forget(),new e.Rule(d,f,(!1),h,j,c);l||f||(f=this.value()),g=this.important()}if(f&&this.end())return o.forget(),new e.Rule(d,f,g,h,j,c);if(o.restore(),f&&!b)return this.rule(!0)}else o.forget()},anonymousValue:function(){var a=o.$re(/^([^@+\/'"*`(;{}-]*);/);if(a)return new e.Anonymous(a[1])},"import":function(){var a,b,d=o.i,f=o.$re(/^@import?\s+/);if(f){var g=(f?this.importOptions():null)||{};if(a=this.entities.quoted()||this.entities.url())return b=this.mediaFeatures(),o.$char(";")||(o.i=d,i("missing semi-colon or unrecognised media features on import")),b=b&&new e.Value(b),new e.Import(a,b,g,d,c);o.i=d,i("malformed import statement")}},importOptions:function(){var a,b,c,d={};if(!o.$char("("))return null;do if(a=this.importOption()){switch(b=a,c=!0,b){case"css":b="less",c=!1;break;case"once":b="multiple",c=!1}if(d[b]=c,!o.$char(","))break}while(a);return l(")"),d},importOption:function(){var a=o.$re(/^(less|css|multiple|once|inline|reference|optional)/);if(a)return a[1]},mediaFeature:function(){var a,b,d=this.entities,f=[];o.save();do a=d.keyword()||d.variable(),a?f.push(a):o.$char("(")&&(b=this.property(),a=this.value(),o.$char(")")?b&&a?f.push(new e.Paren(new e.Rule(b,a,null,null,o.i,c,(!0)))):a?f.push(new e.Paren(a)):i("badly formed media feature definition"):i("Missing closing ')'","Parse"));while(a);if(o.forget(),f.length>0)return new e.Expression(f)},mediaFeatures:function(){var a,b=this.entities,c=[];do if(a=this.mediaFeature()){if(c.push(a),!o.$char(","))break}else if(a=b.variable(),a&&(c.push(a),!o.$char(",")))break;while(a);return c.length>0?c:null},media:function(){var b,d,f,g,h=o.i;return a.dumpLineNumbers&&(g=m(h)),o.save(),o.$str("@media")?(b=this.mediaFeatures(),d=this.block(),d||i("media definitions require block statements after any features"),o.forget(),f=new e.Media(d,b,h,c),a.dumpLineNumbers&&(f.debugInfo=g),f):void o.restore()},plugin:function(){var a,b=o.i,d=o.$re(/^@plugin?\s+/);if(d){var f={plugin:!0};if(a=this.entities.quoted()||this.entities.url())return o.$char(";")||(o.i=b,i("missing semi-colon on plugin")),new e.Import(a,null,f,b,c);o.i=b,i("malformed plugin statement")}},directive:function(){var b,d,f,g,h,j,k,l=o.i,n=!0,p=!0;if("@"===o.currentChar()){if(d=this["import"]()||this.plugin()||this.media())return d;if(o.save(),b=o.$re(/^@[a-z-]+/)){switch(g=b,"-"==b.charAt(1)&&b.indexOf("-",2)>0&&(g="@"+b.slice(b.indexOf("-",2)+1)),g){case"@charset":h=!0,n=!1;break;case"@namespace":j=!0,n=!1;break;case"@keyframes":case"@counter-style":h=!0;break;case"@document":case"@supports":k=!0,p=!1;break;default:k=!0}return o.commentStore.length=0,h?(d=this.entity(),d||i("expected "+b+" identifier")):j?(d=this.expression(),d||i("expected "+b+" expression")):k&&(d=(o.$re(/^[^{;]+/)||"").trim(),n="{"==o.currentChar(),d&&(d=new e.Anonymous(d))),n&&(f=this.blockRuleset()),f||!n&&d&&o.$char(";")?(o.forget(),new e.Directive(b,d,f,l,c,a.dumpLineNumbers?m(l):null,p)):void o.restore("directive options not recognised")}}},value:function(){var a,b=[];do if(a=this.expression(),a&&(b.push(a),!o.$char(",")))break;while(a);if(b.length>0)return new e.Value(b)},important:function(){if("!"===o.currentChar())return o.$re(/^! *important/)},sub:function(){var a,b;return o.save(),o.$char("(")?(a=this.addition(),a&&o.$char(")")?(o.forget(),b=new e.Expression([a]),b.parens=!0,b):void o.restore("Expected ')'")):void o.restore()},multiplication:function(){var a,b,c,d,f;if(a=this.operand()){for(f=o.isWhitespace(-1);;){if(o.peek(/^\/[*\/]/))break;if(o.save(),c=o.$char("/")||o.$char("*"),!c){o.forget();break}if(b=this.operand(),!b){o.restore();break}o.forget(),a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=o.isWhitespace(-1)}return d||a}},addition:function(){var a,b,c,d,f;if(a=this.multiplication()){for(f=o.isWhitespace(-1);;){if(c=o.$re(/^[-+]\s+/)||!f&&(o.$char("+")||o.$char("-")),!c)break;if(b=this.multiplication(),!b)break;a.parensInOp=!0,b.parensInOp=!0,d=new e.Operation(c,[d||a,b],f),f=o.isWhitespace(-1)}return d||a}},conditions:function(){var a,b,c,d=o.i;if(a=this.condition()){for(;;){if(!o.peek(/^,\s*(not\s*)?\(/)||!o.$char(","))break;if(b=this.condition(),!b)break;c=new e.Condition("or",c||a,b,d)}return c||a}},condition:function(){function a(){return o.$str("or")}var b,c,d;if(b=this.conditionAnd(this)){if(c=a()){if(d=this.condition(),!d)return;b=new e.Condition(c,b,d)}return b}},conditionAnd:function(){function a(a){return a.negatedCondition()||a.parenthesisCondition()}function b(){return o.$str("and")}var c,d,f;if(c=a(this)){if(d=b()){if(f=this.conditionAnd(),!f)return;c=new e.Condition(d,c,f)}return c}},negatedCondition:function(){if(o.$str("not")){var a=this.parenthesisCondition();return a&&(a.negate=!a.negate),a}},parenthesisCondition:function(){function a(a){var b;return o.save(),(b=a.condition())&&o.$char(")")?(o.forget(),b):void o.restore()}var b;return o.save(),o.$str("(")?(b=a(this))?(o.forget(),b):(b=this.atomicCondition())?o.$char(")")?(o.forget(),b):void o.restore("expected ')' got '"+o.currentChar()+"'"):void o.restore():void o.restore()},atomicCondition:function(){var a,b,c,d,f=this.entities,g=o.i;if(a=this.addition()||f.keyword()||f.quoted())return o.$char(">")?d=o.$char("=")?">=":">":o.$char("<")?d=o.$char("=")?"<=":"<":o.$char("=")&&(d=o.$char(">")?"=>":o.$char("<")?"=<":"="),d?(b=this.addition()||f.keyword()||f.quoted(),b?c=new e.Condition(d,a,b,g,(!1)):i("expected expression")):c=new e.Condition("=",a,new e.Keyword("true"),g,(!1)),c},operand:function(){var a,b=this.entities;o.peek(/^-[@\(]/)&&(a=o.$char("-"));var c=this.sub()||b.dimension()||b.color()||b.variable()||b.call()||b.colorKeyword();return a&&(c.parensInOp=!0,c=new e.Negative(c)),c},expression:function(){var a,b,c=[];do a=this.comment(),a?c.push(a):(a=this.addition()||this.entity(),a&&(c.push(a),o.peek(/^\/[\/*]/)||(b=o.$char("/"),b&&c.push(new e.Anonymous(b)))));while(a);if(c.length>0)return new e.Expression(c)},property:function(){var a=o.$re(/^(\*?-?[_a-zA-Z0-9-]+)\s*:/);if(a)return a[1]},ruleProperty:function(){function a(a){var b=o.i,c=o.$re(a);if(c)return g.push(b),f.push(c[1])}var b,d,f=[],g=[];o.save();var h=o.$re(/^([_a-zA-Z0-9-]+)\s*:/);if(h)return f=[new e.Keyword(h[1])],o.forget(),f;for(a(/^(\*?)/);;)if(!a(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/))break;if(f.length>1&&a(/^((?:\+_|\+)?)\s*:/)){for(o.forget(),""===f[0]&&(f.shift(),g.shift()),d=0;d=b);c++);this.preProcessors.splice(c,0,{preProcessor:a,priority:b})},d.prototype.addPostProcessor=function(a,b){var c;for(c=0;c=b);c++);this.postProcessors.splice(c,0,{postProcessor:a,priority:b})},d.prototype.addFileManager=function(a){this.fileManagers.push(a)},d.prototype.getPreProcessors=function(){for(var a=[],b=0;b0){var d,e=JSON.stringify(this._sourceMapGenerator.toJSON());this.sourceMapURL?d=this.sourceMapURL:this._sourceMapFilename&&(d=this._sourceMapFilename),this.sourceMapURL=d,this.sourceMap=e}return this._css.join("")},b}},{}],44:[function(a,b,c){var d=a("./contexts"),e=a("./visitors"),f=a("./tree");b.exports=function(a,b){b=b||{};var c,g=b.variables,h=new d.Eval(b);"object"!=typeof g||Array.isArray(g)||(g=Object.keys(g).map(function(a){var b=g[a];return b instanceof f.Value||(b instanceof f.Expression||(b=new f.Expression([b])),b=new f.Value([b])),new f.Rule("@"+a,b,(!1),null,0)}),h.frames=[new f.Ruleset(null,g)]);var i,j=[],k=[new e.JoinSelectorVisitor,new e.MarkVisibleSelectorsVisitor((!0)),new e.ExtendVisitor,new e.ToCSSVisitor({compress:Boolean(b.compress)})];if(b.pluginManager){var l=b.pluginManager.getVisitors();for(i=0;i.5?j/(2-g-h):j/(g+h),g){case c:a=(d-e)/j+(d="===a||"=<"===a||"<="===a;case 1:return">"===a||">="===a;default:return!1}}}(this.op,this.lvalue.eval(a),this.rvalue.eval(a));return this.negate?!b:b},b.exports=e},{"./node":70}],54:[function(a,b,c){var d=function(a,b,c){var e="";if(a.dumpLineNumbers&&!a.compress)switch(a.dumpLineNumbers){case"comments":e=d.asComment(b);break;case"mediaquery":e=d.asMediaQuery(b);break;case"all":e=d.asComment(b)+(c||"")+d.asMediaQuery(b)}return e};d.asComment=function(a){return"/* line "+a.debugInfo.lineNumber+", "+a.debugInfo.fileName+" */\n"},d.asMediaQuery=function(a){var b=a.debugInfo.fileName;return/^[a-z]+:\/\//i.test(b)||(b="file://"+b),"@media -sass-debug-info{filename{font-family:"+b.replace(/([.:\/\\])/g,function(a){return"\\"==a&&(a="/"),"\\"+a})+"}line{font-family:\\00003"+a.debugInfo.lineNumber+"}}\n"},b.exports=d},{}],55:[function(a,b,c){var d=a("./node"),e=a("../contexts"),f=function(a,b){this.ruleset=a,this.frames=b};f.prototype=new d,f.prototype.type="DetachedRuleset",f.prototype.evalFirst=!0,f.prototype.accept=function(a){this.ruleset=a.visit(this.ruleset)},f.prototype.eval=function(a){var b=this.frames||a.frames.slice(0);return new f(this.ruleset,b)},f.prototype.callEval=function(a){return this.ruleset.eval(this.frames?new e.Eval(a,this.frames.concat(a.frames)):a)},b.exports=f},{"../contexts":11,"./node":70}],56:[function(a,b,c){var d=a("./node"),e=a("../data/unit-conversions"),f=a("./unit"),g=a("./color"),h=function(a,b){this.value=parseFloat(a),this.unit=b&&b instanceof f?b:new f(b?[b]:void 0)};h.prototype=new d,h.prototype.type="Dimension",h.prototype.accept=function(a){this.unit=a.visit(this.unit)},h.prototype.eval=function(a){return this},h.prototype.toColor=function(){return new g([this.value,this.value,this.value])},h.prototype.genCSS=function(a,b){if(a&&a.strictUnits&&!this.unit.isSingular())throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());var c=this.fround(a,this.value),d=String(c);if(0!==c&&c<1e-6&&c>-1e-6&&(d=c.toFixed(20).replace(/0+$/,"")),a&&a.compress){if(0===c&&this.unit.isLength())return void b.add(d);c>0&&c<1&&(d=d.substr(1))}b.add(d),this.unit.genCSS(a,b)},h.prototype.operate=function(a,b,c){var d=this._operate(a,b,this.value,c.value),e=this.unit.clone();if("+"===b||"-"===b)if(0===e.numerator.length&&0===e.denominator.length)e=c.unit.clone(),this.unit.backupUnit&&(e.backupUnit=this.unit.backupUnit);else if(0===c.unit.numerator.length&&0===e.denominator.length);else{if(c=c.convertTo(this.unit.usedUnits()),a.strictUnits&&c.unit.toString()!==e.toString())throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '"+e.toString()+"' and '"+c.unit.toString()+"'.");d=this._operate(a,b,this.value,c.value)}else"*"===b?(e.numerator=e.numerator.concat(c.unit.numerator).sort(),e.denominator=e.denominator.concat(c.unit.denominator).sort(),e.cancel()):"/"===b&&(e.numerator=e.numerator.concat(c.unit.denominator).sort(),e.denominator=e.denominator.concat(c.unit.numerator).sort(),e.cancel());return new h(d,e)},h.prototype.compare=function(a){var b,c;if(a instanceof h){if(this.unit.isEmpty()||a.unit.isEmpty())b=this,c=a;else if(b=this.unify(),c=a.unify(),0!==b.unit.compare(c.unit))return;return d.numericCompare(b.value,c.value)}},h.prototype.unify=function(){return this.convertTo({length:"px",duration:"s",angle:"rad"})},h.prototype.convertTo=function(a){var b,c,d,f,g,i=this.value,j=this.unit.clone(),k={};if("string"==typeof a){for(b in e)e[b].hasOwnProperty(a)&&(k={},k[b]=a);a=k}g=function(a,b){return d.hasOwnProperty(a)?(b?i/=d[a]/d[f]:i*=d[a]/d[f],f):a};for(c in a)a.hasOwnProperty(c)&&(f=a[c],d=e[c],j.map(g));return j.cancel(),new h(i,j)},b.exports=h},{"../data/unit-conversions":14,"./color":50,"./node":70,"./unit":79}],57:[function(a,b,c){var d=a("./node"),e=a("./selector"),f=a("./ruleset"),g=function(a,b,c,d,f,g,h,i){var j;if(this.name=a,this.value=b,c)for(Array.isArray(c)?this.rules=c:(this.rules=[c],this.rules[0].selectors=new e([],null,null,this.index,f).createEmptySelectors()),j=0;j1?b=new g(this.value.map(function(b){return b.eval(a)})):1===this.value.length?(this.value[0].parens&&!this.value[0].parensInOp&&(d=!0),b=this.value[0].eval(a)):b=this,c&&a.outOfParenthesis(),this.parens&&this.parensInOp&&!a.isMathOn()&&!d&&(b=new e(b)),b},g.prototype.genCSS=function(a,b){for(var c=0;c0&&c.length&&""===c[0].combinator.value&&(c[0].combinator.value=" "),d=d.concat(a[b].elements);this.selfSelectors=[new e(d)],this.selfSelectors[0].copyVisibilityInfo(this.visibilityInfo())},b.exports=f},{"./node":70,"./selector":77}],61:[function(a,b,c){var d=a("./node"),e=a("./media"),f=a("./url"),g=a("./quoted"),h=a("./ruleset"),i=a("./anonymous"),j=function(a,b,c,d,e,f){if(this.options=c,this.index=d,this.path=a,this.features=b,this.currentFileInfo=e,this.allowRoot=!0,void 0!==this.options.less||this.options.inline)this.css=!this.options.less||this.options.inline;else{var g=this.getPath();g&&/[#\.\&\?\/]css([\?;].*)?$/.test(g)&&(this.css=!0)}this.copyVisibilityInfo(f)};j.prototype=new d,j.prototype.type="Import",j.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.path=a.visit(this.path),this.options.plugin||this.options.inline||!this.root||(this.root=a.visit(this.root))},j.prototype.genCSS=function(a,b){this.css&&void 0===this.path.currentFileInfo.reference&&(b.add("@import ",this.currentFileInfo,this.index),this.path.genCSS(a,b),this.features&&(b.add(" "),this.features.genCSS(a,b)),b.add(";"))},j.prototype.getPath=function(){return this.path instanceof f?this.path.value.value:this.path.value},j.prototype.isVariableImport=function(){var a=this.path;return a instanceof f&&(a=a.value),!(a instanceof g)||a.containsVariables()},j.prototype.evalForImport=function(a){var b=this.path;return b instanceof f&&(b=b.value),new j(b.eval(a),this.features,this.options,this.index,this.currentFileInfo,this.visibilityInfo())},j.prototype.evalPath=function(a){var b=this.path.eval(a),c=this.currentFileInfo&&this.currentFileInfo.rootpath;if(!(b instanceof f)){if(c){var d=b.value;d&&a.isPathRelative(d)&&(b.value=c+d)}b.value=a.normalizePath(b.value)}return b},j.prototype.eval=function(a){var b=this.doEval(a);return(this.options.reference||this.blocksVisibility())&&(b.length||0===b.length?b.forEach(function(a){a.addVisibilityBlock()}):b.addVisibilityBlock()),b},j.prototype.doEval=function(a){var b,c,d=this.features&&this.features.eval(a);if(this.options.plugin)return c=a.frames[0]&&a.frames[0].functionRegistry,c&&this.root&&this.root.functions&&c.addMultiple(this.root.functions),[];if(this.skip&&("function"==typeof this.skip&&(this.skip=this.skip()),this.skip))return[];if(this.options.inline){var f=new i(this.root,0,{filename:this.importedFilename,reference:this.path.currentFileInfo&&this.path.currentFileInfo.reference},(!0),(!0));return this.features?new e([f],this.features.value):[f]}if(this.css){var g=new j(this.evalPath(a),d,this.options,this.index);if(!g.css&&this.error)throw this.error;return g}return b=new h(null,this.root.rules.slice(0)),b.evalImports(a),this.features?new e(b.rules,this.features.value):b.rules},b.exports=j},{"./anonymous":46,"./media":66,"./node":70,"./quoted":73,"./ruleset":76,"./url":80}],62:[function(a,b,c){var d={};d.Node=a("./node"),d.Alpha=a("./alpha"),d.Color=a("./color"),d.Directive=a("./directive"),d.DetachedRuleset=a("./detached-ruleset"),d.Operation=a("./operation"),d.Dimension=a("./dimension"),d.Unit=a("./unit"),d.Keyword=a("./keyword"),d.Variable=a("./variable"),d.Ruleset=a("./ruleset"),d.Element=a("./element"),d.Attribute=a("./attribute"),d.Combinator=a("./combinator"),d.Selector=a("./selector"),d.Quoted=a("./quoted"),d.Expression=a("./expression"),d.Rule=a("./rule"),d.Call=a("./call"),d.URL=a("./url"),d.Import=a("./import"),d.mixin={Call:a("./mixin-call"),Definition:a("./mixin-definition")},d.Comment=a("./comment"),d.Anonymous=a("./anonymous"),d.Value=a("./value"),d.JavaScript=a("./javascript"),d.Assignment=a("./assignment"),d.Condition=a("./condition"),d.Paren=a("./paren"),d.Media=a("./media"),d.UnicodeDescriptor=a("./unicode-descriptor"),d.Negative=a("./negative"),d.Extend=a("./extend"),d.RulesetCall=a("./ruleset-call"),b.exports=d},{"./alpha":45,"./anonymous":46,"./assignment":47,"./attribute":48,"./call":49,"./color":50,"./combinator":51,"./comment":52,"./condition":53,"./detached-ruleset":55,"./dimension":56,"./directive":57,"./element":58,"./expression":59,"./extend":60,"./import":61,"./javascript":63,"./keyword":65,"./media":66,"./mixin-call":67,"./mixin-definition":68,"./negative":69,"./node":70,"./operation":71,"./paren":72,"./quoted":73,"./rule":74,"./ruleset":76,"./ruleset-call":75,"./selector":77,"./unicode-descriptor":78,"./unit":79,"./url":80,"./value":81,"./variable":82}],63:[function(a,b,c){var d=a("./js-eval-node"),e=a("./dimension"),f=a("./quoted"),g=a("./anonymous"),h=function(a,b,c,d){this.escaped=b,this.expression=a,this.index=c,this.currentFileInfo=d};h.prototype=new d,h.prototype.type="JavaScript",h.prototype.eval=function(a){var b=this.evaluateJavaScript(this.expression,a);return"number"==typeof b?new e(b):"string"==typeof b?new f('"'+b+'"',b,this.escaped,this.index):new g(Array.isArray(b)?b.join(", "):b)},b.exports=h},{"./anonymous":46,"./dimension":56,"./js-eval-node":64,"./quoted":73}],64:[function(a,b,c){var d=a("./node"),e=a("./variable"),f=function(){};f.prototype=new d,f.prototype.evaluateJavaScript=function(a,b){var c,d=this,f={};if(void 0!==b.javascriptEnabled&&!b.javascriptEnabled)throw{message:"You are using JavaScript, which has been disabled.",filename:this.currentFileInfo.filename,index:this.index};a=a.replace(/@\{([\w-]+)\}/g,function(a,c){return d.jsify(new e("@"+c,d.index,d.currentFileInfo).eval(b))});try{a=new Function("return ("+a+")")}catch(g){throw{message:"JavaScript evaluation error: "+g.message+" from `"+a+"`",filename:this.currentFileInfo.filename,index:this.index}}var h=b.frames[0].variables();for(var i in h)h.hasOwnProperty(i)&&(f[i.slice(1)]={value:h[i].value,toJS:function(){return this.value.eval(b).toCSS()}});try{c=a.call(f)}catch(g){throw{message:"JavaScript evaluation error: '"+g.name+": "+g.message.replace(/["]/g,"'")+"'",filename:this.currentFileInfo.filename,index:this.index}}return c},f.prototype.jsify=function(a){return Array.isArray(a.value)&&a.value.length>1?"["+a.value.map(function(a){return a.toCSS()}).join(", ")+"]":a.toCSS()},b.exports=f},{"./node":70,"./variable":82}],65:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Keyword",e.prototype.genCSS=function(a,b){if("%"===this.value)throw{type:"Syntax",message:"Invalid % without number"};b.add(this.value)},e.True=new e("true"),e.False=new e("false"),b.exports=e},{"./node":70}],66:[function(a,b,c){var d=a("./ruleset"),e=a("./value"),f=a("./selector"),g=a("./anonymous"),h=a("./expression"),i=a("./directive"),j=function(a,b,c,g,h){this.index=c,this.currentFileInfo=g;var i=new f([],null,null,this.index,this.currentFileInfo).createEmptySelectors();this.features=new e(b),this.rules=[new d(i,a)],this.rules[0].allowImports=!0,this.copyVisibilityInfo(h),this.allowRoot=!0};j.prototype=new i,j.prototype.type="Media",j.prototype.isRulesetLike=!0,j.prototype.accept=function(a){this.features&&(this.features=a.visit(this.features)),this.rules&&(this.rules=a.visitArray(this.rules))},j.prototype.genCSS=function(a,b){b.add("@media ",this.currentFileInfo,this.index),this.features.genCSS(a,b),this.outputRuleset(a,b,this.rules)},j.prototype.eval=function(a){a.mediaBlocks||(a.mediaBlocks=[],a.mediaPath=[]);var b=new j(null,[],this.index,this.currentFileInfo,this.visibilityInfo());this.debugInfo&&(this.rules[0].debugInfo=this.debugInfo,b.debugInfo=this.debugInfo);var c=!1;a.strictMath||(c=!0,a.strictMath=!0);try{b.features=this.features.eval(a)}finally{c&&(a.strictMath=!1)}return a.mediaPath.push(b),a.mediaBlocks.push(b),this.rules[0].functionRegistry=a.frames[0].functionRegistry.inherit(),a.frames.unshift(this.rules[0]),b.rules=[this.rules[0].eval(a)],a.frames.shift(),a.mediaPath.pop(),0===a.mediaPath.length?b.evalTop(a):b.evalNested(a)},j.prototype.evalTop=function(a){var b=this;if(a.mediaBlocks.length>1){var c=new f([],null,null,this.index,this.currentFileInfo).createEmptySelectors();b=new d(c,a.mediaBlocks),b.multiMedia=!0,b.copyVisibilityInfo(this.visibilityInfo())}return delete a.mediaBlocks,delete a.mediaPath,b},j.prototype.evalNested=function(a){var b,c,f=a.mediaPath.concat([this]);for(b=0;b0;b--)a.splice(b,0,new g("and"));return new h(a)})),new d([],[])},j.prototype.permute=function(a){if(0===a.length)return[];if(1===a.length)return a[0];for(var b=[],c=this.permute(a.slice(1)),d=0;d0){for(n=!0,k=0;k0)p=B;else if(p=A,q[A]+q[B]>1)throw{type:"Runtime",message:"Ambiguous use of `default()` found when matching for `"+this.format(t)+"`",index:this.index,filename:this.currentFileInfo.filename};for(k=0;kthis.params.length)return!1}c=Math.min(f,this.arity);for(var g=0;gb?1:void 0},d.prototype.blocksVisibility=function(){return null==this.visibilityBlocks&&(this.visibilityBlocks=0),0!==this.visibilityBlocks},d.prototype.addVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks+1},d.prototype.removeVisibilityBlock=function(){null==this.visibilityBlocks&&(this.visibilityBlocks=0),this.visibilityBlocks=this.visibilityBlocks-1},d.prototype.ensureVisibility=function(){this.nodeVisible=!0},d.prototype.ensureInvisibility=function(){this.nodeVisible=!1},d.prototype.isVisible=function(){return this.nodeVisible},d.prototype.visibilityInfo=function(){return{visibilityBlocks:this.visibilityBlocks,nodeVisible:this.nodeVisible}},d.prototype.copyVisibilityInfo=function(a){a&&(this.visibilityBlocks=a.visibilityBlocks,this.nodeVisible=a.nodeVisible)},b.exports=d},{}],71:[function(a,b,c){var d=a("./node"),e=a("./color"),f=a("./dimension"),g=function(a,b,c){this.op=a.trim(),this.operands=b,this.isSpaced=c};g.prototype=new d,g.prototype.type="Operation",g.prototype.accept=function(a){this.operands=a.visit(this.operands)},g.prototype.eval=function(a){var b=this.operands[0].eval(a),c=this.operands[1].eval(a);if(a.isMathOn()){if(b instanceof f&&c instanceof e&&(b=b.toColor()),c instanceof f&&b instanceof e&&(c=c.toColor()),!b.operate)throw{type:"Operation",message:"Operation on an invalid type"};return b.operate(a,this.op,c)}return new g(this.op,[b,c],this.isSpaced)},g.prototype.genCSS=function(a,b){this.operands[0].genCSS(a,b),this.isSpaced&&b.add(" "),b.add(this.op),this.isSpaced&&b.add(" "),this.operands[1].genCSS(a,b)},b.exports=g},{"./color":50,"./dimension":56,"./node":70}],72:[function(a,b,c){var d=a("./node"),e=function(a){this.value=a};e.prototype=new d,e.prototype.type="Paren",e.prototype.genCSS=function(a,b){b.add("("),this.value.genCSS(a,b),b.add(")")},e.prototype.eval=function(a){return new e(this.value.eval(a))},b.exports=e},{"./node":70}],73:[function(a,b,c){var d=a("./node"),e=a("./js-eval-node"),f=a("./variable"),g=function(a,b,c,d,e){this.escaped=null==c||c,this.value=b||"",this.quote=a.charAt(0),this.index=d,this.currentFileInfo=e};g.prototype=new e,g.prototype.type="Quoted",g.prototype.genCSS=function(a,b){this.escaped||b.add(this.quote,this.currentFileInfo,this.index),b.add(this.value),this.escaped||b.add(this.quote)},g.prototype.containsVariables=function(){return this.value.match(/(`([^`]+)`)|@\{([\w-]+)\}/)},g.prototype.eval=function(a){function b(a,b,c){var d=a;do a=d,d=a.replace(b,c);while(a!==d);return d}var c=this,d=this.value,e=function(b,d){return String(c.evaluateJavaScript(d,a))},h=function(b,d){var e=new f("@"+d,c.index,c.currentFileInfo).eval(a,!0);return e instanceof g?e.value:e.toCSS()};return d=b(d,/`([^`]+)`/g,e),d=b(d,/@\{([\w-]+)\}/g,h),new g(this.quote+d+this.quote,d,this.escaped,this.index,this.currentFileInfo)},g.prototype.compare=function(a){return"Quoted"!==a.type||this.escaped||a.escaped?a.toCSS&&this.toCSS()===a.toCSS()?0:void 0:d.numericCompare(this.value,a.value)},b.exports=g},{"./js-eval-node":64,"./node":70,"./variable":82}],74:[function(a,b,c){function d(a,b){var c,d="",e=b.length,f={add:function(a){d+=a}};for(c=0;cd){if(!c||c(h)){e=h.find(new f(a.elements.slice(d)),b,c);for(var j=0;j0&&b.add(k),a.firstSelector=!0,h[0].genCSS(a,b),a.firstSelector=!1,e=1;e0?(e=a.slice(0),f=e.pop(),h=d.createDerived(f.elements.slice(0))):h=d.createDerived([]),b.length>0){var i=c.combinator,j=b[0].elements[0];i.emptyOrWhitespace&&!j.combinator.emptyOrWhitespace&&(i=j.combinator),h.elements.push(new g(i,j.value,c.index,c.currentFileInfo)),h.elements=h.elements.concat(b[0].elements.slice(1))}if(0!==h.elements.length&&e.push(h),b.length>1){var k=b.slice(1);k=k.map(function(a){return a.createDerived(a.elements,[])}),e=e.concat(k)}return e}function j(a,b,c,d,e){var f;for(f=0;f0?d[d.length-1]=d[d.length-1].createDerived(d[d.length-1].elements.concat(a)):d.push(new f(a))}}function l(a,b,c){function f(a){var b;return"Paren"!==a.value.type?null:(b=a.value.value,"Selector"!==b.type?null:b)}var h,m,n,o,p,q,r,s,t,u,v=!1;for(o=[],p=[[]],h=0;h0&&r[0].elements.push(new g(s.combinator,"",s.index,s.currentFileInfo)),q.push(r);else for(n=0;n0&&(a.push(p[h]),u=p[h][t-1],p[h][t-1]=u.createDerived(u.elements,c.extendList));return v}function m(a,b){var c=b.createDerived(b.elements,b.extendList,b.evaldCondition);return c.copyVisibilityInfo(a),c}var n,o,p;if(o=[],p=l(o,b,c),!p)if(b.length>0)for(o=[],n=0;n0)for(b=0;b=0&&"\n"!==b.charAt(c);)e++;return"number"==typeof a&&(d=(b.slice(0,a).match(/\n/g)||"").length),{line:d,column:e}}}},{}],84:[function(a,b,c){var d=a("../tree"),e=a("./visitor"),f=a("../logger"),g=function(){this._visitor=new e(this),this.contexts=[],this.allExtendsStack=[[]]};g.prototype={run:function(a){return a=this._visitor.visit(a),a.allExtends=this.allExtendsStack[0],a},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitRuleset:function(a,b){if(!a.root){var c,e,f,g,h=[],i=a.rules,j=i?i.length:0;for(c=0;c=0||(i=[k.selfSelectors[0]],g=n.findMatch(j,i),g.length&&(j.hasFoundMatches=!0,j.selfSelectors.forEach(function(a){var b=k.visibilityInfo();h=n.extendSelector(g,i,a,j.isVisible()),l=new d.Extend(k.selector,k.option,0,k.currentFileInfo,b),l.selfSelectors=h,h[h.length-1].extendList=[l],m.push(l),l.ruleset=k.ruleset,l.parent_ids=l.parent_ids.concat(k.parent_ids,j.parent_ids),k.firstExtendOnThisSelectorPath&&(l.firstExtendOnThisSelectorPath=!0,k.ruleset.paths.push(h))})));if(m.length){if(this.extendChainCount++,c>100){var o="{unable to calculate}",p="{unable to calculate}";try{o=m[0].selfSelectors[0].toCSS(),p=m[0].selector.toCSS()}catch(q){}throw{message:"extend circular reference detected. One of the circular extends is currently:"+o+":extend("+p+")"}}return m.concat(n.doExtendChaining(m,b,c+1))}return m},visitRule:function(a,b){b.visitDeeper=!1},visitMixinDefinition:function(a,b){b.visitDeeper=!1},visitSelector:function(a,b){b.visitDeeper=!1},visitRuleset:function(a,b){if(!a.root){var c,d,e,f,g=this.allExtendsStack[this.allExtendsStack.length-1],h=[],i=this;for(e=0;e0&&k[i.matched].combinator.value!==g?i=null:i.matched++,i&&(i.finished=i.matched===k.length,i.finished&&!a.allowAfter&&(e+1k&&l>0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),l=0,k++),j=g.elements.slice(l,i.index).concat([h]).concat(c.elements.slice(1)),k===i.pathIndex&&f>0?m[m.length-1].elements=m[m.length-1].elements.concat(j):(m=m.concat(b.slice(k,i.pathIndex)),m.push(new d.Selector(j))),k=i.endPathIndex,l=i.endPathElementIndex,l>=b[k].elements.length&&(l=0,k++);return k0&&(m[m.length-1].elements=m[m.length-1].elements.concat(b[k].elements.slice(l)),k++),m=m.concat(b.slice(k,b.length)),m=m.map(function(a){var b=a.createDerived(a.elements);return e?b.ensureVisibility():b.ensureInvisibility(),b})},visitMedia:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitMediaOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b},visitDirective:function(a,b){var c=a.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length-1]);c=c.concat(this.doExtendChaining(c,a.allExtends)),this.allExtendsStack.push(c)},visitDirectiveOut:function(a){var b=this.allExtendsStack.length-1;this.allExtendsStack.length=b}},b.exports=h},{"../logger":33,"../tree":62,"./visitor":91}],85:[function(a,b,c){function d(a){this.imports=[],this.variableImports=[],this._onSequencerEmpty=a,this._currentDepth=0}d.prototype.addImport=function(a){var b=this,c={callback:a,args:null,isReady:!1};return this.imports.push(c),function(){c.args=Array.prototype.slice.call(arguments,0),c.isReady=!0,b.tryRun()}},d.prototype.addVariableImport=function(a){this.variableImports.push(a)},d.prototype.tryRun=function(){this._currentDepth++;try{for(;;){for(;this.imports.length>0;){var a=this.imports[0];if(!a.isReady)return; -this.imports=this.imports.slice(1),a.callback.apply(null,a.args)}if(0===this.variableImports.length)break;var b=this.variableImports[0];this.variableImports=this.variableImports.slice(1),b()}}finally{this._currentDepth--}0===this._currentDepth&&this._onSequencerEmpty&&this._onSequencerEmpty()},b.exports=d},{}],86:[function(a,b,c){var d=a("../contexts"),e=a("./visitor"),f=a("./import-sequencer"),g=function(a,b){this._visitor=new e(this),this._importer=a,this._finish=b,this.context=new d.Eval,this.importCount=0,this.onceFileDetectionMap={},this.recursionDetector={},this._sequencer=new f(this._onSequencerEmpty.bind(this))};g.prototype={isReplacing:!1,run:function(a){try{this._visitor.visit(a)}catch(b){this.error=b}this.isFinished=!0,this._sequencer.tryRun()},_onSequencerEmpty:function(){this.isFinished&&this._finish(this.error)},visitImport:function(a,b){var c=a.options.inline;if(!a.css||c){var e=new d.Eval(this.context,this.context.frames.slice(0)),f=e.frames[0];this.importCount++,a.isVariableImport()?this._sequencer.addVariableImport(this.processImportNode.bind(this,a,e,f)):this.processImportNode(a,e,f)}b.visitDeeper=!1},processImportNode:function(a,b,c){var d,e=a.options.inline;try{d=a.evalForImport(b)}catch(f){f.filename||(f.index=a.index,f.filename=a.currentFileInfo.filename),a.css=!0,a.error=f}if(!d||d.css&&!e)this.importCount--,this.isFinished&&this._sequencer.tryRun();else{d.options.multiple&&(b.importMultiple=!0);for(var g=void 0===d.css,h=0;h0},resolveVisibility:function(a,b){if(!a.blocksVisibility()){if(this.isEmpty(a)&&!this.containsSilentNonBlockedChild(b))return;return a}var c=a.rules[0];if(this.keepOnlyVisibleChilds(c),!this.isEmpty(c))return a.ensureVisibility(),a.removeVisibilityBlock(),a},isVisibleRuleset:function(a){return!!a.firstRoot||!this.isEmpty(a)&&!(!a.root&&!this.hasVisibleSelector(a))}};var g=function(a){this._visitor=new e(this),this._context=a,this.utils=new f(a)};g.prototype={isReplacing:!0,run:function(a){return this._visitor.visit(a)},visitRule:function(a,b){if(!a.blocksVisibility()&&!a.variable)return a},visitMixinDefinition:function(a,b){a.frames=[]},visitExtend:function(a,b){},visitComment:function(a,b){if(!a.blocksVisibility()&&!a.isSilent(this._context))return a},visitMedia:function(a,b){var c=a.rules[0].rules;return a.accept(this._visitor),b.visitDeeper=!1,this.utils.resolveVisibility(a,c)},visitImport:function(a,b){if(!a.blocksVisibility())return a},visitDirective:function(a,b){return a.rules&&a.rules.length?this.visitDirectiveWithBody(a,b):this.visitDirectiveWithoutBody(a,b)},visitDirectiveWithBody:function(a,b){function c(a){var b=a.rules;return 1===b.length&&(!b[0].paths||0===b[0].paths.length)}function d(a){var b=a.rules;return c(a)?b[0].rules:b}var e=d(a);return a.accept(this._visitor),b.visitDeeper=!1,this.utils.isEmpty(a)||this._mergeRules(a.rules[0].rules),this.utils.resolveVisibility(a,e)},visitDirectiveWithoutBody:function(a,b){if(!a.blocksVisibility()){if("@charset"===a.name){if(this.charset){if(a.debugInfo){var c=new d.Comment("/* "+a.toCSS(this._context).replace(/\n/g,"")+" */\n");return c.debugInfo=a.debugInfo,this._visitor.visit(c)}return}this.charset=!0}return a}},checkValidNodes:function(a,b){if(a)for(var c=0;c0?a.accept(this._visitor):a.rules=null,b.visitDeeper=!1}return a.rules&&(this._mergeRules(a.rules),this._removeDuplicateRules(a.rules)),this.utils.isVisibleRuleset(a)&&(a.ensureVisibility(),d.splice(0,0,a)),1===d.length?d[0]:d},_compileRulesetPaths:function(a){a.paths&&(a.paths=a.paths.filter(function(a){var b;for(" "===a[0].elements[0].combinator.value&&(a[0].elements[0].combinator=new d.Combinator("")),b=0;b=0;e--)if(c=a[e],c instanceof d.Rule)if(f[c.name]){b=f[c.name],b instanceof d.Rule&&(b=f[c.name]=[f[c.name].toCSS(this._context)]);var g=c.toCSS(this._context);b.indexOf(g)!==-1?a.splice(e,1):b.push(g)}else f[c.name]=c}},_mergeRules:function(a){if(a){for(var b,c,e,f={},g=0;g1){c=b[0];var h=[],i=[];b.map(function(a){"+"===a.merge&&(i.length>0&&h.push(e(i)),i=[]),i.push(a)}),h.push(e(i)),c.value=g(h)}})}},visitAnonymous:function(a,b){if(!a.blocksVisibility())return a.accept(this._visitor),a}},b.exports=g},{"../tree":62,"./visitor":91}],91:[function(a,b,c){function d(a){return a}function e(a,b){var c,d;for(c in a)if(a.hasOwnProperty(c))switch(d=a[c],typeof d){case"function":d.prototype&&d.prototype.type&&(d.prototype.typeIndex=b++);break;case"object":b=e(d,b)}return b}var f=a("../tree"),g={visitDeeper:!0},h=!1,i=function(a){this._implementation=a,this._visitFnCache=[],h||(e(f,1),h=!0)};i.prototype={visit:function(a){if(!a)return a;var b=a.typeIndex;if(!b)return a;var c,e=this._visitFnCache,f=this._implementation,h=b<<1,i=1|h,j=e[h],k=e[i],l=g;if(l.visitDeeper=!0,j||(c="visit"+a.type,j=f[c]||d,k=f[c+"Out"]||d,e[h]=j,e[i]=k),j!==d){var m=j.call(f,a,l);f.isReplacing&&(a=m)}return l.visitDeeper&&a&&a.accept&&a.accept(this),k!=d&&k.call(f,a),a},visitArray:function(a,b){if(!a)return a;var c,d=a.length;if(b||!this._implementation.isReplacing){for(c=0;ck){for(var b=0,c=h.length-j;b { + id?: number; +} + +export interface SelectedTrackItem extends Omit { + id?: number; } /* -id: 472, - taskName: 'AppTrackItem', beginDate: 2017-12-08T07:15:49.792Z, endDate: 2017-12-08T07:15:52.792Z, app: 'Code', diff --git a/client/src/@types/modules/less.d.ts b/client/src/@types/modules/less.d.ts deleted file mode 100644 index 4204d5bb..00000000 --- a/client/src/@types/modules/less.d.ts +++ /dev/null @@ -1,5 +0,0 @@ -// declaration.d.ts -declare module '*.less' { - const content: any; - export default content; -} diff --git a/client/src/@types/moment.ts b/client/src/@types/moment.ts deleted file mode 100644 index bd57e528..00000000 --- a/client/src/@types/moment.ts +++ /dev/null @@ -1,100 +0,0 @@ -import moment from 'moment'; - -moment(); -declare module 'moment' { - namespace duration { - const fn: Duration; - } - - interface Duration { - format: Format; - } - - interface Format { - defaults: DurationFormatSettings; - - ( - template: string | TemplateFunction, - precision: number, - settings?: DurationFormatSettings, - ): string; - (template: string | TemplateFunction, settings?: DurationFormatSettings): string; - (settings?: DurationFormatSettings): string; - } - - type UnitOfTrimV1 = 'left' | 'right'; - type UnitOfTrim = 'large' | 'small' | 'both' | 'mid' | 'all' | 'final'; - - interface DurationFormatSettings { - trim?: false | UnitOfTrimV1 | UnitOfTrim | string | Array; - largest?: number; - trunc?: true; - stopTrim?: string; - - minValue?: number; - maxValue?: number; - - useGrouping?: boolean; - precision?: number; - decimalSeparator?: string; - groupingSeparator?: string; - grouping?: number[]; - - useSignificantDigits?: true; - - forceLength?: boolean; - template?: string | TemplateFunction; - - userLocale?: string; - usePlural?: boolean; - useLeftUnits?: boolean; - useToLocaleString?: boolean; - } - - type DurationLabelType = 'long' | 'standard' | 'short'; - type DurationTemplate = 'HMS' | 'HM' | 'MS'; - type DurationToken = - | 'S' - | 'SS' - | 'SSS' - | 's' - | 'ss' - | 'sss' - | 'm' - | 'mm' - | 'mmm' - | 'h' - | 'hh' - | 'hhh' - | 'd' - | 'dd' - | 'ddd' - | 'w' - | 'ww' - | 'www' - | 'M' - | 'MM' - | 'MMM' - | 'y' - | 'yy' - | 'yyy'; - - type DurationLabelDef = { [duration in DurationToken]: string }; - type DurationTimeDef = { [template in DurationTemplate]: string }; - - interface DurationLabelTypeDef { - type: DurationLabelType; - string: string; - } - - interface LocaleSpecification { - durationLabelsLong: DurationLabelDef; - durationLabelsStandard: DurationLabelDef; - durationLabelsShort: DurationLabelDef; - durationTimeTemplates: DurationTimeDef; - durationLabelTypes: DurationLabelTypeDef[]; - durationPluralKey: (token: string, integerValue: number, decimalValue: number) => string; - } - - type TemplateFunction = (this: DurationFormatSettings) => string; -} diff --git a/client/src/MainRouter.tsx b/client/src/MainRouter.tsx new file mode 100644 index 00000000..70c4c0e0 --- /dev/null +++ b/client/src/MainRouter.tsx @@ -0,0 +1,77 @@ +import { useColorMode } from '@chakra-ui/react'; +import { StoreProvider } from 'easy-peasy'; +import { Settings } from 'luxon'; +import { useCallback, useEffect } from 'react'; +import { Navigate, Route, Routes } from 'react-router-dom'; +import { ErrorBoundary } from './components/ErrorBoundary/ErrorBoundary'; +import { TrayLayout } from './components/TrayLayout/TrayLayout'; +import { Logger } from './logger'; +import { RootProvider } from './RootContext'; +import { ChartThemeProvider } from './routes/ChartThemeProvider'; +import { MainAppPage } from './routes/MainAppPage'; +import { NotificationAppPage } from './routes/NotificationAppPage'; +import { TrayAppPage } from './routes/TrayAppPage'; +import { ElectronEventEmitter } from './services/ElectronEventEmitter'; +import { mainStore } from './store/mainStore'; +import { useGoogleAnalytics } from './useGoogleAnalytics'; + +Settings.defaultLocale = 'en-GB'; + +export function MainRouter() { + useGoogleAnalytics(); + const { setColorMode } = useColorMode(); + + const changeActiveTheme = useCallback( + (themeName) => { + setColorMode(themeName); + }, + [setColorMode], + ); + + useEffect(() => { + ElectronEventEmitter.on('activeThemeChanged', changeActiveTheme); + + return () => { + Logger.debug('Clearing eventEmitter'); + ElectronEventEmitter.off('activeThemeChanged', changeActiveTheme); + }; + }, [changeActiveTheme]); + + return ( + + + + {/* Main App with main store */} + + + + } + /> + + {/* Redirect from root to /app */} + } /> + + {/* Tray App - No longer needs trayStore */} + + + + + + } + /> + + } /> + + {/* Fallback redirect to /app */} + } /> + + + + ); +} diff --git a/client/src/RootContext.tsx b/client/src/RootContext.tsx index cc7a4267..5c40a8f2 100644 --- a/client/src/RootContext.tsx +++ b/client/src/RootContext.tsx @@ -1,46 +1,107 @@ -import React, { useEffect, useState, createContext, useCallback } from 'react'; -import useReactRouter from 'use-react-router'; -import { EventEmitter } from './services/EventEmitter'; +import { ReactNode, createContext, useCallback, useEffect, useState } from 'react'; +import { useNavigate } from 'react-router-dom'; +import { DataSettingsI } from './components/Settings/DataForm.util'; +import { WorkSettingsI } from './components/Settings/WorkForm.util'; import { Logger } from './logger'; +import { ElectronEventEmitter } from './services/ElectronEventEmitter'; +import { fetchDataSettings, fetchWorkSettings, saveDataSettings, saveWorkSettings } from './services/settings.api'; -const defaultWorkSettings = { +const defaultWorkSettings: WorkSettingsI = { workDayStartTime: '08:30', // not used workDayEndTime: '17:00', // not used splitTaskAfterIdlingForMinutes: 3, // not used in client, put used in backend - hoursToWork: 8, + hoursToWork: 8, // not used + sessionLength: 50, + minBreakTime: 5, + notificationDuration: 10, + reNotifyInterval: 5, + smallNotificationsEnabled: true, +}; +const defaultDataSettings: DataSettingsI = { + idleAfterSeconds: 60, + backgroundJobInterval: 3, + recentDaysCount: 7, }; -export const RootContext = createContext({}); +interface RootContextType { + workSettings: WorkSettingsI; + updateWorkSettings: (settings: WorkSettingsI) => void; + dataSettings: DataSettingsI; + updateDataSettings: (settings: DataSettingsI) => void; +} -export const RootProvider = ({ children }) => { - const { history } = useReactRouter(); +export const RootContext = createContext({ + workSettings: defaultWorkSettings, + updateWorkSettings: () => {}, + dataSettings: defaultDataSettings, + updateDataSettings: () => {}, +}); - const prevWorkSettings = JSON.parse((window as any).localStorage.getItem('workSettings')) || { - defaultWorkSettings, - }; +interface RootProviderProps { + children: ReactNode; +} + +export const RootProvider = ({ children }: RootProviderProps) => { + const navigate = useNavigate(); const gotoSettingsPage = useCallback(() => { Logger.debug('Navigating to settings page'); - history.push('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/app/settings'); - }, [history]); + navigate('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/app/settings'); + }, [navigate]); + + const [workSettings, setWorkSettings] = useState(defaultWorkSettings); + const [dataSettings, setDataSettings] = useState(defaultDataSettings); + + const updateWorkSettings = useCallback((newWorkSettings: WorkSettingsI) => { + setWorkSettings(newWorkSettings); + saveWorkSettings(newWorkSettings); + }, []); + + const updateDataSettings = useCallback((newDataSettings: DataSettingsI) => { + setDataSettings(newDataSettings); + saveDataSettings(newDataSettings); + }, []); + + const loadSettings = useCallback(async () => { + const newWorkSettings = await fetchWorkSettings(); - const [workSettings, setWorkSettings] = useState(prevWorkSettings); + if (newWorkSettings) { + setWorkSettings(newWorkSettings); + } + const newDataSettings = await fetchDataSettings(); + + if (newDataSettings) { + setDataSettings(newDataSettings); + } + }, []); + + useEffect(() => { + loadSettings(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); useEffect(() => { - window.localStorage.setItem('workSettings', JSON.stringify(workSettings)); - }, [workSettings]); + ElectronEventEmitter.on('WORK_SETTINGS_UPDATED', loadSettings); + + return () => { + ElectronEventEmitter.off('WORK_SETTINGS_UPDATED', loadSettings); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); useEffect(() => { - EventEmitter.on('side:preferences', gotoSettingsPage); + ElectronEventEmitter.on('side:preferences', gotoSettingsPage); return () => { Logger.debug('Clearing eventEmitter'); - EventEmitter.off('side:preferences', gotoSettingsPage); + ElectronEventEmitter.off('side:preferences', gotoSettingsPage); }; }, [gotoSettingsPage]); - const defaultContext = { + const defaultContext: RootContextType = { workSettings, - setWorkSettings, + updateWorkSettings, + dataSettings, + updateDataSettings, }; return {children}; diff --git a/client/src/SummaryContext.tsx b/client/src/SummaryContext.tsx index 7f9b88c8..17a50a81 100644 --- a/client/src/SummaryContext.tsx +++ b/client/src/SummaryContext.tsx @@ -1,44 +1,64 @@ -import moment from 'moment'; -import React, { createContext, useState, useCallback, useEffect } from 'react'; -import { findAllDayItemsForEveryTrack } from './services/trackItem.api'; +import { DateTime } from 'luxon'; +import { createContext, useCallback, useEffect, useState } from 'react'; import { + ISummary, + ISummaryOnlineTime, summariseLog, summariseOnline, summariseTimeOnline, } from './components/SummaryCalendar/SummaryCalendar.util'; import { Logger } from './logger'; -import { MODE_MONTH } from './SummaryContext.util'; +import { findAllDayItemsForEveryTrack } from './services/trackItem.api'; +import { CALENDAR_MODE } from './SummaryContext.util'; -export const SummaryContext = createContext({}); +interface SummaryContextType { + selectedDate: DateTime; + setSelectedDate: (date: DateTime) => void; + selectedMode: CALENDAR_MODE; + setSelectedMode: (mode: CALENDAR_MODE) => void; + logSummary: ISummary; + onlineSummary: ISummary; + onlineTimesSummary: ISummaryOnlineTime; + isLoading: boolean; +} -export const SummaryProvider = ({ children }) => { - const [isLoading, setIsLoading] = useState(false); - const [selectedDate, setSelectedDate] = useState(moment()); - const [selectedMode, setSelectedMode] = useState(MODE_MONTH); +export const SummaryContext = createContext({ + selectedDate: DateTime.now(), + setSelectedDate: () => {}, + selectedMode: CALENDAR_MODE.MONTH, + setSelectedMode: () => {}, + logSummary: {}, + onlineSummary: {}, + onlineTimesSummary: {}, + isLoading: false, +}); - const [logSummary, setLogSummary] = useState([]); - const [onlineSummary, setOnlineSummary] = useState([]); - const [onlineTimesSummary, setOnlineTimesSummary] = useState([]); +export const SummaryProvider = ({ children }: { children: React.ReactNode }) => { + const [isLoading, setIsLoading] = useState(false); + const [selectedDate, setSelectedDate] = useState(DateTime.now()); + const [selectedMode, setSelectedMode] = useState(CALENDAR_MODE.MONTH); + + const [logSummary, setLogSummary] = useState({}); + const [onlineSummary, setOnlineSummary] = useState({}); + const [onlineTimesSummary, setOnlineTimesSummary] = useState({}); const loadData = useCallback(async () => { setIsLoading(true); try { // TODO, query month +1 day for sleep time - const beginDate = moment(selectedDate).startOf(selectedMode); - const endDate = moment(selectedDate).endOf(selectedMode); + const beginDate = selectedDate.startOf(selectedMode.toLowerCase() as 'month' | 'week' | 'day'); + let endDate = selectedDate.endOf(selectedMode.toLowerCase() as 'month' | 'week' | 'day'); - if (selectedMode === MODE_MONTH) { - endDate.add(1, 'day'); + if (selectedMode === CALENDAR_MODE.MONTH) { + endDate = endDate.plus({ days: 1 }); } - const { statusItems, logItems } = await findAllDayItemsForEveryTrack( - beginDate, - endDate, - ); + + const { statusItems, logItems } = await findAllDayItemsForEveryTrack(beginDate, endDate); setLogSummary(summariseLog(logItems, selectedMode)); setOnlineSummary(summariseOnline(statusItems, selectedMode)); setOnlineTimesSummary(summariseTimeOnline(statusItems, selectedMode, beginDate)); } catch (e) { - Logger.error('Errod loading summary data.', e); + Logger.error('Error loading summary data.', e); } finally { setIsLoading(false); } diff --git a/client/src/SummaryContext.util.ts b/client/src/SummaryContext.util.ts index 389df336..527f22ed 100644 --- a/client/src/SummaryContext.util.ts +++ b/client/src/SummaryContext.util.ts @@ -1,3 +1,7 @@ -export const MODE_MONTH = 'month'; -export const DAY_MONTH_FORMAT = 'MM-DD'; +export enum CALENDAR_MODE { + MONTH = 'month', + YEAR = 'year', +} + +export const DAY_MONTH_FORMAT = 'MM-dd'; export const MONTH_FORMAT = 'MM'; diff --git a/client/src/__mocks__/logger.ts b/client/src/__mocks__/logger.ts new file mode 100644 index 00000000..94e0cb2e --- /dev/null +++ b/client/src/__mocks__/logger.ts @@ -0,0 +1,8 @@ +import { vi } from 'vitest'; + +export const Logger = { + info: vi.fn(), + error: vi.fn(), + warn: vi.fn(), + debug: vi.fn(), +}; diff --git a/client/src/__tests__/time.testUtils.ts b/client/src/__tests__/time.testUtils.ts new file mode 100644 index 00000000..40621f83 --- /dev/null +++ b/client/src/__tests__/time.testUtils.ts @@ -0,0 +1,5 @@ +export function getTimestamp(dateString: string): number { + return new Date(dateString).getTime(); +} + +export const wait = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); diff --git a/client/src/analytics.ts b/client/src/analytics.ts deleted file mode 100644 index e6542580..00000000 --- a/client/src/analytics.ts +++ /dev/null @@ -1,24 +0,0 @@ -import Analytics from 'analytics'; -import googleAnalytics from '@analytics/google-analytics'; - -// https://www.npmjs.com/package/@analytics/google-analytics -const analytics = Analytics({ - app: 'tockler', - plugins: [ - googleAnalytics({ - trackingId: 'UA-196817622-1', - anonymizeIp: true, - customDimensions: { - version: 'dimension1', - }, - tasks: { - // Set checkProtocolTask, checkStorageTask, & historyImportTask for electron apps - checkProtocolTask: null, - checkStorageTask: null, - historyImportTask: null, - }, - }), - ], -}); - -export { analytics }; diff --git a/client/src/components/BlackBox.tsx b/client/src/components/BlackBox.tsx new file mode 100644 index 00000000..5ddc0722 --- /dev/null +++ b/client/src/components/BlackBox.tsx @@ -0,0 +1,7 @@ +import { Box, useColorModeValue, BoxProps } from '@chakra-ui/react'; + +export const BlackBox = ({ children, ...rest }: BoxProps) => ( + + {children} + +); diff --git a/client/src/components/Card.tsx b/client/src/components/Card.tsx new file mode 100644 index 00000000..a5e073e7 --- /dev/null +++ b/client/src/components/Card.tsx @@ -0,0 +1,15 @@ +import { Box, Flex, Text } from '@chakra-ui/react'; + +export const Card = ({ title, children, extra, ...rest }) => { + return ( + + + + {title} + + {extra} + + {children} + + ); +}; diff --git a/client/src/components/CardBox.tsx b/client/src/components/CardBox.tsx new file mode 100644 index 00000000..d48bc915 --- /dev/null +++ b/client/src/components/CardBox.tsx @@ -0,0 +1,44 @@ +import { Box, BoxProps, Flex, Text, useColorModeValue } from '@chakra-ui/react'; +import { ReactNode } from 'react'; + +interface CardBoxProps extends BoxProps { + title?: string; + extra?: ReactNode; + p?: number; + divider?: boolean; +} + +export const CardBox = ({ title, children, extra, p = 4, divider, ...rest }: CardBoxProps) => { + const titleColor = useColorModeValue('gray.900', 'white'); + const dividerColor = useColorModeValue('gray.200', 'gray.500'); + + return ( + + {title && ( + + + {title} + + {extra} + + )} + {divider && } + {children} + + ); +}; diff --git a/client/src/components/ColorModeSwitcher.tsx b/client/src/components/ColorModeSwitcher.tsx new file mode 100644 index 00000000..1faf0529 --- /dev/null +++ b/client/src/components/ColorModeSwitcher.tsx @@ -0,0 +1,39 @@ +import { useColorMode, useColorModeValue, IconButton, IconButtonProps, Tooltip } from '@chakra-ui/react'; +import { FaMoon, FaSun } from 'react-icons/fa'; +import { saveThemeToStorage } from '../services/settings.api'; +import { THEMES } from '../store/theme.util'; + +type ColorModeSwitcherProps = Omit; + +export const ColorModeSwitcher = (props: ColorModeSwitcherProps) => { + const { colorMode, setColorMode } = useColorMode(); + const text = useColorModeValue('dark', 'light'); + + const SwitchIcon = useColorModeValue(FaMoon, FaSun); + + const setColorModeAndSave = () => { + const theme = colorMode === THEMES.DARK ? THEMES.LIGHT : THEMES.DARK; + setColorMode(theme); + saveThemeToStorage(theme); + }; + + // TODO: Add Auto mode to toggle also + + const label = `Switch to ${text} mode`; + + return ( + + } + aria-label={label} + {...props} + /> + + ); +}; diff --git a/client/src/components/Common.styles.ts b/client/src/components/Common.styles.ts deleted file mode 100644 index 6056f6a1..00000000 --- a/client/src/components/Common.styles.ts +++ /dev/null @@ -1,3 +0,0 @@ -import styled from 'styled-components'; - -export const Smtng = styled.div``; diff --git a/client/src/components/Datepicker/Calendar.tsx b/client/src/components/Datepicker/Calendar.tsx new file mode 100644 index 00000000..bd9d8a63 --- /dev/null +++ b/client/src/components/Datepicker/Calendar.tsx @@ -0,0 +1,137 @@ +import { Box, Button, Flex, HStack, Spacer, StylesProvider, useMultiStyleConfig } from '@chakra-ui/react'; +import { useDatepicker } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; + +import { useEffect } from 'react'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; +import { CALENDAR_MODE } from '../../SummaryContext.util'; +import { CalendarMonth } from './CalendarMonth'; +import { CalendarYear } from './CalendarYear'; +import { DatepickerProvider } from './context/DatepickerContext'; +import { MonthSelect } from './MonthSelect'; +import { monthLabelFormatFn, weekdayLabelFormatLong } from './utils/formatters'; +import { YearSelect } from './YearSelect'; + +export interface ICalendarProps { + dateCellRender: (date: DateTime) => React.ReactNode; + onDateClicked: (date: DateTime) => void; + setSelectedDate: (date: DateTime) => void; + selectedDate: DateTime; + selectedMode: CALENDAR_MODE; + setSelectedMode: (mode: CALENDAR_MODE) => void; + focusedDate: Date; +} + +export const Calendar = ({ + selectedDate, + dateCellRender, + onDateClicked, + setSelectedDate, + selectedMode, + setSelectedMode, + focusedDate, +}: ICalendarProps) => { + const inputDate = selectedDate.toJSDate(); + + const dp = useDatepicker({ + onDatesChange: () => null, + startDate: inputDate, + endDate: inputDate, + focusedInput: null, + numberOfMonths: 1, + }); + + useEffect(() => { + dp.onDateFocus(focusedDate); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [focusedDate]); + + const styles = useMultiStyleConfig('Calendar', {}); + + const year = selectedDate.year; + const month = selectedDate.month - 1; // Luxon months are 1-12, but we need 0-11 for the selects + + function goToPrevious() { + const newDate = selectedDate.minus({ [selectedMode]: 1 }); + setSelectedDate(newDate); + dp.onDateSelect(newDate.toJSDate()); + } + + function goToNext() { + const newDate = selectedDate.plus({ [selectedMode]: 1 }); + setSelectedDate(newDate); + dp.onDateSelect(newDate.toJSDate()); + } + + const onChangeYear = (event) => { + const value = event.target.value; + const newDate = selectedDate.set({ year: value }); + setSelectedDate(newDate); + dp.onDateSelect(newDate.toJSDate()); + }; + + const onChangeMonth = (event) => { + const value = Number(event.target.value) + 1; // Convert back to 1-12 for Luxon + const newDate = selectedDate.set({ month: value }); + setSelectedDate(newDate); + dp.onDateSelect(newDate.toJSDate()); + }; + + const isMonthView = selectedMode === CALENDAR_MODE.MONTH; + + return ( + + + + + + + + {isMonthView && } + + + + + + + + + + + + + {isMonthView && ( + + )} + {!isMonthView && ( + + )} + + + + ); +}; diff --git a/client/src/components/Datepicker/CalendarMonth.tsx b/client/src/components/Datepicker/CalendarMonth.tsx new file mode 100644 index 00000000..53a4bb04 --- /dev/null +++ b/client/src/components/Datepicker/CalendarMonth.tsx @@ -0,0 +1,57 @@ +import { Box, Flex, SimpleGrid, useStyles } from '@chakra-ui/react'; +import { CalendarDay as DatepickerCalendarDay, useMonth } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; + +import { DayBox } from './components/DayBox'; +import { useDatepickerContext } from './context/DatepickerContext'; + +export interface MonthProps { + year: number; + month: number; + dateCellRender: (date: DateTime) => React.ReactNode; + onDateClicked: (date: DateTime) => void; +} + +export const CalendarMonth = ({ year, month, dateCellRender, onDateClicked }: MonthProps) => { + const styles = useStyles(); + const { dayLabelFormat, monthLabelFormat, weekdayLabelFormat, firstDayOfWeek } = useDatepickerContext(); + + const { days, weekdayLabels } = useMonth({ + year, + month, + dayLabelFormat, + monthLabelFormat, + weekdayLabelFormat, + firstDayOfWeek, + }); + + return ( + + + {weekdayLabels.map((weekdayLabel: string) => ( + + {weekdayLabel} + + ))} + + + + {days.map((day: DatepickerCalendarDay, index: number) => + typeof day === 'object' ? ( + + {dateCellRender(DateTime.fromJSDate(day.date))} + + ) : ( + + ), + )} + + + + ); +}; diff --git a/client/src/components/Datepicker/CalendarStyle.tsx b/client/src/components/Datepicker/CalendarStyle.tsx new file mode 100644 index 00000000..6716029e --- /dev/null +++ b/client/src/components/Datepicker/CalendarStyle.tsx @@ -0,0 +1,98 @@ +import { mode } from '@chakra-ui/theme-tools'; +import { ComponentStyleConfig } from '@chakra-ui/react'; + +const dayStyle = { + height: '156px', + width: '100%', + minWidth: 'unset', + border: '2px solid', + borderColor: 'transparent', +}; + +export const CalendarStyle = { + parts: ['calendar', 'weekdayLabel', 'grid'], + baseStyle: props => ({ + calendar: { + w: '100%', + }, + separator: { + bg: mode('gray.200', 'gray.500')(props), + h: '1px', + }, + weekdayLabel: { + bg: mode('gray.500', 'gray.500')(props), + color: 'white', + p: 3, + pl: 4, + fontWeight: 'bold', + fontSize: 'md', + }, + + grid: { + bg: mode('gray.200', 'gray.500')(props), + }, + day: { + bg: mode('white', 'gray.700')(props), + ...dayStyle, + }, + emptyDay: { + bg: mode('gray.100', 'gray.800')(props), + ...dayStyle, + }, + }), + + defaultProps: { + size: 'md', + }, +}; + +export const CalendarDayStyle: ComponentStyleConfig = { + baseStyle: props => ({ + height: '156px', + width: '100%', + minWidth: 'unset', + fontWeight: 'medium', + fontSize: 'md', + border: '2px solid', + + borderColor: 'transparent', + background: mode('white', 'gray.700')(props), + overflow: 'hidden', + + _hover: { + borderColor: 'transparent', + background: 'transparent', + cursor: 'pointer', + }, + }), + variants: { + normal: props => ({ + _hover: { + borderColor: mode('gray.700', 'white')(props), + }, + }), + rangeHover: props => ({ + _hover: { + borderColor: mode('gray.700', 'white')(props), + }, + }), + selected: props => ({ + borderColor: mode('brand.mainColor', 'brand.mainColor')(props), + + _hover: { + borderColor: mode('gray.700', 'white')(props), + }, + }), + firstOrLast: props => ({ + textColor: mode('white', 'black')(props), + background: mode('black', 'white')(props), + _hover: { + textColor: mode('white', 'black')(props), + background: mode('black', 'white')(props), + }, + }), + }, + defaultProps: { + variant: 'normal', + }, +}; diff --git a/client/src/components/Datepicker/CalendarYear.tsx b/client/src/components/Datepicker/CalendarYear.tsx new file mode 100644 index 00000000..13839d1d --- /dev/null +++ b/client/src/components/Datepicker/CalendarYear.tsx @@ -0,0 +1,39 @@ +import { Box, SimpleGrid, useStyles } from '@chakra-ui/react'; +import { DateTime } from 'luxon'; +import { MonthBox } from './components/MonthBox'; +import { useDatepickerContext } from './context/DatepickerContext'; + +export interface YearProps { + year: number; + dateCellRender: (date: DateTime) => React.ReactNode; + onDateClicked: (date: DateTime) => void; +} + +export const CalendarYear = ({ dateCellRender, onDateClicked }: YearProps) => { + const styles = useStyles(); + const { monthLabelFormat } = useDatepickerContext(); + + const months = Array.from({ length: 12 }, (_, i) => { + return DateTime.now().set({ month: i + 1 }); + }); + + return ( + + + + + {months.map((month: DateTime) => ( + + {dateCellRender(month)} + + ))} + + + + ); +}; diff --git a/client/src/components/Datepicker/DateRangeInput.tsx b/client/src/components/Datepicker/DateRangeInput.tsx new file mode 100644 index 00000000..bf4c4a96 --- /dev/null +++ b/client/src/components/Datepicker/DateRangeInput.tsx @@ -0,0 +1,232 @@ +import { CalendarIcon } from '@chakra-ui/icons'; +import { Box, Stack, StackDivider, useBreakpointValue, Icon } from '@chakra-ui/react'; +import { END_DATE, FocusedInput, getInputValue, OnDatesChangeProps, START_DATE } from '@datepicker-react/hooks'; +import { Ref, useEffect, useRef, useState } from 'react'; +import { AiOutlineSwapRight } from 'react-icons/ai'; +import { Input, InputProps } from './components'; +import { StylesProvider, StylesProviderProps, useStyleProps } from './context/StylesContext'; +import { Datepicker, DatepickerElement, DatepickerProps } from './Datepicker'; +import { dateRangeInputPhrases, DateRangeInputPhrases } from './phrases'; +import { DateRangeInputStyles, InputDate } from './types'; +import { defaultDisplayFormat } from './utils/formatters'; + +export interface DateRangeInputProps extends Partial, Partial { + startDateInputProps?: Partial; + endDateInputProps?: Partial; + phrases?: DateRangeInputPhrases; + showDivider?: boolean; + placement?: 'top' | 'bottom'; + onFocusChange?(focusedInput: FocusedInput): void; + endIcon?: typeof CalendarIcon; + endId?: string; + endName?: string; + endPlaceholder?: string; + endRef?: Ref; + endShowCalendarIcon?: boolean; + startIcon?: typeof CalendarIcon; + startId?: string; + startName?: string; + startPlaceholder?: string; + startRef?: Ref; + startShowCalendarIcon?: boolean; + allowEditableInputs?: boolean; +} + +export const DateRangeInput = (props: DateRangeInputProps) => { + const { + endDate: endDateProp = null, + startDate: startDateProp = null, + focusedInput: focusedInputProp = null, + displayFormat = defaultDisplayFormat, + endShowCalendarIcon = true, + isDateBlocked = () => false, + minBookingDays = 1, + phrases = dateRangeInputPhrases, + placement = 'bottom', + showClose = true, + showDivider = false, + showResetDates = true, + showSelectedDates = true, + startShowCalendarIcon = true, + onClose = () => {}, + onDatesChange = () => {}, + onFocusChange = () => {}, + styles: customStyles, + overwriteDefaultStyles, + startIcon, + startId, + startName, + startPlaceholder, + startRef, + endId, + endName, + endRef, + endIcon, + endPlaceholder, + changeActiveMonthOnSelect, + dayLabelFormat, + exactMinBookingDays, + firstDayOfWeek, + initialVisibleMonth, + maxBookingDate, + minBookingDate, + monthLabelFormat, + numberOfMonths, + onDayRender, + unavailableDates, + weekdayLabelFormat, + allowEditableInputs, + } = props; + + const datepickerRef = useRef(null); + const datepickerWrapperRef = useRef(null); + + const [startDate, setStartDate] = useState(startDateProp); + const [endDate, setEndDate] = useState(endDateProp); + const [focusedInput, setFocusedInput] = useState(focusedInputProp); + + useEffect(() => { + setStartDate(startDateProp); + setEndDate(endDateProp); + }, [startDateProp, endDateProp]); + + const styleProps = useStyleProps({ + dateRangeInputContainer: { spacing: 1 }, + dateRangeInputDivider: {}, + }); + + useEffect(() => { + if (typeof window !== 'undefined') { + window.addEventListener('click', onClickOutsideHandler); + } + return () => { + window.removeEventListener('click', onClickOutsideHandler); + }; + }); + + function handleOnFocusChange(_focusedInput: FocusedInput) { + setFocusedInput(_focusedInput); + onFocusChange(_focusedInput); + } + + function handleOnDatesChange(data: OnDatesChangeProps) { + setStartDate(data.startDate); + setEndDate(data.endDate); + setFocusedInput(data.focusedInput); + + if (!data.focusedInput) { + onDatesChange(data); + } + } + + function onClickOutsideHandler(event: Event) { + if ( + focusedInput !== null && + datepickerWrapperRef && + datepickerWrapperRef.current && + // @ts-ignore + !datepickerWrapperRef.current.contains(event.target) + ) { + handleOnFocusChange(null); + } + } + + function handleOnClose() { + handleOnFocusChange(null); + onClose(); + } + + function handleInputChange(date: Date) { + if (datepickerRef && datepickerRef.current && datepickerRef.current.onDateSelect) { + datepickerRef.current.onDateSelect(date); + } + } + + const isMobile = useBreakpointValue({ base: true, md: false }); + const vertical = props.vertical || isMobile; + + return ( + + + : undefined} + alignItems="center" + > + handleOnFocusChange(START_DATE)} + value={getInputValue(startDate, displayFormat, '')} + allowEditableInputs={allowEditableInputs} + /> + + + handleOnFocusChange(!startDate ? START_DATE : END_DATE)} + value={getInputValue(endDate, displayFormat, '')} + allowEditableInputs={allowEditableInputs} + /> + + + {focusedInput !== null && ( + + )} + + + + ); +}; diff --git a/client/src/components/Datepicker/DateSingleInput.tsx b/client/src/components/Datepicker/DateSingleInput.tsx new file mode 100644 index 00000000..243e3bcd --- /dev/null +++ b/client/src/components/Datepicker/DateSingleInput.tsx @@ -0,0 +1,182 @@ +import { Box } from '@chakra-ui/react'; +import { getInputValue, OnDatesChangeProps, START_DATE } from '@datepicker-react/hooks'; +import { forwardRef, Ref, useEffect, useRef, useState } from 'react'; +import { Input, InputProps } from './components'; +import { StylesProvider } from './context/StylesContext'; +import { Datepicker, DatepickerElement, DatepickerProps } from './Datepicker'; +import { DateSingleInputPhrases, dateSingleInputPhrases } from './phrases'; +import { InputDate } from './types'; +import { defaultDisplayFormat } from './utils/formatters'; + +export interface OnDateChangeProps { + date: InputDate; + showDatepicker: boolean; +} + +export interface DateSingleInputProps extends Partial, Partial { + onFocusChange?(focusInput: boolean): void; + phrases?: DateSingleInputPhrases; + placement?: 'top' | 'bottom'; + showDatepicker?: boolean; + date?: InputDate; + showResetDate?: boolean; +} + +export const DateSingleInput = forwardRef( + ( + { + date: dateProp = null, + showDatepicker: showDatepickerProp = false, + changeActiveMonthOnSelect, + dayLabelFormat, + displayFormat = defaultDisplayFormat, + firstDayOfWeek, + iconComponent, + id = 'startDate', + initialVisibleMonth, + isDateBlocked = () => false, + maxBookingDate, + minBookingDate, + monthLabelFormat, + name = 'startDate', + numberOfMonths = 1, + onChange = () => {}, + onClick = () => {}, + onClose = () => {}, + onDayRender, + onFocusChange = () => {}, + overwriteDefaultStyles, + phrases = dateSingleInputPhrases, + placeholder, + placement = 'bottom', + showCalendarIcon = true, + showClose = true, + showResetDate = true, + styles, + unavailableDates = [], + value, + vertical = false, + weekdayLabelFormat, + allowEditableInputs = false, + }: DateSingleInputProps, + ref: Ref, + ) => { + const datepickerRef = useRef(null); + const datepickerWrapperRef = useRef(null); + + const [date, setDate] = useState(value ? new Date(value) : dateProp); + const [showDatepicker, setShowDatepicker] = useState(showDatepickerProp); + + useEffect(() => { + onChange(date); + }, [date, onChange]); + + useEffect(() => { + onFocusChange(showDatepicker); + }, [onFocusChange, showDatepicker]); + + useEffect(() => { + if (typeof window !== 'undefined') { + window.addEventListener('click', onClickOutsideHandler); + } + return () => { + window.removeEventListener('click', onClickOutsideHandler); + }; + }); + + function handleOnFocusChange(show: boolean) { + setShowDatepicker(show); + } + + function onClickOutsideHandler(event: Event) { + if ( + showDatepicker && + datepickerWrapperRef && + datepickerWrapperRef.current && + // @ts-ignore + !datepickerWrapperRef.current.contains(event.target) + ) { + handleOnFocusChange(false); + } + } + + function handleDatepickerClose() { + handleOnFocusChange(false); + onClose(); + } + + function handleOnDatesChange(data: OnDatesChangeProps) { + handleOnFocusChange(data.focusedInput !== null); + setDate(data.startDate); + } + + function handleInputChange(date: Date) { + if (datepickerRef && datepickerRef.current && datepickerRef.current.onDateSelect) { + datepickerRef.current.onDateSelect(date); + } + } + + return ( + + + { + handleOnFocusChange(true); + onClick(); + }} + disableAccessibility={false} + iconComponent={iconComponent} + allowEditableInputs={allowEditableInputs} + /> + + + {showDatepicker && ( + + )} + + + + ); + }, +); diff --git a/client/src/components/Datepicker/Datepicker.tsx b/client/src/components/Datepicker/Datepicker.tsx new file mode 100644 index 00000000..a7c13355 --- /dev/null +++ b/client/src/components/Datepicker/Datepicker.tsx @@ -0,0 +1,226 @@ +import { ArrowForwardIcon } from '@chakra-ui/icons'; +import { Box, Flex, HStack, Stack, useBreakpointValue, useColorModeValue } from '@chakra-ui/react'; +import { END_DATE, MonthType, START_DATE, useDatepicker, UseDatepickerProps } from '@datepicker-react/hooks'; +import { forwardRef, ReactNode, Ref, useImperativeHandle, useRef } from 'react'; +import { ActionButton, CloseButton, Month, ResetDatesButton, SelectedDate } from './components'; +import { DatepickerFormatProps, DatepickerProvider } from './context/DatepickerContext'; +import { StylesProvider, StylesProviderProps, useStyleProps } from './context/StylesContext'; +import { DatepickerPhrases, datepickerPhrases } from './phrases'; +import { DatepickerComponentStyles } from './types'; +import { dayLabelFormatFn, defaultDisplayFormat, monthLabelFormatFn, weekdayLabelFormatFn } from './utils/formatters'; + +export interface DatepickerElement { + onDateSelect?(date: Date): void; +} + +export interface DatepickerProps + extends Partial, + Partial, + Partial { + displayFormat?: string; + onClose?(): void; + onDayRender?(date: Date): ReactNode; + phrases?: DatepickerPhrases; + showClose?: boolean; + showResetDates?: boolean; + showSelectedDates?: boolean; + vertical?: boolean; +} + +export const Datepicker = forwardRef((props: DatepickerProps, ref: Ref) => { + const { + changeActiveMonthOnSelect, + dayLabelFormat, + displayFormat = defaultDisplayFormat, + endDate = null, + exactMinBookingDays = false, + firstDayOfWeek, + focusedInput = null, + initialVisibleMonth, + isDateBlocked = () => false, + maxBookingDate, + minBookingDate, + minBookingDays = 1, + monthLabelFormat, + numberOfMonths = 2, + onClose = () => {}, + onDatesChange = () => {}, + onDayRender, + overwriteDefaultStyles, + phrases = datepickerPhrases, + showClose = true, + showResetDates = true, + showSelectedDates = true, + startDate = null, + styles: customStyles, + unavailableDates = [], + weekdayLabelFormat, + } = props; + + const dp = useDatepicker({ + changeActiveMonthOnSelect, + endDate, + exactMinBookingDays, + firstDayOfWeek, + focusedInput, + initialVisibleMonth, + isDateBlocked, + maxBookingDate, + minBookingDate, + minBookingDays, + numberOfMonths, + onDatesChange, + startDate, + unavailableDates, + }); + + useImperativeHandle(ref, () => ({ + onDateSelect: (date: Date) => { + dp.onDateSelect(date); + }, + })); + + const monthGridRef = useRef(null); + + function scrollTopToMonthGrid() { + if (monthGridRef && monthGridRef.current && vertical) { + monthGridRef.current.scrollTop = 0; + } + } + + function _goToNextMonths() { + dp.goToNextMonths(); + scrollTopToMonthGrid(); + } + + function _goToPreviousMonths() { + dp.goToPreviousMonths(); + scrollTopToMonthGrid(); + } + + const isMobile = useBreakpointValue({ base: true, md: false }); + const vertical = props.vertical || isMobile; + + const styleProps = useStyleProps({ + datepickerContainer: { + background: useColorModeValue('gray.100', 'gray.800'), + borderRadius: 'md', + position: 'relative', + width: 'fit-content', + shadow: 'md', + px: [3, 5], + py: [5, 7], + zIndex: 1, + }, + monthsWrapper: { + spacing: [0, 8], + }, + buttonsWrapper: { + spacing: [1, 3], + }, + arrowIcon: { + my: [5, 15], + color: 'gray.500', + }, + datepickerHeader: { + justifyContent: 'space-between', + pt: [1, 3], + }, + }); + + return ( + + + + {showClose && } + + {showSelectedDates && ( + + + + + + + + + + )} + + { + if (dp.hoveredDate) { + dp.onDateHover(null); + } + }} + > + {dp.activeMonths.map((month: MonthType) => ( + + ))} + + + + + + + + {showResetDates && ( + + )} + + + + + + ); +}); diff --git a/client/src/components/Datepicker/MonthSelect.tsx b/client/src/components/Datepicker/MonthSelect.tsx new file mode 100644 index 00000000..c61932ca --- /dev/null +++ b/client/src/components/Datepicker/MonthSelect.tsx @@ -0,0 +1,27 @@ +import { Select } from '@chakra-ui/react'; + +export const MonthSelect = ({ value, onChange }) => { + const months = [ + 'January', + 'February', + 'March', + 'April', + 'May', + 'June', + 'July', + 'August', + 'September', + 'October', + 'November', + 'December', + ]; + return ( + + ); +}; diff --git a/client/src/components/Datepicker/YearSelect.tsx b/client/src/components/Datepicker/YearSelect.tsx new file mode 100644 index 00000000..9c4be7cf --- /dev/null +++ b/client/src/components/Datepicker/YearSelect.tsx @@ -0,0 +1,17 @@ +import { Select } from '@chakra-ui/react'; +import { range } from 'lodash'; + +export const YearSelect = ({ value, onChange }) => { + var currentYear = new Date().getFullYear(); + const years = range(2016, currentYear + 1); + + return ( + + ); +}; diff --git a/client/src/components/Datepicker/components/ActionButton.tsx b/client/src/components/Datepicker/components/ActionButton.tsx new file mode 100644 index 00000000..1adfb6a5 --- /dev/null +++ b/client/src/components/Datepicker/components/ActionButton.tsx @@ -0,0 +1,41 @@ +import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from '@chakra-ui/icons'; +import { IconButton, IconButtonProps, Tooltip } from '@chakra-ui/react'; + +import { useStyleProps } from '../context/StylesContext'; +import { ActionButtonStyles } from '../types'; + +export interface ActionButtonProps extends Omit { + direction?: 'up' | 'right' | 'down' | 'left'; + tooltipLabel; +} + +export const ActionButton = ({ direction, tooltipLabel, ...props }: ActionButtonProps) => { + let IconComponent = ChevronLeftIcon; + + const styleProps = useStyleProps({ + actionButton: { + position: 'relative', + }, + }); + + if (direction === 'up') { + IconComponent = ChevronUpIcon; + } else if (direction === 'right') { + IconComponent = ChevronRightIcon; + } else if (direction === 'down') { + IconComponent = ChevronDownIcon; + } else if (direction === 'left') { + IconComponent = ChevronLeftIcon; + } + + return ( + + } + {...props} + {...styleProps.actionButton} + /> + + ); +}; diff --git a/client/src/components/Datepicker/components/CloseButton.tsx b/client/src/components/Datepicker/components/CloseButton.tsx new file mode 100644 index 00000000..ce278945 --- /dev/null +++ b/client/src/components/Datepicker/components/CloseButton.tsx @@ -0,0 +1,17 @@ +import { CloseButton as ChakraCloseButton, CloseButtonProps as ChakraCloseButtonProps } from '@chakra-ui/react'; +import { useStyleProps } from '../context/StylesContext'; +import { CloseButtonStyles } from '../types'; + +export interface CloseButtonProps extends ChakraCloseButtonProps {} + +export const CloseButton = (props: CloseButtonProps) => { + const styleProps = useStyleProps({ + closeButton: { + top: 1, + right: 1, + zIndex: 1, + position: 'absolute', + }, + }); + return ; +}; diff --git a/client/src/components/Datepicker/components/Day.tsx b/client/src/components/Datepicker/components/Day.tsx new file mode 100644 index 00000000..fa29bf7d --- /dev/null +++ b/client/src/components/Datepicker/components/Day.tsx @@ -0,0 +1,230 @@ +import { Box, Button, useColorModeValue } from '@chakra-ui/react'; +import { isEndDate, isStartDate, useDay } from '@datepicker-react/hooks'; +import { useMemo, useRef } from 'react'; +import { OnDayRenderType, useDatepickerContext } from '../context/DatepickerContext'; +import { useStyleProps } from '../context/StylesContext'; +import { DayState, DayStyles } from '../types'; + +function getColor( + { isSelected, isWithinHoverRange, isFirst, isLast }: OnDayRenderType, + { base, normal, rangeHover, selected, firstOrLast, first, last }: DayState, +) { + let style = base; + if (!isSelected && !isWithinHoverRange) style = { ...style, ...normal }; + if (isSelected) style = { ...style, ...selected }; + if (isWithinHoverRange) style = { ...style, ...rangeHover }; + if (isFirst || isLast) style = { ...style, ...firstOrLast }; + if (isFirst) style = { ...style, ...first }; + if (isLast) style = { ...style, ...last }; + return style; +} + +interface DayProps { + day: string; + date: Date; +} + +export function Day({ day, date }: DayProps) { + const dayRef = useRef(null); + + const { + focusedDate, + isDateFocused, + isDateSelected, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateSelect, + onDateFocus, + onDateHover, + onDayRender, + startDate, + endDate, + } = useDatepickerContext(); + + const dayProps = useDay({ + date, + focusedDate, + isDateFocused, + isDateSelected, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateFocus, + onDateSelect, + onDateHover, + dayRef, + }); + + const { + onClick, + onKeyDown, + onMouseEnter, + tabIndex, + isSelectedStartOrEnd, + isSelected, + isWithinHoverRange, + disabledDate, + } = dayProps; + + const styleProps = useStyleProps({ + day: { + base: { + height: ['32px', '48px'], + width: ['32px', '48px'], + minWidth: 'unset', + fontWeight: 'medium', + fontSize: ['sm', 'md'], + border: '2px solid', + textColor: useColorModeValue('gray.900', 'white'), + borderRadius: '100%', + borderColor: 'transparent', + background: 'transparent', + overflow: 'hidden', + _hover: { + borderColor: 'transparent', + background: 'transparent', + }, + }, + normal: { + _hover: { + borderColor: useColorModeValue('black', 'white'), + }, + }, + rangeHover: { + _hover: { + borderColor: useColorModeValue('black', 'white'), + }, + }, + selected: { + _hover: { + borderColor: useColorModeValue('black', 'white'), + }, + }, + firstOrLast: { + textColor: useColorModeValue('white', 'black'), + background: useColorModeValue('black', 'white'), + _hover: { + textColor: useColorModeValue('white', 'black'), + background: useColorModeValue('black', 'white'), + }, + }, + first: {}, + last: {}, + }, + dayContainer: { + base: { + height: ['32px', '48px'], + width: ['32px', '48px'], + _hover: { + borderRightRadius: '100%', + }, + }, + normal: {}, + rangeHover: { + background: useColorModeValue('gray.100', 'gray.500'), + _hover: { + borderRightRadius: '100%', + }, + }, + selected: { + background: useColorModeValue('gray.100', 'gray.500'), + _hover: { + borderRightRadius: '0%', + }, + }, + firstOrLast: { + background: useColorModeValue('gray.100', 'gray.500'), + }, + first: { + borderLeftRadius: '100%', + }, + last: { + borderRightRadius: '100%', + _hover: { + borderRightRadius: '100%', + }, + }, + }, + }); + + const isFirst = isStartDate(date, startDate); + const isLast = isEndDate(date, endDate); + + const containerStyle = useMemo( + () => + getColor( + { + isFirst, + isLast, + isSelected, + isWithinHoverRange, + isSelectedStartOrEnd, + disabledDate, + }, + { + base: styleProps.dayContainer.base, + normal: styleProps.dayContainer.normal, + rangeHover: styleProps.dayContainer.rangeHover, + selected: styleProps.dayContainer.selected, + first: styleProps.dayContainer.first, + last: styleProps.dayContainer.last, + firstOrLast: styleProps.dayContainer.firstOrLast, + }, + ), + [isFirst, isLast, isSelected, isWithinHoverRange, isSelectedStartOrEnd, disabledDate, styleProps], + ); + + const buttonStyle = useMemo( + () => + getColor( + { + isFirst, + isLast, + isSelected, + isWithinHoverRange, + isSelectedStartOrEnd, + disabledDate, + }, + { + base: styleProps.day.base, + normal: styleProps.day.normal, + rangeHover: styleProps.day.rangeHover, + selected: styleProps.day.selected, + first: styleProps.day.first, + last: styleProps.day.last, + firstOrLast: styleProps.day.firstOrLast, + }, + ), + [isFirst, isLast, isSelected, isWithinHoverRange, isSelectedStartOrEnd, disabledDate, styleProps], + ); + + return ( + + + + ); +} diff --git a/client/src/components/Datepicker/components/DayBox.tsx b/client/src/components/Datepicker/components/DayBox.tsx new file mode 100644 index 00000000..5eb33c2e --- /dev/null +++ b/client/src/components/Datepicker/components/DayBox.tsx @@ -0,0 +1,81 @@ +import { Box, Text } from '@chakra-ui/react'; +import { isEndDate, isStartDate, useDay } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; +import { useDatepickerContext } from '../context/DatepickerContext'; +import { DayWrapper } from './DayWrapper'; + +interface DayProps { + day: string; + date: Date; + children: React.ReactNode; + onDateClicked: (date: DateTime) => void; +} + +function getVariant({ isSelected, isWithinHoverRange, isFirst, isLast }) { + if (!isSelected && !isWithinHoverRange) return 'normal'; + if (isSelected) return 'selected'; + if (isWithinHoverRange) return 'rangeHover'; + if (isFirst || isLast) return 'firstOrLast'; + if (isFirst) return 'first'; + if (isLast) return 'last'; + + return 'normal'; +} +export function DayBox({ day, date, onDateClicked, children }: DayProps) { + const { + focusedDate, + isDateFocused, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateSelect, + onDateFocus, + onDateHover, + startDate, + endDate, + } = useDatepickerContext(); + + const dayProps = useDay({ + date, + focusedDate, + isDateFocused, + isDateSelected: isDateFocused, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateFocus, + onDateSelect, + onDateHover, + }); + + const { onKeyDown, onMouseEnter, tabIndex, isSelected, isWithinHoverRange, disabledDate } = dayProps; + + const isFirst = isStartDate(date, startDate); + const isLast = isEndDate(date, endDate); + + const variant = getVariant({ + isSelected, + isWithinHoverRange, + isFirst, + isLast, + }); + + return ( + onDateClicked(DateTime.fromJSDate(date))} + onKeyDown={onKeyDown} + onMouseEnter={onMouseEnter} + tabIndex={tabIndex} + disabled={disabledDate} + aria-label={`Day-${date.toDateString()}`} + > + + + {day} + + + {children} + + ); +} diff --git a/client/src/components/Datepicker/components/DayWrapper.tsx b/client/src/components/Datepicker/components/DayWrapper.tsx new file mode 100644 index 00000000..9236f4ad --- /dev/null +++ b/client/src/components/Datepicker/components/DayWrapper.tsx @@ -0,0 +1,6 @@ +import { Box, useStyleConfig } from '@chakra-ui/react'; + +export const DayWrapper = ({ variant, ...rest }) => { + const styles = useStyleConfig('CalendarDay', { variant }); + return ; +}; diff --git a/client/src/components/Datepicker/components/Input.tsx b/client/src/components/Datepicker/components/Input.tsx new file mode 100644 index 00000000..e41106fc --- /dev/null +++ b/client/src/components/Datepicker/components/Input.tsx @@ -0,0 +1,129 @@ +import { CalendarIcon } from '@chakra-ui/icons'; +import { + Icon, + Input as ChakraInput, + InputGroup, + InputRightElement, + InputProps as ChakraInputProps, +} from '@chakra-ui/react'; +import { parseDate } from '@datepicker-react/hooks'; +import { ChangeEvent, FocusEvent, forwardRef, Ref, useEffect, useRef, useState } from 'react'; +import { useStyleProps } from '../context/StylesContext'; +import { InputComponentStyles, InputDate } from '../types'; +import { defaultDisplayFormat } from '../utils/formatters'; +import { getStateStyle } from '../utils/getStateStyle'; + +export interface InputProps { + allowEditableInputs?: boolean; + dateFormat?: string; + disableAccessibility?: boolean; + iconComponent?: typeof CalendarIcon; + id?: string; + isActive?: boolean; + name?: string; + onChange?(date: InputDate): void; + onClick?(): void; + placeholder?: string; + showCalendarIcon?: boolean; + value?: string; +} + +interface BaseProps extends Omit, InputProps {} + +export const Input = forwardRef((props: BaseProps, inputRef: Ref) => { + const { + dateFormat = defaultDisplayFormat, + disableAccessibility, + iconComponent = CalendarIcon, + id, + isActive = false, + name, + onChange = () => {}, + onClick = () => {}, + placeholder, + showCalendarIcon = true, + value, + allowEditableInputs = false, + + ...inputProps + } = props; + + const ref = useRef(null); + + const [searchString, setSearchString] = useState(value); + + const styleProps = useStyleProps({ + inputComponentInputGroup: { + base: {}, + active: {}, + }, + inputComponentInput: { + base: {}, + active: {}, + }, + inputComponentIcon: { + base: {}, + active: {}, + }, + inputComponentInputAddon: { + base: {}, + active: {}, + }, + }); + + // Note: value was updated outside of InputComponent + useEffect(() => { + setSearchString(value); + }, [value]); + + function handleOnChange(e: ChangeEvent) { + const dateValue = e.target.value; + setSearchString(dateValue); + + if (typeof ref.current === 'number') { + clearTimeout(ref.current); + } + + ref.current = setTimeout(() => { + onClick(); + const parsedDate = parseDate(dateValue, dateFormat, new Date()); + const isValidDate = !isNaN(parsedDate.getDate()); + + if (isValidDate) { + onChange(parsedDate); + } else { + onChange(null); + } + }, 1000); + } + + function handleOnFocus(_e: FocusEvent) { + onClick(); + } + + return ( + + {showCalendarIcon && ( + } + /> + )} + + + ); +}); diff --git a/client/src/components/Datepicker/components/Month.tsx b/client/src/components/Datepicker/components/Month.tsx new file mode 100644 index 00000000..9fd51c7b --- /dev/null +++ b/client/src/components/Datepicker/components/Month.tsx @@ -0,0 +1,69 @@ +import { Box, Flex, SimpleGrid, Text } from '@chakra-ui/react'; +import { CalendarDay, useMonth } from '@datepicker-react/hooks'; + +import { useDatepickerContext } from '../context/DatepickerContext'; +import { useStyleProps } from '../context/StylesContext'; +import { MonthStyles } from '../types'; +import { Day } from './Day'; + +export interface MonthProps { + year: number; + month: number; +} + +export const Month = ({ year, month }: MonthProps) => { + const styleProps = useStyleProps({ + monthContainer: {}, + monthMonthLabel: { + justifyContent: 'center', + fontWeight: 'bold', + mb: 6, + fontSize: ['md', 'lg'], + }, + monthWeekdayLabel: { + justifyContent: 'center', + color: 'gray.500', + mb: 4, + fontSize: ['sm', 'md'], + }, + monthDayGrid: { + rowGap: 1, + }, + emptyDay: {}, + }); + + const { dayLabelFormat, monthLabelFormat, weekdayLabelFormat, firstDayOfWeek } = useDatepickerContext(); + + const { days, weekdayLabels, monthLabel } = useMonth({ + year, + month, + dayLabelFormat, + monthLabelFormat, + weekdayLabelFormat, + firstDayOfWeek, + }); + + return ( + + + {monthLabel} + + + {weekdayLabels.map((weekdayLabel: string) => ( + + {weekdayLabel} + + ))} + + + {days.map((day: CalendarDay, index: number) => + typeof day === 'object' ? ( + + ) : ( +
    + ), + )} + + + ); +}; diff --git a/client/src/components/Datepicker/components/MonthBox.tsx b/client/src/components/Datepicker/components/MonthBox.tsx new file mode 100644 index 00000000..9dea1057 --- /dev/null +++ b/client/src/components/Datepicker/components/MonthBox.tsx @@ -0,0 +1,81 @@ +import { Box, Text } from '@chakra-ui/react'; +import { isEndDate, isStartDate, useDay } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; +import { useDatepickerContext } from '../context/DatepickerContext'; +import { DayWrapper } from './DayWrapper'; + +interface DayProps { + month: string; + date: Date; + children: React.ReactNode; + onDateClicked: (date: DateTime) => void; +} + +function getVariant({ isSelected, isWithinHoverRange, isFirst, isLast }) { + if (!isSelected && !isWithinHoverRange) return 'normal'; + if (isSelected) return 'selected'; + if (isWithinHoverRange) return 'rangeHover'; + if (isFirst || isLast) return 'firstOrLast'; + if (isFirst) return 'first'; + if (isLast) return 'last'; + + return 'normal'; +} +export function MonthBox({ month, date, onDateClicked, children }: DayProps) { + const { + focusedDate, + isDateFocused, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateSelect, + onDateFocus, + onDateHover, + startDate, + endDate, + } = useDatepickerContext(); + + const dayProps = useDay({ + date, + focusedDate, + isDateFocused, + isDateSelected: isDateFocused, + isDateHovered, + isDateBlocked, + isFirstOrLastSelectedDate, + onDateFocus, + onDateSelect, + onDateHover, + }); + + const { onKeyDown, onMouseEnter, tabIndex, isSelected, isWithinHoverRange, disabledDate } = dayProps; + + const isFirst = isStartDate(date, startDate); + const isLast = isEndDate(date, endDate); + + const variant = getVariant({ + isSelected, + isWithinHoverRange, + isFirst, + isLast, + }); + + return ( + onDateClicked(DateTime.fromJSDate(date))} + onKeyDown={onKeyDown} + onMouseEnter={onMouseEnter} + tabIndex={tabIndex} + disabled={disabledDate} + aria-label={`Day-${date.toDateString()}`} + > + + + {month} + + + {children} + + ); +} diff --git a/client/src/components/Datepicker/components/ResetDatesButton.tsx b/client/src/components/Datepicker/components/ResetDatesButton.tsx new file mode 100644 index 00000000..235009ae --- /dev/null +++ b/client/src/components/Datepicker/components/ResetDatesButton.tsx @@ -0,0 +1,34 @@ +import { RepeatIcon } from '@chakra-ui/icons'; +import { Button } from '@chakra-ui/react'; + +import { useDatepickerContext } from '../context/DatepickerContext'; +import { useStyleProps } from '../context/StylesContext'; +import { ResetDatesButtonStyles } from '../types'; + +interface ResetDatesProps { + onResetDates(): void; + text: string; +} + +export function ResetDatesButton({ onResetDates, text }: ResetDatesProps) { + const { phrases } = useDatepickerContext(); + + const styleProps = useStyleProps({ + resetDatesButton: {}, + }); + + return ( + + ); +} diff --git a/client/src/components/Datepicker/components/SelectedDate.tsx b/client/src/components/Datepicker/components/SelectedDate.tsx new file mode 100644 index 00000000..f147246e --- /dev/null +++ b/client/src/components/Datepicker/components/SelectedDate.tsx @@ -0,0 +1,52 @@ +import { Stack, Text } from '@chakra-ui/react'; +import { getInputValue } from '@datepicker-react/hooks'; +import { useDatepickerContext } from '../context/DatepickerContext'; +import { useStyleProps } from '../context/StylesContext'; +import { InputDate, SelectDateStyles } from '../types'; +import { getStateStyle } from '../utils/getStateStyle'; + +export interface SelectedDateProps { + isFocused: boolean; + date: InputDate; +} + +export const SelectedDate = ({ isFocused, date }: SelectedDateProps) => { + const { phrases, displayFormat } = useDatepickerContext(); + + const styleProps = useStyleProps({ + selectDateContainer: { + base: { + width: '100%', + borderBottom: '2px solid', + borderColor: 'gray.300', + paddingBottom: [1, 3], + }, + active: { + borderColor: 'blue.400', + }, + }, + selectDateText: { + base: { + fontSize: 'xs', + color: 'gray.500', + }, + active: {}, + }, + selectDateDateText: { + base: { + fontWeight: 'bold', + fontSize: ['sm', 'md', 'lg'], + }, + active: {}, + }, + }); + + return ( + + {phrases.datepickerStartDateLabel} + + {getInputValue(date, displayFormat, phrases.datepickerStartDatePlaceholder)} + + + ); +}; diff --git a/client/src/components/Datepicker/components/index.ts b/client/src/components/Datepicker/components/index.ts new file mode 100644 index 00000000..4a26b1a9 --- /dev/null +++ b/client/src/components/Datepicker/components/index.ts @@ -0,0 +1,7 @@ +export * from './ActionButton' +export * from './CloseButton' +export * from './Day' +export * from './Input' +export * from './Month' +export * from './ResetDatesButton' +export * from './SelectedDate' diff --git a/client/src/components/Datepicker/context/DatepickerContext.tsx b/client/src/components/Datepicker/context/DatepickerContext.tsx new file mode 100644 index 00000000..d63c9f73 --- /dev/null +++ b/client/src/components/Datepicker/context/DatepickerContext.tsx @@ -0,0 +1,96 @@ +import { FocusedInput, FormatFunction, useDatepicker } from '@datepicker-react/hooks'; +import { createContext, ReactNode, useContext } from 'react'; +import { datepickerPhrases, DatepickerPhrases } from '../phrases'; +import { InputDate } from '../types'; +import { dayLabelFormatFn, defaultDisplayFormat, monthLabelFormatFn, weekdayLabelFormatFn } from '../utils/formatters'; + +export type UseDatepickerReturnType = ReturnType; + +export interface DatepickerFormatProps { + dayLabelFormat: typeof dayLabelFormatFn; + weekdayLabelFormat: typeof weekdayLabelFormatFn; + monthLabelFormat: typeof monthLabelFormatFn; +} + +export type OnDayRenderType = { + isFirst: boolean; + isLast: boolean; + isSelected: boolean; + isWithinHoverRange: boolean; + isSelectedStartOrEnd: boolean; + disabledDate: boolean; +}; + +export interface DatepickerContextBaseProps { + displayFormat: FormatFunction | string; + startDate: InputDate; + endDate: InputDate; + phrases: DatepickerPhrases; + focusedInput: FocusedInput; + onDayRender?(date: Date, state: OnDayRenderType): ReactNode; + children?: ReactNode; +} + +export interface DatepickerContextProps + extends DatepickerContextBaseProps, + DatepickerFormatProps, + UseDatepickerReturnType {} + +export interface DatepickerProviderProps extends Partial {} + +const defaultBase: DatepickerContextBaseProps = { + startDate: null, + endDate: null, + focusedInput: null, + onDayRender: undefined, + displayFormat: defaultDisplayFormat, + phrases: datepickerPhrases, +}; + +const defaultFormatters: DatepickerFormatProps = { + monthLabelFormat: monthLabelFormatFn, + weekdayLabelFormat: weekdayLabelFormatFn, + dayLabelFormat: dayLabelFormatFn, +}; + +const defaultUseDatepicker: UseDatepickerReturnType = { + numberOfMonths: 2, + activeMonths: [], + firstDayOfWeek: 0, + focusedDate: null, + hoveredDate: null, + goToDate: () => {}, + goToNextMonths: () => {}, + goToNextMonthsByOneMonth: () => {}, + goToNextYear: () => {}, + goToPreviousMonths: () => {}, + goToPreviousMonthsByOneMonth: () => {}, + goToPreviousYear: () => {}, + isDateBlocked: () => false, + isDateFocused: () => false, + isDateHovered: () => false, + isDateSelected: () => false, + isEndDate: () => false, + isFirstOrLastSelectedDate: () => false, + isStartDate: () => false, + onDateFocus: () => {}, + onDateHover: () => {}, + onDateSelect: () => {}, + onResetDates: () => {}, +}; + +export const datepickerContextDefaultValue: DatepickerContextProps = { + ...defaultBase, + ...defaultFormatters, + ...defaultUseDatepicker, +}; + +export const DatepickerContext = createContext(datepickerContextDefaultValue); + +export const useDatepickerContext = () => useContext(DatepickerContext); + +export const DatepickerProvider = ({ children, ...props }: DatepickerProviderProps) => ( + + {children} + +); diff --git a/client/src/components/Datepicker/context/StylesContext.tsx b/client/src/components/Datepicker/context/StylesContext.tsx new file mode 100644 index 00000000..953937b2 --- /dev/null +++ b/client/src/components/Datepicker/context/StylesContext.tsx @@ -0,0 +1,104 @@ +import { createContext, FC, ReactNode, useContext } from 'react'; +import { DatepickerStyles } from '../types'; +import merge from '../utils/deepmerge'; +import pick from '../utils/pick'; + +export interface StylesContextProps { + overwriteDefaultStyles: boolean; + styles: DatepickerStyles; +} + +export interface StylesProviderProps { + overwriteDefaultStyles?: boolean; + styles?: Partial; + children: ReactNode; +} + +export const emptyStylesObject: DatepickerStyles = { + actionButton: {}, + arrowIcon: {}, + buttonsWrapper: {}, + closeButton: {}, + datepickerContainer: {}, + dateRangeInputContainer: {}, + dateRangeInputDivider: {}, + day: { + base: {}, + normal: {}, + rangeHover: {}, + selected: {}, + first: {}, + firstOrLast: {}, + last: {}, + }, + dayContainer: { + base: {}, + normal: {}, + rangeHover: {}, + selected: {}, + first: {}, + firstOrLast: {}, + last: {}, + }, + inputComponentIcon: { + active: {}, + base: {}, + }, + inputComponentInput: { + active: {}, + base: {}, + }, + inputComponentInputAddon: { + active: {}, + base: {}, + }, + inputComponentInputGroup: { + active: {}, + base: {}, + }, + monthContainer: {}, + monthDayGrid: {}, + monthMonthLabel: {}, + monthsWrapper: {}, + monthWeekdayLabel: {}, + resetDatesButton: {}, + selectDateContainer: { + active: {}, + base: {}, + }, + selectDateDateText: { + active: {}, + base: {}, + }, + selectDateText: { + active: {}, + base: {}, + }, + datepickerHeader: {}, + emptyDay: {}, +}; + +export const StylesContext = createContext({ + styles: emptyStylesObject, + overwriteDefaultStyles: false, +}); + +export const StylesProvider: FC = ({ + children, + overwriteDefaultStyles = false, + styles = emptyStylesObject, +}) => ( + + {children} + +); + +export function useStyleProps = Partial>( + inlineStyles: InitialStyles, +) { + const { styles, overwriteDefaultStyles } = useContext(StylesContext); + const keys = Object.keys(inlineStyles) as (keyof DatepickerStyles)[]; + const filteredStyles = pick(styles, keys); + const result = merge(filteredStyles, !overwriteDefaultStyles ? inlineStyles : ({} as InitialStyles)); + return result; +} diff --git a/client/src/components/Datepicker/index.ts b/client/src/components/Datepicker/index.ts new file mode 100644 index 00000000..470b4c50 --- /dev/null +++ b/client/src/components/Datepicker/index.ts @@ -0,0 +1,6 @@ +export * from './Datepicker' +export * from './DateRangeInput' +export * from './DateSingleInput' +export * from './phrases' +export * from './types' +export * from './utils/formatters' diff --git a/client/src/components/Datepicker/phrases.ts b/client/src/components/Datepicker/phrases.ts new file mode 100644 index 00000000..c7bb74e6 --- /dev/null +++ b/client/src/components/Datepicker/phrases.ts @@ -0,0 +1,52 @@ +export interface DatepickerPhrases { + datepickerStartDatePlaceholder: string + datepickerStartDateLabel: string + datepickerEndDateLabel: string + datepickerEndDatePlaceholder: string + resetDates: string + close: string +} + +export interface DateRangeInputPhrases extends DatepickerPhrases { + startDateAriaLabel: string + endDateAriaLabel: string + startDatePlaceholder: string + endDatePlaceholder: string +} + +export interface DateRangeInputPhrases extends DatepickerPhrases { + startDateAriaLabel: string + endDateAriaLabel: string + startDatePlaceholder: string + endDatePlaceholder: string +} + +export interface DateSingleInputPhrases extends DatepickerPhrases { + dateAriaLabel: string + datePlaceholder: string +} + +export const datepickerPhrases: DatepickerPhrases = { + datepickerStartDatePlaceholder: 'Select', + datepickerStartDateLabel: 'Start date:', + datepickerEndDatePlaceholder: 'Select', + datepickerEndDateLabel: 'End date:', + resetDates: 'Reset dates', + close: 'Close', +} + +export const dateRangeInputPhrases: DateRangeInputPhrases = { + ...datepickerPhrases, + + startDateAriaLabel: 'Start date', + endDateAriaLabel: 'End date', + + startDatePlaceholder: 'Start date', + endDatePlaceholder: 'End date', +} + +export const dateSingleInputPhrases: DateSingleInputPhrases = { + ...datepickerPhrases, + dateAriaLabel: 'Select date', + datePlaceholder: 'Select date', +} diff --git a/client/src/components/Datepicker/types/index.ts b/client/src/components/Datepicker/types/index.ts new file mode 100644 index 00000000..115db144 --- /dev/null +++ b/client/src/components/Datepicker/types/index.ts @@ -0,0 +1,2 @@ +export * from './styles' +export * from './utils' diff --git a/client/src/components/Datepicker/types/styles.ts b/client/src/components/Datepicker/types/styles.ts new file mode 100644 index 00000000..43713d6c --- /dev/null +++ b/client/src/components/Datepicker/types/styles.ts @@ -0,0 +1,88 @@ +import { + BoxProps, + ButtonProps, + CloseButtonProps, + FlexProps, + IconButtonProps, + IconProps, + InputAddonProps, + InputGroupProps, + InputProps, + SimpleGridProps, + StackDividerProps, + StackProps, +} from '@chakra-ui/react'; + +export type StateProp = { base: T; active?: T }; + +export interface ActionButtonStyles { + actionButton: Partial; +} + +export interface CloseButtonStyles { + closeButton: Partial; +} + +export interface DatepickerComponentStyles { + datepickerContainer: BoxProps; + monthsWrapper: StackProps; + buttonsWrapper: StackProps; + arrowIcon: Omit; + datepickerHeader: FlexProps; +} + +export interface DayState { + base: T; + normal: T; + rangeHover: T; + selected: T; + firstOrLast: T; + first: T; + last: T; +} + +export interface DayStyles { + day: DayState; + dayContainer: DayState; +} + +export interface InputComponentStyles { + inputComponentInputGroup: StateProp; + inputComponentInput: StateProp; + inputComponentIcon: StateProp>; + inputComponentInputAddon: StateProp; +} + +export interface MonthStyles { + monthContainer: BoxProps; + monthMonthLabel: BoxProps; + monthWeekdayLabel: BoxProps; + emptyDay: BoxProps; + monthDayGrid: SimpleGridProps; +} + +export interface ResetDatesButtonStyles { + resetDatesButton: ButtonProps; +} + +export interface SelectDateStyles { + selectDateContainer: StateProp; + selectDateText: StateProp; + selectDateDateText: StateProp; +} + +export interface DateRangeInputStyles { + dateRangeInputContainer: StackProps; + dateRangeInputDivider: StackDividerProps; +} + +export interface DatepickerStyles + extends ActionButtonStyles, + CloseButtonStyles, + DatepickerComponentStyles, + DayStyles, + InputComponentStyles, + MonthStyles, + ResetDatesButtonStyles, + SelectDateStyles, + DateRangeInputStyles {} diff --git a/client/src/components/Datepicker/types/utils.ts b/client/src/components/Datepicker/types/utils.ts new file mode 100644 index 00000000..a930cb7f --- /dev/null +++ b/client/src/components/Datepicker/types/utils.ts @@ -0,0 +1 @@ +export type InputDate = Date | null diff --git a/client/src/components/Datepicker/utils/deepmerge.ts b/client/src/components/Datepicker/utils/deepmerge.ts new file mode 100644 index 00000000..a8f35c5e --- /dev/null +++ b/client/src/components/Datepicker/utils/deepmerge.ts @@ -0,0 +1,41 @@ +// source: https://github.com/voodoocreation/ts-deepmerge/blob/master/src/index.ts +interface IObject { + [key: string]: any +} + +type TUnionToIntersection = (U extends any +? (k: U) => void +: never) extends (k: infer I) => void + ? I + : never + +// istanbul ignore next +const isObject = (obj: any) => { + if (typeof obj === 'object' && obj !== null) { + if (typeof Object.getPrototypeOf === 'function') { + const prototype = Object.getPrototypeOf(obj) + return prototype === Object.prototype || prototype === null + } + + return Object.prototype.toString.call(obj) === '[object Object]' + } + + return false +} + +const merge = (...objects: T): TUnionToIntersection => + objects.reduce((result, current) => { + Object.keys(current).forEach(key => { + if (Array.isArray(result[key]) && Array.isArray(current[key])) { + result[key] = Array.from(new Set(result[key].concat(current[key]))) + } else if (isObject(result[key]) && isObject(current[key])) { + result[key] = merge(result[key], current[key]) + } else { + result[key] = current[key] + } + }) + + return result + }, {}) as any + +export default merge diff --git a/client/src/components/Datepicker/utils/formatters.ts b/client/src/components/Datepicker/utils/formatters.ts new file mode 100644 index 00000000..61c8e866 --- /dev/null +++ b/client/src/components/Datepicker/utils/formatters.ts @@ -0,0 +1,10 @@ +import dateFormat from 'date-fns/format'; + +export { weekdayLabelFormat as weekdayLabelFormatFn } from '@datepicker-react/hooks'; + +export const weekdayLabelFormatLong = (date: Date) => dateFormat(date, 'EEEE'); + +export const dayLabelFormatFn = (date: Date) => dateFormat(date, 'd'); +export const monthLabelFormatFn = (date: Date) => dateFormat(date, 'MMMM'); + +export const defaultDisplayFormat = 'MM/dd/yyyy'; diff --git a/client/src/components/Datepicker/utils/getStateStyle.ts b/client/src/components/Datepicker/utils/getStateStyle.ts new file mode 100644 index 00000000..870ffec9 --- /dev/null +++ b/client/src/components/Datepicker/utils/getStateStyle.ts @@ -0,0 +1,5 @@ +import { StateProp } from '../types' + +export const getStateStyle = ({ base, active }: StateProp, isActive: boolean) => { + return isActive ? { ...base, ...active } : base +} diff --git a/client/src/components/Datepicker/utils/pick.ts b/client/src/components/Datepicker/utils/pick.ts new file mode 100644 index 00000000..4ceb3281 --- /dev/null +++ b/client/src/components/Datepicker/utils/pick.ts @@ -0,0 +1,9 @@ +function pick(obj: T, keys: K[]): Pick { + const ret: any = {} + keys.forEach(key => { + ret[key] = obj[key] + }) + return ret +} + +export default pick diff --git a/client/src/components/ErrorBoundary/ErrorBoundary.tsx b/client/src/components/ErrorBoundary/ErrorBoundary.tsx new file mode 100644 index 00000000..163c00e9 --- /dev/null +++ b/client/src/components/ErrorBoundary/ErrorBoundary.tsx @@ -0,0 +1,138 @@ +import { + Alert, + AlertDescription, + AlertIcon, + AlertTitle, + Box, + Button, + Code, + Heading, + HStack, + Stack, + Text, + useColorModeValue, +} from '@chakra-ui/react'; +import { Component, ErrorInfo, ReactNode } from 'react'; + +interface Props { + children: ReactNode; + fallback?: ReactNode; +} + +interface State { + hasError: boolean; + error: Error | null; + errorInfo: ErrorInfo | null; +} + +const ErrorFallback = ({ + error, + errorInfo, + resetErrorBoundary, +}: { + error: Error | null; + errorInfo: ErrorInfo | null; + resetErrorBoundary: () => void; +}) => { + const bgColor = useColorModeValue('red.50', 'rgba(254, 178, 178, 0.16)'); + const borderColor = useColorModeValue('red.400', 'red.300'); + + return ( + + + + Something went wrong + An error occurred in the application + + + + + Error Details + + {error && ( + + Error: + + {error.toString()} + + + )} + + {errorInfo && ( + + Component Stack: + + {errorInfo.componentStack} + + + )} + + + + + + + ); +}; + +export class ErrorBoundary extends Component { + constructor(props: Props) { + super(props); + this.state = { + hasError: false, + error: null, + errorInfo: null, + }; + } + + static getDerivedStateFromError(error: Error): State { + return { + hasError: true, + error, + errorInfo: null, + }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo): void { + this.setState({ + error, + errorInfo, + }); + + // You can also log the error to an error reporting service here + console.error('Error caught by ErrorBoundary:', error, errorInfo); + } + + resetErrorBoundary = () => { + this.setState({ + hasError: false, + error: null, + errorInfo: null, + }); + }; + + render(): ReactNode { + const { hasError, error, errorInfo } = this.state; + const { children, fallback } = this.props; + + if (hasError) { + if (fallback) { + return fallback; + } + + return ; + } + + return children; + } +} diff --git a/client/src/components/Header/Header.tsx b/client/src/components/Header/Header.tsx new file mode 100644 index 00000000..77eb3f03 --- /dev/null +++ b/client/src/components/Header/Header.tsx @@ -0,0 +1,32 @@ +import { Flex, Box, Center, Link } from '@chakra-ui/react'; +import { useColorModeValue } from '@chakra-ui/react'; +import { TocklerLogo } from './TocklerLogo'; +import { TocklerLogoText } from './TocklerLogoText'; + +export const Header = ({ children, brandLinkProps }) => ( + + + + +
    + +
    + + + +
    + +
    + {children} +
    +); diff --git a/client/src/components/Header/MenuItem.tsx b/client/src/components/Header/MenuItem.tsx new file mode 100644 index 00000000..6d5fa19f --- /dev/null +++ b/client/src/components/Header/MenuItem.tsx @@ -0,0 +1,14 @@ +import { Link as RouterLink } from 'react-router-dom'; +import { Box, Center } from '@chakra-ui/react'; +import { Button } from '@chakra-ui/react'; + +export const MenuItem = ({ to, icon, title }) => ( + + + +); diff --git a/client/src/components/Header/TocklerLogo.tsx b/client/src/components/Header/TocklerLogo.tsx new file mode 100644 index 00000000..5aad2e69 --- /dev/null +++ b/client/src/components/Header/TocklerLogo.tsx @@ -0,0 +1,38 @@ +import { Icon } from '@chakra-ui/icons'; + +export const TocklerLogo = (props) => ( + + + + + + + + + + + + + + + + + + + + + +); diff --git a/client/src/components/Header/TocklerLogoText.tsx b/client/src/components/Header/TocklerLogoText.tsx new file mode 100644 index 00000000..a1ab6e2c --- /dev/null +++ b/client/src/components/Header/TocklerLogoText.tsx @@ -0,0 +1,14 @@ +import { Icon } from '@chakra-ui/icons'; + +export const TocklerLogoText = (props) => ( + + Tockler + + + + + + + + +); diff --git a/client/src/components/LineCharts/LineChart.tsx b/client/src/components/LineCharts/LineChart.tsx index 1f89f7ec..e250b8d1 100644 --- a/client/src/components/LineCharts/LineChart.tsx +++ b/client/src/components/LineCharts/LineChart.tsx @@ -1,25 +1,32 @@ -import React, { useContext } from 'react'; -import moment from 'moment'; import { values } from 'lodash'; -import { VictoryBar, VictoryChart, VictoryAxis, VictoryTooltip } from 'victory'; -import { convertDate, TIME_FORMAT, DAY_MONTH_LONG_FORMAT, COLORS } from '../../constants'; +import { useContext } from 'react'; -import { useWindowWidth } from '@react-hook/window-size/throttled'; -import { SummaryContext } from '../../SummaryContext'; +import { useMeasure } from '@uidotdev/usehooks'; +import { IoMdMoon, IoMdSunny } from 'react-icons/io'; import { - addToTimeDuration, - formatToTimeEveryOther, - formatToDay, - toTimeDuration, -} from './LineChart.util'; -import { diffAndFormatShort } from '../../utils'; + DomainPaddingPropType, + DomainTuple, + ForAxes, + VictoryAxis, + VictoryBar, + VictoryChart, + VictoryScatter, + VictoryTooltip, + VictoryVoronoiContainer, +} from 'victory'; +import { COLORS, convertDate, DAY_MONTH_LONG_FORMAT, TIME_FORMAT } from '../../constants'; import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { SummaryContext } from '../../SummaryContext'; +import { formatDurationInternal } from '../../utils'; +import { BlackBox } from '../BlackBox'; +import { BAR_WIDTH } from '../Timeline/timeline.constants'; +import { dateToDayLabel, formatToHours } from './LineChart.util'; -const scale: any = { x: 'time', y: 'time' }; -const padding: any = { left: 50, top: 20, bottom: 20, right: 10 }; -const domainPadding: any = { y: 40, x: [20, 40] }; +const scale: { x: 'time'; y: 'linear' } = { x: 'time', y: 'linear' }; +const padding = { left: 25, top: 20, bottom: 30, right: 10 }; +const domainPadding: DomainPaddingPropType = { y: 0, x: [BAR_WIDTH, 0] }; -const labelComponent = theme => ( +const labelComponent = (theme) => ( ( /> ); +const formatToTime = (d) => convertDate(d).toFormat(TIME_FORMAT); +const formatToLong = (d) => convertDate(d).toFormat(DAY_MONTH_LONG_FORMAT); + +const dateToMinutes = (useStartDate) => (d) => { + const m = convertDate(useStartDate ? d.beginDate : d.endDate); + const hours = m.hour + m.minute / 60; + + return hours / 24; +}; + +const ScatterPoint = ({ x = 0, y = 0, showMoon = false, showSun = false }) => { + if (showMoon) { + return ; + } + if (showSun) { + return ; + } + return null; +}; + +const getXAxisDay = (d) => convertDate(d.beginDate).startOf('day').valueOf(); + export const LineChart = () => { const { chartTheme } = useChartThemeState(); - const chartWidth = useWindowWidth(); + const [ref, { width }] = useMeasure(); const { onlineTimesSummary, selectedDate } = useContext(SummaryContext); const onlineTimesValues = values(onlineTimesSummary); - const barHeight = 20; + const daysInMonth = selectedDate?.daysInMonth; + + const maxOnline = Math.max(...onlineTimesValues.map((d) => d.online)); + + const domain: ForAxes = { + x: [selectedDate.startOf('month').toJSDate(), selectedDate.endOf('month').toJSDate()], + y: [0, 1], + }; - const daysInMonth = selectedDate.daysInMonth(); - const daysArray = Array.from(Array(daysInMonth), (_, i) => i + 1); + const axisStyle = { + grid: { strokeWidth: 0 }, + ticks: { stroke: 'gray', size: 5 }, + }; + + const isNarrow = width ? width < 1400 : false; return ( - - - - - - toTimeDuration(convertDate(d.beginDate), convertDate(d.beginDate))} - y0={d => toTimeDuration(convertDate(d.beginDate), convertDate(d.endDate))} - x={d => formatToDay(convertDate(d.beginDate).startOf('day'))} - barWidth={barHeight} - data={onlineTimesValues} - labelComponent={labelComponent(chartTheme)} - labels={({ datum }) => - `${convertDate(datum.beginDate).format(DAY_MONTH_LONG_FORMAT)}\r\n - Start time: ${convertDate(datum.beginDate).format( - TIME_FORMAT, - )}\r\nEnd time: ${convertDate(datum.endDate).format( - TIME_FORMAT, - )}\r\nDuration: ${diffAndFormatShort(datum.beginDate, datum.endDate)}` - } - /> - toTimeDuration(convertDate(d.beginDate), convertDate(d.beginDate))} - y0={d => addToTimeDuration(convertDate(d.beginDate), d.online)} - x={d => formatToDay(convertDate(d.beginDate).startOf('day'))} - barWidth={10} - style={{ data: { fill: COLORS.green } }} - data={onlineTimesValues} - labelComponent={labelComponent(chartTheme)} - labels={({ datum }) => - `${convertDate(datum.beginDate).format( - DAY_MONTH_LONG_FORMAT, - )}\r\nWorked: ${moment.duration(datum.online).format()}` +
    + + { + const { childName, beginDate, endDate, online } = datum; + if (childName === 'beginDate') { + return `Start time: ${formatToTime(beginDate)}`; + } + if (childName === 'endDate') { + return `End time: ${formatToTime(endDate)}`; + } + if (childName === 'online') { + return `${formatToLong(datum.beginDate)}\r\nWorked: ${formatDurationInternal(online)}`; + } + return ''; + }} + /> } - /> - + > + + + + d.online / maxOnline} + barWidth={BAR_WIDTH} + style={{ data: { fill: COLORS.green } }} + data={onlineTimesValues} + /> + } + /> + } + /> + +
    ); }; diff --git a/client/src/components/LineCharts/LineChart.util.ts b/client/src/components/LineCharts/LineChart.util.ts index fe6bf865..18ee1401 100644 --- a/client/src/components/LineCharts/LineChart.util.ts +++ b/client/src/components/LineCharts/LineChart.util.ts @@ -1,46 +1,60 @@ -import moment from 'moment'; -import { convertDate } from '../../constants'; +import { intervalToDuration } from 'date-fns'; import { toInteger } from 'lodash'; +import { DateTime } from 'luxon'; +import { convertDate } from '../../constants'; export const generateTickValues = (date, ticks, unit, startOf) => { const day = convertDate(date).startOf(startOf); const dates = [...Array(ticks)].map((__, i) => { - return day.clone().add(i, unit); + return day.plus({ [unit]: i }); }); return dates; }; export const toTimeDuration = (from, to) => { - const start = moment(from).startOf('day'); - - return moment(moment(to).diff(start)); + const start = DateTime.fromJSDate(from).startOf('day'); + return DateTime.fromJSDate(to).diff(start); }; -export const addToTimeDuration = (from, duration) => { - const start = moment(from).startOf('day'); - return moment(moment(from).diff(start) + duration); +export const addToTimeDuration = (from, duration) => { + const start = DateTime.fromJSDate(from).startOf('day'); + return DateTime.fromJSDate(from).diff(start).plus(duration); }; -export const isOddHour = date => moment(date).get('hour') % 2; +export const isOddHour = (date) => DateTime.fromJSDate(date).hour % 2; -export const formatToTime = t => moment.utc(t).format('HH:mm'); +export const formatToTime = (t: number) => DateTime.fromMillis(t).toFormat('HH:mm'); -export const formatToTimeEveryOther = t => { - const hour = moment(t).startOf('hour'); - return formatToTime(hour); +export const formatToTimeEveryOther = (t: number) => { + const hour = DateTime.fromMillis(t).startOf('hour'); + return formatToTime(hour.toMillis()); }; -export const formatToDay = t => toInteger(t.format('DD')); +export const toHours = (t: number) => { + const duration = intervalToDuration({ start: 0, end: t }); + return duration.hours ?? 0; +}; + +export const formatToHours = (max: number) => (t: number) => { + const duration = intervalToDuration({ start: 0, end: t * max }); + return `${duration.hours} h`; +}; + +export const formatToDay = (t: DateTime) => toInteger(t.toFormat('dd')); + +export const dateToDayLabel = (short) => (date) => { + return DateTime.fromJSDate(date).toFormat(short ? 'dd' : 'dd ccc'); +}; -export const timeTickValues = t => { +export const timeTickValues = () => { const ticks = 36; - const day = moment(); + const day = DateTime.now(); const dates = [...Array(ticks)].map((__, i) => { - return toTimeDuration(day, day.clone().add(i, 'hour')); + return toTimeDuration(day.toJSDate(), day.plus({ hours: i }).toJSDate()); }); return dates; }; -export const dayTickValues = t => generateTickValues(t, 31, 'day', 'month'); +export const dayTickValues = (t) => generateTickValues(t, 31, 'day', 'month'); diff --git a/client/src/components/LineCharts/LineCharts.styles.ts b/client/src/components/LineCharts/LineCharts.styles.ts deleted file mode 100644 index b66050c9..00000000 --- a/client/src/components/LineCharts/LineCharts.styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from 'styled-components'; -import { Box } from 'reflexbox'; - -export const LineChartBox = styled(Box).attrs({ m: 2, p: 2 })` - background: ${({ theme: { variables } }) => variables['@component-background']}; -`; diff --git a/client/src/components/Loader.jsx b/client/src/components/Loader.jsx new file mode 100644 index 00000000..2ca9db87 --- /dev/null +++ b/client/src/components/Loader.jsx @@ -0,0 +1,9 @@ +import { Box, CircularProgress } from '@chakra-ui/react'; + +export const Loader = () => { + return ( + + + + ); +}; diff --git a/client/src/components/LoadingLine.tsx b/client/src/components/LoadingLine.tsx new file mode 100644 index 00000000..b58e62ae --- /dev/null +++ b/client/src/components/LoadingLine.tsx @@ -0,0 +1,25 @@ +import { Box, useToken } from '@chakra-ui/react'; +import { keyframes } from '@emotion/react'; + +// Loading line animation +const loadingAnimation = keyframes` + 0% { width: 0%; left: 0; } + 50% { width: 70%; left: 15%; } + 100% { width: 100%; left: 0; } +`; + +export const LoadingLine = () => { + const [blue500] = useToken('colors', ['blue.500']); + + return ( + + ); +}; diff --git a/client/src/components/MainLayout/HeaderMenu.styles.ts b/client/src/components/MainLayout/HeaderMenu.styles.ts deleted file mode 100644 index 1433c913..00000000 --- a/client/src/components/MainLayout/HeaderMenu.styles.ts +++ /dev/null @@ -1,12 +0,0 @@ -import styled from 'styled-components'; - -export const Brand = styled.div` - font-family: 'Berkshire Swash', cursive; - text-align: left; - font-size: 26px; -`; - -export const Img = styled.img` - margin-right: 15px; - margin-bottom: 6px; -`; diff --git a/client/src/components/MainLayout/HeaderMenu.tsx b/client/src/components/MainLayout/HeaderMenu.tsx index abed35ad..28d0d944 100644 --- a/client/src/components/MainLayout/HeaderMenu.tsx +++ b/client/src/components/MainLayout/HeaderMenu.tsx @@ -1,59 +1,28 @@ -import { Menu } from 'antd'; import { - BarsOutlined, - AreaChartOutlined, - SearchOutlined, - SettingOutlined, - QuestionCircleOutlined, -} from '@ant-design/icons'; -import React from 'react'; -import { Link } from 'react-router-dom'; -import styled from 'styled-components'; -import tocklerIcon from '../../assets/icons/tockler_icon.png'; -import { Brand, Img } from './HeaderMenu.styles'; + AiOutlineAreaChart, + AiOutlineBars, + AiOutlineQuestionCircle, + AiOutlineSearch, + AiOutlineSetting, +} from 'react-icons/ai'; -const GrayMenu = styled(Menu)``; +import { Box } from '@chakra-ui/react'; +import { Link as RouterLink } from 'react-router-dom'; +import { ColorModeSwitcher } from '../ColorModeSwitcher'; +import { Header } from '../Header/Header'; +import { MenuItem } from '../Header/MenuItem'; -export const HeaderMenu = ({ location }: any) => ( - - - - - - Tockler - - - - - - - Timeline - - - - - - Summary - - - - - - Search - - - - - - Settings - - +export const HeaderMenu = () => ( +
    + } title="Timeline" /> + } title="Summary" /> + } title="Search" /> + } title="Settings" /> + } title="Support" /> + - - - - Support - - - + + + +
    ); diff --git a/client/src/components/MainLayout/MainLayout.tsx b/client/src/components/MainLayout/MainLayout.tsx index 62c09e10..e00eaf3f 100644 --- a/client/src/components/MainLayout/MainLayout.tsx +++ b/client/src/components/MainLayout/MainLayout.tsx @@ -1,19 +1,15 @@ -import { Layout } from 'antd'; -import React from 'react'; -import { HeaderMenu } from './HeaderMenu'; +import { Box } from '@chakra-ui/react'; -const { Footer, Content } = Layout; +import { Outlet } from 'react-router-dom'; +import { HeaderMenu } from './HeaderMenu'; -export function MainLayout({ children, location }: any) { +export function MainLayout() { return ( -
    - - - {children} - - -
    + + + + + + ); } diff --git a/client/src/components/MakeUnitSmaller.tsx b/client/src/components/MakeUnitSmaller.tsx new file mode 100644 index 00000000..9ea7e72a --- /dev/null +++ b/client/src/components/MakeUnitSmaller.tsx @@ -0,0 +1,17 @@ +import { Text, useColorModeValue } from '@chakra-ui/react'; + +export const MakeUnitSmaller = ({ children }) => { + const values = children.split(/(\d+)/); + const color = useColorModeValue('gray.700', 'gray.300'); + + return values.map((value) => { + if (isNaN(value)) { + return ( + + {value} + + ); + } + return value; + }); +}; diff --git a/client/src/components/Metric.tsx b/client/src/components/Metric.tsx new file mode 100644 index 00000000..07b18aaa --- /dev/null +++ b/client/src/components/Metric.tsx @@ -0,0 +1,16 @@ +import { Box, Text, useColorModeValue } from '@chakra-ui/react'; + +export const Metric = ({ title, value }) => { + return ( + + + + {title} + + + + {value} + + + ); +}; diff --git a/client/src/components/MetricTile.tsx b/client/src/components/MetricTile.tsx new file mode 100644 index 00000000..5a2ea551 --- /dev/null +++ b/client/src/components/MetricTile.tsx @@ -0,0 +1,10 @@ +import { BoxProps, Flex } from '@chakra-ui/react'; +import { TileBox } from './TileBox'; + +export const MetricTile = ({ children, ...rest }: BoxProps) => { + return ( + + {children} + + ); +}; diff --git a/client/src/components/PieCharts/AppUsageChart.tsx b/client/src/components/PieCharts/AppUsageChart.tsx new file mode 100644 index 00000000..73b74afa --- /dev/null +++ b/client/src/components/PieCharts/AppUsageChart.tsx @@ -0,0 +1,101 @@ +import _ from 'lodash'; +import { memo } from 'react'; + +import { useMeasure } from '@uidotdev/usehooks'; +import { VictoryBar, VictoryLabel, VictoryStack, VictoryStyleInterface } from 'victory'; +import { useStoreState } from '../../store/easyPeasy'; +import { BAR_WIDTH } from '../Timeline/timeline.constants'; +import { filterItems } from '../Timeline/timeline.utils'; +import { sumAppObject, SumItem } from './MetricTiles.utils'; + +import { TrackItemType } from '../../enum/TrackItemType'; +import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { formatDurationInternal } from '../../utils'; +import { BarWithTooltip } from '../Timeline/BarWithTooltip'; +import { colorProp } from '../charts.utils'; +import { getTextWidth } from './AppUsageChart.utils'; + +export const AppUsageChart = memo(() => { + const [ref, { width }] = useMeasure(); + const { chartTheme } = useChartThemeState(); + const timeItems = useStoreState((state) => state.timeItems); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + + const appItems = filterItems(timeItems[TrackItemType.AppTrackItem] || [], visibleTimerange); + + const groupByField = 'app'; + + const data = _(appItems) + .groupBy(groupByField) + .map((b) => { + return b.reduce(sumAppObject(visibleTimerange), { + app: b[0].app, + title: b[0].title, + timeDiffInMs: 0, + color: b[0].color, + } as SumItem); + }) + .sortBy('timeDiffInMs') + .reverse() + .valueOf(); + + const getTooltipLabel = (datum) => { + return `${datum[groupByField]}\r\n${formatDurationInternal(datum.timeDiffInMs)}`; + }; + + const style: VictoryStyleInterface = { + data: { + fill: colorProp, + stroke: colorProp, + strokeWidth: 0.5, + fillOpacity: 0.75, + }, + }; + + const labelPadding = 25; + return ( +
    + + {data.map((item) => ( + datum.app} + labelComponent={ + { + const text = `${datum.app} - ${formatDurationInternal(datum.timeDiffInMs)}`; + const textWidth = getTextWidth( + text, + 14, + '"Gill Sans", Seravek, "Trebuchet MS", sans-serif;', + ); + + const timeDiff = datum._y1 - datum._y0; + + const width = + typeof scale === 'object' && typeof scale.y === 'function' + ? scale.y(timeDiff) + : 0; + + const canFit = textWidth + labelPadding * 2 < width; + + return canFit ? text : ''; + }} + dx={-labelPadding} + dy={-5} + /> + } + dataComponent={} + /> + ))} + +
    + ); +}); diff --git a/client/src/components/PieCharts/AppUsageChart.utils.ts b/client/src/components/PieCharts/AppUsageChart.utils.ts new file mode 100644 index 00000000..f91895f0 --- /dev/null +++ b/client/src/components/PieCharts/AppUsageChart.utils.ts @@ -0,0 +1,17 @@ +/** + * Measures the rendered width of arbitrary text given the font size and font face + * @param {string} text The text to measure + * @param {number} fontSize The font size in pixels + * @param {string} fontFace The font face ("Arial", "Helvetica", etc.) + * @returns {number} The width of the text + * */ +export function getTextWidth(text, fontSize, fontFace) { + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d'); + if (!context) { + console.warn('No 2d context'); + return 0; + } + context.font = `${fontSize}px ${fontFace}`; + return context.measureText(text).width; +} diff --git a/client/src/components/PieCharts/MetricTiles.tsx b/client/src/components/PieCharts/MetricTiles.tsx new file mode 100644 index 00000000..1335cbb8 --- /dev/null +++ b/client/src/components/PieCharts/MetricTiles.tsx @@ -0,0 +1,78 @@ +import { memo } from 'react'; +import { filterItems } from '../Timeline/timeline.utils'; + +import { HStack } from '@chakra-ui/react'; +import { maxBy, minBy } from 'lodash'; +import { DateTime } from 'luxon'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { TIME_FORMAT_SHORT } from '../../constants'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { useStoreState } from '../../store/easyPeasy'; +import { secondsToClock } from '../../time.util'; +import { MakeUnitSmaller } from '../MakeUnitSmaller'; +import { Metric } from '../Metric'; +import { MetricTile } from '../MetricTile'; +import { getOnlineTime, getTasksTime } from './MetricTiles.utils'; + +const NO_VALUE = '-'; + +const EMPTY_ARRAY: ITrackItem[] = []; + +export const MetricTiles = memo(() => { + const timeItems = useStoreState((state) => state.timeItems); + const timerange = useStoreState((state) => state.timerange); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + + const logItems = filterItems(timeItems[TrackItemType.LogTrackItem] || EMPTY_ARRAY, visibleTimerange); + + const onlineItems = + timeItems[TrackItemType.StatusTrackItem]?.filter((item) => item.app === 'ONLINE') || EMPTY_ARRAY; + + // + const onlineTotal = getOnlineTime(onlineItems, timerange); + const onlineTotalVisible = getOnlineTime(filterItems(onlineItems, visibleTimerange), visibleTimerange); + const tasksTotal = getTasksTime(timeItems[TrackItemType.LogTrackItem] || EMPTY_ARRAY, timerange); + const tasksTotalVisible = getTasksTime(logItems, visibleTimerange); + + const wakeItem: ITrackItem | undefined = minBy(onlineItems, (c: ITrackItem) => c.beginDate); + const sleepItem: ITrackItem | undefined = maxBy(onlineItems, (c: ITrackItem) => c.endDate); + + return ( + + + {secondsToClock(onlineTotal / 1000, 0, 2)}} + /> + {secondsToClock(onlineTotalVisible / 1000, 0, 2) || NO_VALUE} + } + /> + + + {secondsToClock(tasksTotal / 1000, 0, 2) || NO_VALUE}} + /> + {secondsToClock(tasksTotalVisible / 1000, 0, 2) || NO_VALUE} + } + /> + + + + + + + ); +}); diff --git a/client/src/components/PieCharts/MetricTiles.utils.test.ts b/client/src/components/PieCharts/MetricTiles.utils.test.ts new file mode 100644 index 00000000..d3b02145 --- /dev/null +++ b/client/src/components/PieCharts/MetricTiles.utils.test.ts @@ -0,0 +1,95 @@ +import { DateTime } from 'luxon'; +import { describe, expect, it } from 'vitest'; +import { sumApp } from './MetricTiles.utils'; + +describe('MetricTiles utils', () => { + it('sumApp in range items', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items = [ + { + id: 1, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T17:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T17:10:00.000Z').toMillis(), + }, + { + id: 2, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + { + id: 3, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T18:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:00:00.000Z').toMillis(), + }, + ]; + const actual = items.reduce(sumApp(visibleTimerange), 0); + expect(actual).toEqual(30 * 60 * 1000); + }); + it('sumApp does not include out of range items', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items = [ + { + id: 1, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T16:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T16:59:59.000Z').toMillis(), + }, + { + id: 2, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + { + id: 3, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T19:00:01.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:10:00.000Z').toMillis(), + }, + ]; + const actual = items.reduce(sumApp(visibleTimerange), 0); + expect(actual).toEqual(10 * 60 * 1000); + }); + + it('sumApp uses only in range time', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items = [ + { + id: 1, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T16:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T17:10:00.000Z').toMillis(), + }, + { + id: 2, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + { + id: 3, + app: 'Test', + beginDate: DateTime.fromISO('2021-06-19T18:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:10:00.000Z').toMillis(), + }, + ]; + const actual = items.reduce(sumApp(visibleTimerange), 0); + expect(actual).toEqual(30 * 60 * 1000); + }); +}); + +export // Use an empty export to please Babel's single file emit. +// https://github.com/Microsoft/TypeScript/issues/15230 + {}; diff --git a/client/src/components/PieCharts/MetricTiles.utils.ts b/client/src/components/PieCharts/MetricTiles.utils.ts new file mode 100644 index 00000000..2e892d9c --- /dev/null +++ b/client/src/components/PieCharts/MetricTiles.utils.ts @@ -0,0 +1,54 @@ +import { DateTime } from 'luxon'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { convertDate } from '../../constants'; + +export type SumItem = { + app: string; + title?: string; + timeDiffInMs: number; + color?: string; +}; + +export const clampRange = (clampToRange: DateTime[], range: DateTime[]) => { + const begin = DateTime.max(clampToRange[0], convertDate(range[0])); + const end = DateTime.min(clampToRange[1], convertDate(range[1])); + return [begin, end]; +}; + +export const sumAppObject = (visibleTimerange: DateTime[]) => (newItem: { timeDiffInMs: number }, item: ITrackItem) => { + const [beginClamp, endClamp] = visibleTimerange; + + const [beginDate, endDate] = clampRange( + [beginClamp, endClamp], + [convertDate(item.beginDate), convertDate(item.endDate)], + ); + + const diff = endDate.diff(beginDate).milliseconds; + if (diff < 0) { + return { ...item, timeDiffInMs: newItem.timeDiffInMs }; + } + + return { ...item, timeDiffInMs: newItem.timeDiffInMs + diff }; +}; + +export const sumApp = (visibleTimerange: DateTime[]) => (timeDiffInMs: number, item: ITrackItem) => { + const newItem = sumAppObject(visibleTimerange)({ timeDiffInMs }, item); + return newItem.timeDiffInMs; +}; + +export const getOnlineTime = (items: ITrackItem[], visibleTimerange: DateTime[]) => { + const onlineItems = items.filter((item) => item.app === 'ONLINE'); + return onlineItems.reduce(sumApp(visibleTimerange), 0); +}; + +export const getLastOnlineTime = (items: ITrackItem[], visibleTimerange: DateTime[]) => { + const onlineItems = items.filter((item) => item.app === 'ONLINE'); + if (onlineItems.length > 1) { + return [onlineItems.reverse()[1]].reduce(sumApp(visibleTimerange), 0); + } + return; +}; + +export const getTasksTime = (items: ITrackItem[], visibleTimerange: DateTime[]) => { + return items.reduce(sumApp(visibleTimerange), 0); +}; diff --git a/client/src/components/PieCharts/PieChart.tsx b/client/src/components/PieCharts/PieChart.tsx index b4777fcb..bc1a7136 100644 --- a/client/src/components/PieCharts/PieChart.tsx +++ b/client/src/components/PieCharts/PieChart.tsx @@ -1,12 +1,10 @@ -import React from 'react'; - import _ from 'lodash'; -import moment from 'moment'; -import { VictoryContainer, VictoryPie } from 'victory'; +import { VictoryContainer, VictoryPie, VictoryStyleInterface } from 'victory'; import { convertDate } from '../../constants'; -import { PieLabel } from './PieLabel'; -import { colorProp } from '../charts.utils'; import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { formatDurationInternal } from '../../utils'; +import { colorProp } from '../charts.utils'; +import { PieLabel } from './PieLabel'; const sumApp = (p, c) => { return _.extend(p, { @@ -21,7 +19,7 @@ export const PieChart = ({ items, taskName, width }) => { const pieData = _(items) .groupBy(groupByField) - .map(b => { + .map((b) => { return b.reduce(sumApp, { app: b[0].app, title: b[0].title, @@ -31,7 +29,7 @@ export const PieChart = ({ items, taskName, width }) => { }) .valueOf(); - const style: any = { + const style: VictoryStyleInterface = { data: { fill: colorProp, stroke: colorProp, @@ -50,12 +48,9 @@ export const PieChart = ({ items, taskName, width }) => { containerComponent={} style={style} labels={({ datum }) => { - const dur = moment.duration(datum.timeDiffInMs); - const formattedDuration = dur.format(); - - return `${datum[groupByField]} [${formattedDuration}]`; + return `${datum[groupByField]} [${formatDurationInternal(datum.timeDiffInMs)}]`; }} - labelComponent={} + labelComponent={} x="app" y="timeDiffInMs" data={pieData} diff --git a/client/src/components/PieCharts/PieCharts.styles.ts b/client/src/components/PieCharts/PieCharts.styles.ts deleted file mode 100644 index 0b4f57d5..00000000 --- a/client/src/components/PieCharts/PieCharts.styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from 'styled-components'; - -export const Heading = styled.h3` - text-align: center; - color: rgba(0, 0, 0, 0.65); -`; diff --git a/client/src/components/PieCharts/PieCharts.tsx b/client/src/components/PieCharts/PieCharts.tsx deleted file mode 100644 index 5835316a..00000000 --- a/client/src/components/PieCharts/PieCharts.tsx +++ /dev/null @@ -1,58 +0,0 @@ -import { Box, Flex } from 'reflexbox'; -import { useWindowWidth } from '@react-hook/window-size/throttled'; -import React, { memo, useContext } from 'react'; -import { RootContext } from '../../RootContext'; -import { filterItems } from '../Timeline/timeline.utils'; -import { PieChart } from './PieChart'; -import { Heading } from './PieCharts.styles'; -import { WorkProgressChart } from './WorkProgressChart'; -import { useStoreState } from '../../store/easyPeasy'; - -export const PieCharts = memo(() => { - const timeItems = useStoreState(state => state.timeItems); - const visibleTimerange = useStoreState(state => state.visibleTimerange); - - const { workSettings } = useContext(RootContext); - const innerWidth = useWindowWidth(); - - const appItems = filterItems(timeItems.appItems, visibleTimerange); - const statusItems = filterItems(timeItems.statusItems, visibleTimerange); - const logItems = filterItems(timeItems.logItems, visibleTimerange); - - const pieWidth = innerWidth / 4; - - return ( -
    - - - - - - Tasks - - - - - - Status - - - - - - Progress for {workSettings.hoursToWork}h - - - - - - App usage - - -
    - ); -}); diff --git a/client/src/components/PieCharts/PieLabel.tsx b/client/src/components/PieCharts/PieLabel.tsx index 3b111574..973192b2 100644 --- a/client/src/components/PieCharts/PieLabel.tsx +++ b/client/src/components/PieCharts/PieLabel.tsx @@ -1,39 +1,39 @@ -import React from 'react'; +import { PureComponent } from 'react'; import { VictoryTooltip } from 'victory'; +import { gray900 } from '../Timeline/ChartTheme'; interface IProps { text?: string; width: number; + innerWidth: number; color?: string; - datum?: any; - theme: any; + datum?: { beginDate: number; endDate: number; diff: number }; + theme: { tooltip: { style: { fontSize: number } }; isDark: boolean }; } -export class PieLabel extends React.PureComponent { +export class PieLabel extends PureComponent { public static defaultEvents = VictoryTooltip.defaultEvents; public render() { - const { width, datum, theme } = this.props; - - const labelWidth = width / 2; + const { width, innerWidth, theme } = this.props; return ( diff --git a/client/src/components/PieCharts/WorkProgressChart.tsx b/client/src/components/PieCharts/WorkProgressChart.tsx index ffae0b6c..d3f51234 100644 --- a/client/src/components/PieCharts/WorkProgressChart.tsx +++ b/client/src/components/PieCharts/WorkProgressChart.tsx @@ -1,12 +1,10 @@ -import React from 'react'; - import _ from 'lodash'; -import moment from 'moment'; import { VictoryContainer, VictoryPie } from 'victory'; import { convertDate } from '../../constants'; import { PieLabel } from './PieLabel'; import { colorProp } from '../charts.utils'; import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { formatDurationInternal } from '../../utils'; const sumApp = (p, c) => { return _.extend(p, { @@ -19,9 +17,9 @@ export const WorkProgressChart = ({ items, width, hoursToWork }) => { const groupByField = 'app'; const pieData: any[] = _(items) - .filter(item => item.app === 'ONLINE') + .filter((item) => item.app === 'ONLINE') .groupBy(groupByField) - .map(b => { + .map((b) => { return b.reduce(sumApp, { app: 'Worked', timeDiffInMs: 0, @@ -31,21 +29,20 @@ export const WorkProgressChart = ({ items, width, hoursToWork }) => { .valueOf(); if (pieData.length) { - const workDay = moment.duration(Number(hoursToWork), 'hours'); + const workDayMs = hoursToWork * 60 * 60 * 1000; const workedMs = pieData[0].timeDiffInMs; // pauses must be 10% of worked time const pausesInHour = 0.1; - const worked = moment.duration(workedMs); - const pauses = moment.duration(workedMs * pausesInHour); + const pausesMs = workedMs * pausesInHour; - const undone = workDay.subtract(worked).subtract(pauses); + const undoneMs = workDayMs - workedMs - pausesMs; const undoneItem = { app: 'Work to be done', title: 'Work to be done', - timeDiffInMs: undone.asMilliseconds(), + timeDiffInMs: undoneMs, color: 'lightgray', }; pieData.push(undoneItem); @@ -53,7 +50,7 @@ export const WorkProgressChart = ({ items, width, hoursToWork }) => { const pausesItem = { app: 'Pauses', title: 'Pauses', - timeDiffInMs: pauses.asMilliseconds(), + timeDiffInMs: pausesMs, color: 'gray', }; pieData.push(pausesItem); @@ -78,12 +75,9 @@ export const WorkProgressChart = ({ items, width, hoursToWork }) => { containerComponent={} style={style} labels={({ datum }) => { - const dur = moment.duration(datum.timeDiffInMs); - const formattedDuration = dur.format(); - - return `${datum[groupByField]} [${formattedDuration}]`; + return `${datum[groupByField]} [${formatDurationInternal(datum.timeDiffInMs)}]`; }} - labelComponent={} + labelComponent={} x="app" y="timeDiffInMs" data={pieData} diff --git a/client/src/components/SearchResults/SearchDeleteButtons.tsx b/client/src/components/SearchResults/SearchDeleteButtons.tsx new file mode 100644 index 00000000..5970f0e1 --- /dev/null +++ b/client/src/components/SearchResults/SearchDeleteButtons.tsx @@ -0,0 +1,46 @@ +import { Button, HStack, Text } from '@chakra-ui/react'; +import { Logger } from '../../logger'; +import { deleteByIds } from '../../services/trackItem.api'; +import { TableButtonsProps } from '../TrackItemTable/TrackItemTable.utils'; + +interface Props extends TableButtonsProps { + refreshData: () => void; +} + +export const SearchDeleteButtons: React.FC = (props) => { + const { selectedFlatRows, selectedRowIds, refreshData } = props; + + const deleteTimelineItems = async (ids: number[]) => { + console.log('Delete timeline items', ids); + + if (ids) { + await deleteByIds(ids); + Logger.debug('Deleted timeline items', ids); + } else { + Logger.error('No ids, not deleting from DB'); + } + }; + + const deleteSelectedItems = () => { + console.log('selectedFlatRows...', selectedFlatRows); + deleteTimelineItems(selectedFlatRows.map(({ original }) => original.id)).then(() => { + refreshData(); + }); + }; + + const hasSelected = Object.keys(selectedRowIds).length > 0; + + return ( + + {hasSelected && ( + + )} + + ); +}; diff --git a/client/src/components/SearchResults/SearchOptions.tsx b/client/src/components/SearchResults/SearchOptions.tsx index a74b33cb..5e44b6f6 100644 --- a/client/src/components/SearchResults/SearchOptions.tsx +++ b/client/src/components/SearchResults/SearchOptions.tsx @@ -1,124 +1,127 @@ -import { Box, Flex } from 'reflexbox'; -import { Button, DatePicker } from 'antd'; -import { LeftOutlined, RightOutlined } from '@ant-design/icons'; -import moment from 'moment'; -import React from 'react'; - +import { Box, Button, Flex, HStack, Text, useColorModeValue } from '@chakra-ui/react'; +import { OnDatesChangeProps } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; +import { useState } from 'react'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; import { Logger } from '../../logger'; +import { DateRangeInput } from '../Datepicker'; -const { RangePicker } = DatePicker; +const getDayBefore = (d: DateTime) => d.minus({ days: 1 }); +const getDayAfter = (d: DateTime) => d.plus({ days: 1 }); -const getDayBefore = d => moment(d).subtract(1, 'days'); -const getDayAfter = d => moment(d).add(1, 'days'); +enum RANGE_OPTIONS { + WEEK, + MONTH, + MONTHS_3, + YEAR, + YEARS_3, +} export const SearchOptions = ({ setTimerange, timerange }) => { - const onChange = (dates: any) => { - Logger.debug('TIMERANGE:', dates); - if (dates != null) { - const beginDate = dates[0]; - const endDate = dates[1]; - const newTimerange = [beginDate, endDate]; - setTimerange(newTimerange); - } else { - Logger.error('No dates selected'); - } - }; + const [localRange, setLocalRange] = useState(RANGE_OPTIONS.WEEK); - const selectWeek = () => { - const beginDate = moment() - .startOf('day') - .subtract(7, 'days'); - const endDate = moment().endOf('day'); - setTimerange([beginDate, endDate]); - }; - const selectMonth = () => { - const beginDate = moment() - .startOf('day') - .subtract(1, 'month'); - const endDate = moment().endOf('day'); - setTimerange([beginDate, endDate]); - }; + const selectRange = (range) => { + let beginDate = DateTime.now().startOf('day'); + const endDate = DateTime.now().endOf('day'); - const selectMonth3 = () => { - const beginDate = moment() - .startOf('day') - .subtract(3, 'month'); - const endDate = moment().endOf('day'); - setTimerange([beginDate, endDate]); - }; + if (range === RANGE_OPTIONS.WEEK) { + beginDate = beginDate.minus({ days: 7 }); + } - const selectYear = () => { - const beginDate = moment() - .startOf('day') - .subtract(1, 'year'); - const endDate = moment().endOf('day'); - setTimerange([beginDate, endDate]); - }; + if (range === RANGE_OPTIONS.MONTH) { + beginDate = beginDate.minus({ months: 1 }); + } + if (range === RANGE_OPTIONS.MONTHS_3) { + beginDate = beginDate.minus({ months: 3 }); + } + if (range === RANGE_OPTIONS.YEAR) { + beginDate = beginDate.minus({ years: 1 }); + } + if (range === RANGE_OPTIONS.YEARS_3) { + beginDate = beginDate.minus({ years: 3 }); + } - const selectYear3 = () => { - const beginDate = moment() - .startOf('day') - .subtract(3, 'year'); - const endDate = moment().endOf('day'); setTimerange([beginDate, endDate]); + + setLocalRange(range); }; const goBackOneDay = () => { - const beginDate = getDayBefore(moment(timerange[0])); - const endDate = getDayBefore(moment(timerange[1])); + const beginDate = getDayBefore(timerange[0]); + const endDate = getDayBefore(timerange[1]); setTimerange([beginDate, endDate]); }; const goForwardOneDay = () => { - const beginDate = getDayAfter(moment(timerange[0])); - const endDate = getDayAfter(moment(timerange[1])); + const beginDate = getDayAfter(timerange[0]); + const endDate = getDayAfter(timerange[1]); setTimerange([beginDate, endDate]); }; - Logger.debug('Have timerange in Search:', timerange); + const handleOnDatesChange = (data: OnDatesChangeProps) => { + Logger.debug('TIMERANGE:', data); + + const { startDate, endDate } = data; + if (!startDate || !endDate) { + return; + } + const newTimerange = [DateTime.fromJSDate(startDate).startOf('day'), DateTime.fromJSDate(endDate).endOf('day')]; + + setTimerange(newTimerange); + }; + + const selectVariant = (range) => (localRange === range ? 'solid' : 'outline'); return ( - - - - - - - - - - + - - - - - - - - - - - - - - - + ); }; diff --git a/client/src/components/SearchResults/SearchResults.styles.ts b/client/src/components/SearchResults/SearchResults.styles.ts deleted file mode 100644 index 30fd2d4f..00000000 --- a/client/src/components/SearchResults/SearchResults.styles.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Box, Flex } from 'reflexbox'; -import styled from 'styled-components'; - -export const FilterDropdown = styled(Flex).attrs({ p: 2 })` - border-radius: 6px; - background: #fff; - box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); -`; - -export const FilterInput = styled(Box).attrs({ mr: 1 })` - width: 130px; -`; -export const Highlight = styled.span` - color: #f50; -`; - -export const TotalCount = styled.div` - text-align: right; - padding-right: 10px; -`; diff --git a/client/src/components/SearchResults/SearchResults.tsx b/client/src/components/SearchResults/SearchResults.tsx index 66edbb58..ff3859c4 100644 --- a/client/src/components/SearchResults/SearchResults.tsx +++ b/client/src/components/SearchResults/SearchResults.tsx @@ -1,182 +1,87 @@ -import { Table, Tooltip } from 'antd'; -import { UnorderedListOutlined } from '@ant-design/icons'; -import useReactRouter from 'use-react-router'; -import { sumBy } from 'lodash'; -import moment from 'moment'; -import React, { useState, useRef, useEffect, memo } from 'react'; -import Moment from 'react-moment'; -import { convertDate, DATE_TIME_FORMAT, TIME_FORMAT } from '../../constants'; -import { diffAndFormatShort } from '../../utils'; -import { TotalCount } from './SearchResults.styles'; -import { Logger } from '../../logger'; +import { IconButton, Tooltip } from '@chakra-ui/react'; +import { ColumnDef } from '@tanstack/react-table'; +import { DateTime } from 'luxon'; +import { memo } from 'react'; +import { AiOutlineUnorderedList } from 'react-icons/ai'; +import { useNavigate } from 'react-router-dom'; + +import { ITrackItem } from '../../@types/ITrackItem'; +import { SearchResultI } from '../../services/trackItem.api'; import { useStoreActions } from '../../store/easyPeasy'; +import { ItemsTable } from '../TrackItemTable/ItemsTable'; +import { defaultTableButtonsProps } from '../TrackItemTable/TrackItemTable.utils'; +import { SearchDeleteButtons } from './SearchDeleteButtons'; -const calculateTotal = filteredData => { - const totalMs = sumBy(filteredData, (c: any) => - convertDate(c.endDate).diff(convertDate(c.beginDate)), - ); - const dur = moment.duration(totalMs); - - return Total {dur.format()}; -}; +const ActionCell = ({ cell }) => { + const { beginDate, endDate } = cell.row.original; -const SearchResultsPlain = ({ searchResult, searchPaging, setSearchPaging }) => { - const loadTimerange = useStoreActions(state => state.loadTimerange); - const setVisibleTimerange = useStoreActions(state => state.setVisibleTimerange); - - const { history } = useReactRouter(); - - const paginationConf = { - total: searchResult.total, - showSizeChanger: true, - pageSize: searchPaging.pageSize, - current: searchPaging.page, - pageSizeOptions: ['50', '100', '300', '500'], - onChange: (page, pageSize) => { - console.error('Pagination changed', page, pageSize); - // setSearchPaging({ page, pageSize }); - }, - }; - const [state, setState] = useState({ - filteredInfo: {}, - sortedInfo: {}, - filterDropdownVisible: false, - searchText: '', - filtered: false, - selectedRowKeys: [], - }); + const loadTimerange = useStoreActions((state) => state.loadTimerange); + const setVisibleTimerange = useStoreActions((state) => state.setVisibleTimerange); - const searchInput = useRef(); - - useEffect(() => { - if (searchInput.current) { - searchInput.current.focus(); - } - }, [state.filterDropdownVisible]); - - const handleChange = (pagination: any, filters: any, sorter: any) => { - Logger.debug('Various parameters', pagination, filters, sorter); - setSearchPaging({ page: pagination.current, pageSize: pagination.pageSize }); - setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); - }; - - const onSelectChange = selectedRowKeys => { - Logger.debug('selectedRowKeys changed: ', selectedRowKeys); - setState({ ...state, selectedRowKeys }); - }; + const navigate = useNavigate(); - const goToTimelinePage = record => { - loadTimerange([ - moment(record.beginDate).startOf('day'), - moment(record.beginDate).endOf('day'), - ]); + const goToTimelinePage = (record) => { + const beginDateTime = DateTime.fromMillis(record.beginDate); + loadTimerange([beginDateTime.startOf('day'), beginDateTime.endOf('day')]); setVisibleTimerange([ - moment(record.beginDate).subtract(15, 'minutes'), - moment(record.endDate).add(15, 'minutes'), + DateTime.fromMillis(record.beginDate).minus({ minutes: 15 }), + DateTime.fromMillis(record.endDate).plus({ minutes: 15 }), ]); - history.push('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/app/timeline'); + navigate('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/app/timeline'); }; - const { isOneDay, sortedInfo } = state; - - const columns = [ - { - title: 'App', - dataIndex: 'app', - key: 'app', - width: 200, - sorter: (a: any, b: any) => a.app - b.app, - sortOrder: sortedInfo.columnKey === 'app' && sortedInfo.order, - }, - { - title: 'Title', - dataIndex: 'title', - key: 'title', - - sorter: (a: any, b: any) => a.title.length - b.title.length, - sortOrder: sortedInfo.columnKey === 'title' && sortedInfo.order, - }, - { - title: 'URL', - dataIndex: 'url', - key: 'url', - width: 300, - ellipsis: true, - sorter: (a: any, b: any) => a.url.length - b.url.length, - sortOrder: sortedInfo.columnKey === 'url' && sortedInfo.order, - }, - { - title: 'Begin', - dataIndex: 'beginDate', - key: 'beginDate', - width: 170, - onFilter: (value: any, record: any) => convertDate(record.beginDate) > value, - sorter: (a: any, b: any) => - convertDate(a.beginDate).valueOf() - convertDate(b.beginDate).valueOf(), - sortOrder: sortedInfo.columnKey === 'beginDate' && sortedInfo.order, - render: (text, record) => ( - - {record.beginDate} - - ), - }, - { - title: 'End', - dataIndex: 'endDate', - key: 'endDate', - width: 170, - onFilter: (value: any, record: any) => convertDate(record.endDate) > value, - sorter: (a: any, b: any) => - convertDate(a.endDate).valueOf() - convertDate(b.endDate).valueOf(), - sortOrder: sortedInfo.columnKey === 'endDate' && sortedInfo.order, - - render: (text, record) => ( - {record.endDate} - ), - }, - - { - title: 'Dur', - dataIndex: '', - key: 'duration', - width: 80, - sorter: (a: any, b: any) => - convertDate(a.endDate).diff(convertDate(a.beginDate)) - - convertDate(b.endDate).diff(convertDate(b.beginDate)), - sortOrder: sortedInfo.columnKey === 'duration' && sortedInfo.order, - - render: (text, record) => ( - {diffAndFormatShort(record.beginDate, record.endDate)} - ), - }, - { - title: '', - dataIndex: '', - key: 'actions', - width: 40, - render: (text, record) => ( - - goToTimelinePage(record)} /> - - ), - }, - ]; - - const { selectedRowKeys } = state; - const rowSelection = { - selectedRowKeys, - onChange: onSelectChange, - }; + return ( + + } + onClick={() => goToTimelinePage({ beginDate, endDate })} + /> + + ); +}; +const extraColumns: ColumnDef[] = [ + { + id: 'actions', + header: '', + enableColumnFilter: false, + cell: ActionCell, + size: 20, + minSize: 20, + maxSize: 20, + }, +]; + +interface SearchResultsProps { + searchResult: SearchResultI; + fetchData: (params: { pageSize: number; pageIndex: number; sortBy: { id: string; desc: boolean }[] }) => void; + pageIndex: number; + resetButtonsRef: React.RefObject; + refreshData: () => void; +} + +const SearchResultsPlain = ({ + searchResult, + fetchData, + pageIndex, + resetButtonsRef, + refreshData, +}: SearchResultsProps) => { return ( - `${record.id}`} - columns={columns} - pagination={paginationConf} - dataSource={searchResult.results} - onChange={handleChange} - footer={calculateTotal} + } /> ); }; diff --git a/client/src/components/Settings/AnalyserForm.tsx b/client/src/components/Settings/AnalyserForm.tsx index af6d13ad..6ed5b9d7 100644 --- a/client/src/components/Settings/AnalyserForm.tsx +++ b/client/src/components/Settings/AnalyserForm.tsx @@ -1,38 +1,52 @@ -import { Flex } from 'reflexbox'; -import { Button, Card, Tooltip } from 'antd'; -import { InfoCircleOutlined, PlusOutlined } from '@ant-design/icons'; -import React, { useState, useEffect } from 'react'; -import { AnalyserFormItem } from './AnalyserFormItem'; -import { fetchAnalyserSettings, saveAnalyserSettings } from '../../services/settings.api'; +import { Box, Button, Flex, FormControl, FormLabel, HStack, Switch, Text, Tooltip } from '@chakra-ui/react'; +import { useEffect, useState } from 'react'; +import { AiOutlineInfoCircle } from 'react-icons/ai'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { + fetchAnalyserSettings, + getTaskAnalyserEnabled, + saveAnalyserSettings, + setTaskAnalyserEnabled, +} from '../../services/settings.api'; import { useStoreState } from '../../store/easyPeasy'; +import { CardBox } from '../CardBox'; +import { AnalyserItem } from './AnalyserForm.util'; +import { AnalyserFormItem } from './AnalyserFormItem'; -const defaultAnalyserSettings = [ +const defaultAnalyserSettings: AnalyserItem[] = [ { findRe: '\\w+-\\d+.*JIRA', takeTitle: '', takeGroup: '\\w+-\\d+', enabled: true }, { findRe: '9GAG', takeTitle: '', takeGroup: '9GAG', enabled: true }, ]; -const emptyItem = { findRe: '', takeTitle: '', takeGroup: '', enabled: false }; +const emptyItem: AnalyserItem = { findRe: '', takeTitle: '', takeGroup: '', enabled: false }; + +const EMPTY_APP_ITEMS: ITrackItem[] = []; export const AnalyserForm = () => { - const timeItems = useStoreState(state => state.timeItems); - const { appItems } = timeItems; - const [analyserItems, setAnalyserItems] = useState([]); + const timeItems = useStoreState((state) => state.timeItems); + const appItems = timeItems[TrackItemType.AppTrackItem]; + const [analyserItems, setAnalyserItems] = useState([]); + const [isAnalyserEnabled, setIsAnalyserEnabled] = useState(false); useEffect(() => { async function fetchSettings() { const items = await fetchAnalyserSettings(); setAnalyserItems(items || []); + + const enabled = await getTaskAnalyserEnabled(); + setIsAnalyserEnabled(enabled); } fetchSettings(); }, []); - const removeItem = index => () => { + const removeItem = (index: number) => () => { analyserItems.splice(index, 1); setAnalyserItems([...analyserItems]); saveAnalyserSettings([...analyserItems]); }; - const saveItem = index => data => { + const saveItem = (index: number) => (data: AnalyserItem) => { analyserItems[index] = data; setAnalyserItems([...analyserItems]); saveAnalyserSettings([...analyserItems]); @@ -44,33 +58,84 @@ export const AnalyserForm = () => { const setDefaults = () => { setAnalyserItems([...analyserItems, ...defaultAnalyserSettings]); + saveAnalyserSettings([...analyserItems, ...defaultAnalyserSettings]); + }; + + const handleAnalyserToggle = async (e) => { + const enabled = e.target.checked; + setIsAnalyserEnabled(enabled); + await setTaskAnalyserEnabled(enabled); }; return ( - - - + isAnalyserEnabled && ( + + + + + + + + + + ) } > - {analyserItems.map((item, index) => ( - - ))} - - - - + {isAnalyserEnabled && ( + <> + + + Note: Please ensure that notifications are allowed in your system settings, as they may not + appear otherwise. + + + {analyserItems.map((item, index) => ( + + ))} + + + + + )} + ); }; diff --git a/client/src/components/Settings/AnalyserForm.util.test.ts b/client/src/components/Settings/AnalyserForm.util.test.ts new file mode 100644 index 00000000..40a5e920 --- /dev/null +++ b/client/src/components/Settings/AnalyserForm.util.test.ts @@ -0,0 +1,232 @@ +import { describe, expect, it } from 'vitest'; +import type { ITrackItem } from '../../@types/ITrackItem'; +import type { AnalyserItem, AnalyserTestItemI } from './AnalyserForm.util'; +import { findFirst, testAnalyserItem } from './AnalyserForm.util'; + +describe('findFirst', () => { + it('should return undefined when findRe is empty', () => { + expect(findFirst('test string', '')).toBeUndefined(); + }); + + it('should return the first match when pattern is found', () => { + expect(findFirst('JIRA-123 Some task', '\\w+-\\d+')).toBe('JIRA-123'); + }); + + it('should return undefined when pattern is not found', () => { + expect(findFirst('No match here', '\\d{3}')).toBeUndefined(); + }); + + it('should handle special characters in regex', () => { + expect(findFirst('(test) [group]', '\\(.*?\\)')).toBe('(test)'); + }); + + it('should handle invalid regex patterns gracefully', () => { + // Unterminated group + expect(findFirst('test string', '(abc')).toBeUndefined(); + // Unmatched closing parenthesis + expect(findFirst('test string', 'abc)')).toBeUndefined(); + // Invalid character class + expect(findFirst('test string', '[abc')).toBeUndefined(); + // Invalid quantifier + expect(findFirst('test string', 'abc{2,1}')).toBeUndefined(); + }); +}); + +describe('testAnalyserItem', () => { + const mockAnalyserSetting: AnalyserItem = { + findRe: '\\w+-\\d+', + takeTitle: 'Task:\\s*(.*)', + takeGroup: '\\w+-\\d+', + enabled: true, + }; + + it('should return empty array when appItems is null or undefined', () => { + expect(testAnalyserItem(undefined!, mockAnalyserSetting)).toEqual([]); + }); + + it('should handle invalid regex patterns in analyser settings', () => { + const invalidPatterns: AnalyserItem[] = [ + { + // Unterminated group + findRe: '(abc', + takeTitle: 'Task:\\s*(.*)', + takeGroup: '\\w+-\\d+', + enabled: true, + }, + { + // Valid findRe but invalid takeTitle + findRe: '\\w+-\\d+', + takeTitle: '(Task:.*', + takeGroup: '\\w+-\\d+', + enabled: true, + }, + { + // Valid findRe but invalid takeGroup + findRe: '\\w+-\\d+', + takeTitle: 'Task:\\s*(.*)', + takeGroup: '[group', + enabled: true, + }, + ]; + + const mockAppItems: ITrackItem[] = [ + { + id: 1, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + ]; + const firstPattern = invalidPatterns[0]; + const result = testAnalyserItem(mockAppItems, firstPattern); + expect(result).toEqual([]); + + const secondPattern = invalidPatterns[1]; + const result2 = testAnalyserItem(mockAppItems, secondPattern); + expect(result2).toEqual([ + { + findRe: 'JIRA-123', + takeGroup: 'JIRA-123', + takeTitle: 'JIRA-123 Task: Fix bug', + title: 'JIRA-123 Task: Fix bug', + }, + ]); + + const thirdPattern = invalidPatterns[2]; + const result3 = testAnalyserItem(mockAppItems, thirdPattern); + expect(result3).toEqual([ + { + findRe: 'JIRA-123', + takeGroup: 'JIRA-123', + takeTitle: 'Task: Fix bug', + title: 'JIRA-123 Task: Fix bug', + }, + ]); + }); + + it('should process app items and return matching test items', () => { + const mockAppItems: ITrackItem[] = [ + { + id: 1, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 2, + title: 'JIRA-456 Task: Add feature', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 3, + title: 'No match here', + app: 'Other', + beginDate: Date.now(), + endDate: Date.now(), + }, + ]; + + const expected: AnalyserTestItemI[] = [ + { + title: 'JIRA-123 Task: Fix bug', + findRe: 'JIRA-123', + takeGroup: 'JIRA-123', + takeTitle: 'Task: Fix bug', + }, + { + title: 'JIRA-456 Task: Add feature', + findRe: 'JIRA-456', + takeGroup: 'JIRA-456', + takeTitle: 'Task: Add feature', + }, + ]; + + const result = testAnalyserItem(mockAppItems, mockAnalyserSetting); + expect(result).toEqual(expected); + }); + + it('should remove duplicate items based on title', () => { + const mockAppItems: ITrackItem[] = [ + { + id: 1, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 2, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 3, + title: 'JIRA-456 Task: Add feature', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + ]; + + const result = testAnalyserItem(mockAppItems, mockAnalyserSetting); + expect(result.length).toBe(2); // Should only have 2 unique items + expect(result.filter((item) => item.findRe === 'JIRA-123')).toHaveLength(1); + }); + + it('should handle empty or invalid regex patterns', () => { + const invalidAnalyserSetting: AnalyserItem = { + findRe: '', + takeTitle: '', + takeGroup: '', + enabled: true, + }; + + const mockAppItems: ITrackItem[] = [ + { + id: 1, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + ]; + + const result = testAnalyserItem(mockAppItems, invalidAnalyserSetting); + expect(result).toEqual([]); + }); + + it('should handle missing title in app items', () => { + const mockAppItems: ITrackItem[] = [ + { + id: 1, + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 2, + title: '', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + { + id: 3, + title: 'JIRA-123 Task: Fix bug', + app: 'JIRA', + beginDate: Date.now(), + endDate: Date.now(), + }, + ]; + + const result = testAnalyserItem(mockAppItems, mockAnalyserSetting); + expect(result.length).toBe(1); + expect(result[0].title).toBe('JIRA-123 Task: Fix bug'); + }); +}); diff --git a/client/src/components/Settings/AnalyserForm.util.ts b/client/src/components/Settings/AnalyserForm.util.ts index ff6cbe97..6d515c16 100644 --- a/client/src/components/Settings/AnalyserForm.util.ts +++ b/client/src/components/Settings/AnalyserForm.util.ts @@ -1,33 +1,36 @@ -import _ from 'lodash'; +import { uniqBy } from 'lodash'; +import { ITrackItem } from '../../@types/ITrackItem'; import { Logger } from '../../logger'; -export const findFirst = (str, findRe): any => { +export const findFirst = (str: string, findRe: string): string | undefined => { if (!findRe) { - return; + return undefined; } + try { + const re: RegExp = new RegExp(findRe, 'g'); + const result: RegExpExecArray | null = re.exec(str); - const re = new RegExp(findRe, 'g'); - const result = re.exec(str); - - if (result != null) { - const first = result[0]; - - return first; + if (result != null) { + const first: string = result[0]; + return first; + } + } catch (error) { + Logger.error('Error in findFirst', error); } - return; + return undefined; }; -export const testAnalyserItem = (appItems, analyseSetting) => { +export const testAnalyserItem = (appItems: ITrackItem[], analyseSetting: AnalyserItem): Array => { if (!appItems) { Logger.error('appItems not loaded'); return []; } - const testItems: any = []; + const testItems: AnalyserTestItemI[] = []; - appItems.forEach(item => { - const testItem = { ...item }; - const str = testItem.title; + appItems.forEach((item) => { + const testItem: AnalyserTestItemI = { title: item.title || '' }; + const str: string = testItem.title; testItem.findRe = findFirst(str, analyseSetting.findRe); testItem.takeGroup = findFirst(str, analyseSetting.takeGroup) || testItem.findRe; @@ -38,7 +41,20 @@ export const testAnalyserItem = (appItems, analyseSetting) => { } }); - const analyserTestItems = _.uniqBy(testItems, 'title'); + const analyserTestItems = uniqBy(testItems, 'title'); return analyserTestItems; }; + +export interface AnalyserItem { + findRe: string; + takeTitle: string; + takeGroup: string; + enabled: boolean; +} +export interface AnalyserTestItemI { + title: string; + findRe?: string; + takeTitle?: string; + takeGroup?: string; +} diff --git a/client/src/components/Settings/AnalyserFormItem.tsx b/client/src/components/Settings/AnalyserFormItem.tsx index 1b8832cb..a04203c4 100644 --- a/client/src/components/Settings/AnalyserFormItem.tsx +++ b/client/src/components/Settings/AnalyserFormItem.tsx @@ -1,11 +1,27 @@ -import { Box, Flex } from 'reflexbox'; -import { Button, Divider, Form, Input, Switch } from 'antd'; -import { DeleteOutlined } from '@ant-design/icons'; -import React, { useState } from 'react'; -import { useFormState } from 'react-use-form-state'; -import { testAnalyserItem } from './AnalyserForm.util'; - -const AnalyserTestItem = ({ item }) => ( +import { + Box, + Flex, + FormControl, + FormErrorMessage, + FormLabel, + HStack, + IconButton, + Input, + Switch, + Text, +} from '@chakra-ui/react'; +import { useEffect, useId, useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import { AiOutlineDelete } from 'react-icons/ai'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { BlackBox } from '../BlackBox'; +import { AnalyserItem, AnalyserTestItemI, testAnalyserItem } from './AnalyserForm.util'; + +interface AnalyserTestItemProps { + item: AnalyserTestItemI; +} + +const AnalyserTestItem = ({ item }: AnalyserTestItemProps) => ( {item.title} @@ -18,63 +34,167 @@ const AnalyserTestItem = ({ item }) => ( ); -export const AnalyserFormItem = ({ analyserItem, removeItem, appItems, saveItem }) => { +type Inputs = { + findRe: string; + takeGroup: string; + takeTitle: string; + enabled: boolean; +}; + +interface AnalyserFormItemProps { + analyserItem: AnalyserItem; + removeItem: () => void; + appItems: ITrackItem[]; + saveItem: (data: Inputs) => void; +} + +const validateRegex = (value: string) => { + if (!value) return true; // Empty is valid + try { + new RegExp(value); + return true; + } catch (e: unknown) { + if (e instanceof Error) { + return `Invalid regular expression pattern: ${e.message}`; + } + return 'Invalid regular expression pattern'; + } +}; + +export const AnalyserFormItem = ({ analyserItem, removeItem, appItems, saveItem }: AnalyserFormItemProps) => { + // Generate unique IDs for this component instance + const id = useId(); + const enabledSwitchId = `enabled-switch-${id}`; + const testSwitchId = `test-switch-${id}`; + const [showTests, setShowTests] = useState(false); const toggleShowTests = () => { setShowTests(!showTests); }; - const [, { text, raw }] = useFormState(analyserItem, { - onChange: (__ignore, ___ignore, nextStateValues) => { - saveItem(nextStateValues); - }, + const { + watch, + getValues, + reset, + register, + control, + formState: { isDirty, isValid, errors }, + } = useForm({ + mode: 'onChange', + defaultValues: analyserItem, + reValidateMode: 'onChange', }); - const check = raw('enabled'); + const watchAllFields = watch(); + + useEffect(() => { + if (isDirty && isValid) { + console.info('Save values,', getValues(), analyserItem); + saveItem(getValues()); + reset(getValues()); + } + }, [getValues, saveItem, watchAllFields, isDirty, analyserItem, reset, isValid]); + + const analysedItems = (showTests && testAnalyserItem(appItems, analyserItem)) || []; return ( -
    - - - - - - - + + + + + + {errors.findRe && errors.findRe.message} + + + + + {errors.takeGroup && errors.takeGroup.message} + + + + + {errors.takeTitle && errors.takeTitle.message} + + + + + Active + + ( + { + e.preventDefault(); + e.stopPropagation(); + onChange(e.target.checked); + }} + onClick={(e) => e.stopPropagation()} + ref={ref} + size="lg" + /> + )} + /> + - - + + + + Test mode + + { + e.preventDefault(); + toggleShowTests(); + }} + onClick={(e) => e.stopPropagation()} + size="lg" + /> + - - - { - check.onChange(value); + + } + variant="ghost" + onClick={(e) => { + e.preventDefault(); + removeItem(); }} - checked={check.value} + aria-label="Add Item" /> - - - - - -
    +
    ); }; diff --git a/client/src/components/Settings/AppForm.tsx b/client/src/components/Settings/AppForm.tsx index 41c4eb4b..36bc65da 100644 --- a/client/src/components/Settings/AppForm.tsx +++ b/client/src/components/Settings/AppForm.tsx @@ -1,62 +1,131 @@ -import { Card, Form, Switch, Typography } from 'antd'; -import React from 'react'; +import { FormControl, FormLabel, Switch, Text } from '@chakra-ui/react'; +import { ChangeEvent } from 'react'; + import { - getOpenAtLogin, getIsAutoUpdateEnabled, - saveOpenAtLogin, - saveIsAutoUpdateEnabled, getIsLoggingEnabled, + getMacAutoHideMenuBarEnabled, + getNativeThemeChange, + getOpenAtLogin, + getUsePurpleTrayIcon, + saveIsAutoUpdateEnabled, saveIsLoggingEnabled, + saveMacAutoHideMenuBarEnabled, + saveNativeThemeChange, + saveOpenAtLogin, + saveUsePurpleTrayIcon, } from '../../services/settings.api'; - -const { Text } = Typography; +import '../../types/electron-bridge'; +import { CardBox } from '../CardBox'; export const AppForm = () => { + const isNativeThemeEnabled = getNativeThemeChange(); const openAtLogin = getOpenAtLogin(); const isAutoUpdateEnabled = getIsAutoUpdateEnabled(); const isLoggingEnabled = getIsLoggingEnabled(); - const onChangeOpenAtLogin = value => { - saveOpenAtLogin(value); + const usePurpleTrayIcon = getUsePurpleTrayIcon(); + const macAutoHideMenuBarEnabled = getMacAutoHideMenuBarEnabled(); + const onChangeNativeThemeChange = (event: ChangeEvent) => { + saveNativeThemeChange(event.target.checked); + }; + const onChangeOpenAtLogin = (event: ChangeEvent) => { + saveOpenAtLogin(event.target.checked); }; - const onChangeAutoUpdate = value => { - saveIsAutoUpdateEnabled(value); + const onChangeAutoUpdate = (event: ChangeEvent) => { + saveIsAutoUpdateEnabled(event.target.checked); + }; + const onChangeLogging = (event: ChangeEvent) => { + saveIsLoggingEnabled(event.target.checked); + }; + const onChangeUsePurpleTrayIcon = (event: ChangeEvent) => { + saveUsePurpleTrayIcon(event.target.checked); }; - const onChangeLogging = value => { - saveIsLoggingEnabled(value); + const onChangeMacAutoHideMenuBarEnabled = (event: ChangeEvent) => { + saveMacAutoHideMenuBarEnabled(event.target.checked); }; - const appName = process.env.REACT_APP_NAME; - const platform = (window as any).platform; + const appName = import.meta.env.VITE_NAME; + const platform = window.electronBridge.platform; const linuxPath = `~/.config/${appName}/logs/main.log`; const macOSPath = `~/Library/Logs/${appName}/main.log`; const windowsPath = `%USERPROFILE%\\AppData\\Roaming\${appName}\\logs\\main.log`; let logPath = linuxPath; + + const isMacOS = platform === 'darwin'; if (platform === 'win32') { logPath = windowsPath; - } else if (platform === 'darwin') { + } else if (isMacOS) { logPath = macOSPath; } return ( - - - - {' '} Run at login - - - {' '} - Auto update - - - {' '} - Enable logging (Applies after restart) -
    - Log path: {logPath} -
    - -
    + + + + Use OS theme? + + + + + + Run at login? + + + + + + Auto update? + + + + + + + Use purple tray icon? + + + + + + + Enable logging? (Applies after restart) + + + + + Log path: {logPath} + + {window.electronBridge.platform === 'darwin' && ( + <> + + + Enable tray positioning for auto-hide menu bar + + + + + Enable this if you use "Automatically hide and show the menu bar" in macOS settings + + + )} + ); }; diff --git a/client/src/components/Settings/AppVersion.tsx b/client/src/components/Settings/AppVersion.tsx new file mode 100644 index 00000000..e107ef9c --- /dev/null +++ b/client/src/components/Settings/AppVersion.tsx @@ -0,0 +1,30 @@ +import { Box, Text } from '@chakra-ui/react'; +import { useEffect, useState } from 'react'; +import '../../types/electron-bridge'; + +export const AppVersion = () => { + const [appVersion, setAppVersion] = useState('-'); + + useEffect(() => { + const fetchVersion = async () => { + try { + if (window?.electronBridge?.appVersion) { + const version = await window.electronBridge.appVersion(); + setAppVersion(version); + } + } catch (error) { + console.error('Error fetching app version:', error); + } + }; + + fetchVersion(); + }, []); + + return ( + + + Version: {appVersion} + + + ); +}; diff --git a/client/src/components/Settings/DataForm.tsx b/client/src/components/Settings/DataForm.tsx new file mode 100644 index 00000000..cd504fa6 --- /dev/null +++ b/client/src/components/Settings/DataForm.tsx @@ -0,0 +1,78 @@ +import { Box, FormControl, FormErrorMessage, FormLabel, Input, Text } from '@chakra-ui/react'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { useContext, useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import { useDebouncedCallback } from 'use-debounce'; +import * as yup from 'yup'; +import { RootContext } from '../../RootContext'; +import { CardBox } from '../CardBox'; +import { DataSettingsI } from './DataForm.util'; + +const schema = yup + .object({ + idleAfterSeconds: yup.string().required().label('Idle after in Seconds'), + backgroundJobInterval: yup.number().required().positive().integer().label('Session Length'), + }) + .required(); + +export const DataForm = () => { + const { dataSettings, updateDataSettings } = useContext(RootContext); + + const { + watch, + reset, + formState: { errors, isDirty, isValid }, + register, + } = useForm({ mode: 'onChange', defaultValues: dataSettings, resolver: yupResolver(schema) }); + + const watchAllFields = watch(); + + const debouncedUpdate = useDebouncedCallback( + (value) => { + console.info('Save values: ', value); + updateDataSettings(value); + }, + 1000, + { leading: false, trailing: true }, + ); + + useEffect(() => { + if (isDirty && isValid) { + const formValues = watchAllFields; + debouncedUpdate(formValues); + reset(formValues); + } else if (isDirty) { + debouncedUpdate.cancel(); + } + }, [watchAllFields, isDirty, isValid, debouncedUpdate, reset]); + + return ( + + + Background job interval (in seconds) + + + {errors.backgroundJobInterval && errors.backgroundJobInterval.message} + + + + + Background job runs every 3 seconds by default. In there application checks active window title and + the state of system (idle, offline, online) + + + + + Idle after (in seconds) + + {errors.idleAfterSeconds && errors.idleAfterSeconds.message} + + + + + Time when system adds "Idle" item to timeline. + + + + ); +}; diff --git a/client/src/components/Settings/DataForm.util.tsx b/client/src/components/Settings/DataForm.util.tsx new file mode 100644 index 00000000..126b5440 --- /dev/null +++ b/client/src/components/Settings/DataForm.util.tsx @@ -0,0 +1,5 @@ +export type DataSettingsI = { + idleAfterSeconds: number; + backgroundJobInterval: number; + recentDaysCount: number; +}; diff --git a/client/src/components/Settings/LocaleSelect.tsx b/client/src/components/Settings/LocaleSelect.tsx deleted file mode 100644 index 05cca9b4..00000000 --- a/client/src/components/Settings/LocaleSelect.tsx +++ /dev/null @@ -1,31 +0,0 @@ -import { Select } from 'antd'; -import React from 'react'; -import moment from 'moment'; -import { useAppDataState } from '../../routes/AppDataProvider'; -import etEe from 'antd/es/locale/et_EE'; -import { Logger } from '../../logger'; - -const { Option } = Select; - -export const LocaleSelect = () => { - const localeList = moment.locales(); - const defaultLocale = moment.locale(); - - const state: any = useAppDataState(); - - function handleChange(value) { - Logger.debug(`Setting locale ${value}`); - moment.locale(value); - state.setLocale(etEe); - } - - return ( - - ); -}; diff --git a/client/src/components/Settings/SettingsForm.styles.ts b/client/src/components/Settings/SettingsForm.styles.ts deleted file mode 100644 index b3bf3308..00000000 --- a/client/src/components/Settings/SettingsForm.styles.ts +++ /dev/null @@ -1,6 +0,0 @@ -import styled from 'styled-components'; - -export const EditForm = styled.div``; - -export const labelCol = { span: 6, offset: 0 }; -export const wrapperCol = { span: 14, offset: 0 }; diff --git a/client/src/components/Settings/SettingsForm.tsx b/client/src/components/Settings/SettingsForm.tsx index fe5f5f2b..7481aa86 100644 --- a/client/src/components/Settings/SettingsForm.tsx +++ b/client/src/components/Settings/SettingsForm.tsx @@ -1,31 +1,22 @@ -import { Box, Flex } from 'reflexbox'; -import { Form } from 'antd'; -import React from 'react'; +import { Divider, VStack } from '@chakra-ui/react'; +import '../../types/electron-bridge'; import { AnalyserForm } from './AnalyserForm'; import { AppForm } from './AppForm'; +import { AppVersion } from './AppVersion'; +import { DataForm } from './DataForm'; import { WorkForm } from './WorkForm'; -import { ThemeSelect } from './ThemeSelect'; export const SettingsForm = () => { return ( -
    - - - - - - - - + + + + + - - - - - - - - - + + + + ); }; diff --git a/client/src/components/Settings/ThemeSelect.tsx b/client/src/components/Settings/ThemeSelect.tsx deleted file mode 100644 index bc274768..00000000 --- a/client/src/components/Settings/ThemeSelect.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Select } from 'antd'; -import React from 'react'; -import { Box, Flex } from 'reflexbox'; -import { ColorPicker } from '../Timeline/ColorPicker'; -import { useStoreActions, useStoreState } from '../../store/easyPeasy'; -import { PRIMARY_COLOR_VAR, themes } from '../../store/theme.util'; - -export const ThemeSelect = () => { - const theme: any = useStoreState(state => state.theme); - const setThemeByName = useStoreActions(actions => actions.setThemeByName); - const setThemeWithVariables = useStoreActions(actions => actions.setThemeWithVariables); - - return ( - - -

    Selected Theme

    -
    - - - - - { - setThemeWithVariables({ - ...theme, - variables: { - ...theme.variables, - [PRIMARY_COLOR_VAR]: color, - }, - }); - }} - /> - -
    - ); -}; diff --git a/client/src/components/Settings/WorkForm.tsx b/client/src/components/Settings/WorkForm.tsx index 56684668..07179f8e 100644 --- a/client/src/components/Settings/WorkForm.tsx +++ b/client/src/components/Settings/WorkForm.tsx @@ -1,30 +1,146 @@ -import { Card, Input, Typography } from 'antd'; -import { ClockCircleOutlined } from '@ant-design/icons'; -import React, { useContext } from 'react'; -import { useFormState } from 'react-use-form-state'; +import { + Box, + Button, + Divider, + FormControl, + FormErrorMessage, + FormHelperText, + FormLabel, + Input, + Switch, + Text, +} from '@chakra-ui/react'; +import { yupResolver } from '@hookform/resolvers/yup'; +import { useContext, useEffect } from 'react'; +import { useForm } from 'react-hook-form'; +import { useDebouncedCallback } from 'use-debounce'; +import * as yup from 'yup'; import { RootContext } from '../../RootContext'; +import { notifyUser } from '../../services/settings.api'; +import { CardBox } from '../CardBox'; +import { WorkSettingsI } from './WorkForm.util'; -const { Text } = Typography; +const schema = yup + .object({ + hoursToWork: yup.string().required().label('Hours to work'), + sessionLength: yup.number().required().positive().integer().label('Session Length'), + notificationDuration: yup.number().required().positive().integer().label('Notification duration'), + minBreakTime: yup.number().required().positive().integer().label('Min break time'), + reNotifyInterval: yup.number().required().integer().label('Re-notify interval'), + smallNotificationsEnabled: yup.boolean().label('Notifications'), + }) + .required(); export const WorkForm = () => { - const { workSettings, setWorkSettings } = useContext(RootContext); - // tslint:disable-next-line: variable-name - const [, { number }] = useFormState(workSettings, { - onChange: (__ignore, ___ignore, nextStateValues) => { - setWorkSettings(nextStateValues); + const { workSettings, updateWorkSettings } = useContext(RootContext); + + const { + watch, + reset, + formState: { errors, isDirty, isValid }, + register, + } = useForm({ mode: 'onChange', defaultValues: workSettings, resolver: yupResolver(schema) }); + + const watchAllFields = watch(); + + const debouncedUpdate = useDebouncedCallback( + (value) => { + console.info('Save values: ', value); + updateWorkSettings(value); }, - }); + 1000, + { leading: false, trailing: true }, + ); + + useEffect(() => { + if (isDirty && isValid) { + const formValues = watchAllFields; + debouncedUpdate(formValues); + reset(formValues); + } else if (isDirty) { + debouncedUpdate.cancel(); + } + }, [watchAllFields, isDirty, isValid, debouncedUpdate, reset]); + + const smallNotificationsEnabled = watch('smallNotificationsEnabled'); + const minBreakTime = watch('minBreakTime'); return ( - - } - maxLength={25} - {...number({ name: 'hoursToWork' })} - /> - - Used in Progress pie chart to calculate workday progress - + + + Workday length + + {errors.hoursToWork && errors.hoursToWork.message} + + + + + + + + Break notify settings + + + + + Used to show one session progress in tray graphic and to notify about a break. The idea of this + notification is for you not to lose focus, but to remind you to take a break if you are in between + some work. + + + + Session length in minutes + + {errors.sessionLength && errors.sessionLength.message} + {smallNotificationsEnabled && ( + + You are notified if online time exceeds this. Ignoring idle times less than {minBreakTime}{' '} + minutes + + )} + + + + + Reminder notifications enabled + + + + + + Re-Notify interval minutes + + {errors.reNotifyInterval && errors.reNotifyInterval.message} + + + Notification duration in seconds + + + {errors.notificationDuration && errors.notificationDuration.message} + + + + Min break time in minutes + + {errors.minBreakTime && errors.minBreakTime.message} + + + + + ); }; diff --git a/client/src/components/Settings/WorkForm.util.tsx b/client/src/components/Settings/WorkForm.util.tsx new file mode 100644 index 00000000..ced498cb --- /dev/null +++ b/client/src/components/Settings/WorkForm.util.tsx @@ -0,0 +1,11 @@ +export type WorkSettingsI = { + workDayStartTime: string; + workDayEndTime: string; + splitTaskAfterIdlingForMinutes: number; + hoursToWork: number; + sessionLength: number; + minBreakTime: number; + notificationDuration: number; + reNotifyInterval: number; + smallNotificationsEnabled: boolean; +}; diff --git a/client/src/components/SummaryCalendar/ItemIcon.tsx b/client/src/components/SummaryCalendar/ItemIcon.tsx new file mode 100644 index 00000000..a7b6bc76 --- /dev/null +++ b/client/src/components/SummaryCalendar/ItemIcon.tsx @@ -0,0 +1,13 @@ +import { Box } from '@chakra-ui/react'; + +export const ItemIcon = (props) => ( + +); diff --git a/client/src/components/SummaryCalendar/SummaryCalendar.styles.ts b/client/src/components/SummaryCalendar/SummaryCalendar.styles.ts deleted file mode 100644 index f9c95003..00000000 --- a/client/src/components/SummaryCalendar/SummaryCalendar.styles.ts +++ /dev/null @@ -1,13 +0,0 @@ -import styled from 'styled-components'; - -export const TaskList = styled.ul` - list-style: none; - margin: 0; - padding: 0; -`; - -export const Item = styled.li` - list-style: none; - margin: 0; - padding: 0; -`; diff --git a/client/src/components/SummaryCalendar/SummaryCalendar.tsx b/client/src/components/SummaryCalendar/SummaryCalendar.tsx index d521413b..4f37e174 100644 --- a/client/src/components/SummaryCalendar/SummaryCalendar.tsx +++ b/client/src/components/SummaryCalendar/SummaryCalendar.tsx @@ -1,31 +1,55 @@ -import { Flex } from 'reflexbox'; -import { Calendar, Spin } from 'antd'; -import { CoffeeOutlined, EyeOutlined, LaptopOutlined, ToolOutlined } from '@ant-design/icons'; -import moment from 'moment'; -import React, { useContext, useEffect } from 'react'; -import useReactRouter from 'use-react-router'; +import { Box, Flex, Text, useColorModeValue, VStack } from '@chakra-ui/react'; +import { DateTime } from 'luxon'; +import { useContext, useEffect } from 'react'; +import { IoMdMoon, IoMdSunny } from 'react-icons/io'; +import { useNavigate } from 'react-router-dom'; import { SummaryContext } from '../../SummaryContext'; -import { Spinner } from '../Timeline/Timeline.styles'; -import { Item, TaskList } from './SummaryCalendar.styles'; -import { Logger } from '../../logger'; +import { CALENDAR_MODE, DAY_MONTH_FORMAT } from '../../SummaryContext.util'; import { convertDate, TIME_FORMAT_SHORT } from '../../constants'; -import { formatDuration } from './SummaryCalendar.util'; -import classNames from 'classnames'; -import padStart from 'lodash/padStart'; -import { DAY_MONTH_FORMAT } from '../../SummaryContext.util'; +import { Logger } from '../../logger'; import { useStoreActions, useStoreState } from '../../store/easyPeasy'; - -moment.locale('et'); +import { formatDurationInternal } from '../../utils'; +import { Calendar } from '../Datepicker/Calendar'; +import { Loader } from '../Timeline/Loader'; +import { ItemIcon } from './ItemIcon'; const icons = { - coffee: , - 'eye-invisible': , - laptop: , - tool: , + wakeTime: ( + + + + ), + sleepTime: ( + + + + ), + online:  , + tasks:  , }; + +const DayContent = ({ listData }) => { + const color = useColorModeValue('black', 'gray.300'); + return ( + + {listData.map((item) => ( + + {icons[item.type]} + + {item.time} + + + {item.title} + + + ))} + + ); +}; + export const SummaryCalendar = () => { - const timerange = useStoreState(state => state.timerange); - const loadTimerange = useStoreActions(state => state.loadTimerange); + const timerange = useStoreState((state) => state.timerange); + const loadTimerange = useStoreActions((state) => state.loadTimerange); const { selectedDate, @@ -38,21 +62,16 @@ export const SummaryCalendar = () => { isLoading, } = useContext(SummaryContext); - const { history } = useReactRouter(); + const navigate = useNavigate(); - const onDateClicked = (date: any) => { + const onDateClicked = (date: DateTime) => { if (!date) { Logger.error('No date'); return; } - loadTimerange([date.clone().startOf('day'), date.clone().endOf('day')]); - history.push('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/app/timeline'); - }; - - const changeSelectedDate = (date?: any, mode?: 'month' | 'year') => { - setSelectedDate(date); - setSelectedMode(mode); + loadTimerange([date.startOf('day'), date.endOf('day')]); + navigate('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/app/timeline'); }; useEffect(() => { @@ -60,112 +79,63 @@ export const SummaryCalendar = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const getListData = day => { - const listData: any[] = []; + const getListData = (day: string) => { + const listData: Array<{ type: string; time: string; title: string }> = []; const times = onlineTimesSummary[day]; if (times) { listData.push({ - type: 'coffee', - content: `Wake time ${convertDate(times.beginDate).format(TIME_FORMAT_SHORT)}`, + type: 'wakeTime', + time: convertDate(times.beginDate).toFormat(TIME_FORMAT_SHORT), + title: `Wake time`, }); listData.push({ - type: 'eye-invisible', - content: `Sleep time ${convertDate(times.endDate).format(TIME_FORMAT_SHORT)}`, + type: 'sleepTime', + time: convertDate(times.endDate).toFormat(TIME_FORMAT_SHORT), + title: `Sleep time`, }); } const online = onlineSummary[day]; if (online) { - listData.push({ type: 'laptop', content: `Worked ${formatDuration(online)}` }); + listData.push({ type: 'online', time: formatDurationInternal(online), title: `Online` }); } const worked = logSummary[day]; if (worked) { - listData.push({ type: 'tool', content: `Tasks ${formatDuration(worked)}` }); + listData.push({ type: 'tasks', time: formatDurationInternal(worked), title: `Tasks` }); } return listData || []; }; - const dateCellRender = value => { - if (value.month() === selectedDate.month()) { - const listData = getListData(value.format(DAY_MONTH_FORMAT)); - return ( - - {listData.map(item => ( - - {icons[item.type]} - {' '} - {item.content} - - ))} - - ); - } - return null; - }; - - const dateFullCellRender = date => { - let style = {}; - - const day = date.day(); - const isWeekend = day === 6 || day === 0; - const isToday = moment().isSame(date, 'day'); - if (isWeekend) { - if (isToday) { - style = { background: '#e6f7ff' }; - } else { - style = { background: 'rgb(230, 230, 230, 0.2)' }; + const dateCellRender = (value: DateTime) => { + if (selectedMode === CALENDAR_MODE.MONTH) { + if (value.month === selectedDate.month) { + const listData = getListData(value.toFormat(DAY_MONTH_FORMAT)); + return ; } + return null; + } else if (selectedMode === CALENDAR_MODE.YEAR) { + const listData = getListData(value.month.toString()); + return ; + } else { + Logger.error('Unknown mode for calendar'); } - return ( -
    onDateClicked(date)} - > -
    - {padStart(date.date(), 2, '0')} -
    -
    - {dateCellRender && dateCellRender(date)} -
    -
    - ); - }; - - const monthCellRender = value => { - const listData = getListData(value.month()); - return ( - - {listData.map(item => ( - - {icons[item.type]} - {' '} - {item.content} - - ))} - - ); }; return ( - - {isLoading && ( - - - - )} + <> + {isLoading && } + - + ); }; diff --git a/client/src/components/SummaryCalendar/SummaryCalendar.util.test.ts b/client/src/components/SummaryCalendar/SummaryCalendar.util.test.ts index 0fd9ad08..5731a994 100644 --- a/client/src/components/SummaryCalendar/SummaryCalendar.util.test.ts +++ b/client/src/components/SummaryCalendar/SummaryCalendar.util.test.ts @@ -1,10 +1,12 @@ +import { DateTime } from 'luxon'; +import { describe, expect, it } from 'vitest'; +import { CALENDAR_MODE } from '../../SummaryContext.util'; import { summariseTimeOnline } from './SummaryCalendar.util'; import { TEST_INPUT } from './SummaryCalendar.util.testdata'; -import moment from 'moment'; describe('summariseTimeOnline', () => { it('parses online items', () => { - const actual = summariseTimeOnline(TEST_INPUT, 'month', moment(1589311528755)); + const actual = summariseTimeOnline(TEST_INPUT, CALENDAR_MODE.MONTH, DateTime.fromMillis(1589311528755)); const result = { '05-12': { beginDate: 1589311528755, endDate: 1589312113568, online: 358396 }, '05-14': { beginDate: 1589480558049, endDate: 1589483666850, online: 2707998 }, @@ -18,16 +20,21 @@ describe('summariseTimeOnline', () => { it('online item over midnight - until 04:00 - it goes to previous day', () => { const input = [ { + id: 1, app: 'ONLINE', - beginDate: moment('2020-04-10 02:30').valueOf(), - endDate: moment('2020-04-10 03:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 02:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 03:30', 'yyyy-MM-dd HH:mm').toMillis(), }, ]; - const actual = summariseTimeOnline(input, 'month', moment('2020-04-10 04:30')); + const actual = summariseTimeOnline( + input, + CALENDAR_MODE.MONTH, + DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm'), + ); const result = { '04-09': { - beginDate: moment('2020-04-10 02:30').valueOf(), - endDate: moment('2020-04-10 03:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 02:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 03:30', 'yyyy-MM-dd HH:mm').toMillis(), online: 3600000, }, }; @@ -38,16 +45,21 @@ describe('summariseTimeOnline', () => { it('online item after 04:00 goes to correct day', () => { const input = [ { + id: 1, app: 'ONLINE', - beginDate: moment('2020-04-10 04:30').valueOf(), - endDate: moment('2020-04-10 05:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 05:30', 'yyyy-MM-dd HH:mm').toMillis(), }, ]; - const actual = summariseTimeOnline(input, 'month', moment('2020-04-10 04:30')); + const actual = summariseTimeOnline( + input, + CALENDAR_MODE.MONTH, + DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm'), + ); const result = { '04-10': { - beginDate: moment('2020-04-10 04:30').valueOf(), - endDate: moment('2020-04-10 05:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 05:30', 'yyyy-MM-dd HH:mm').toMillis(), online: 3600000, }, }; @@ -58,31 +70,39 @@ describe('summariseTimeOnline', () => { it('woke up 04:30 and went to sleep 03:30', () => { const input = [ { + id: 1, app: 'ONLINE', - beginDate: moment('2020-04-10 04:30').valueOf(), - endDate: moment('2020-04-10 05:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 05:30', 'yyyy-MM-dd HH:mm').toMillis(), }, { + id: 2, app: 'ONLINE', - beginDate: moment('2020-04-10 11:30').valueOf(), - endDate: moment('2020-04-10 15:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 11:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-10 15:30', 'yyyy-MM-dd HH:mm').toMillis(), }, { + id: 3, app: 'ONLINE', - beginDate: moment('2020-04-10 23:30').valueOf(), - endDate: moment('2020-04-11 01:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 23:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-11 01:30', 'yyyy-MM-dd HH:mm').toMillis(), }, { + id: 4, app: 'ONLINE', - beginDate: moment('2020-04-11 02:30').valueOf(), - endDate: moment('2020-04-11 03:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-11 02:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-11 03:30', 'yyyy-MM-dd HH:mm').toMillis(), }, ]; - const actual = summariseTimeOnline(input, 'month', moment('2020-04-10 04:30')); + const actual = summariseTimeOnline( + input, + CALENDAR_MODE.MONTH, + DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm'), + ); const result = { '04-10': { - beginDate: moment('2020-04-10 04:30').valueOf(), - endDate: moment('2020-04-11 03:30').valueOf(), + beginDate: DateTime.fromFormat('2020-04-10 04:30', 'yyyy-MM-dd HH:mm').toMillis(), + endDate: DateTime.fromFormat('2020-04-11 03:30', 'yyyy-MM-dd HH:mm').toMillis(), online: 28800000, }, }; @@ -93,4 +113,4 @@ describe('summariseTimeOnline', () => { export // Use an empty export to please Babel's single file emit. // https://github.com/Microsoft/TypeScript/issues/15230 -{}; + {}; diff --git a/client/src/components/SummaryCalendar/SummaryCalendar.util.ts b/client/src/components/SummaryCalendar/SummaryCalendar.util.ts index 3775d7b1..5e3df951 100644 --- a/client/src/components/SummaryCalendar/SummaryCalendar.util.ts +++ b/client/src/components/SummaryCalendar/SummaryCalendar.util.ts @@ -1,76 +1,86 @@ import _ from 'lodash'; -import { - convertDate, - TIME_FORMAT, - BREAKPOINT_TIME, - DURATION_FORMAT, - DURATION_SETTINGS, -} from '../../constants'; -import moment from 'moment'; -import { DAY_MONTH_FORMAT, MODE_MONTH } from '../../SummaryContext.util'; - -export const formatDuration = dur => - moment.duration(dur).format(DURATION_FORMAT, DURATION_SETTINGS); - -export const groupByField = mode => item => - mode === MODE_MONTH - ? convertDate(item.beginDate).format(DAY_MONTH_FORMAT) - : convertDate(item.beginDate).month(); - -export const groupByActualDay = item => { +import { DateTime } from 'luxon'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { BREAKPOINT_TIME, convertDate, TIME_FORMAT } from '../../constants'; +import { CALENDAR_MODE, DAY_MONTH_FORMAT } from '../../SummaryContext.util'; + +export const groupByField = (mode) => (item) => + mode === CALENDAR_MODE.MONTH + ? convertDate(item.beginDate).toFormat(DAY_MONTH_FORMAT) + : convertDate(item.beginDate).month; + +export const groupByActualDay = (item) => { const date = convertDate(item.beginDate); - if (date.format(TIME_FORMAT) < BREAKPOINT_TIME) { - return date.subtract(1, 'day').format(DAY_MONTH_FORMAT); + if (date.toFormat(TIME_FORMAT) < BREAKPOINT_TIME) { + return date.minus({ days: 1 }).toFormat(DAY_MONTH_FORMAT); } - return date.format(DAY_MONTH_FORMAT); + return date.toFormat(DAY_MONTH_FORMAT); }; -export const summariseLog = (items, mode) => { - const data = {}; +export interface ISummary { + [key: string]: number; +} + +export const summariseLog = (items: ITrackItem[], mode: CALENDAR_MODE): ISummary => { + const data: ISummary = {}; _(items) .groupBy(groupByField(mode)) .forEach((value, key) => { - data[key] = _.sumBy(value, c => convertDate(c.endDate).diff(convertDate(c.beginDate))); + data[key] = _.sumBy(value, (c) => convertDate(c.endDate).diff(convertDate(c.beginDate)).milliseconds); }); return data; }; export const summariseOnline = (items, mode) => { - const data = {}; + const data: ISummary = {}; _(items) - .filter(item => item.app === 'ONLINE') + .filter((item) => item.app === 'ONLINE') .groupBy(groupByField(mode)) .forEach((value, key) => { - data[key] = _.sumBy(value, c => convertDate(c.endDate).diff(convertDate(c.beginDate))); + data[key] = _.sumBy(value, (c) => convertDate(c.endDate).diff(convertDate(c.beginDate)).milliseconds); }); return data; }; -export const summariseTimeOnline = (items, mode, beginDate) => { +interface IOnlineTime { + beginDate: Date; + endDate: Date; + online: number; +} + +export interface ISummaryOnlineTime { + [key: string]: IOnlineTime; +} + +export const summariseTimeOnline = ( + items: ITrackItem[], + mode: CALENDAR_MODE, + beginDate: DateTime, +): ISummaryOnlineTime => { if (mode === 'year') { - return []; + return {}; } // We are taking sleep time from next months first day, but going to remove it from end result - const currentMonth = beginDate.month(); + const currentMonth = beginDate.month; const data = _(items) - .filter(item => item.app === 'ONLINE') + .filter((item) => item.app === 'ONLINE') .groupBy(groupByActualDay) - .map((value, key) => { + .map((value) => { return { - beginDate: _.minBy(value, c => convertDate(c.beginDate)).beginDate, - endDate: _.maxBy(value, c => convertDate(c.endDate)).endDate, - online: _.sumBy(value, c => convertDate(c.endDate).diff(convertDate(c.beginDate))), + beginDate: _.minBy(value, (c) => convertDate(c.beginDate).toMillis())?.beginDate, + endDate: _.maxBy(value, (c) => convertDate(c.endDate).toMillis())?.endDate, + online: _.sumBy(value, (c) => convertDate(c.endDate).diff(convertDate(c.beginDate)).milliseconds), }; }) .reduce((result, currentValue) => { const key = groupByActualDay(currentValue); - const month = moment(key, DAY_MONTH_FORMAT).month(); + const month = DateTime.fromFormat(key, DAY_MONTH_FORMAT).month; if (currentMonth === month) { result[key] = currentValue; @@ -78,5 +88,6 @@ export const summariseTimeOnline = (items, mode, beginDate) => { return result; }, {}); + console.log('data', data); return data; }; diff --git a/client/src/components/TaskList.tsx b/client/src/components/TaskList.tsx new file mode 100644 index 00000000..a443423c --- /dev/null +++ b/client/src/components/TaskList.tsx @@ -0,0 +1,53 @@ +import _ from 'lodash'; + +import { Box, HStack, Text } from '@chakra-ui/react'; +import { useStoreState } from '../store/easyPeasy'; +import { sumAppObject, SumItem } from './PieCharts/MetricTiles.utils'; +import { filterItems } from './Timeline/timeline.utils'; + +import { TrackItemType } from '../enum/TrackItemType'; +import { shortTime } from '../time.util'; + +export const TaskList = () => { + const timeItems = useStoreState((state) => state.timeItems); + const timerange = useStoreState((state) => state.timerange); + + const logItems = filterItems(timeItems[TrackItemType.LogTrackItem] || [], timerange); + + const groupByField = 'app'; + + const data = _(logItems) + .groupBy(groupByField) + .map((b) => { + return b.reduce(sumAppObject(timerange), { + app: b[0].app, + title: b[0].title, + timeDiffInMs: 0, + color: b[0].color, + } as SumItem); + }) + .valueOf(); + + return ( + <> + {data.map(({ app, title, color, timeDiffInMs }) => { + return ( + + + + + {app} + + + + {title} + + + {shortTime(timeDiffInMs)} + + + ); + })} + + ); +}; diff --git a/client/src/components/TileBox.tsx b/client/src/components/TileBox.tsx new file mode 100644 index 00000000..fd9f398a --- /dev/null +++ b/client/src/components/TileBox.tsx @@ -0,0 +1,14 @@ +import { Box, useColorModeValue } from '@chakra-ui/react'; + +export const TileBox = ({ children, ...rest }) => ( + + {children} + +); diff --git a/client/src/components/Timeline/BarWithTooltip.tsx b/client/src/components/Timeline/BarWithTooltip.tsx index 43bf0491..33505f43 100644 --- a/client/src/components/Timeline/BarWithTooltip.tsx +++ b/client/src/components/Timeline/BarWithTooltip.tsx @@ -1,16 +1,34 @@ -import React, { useState } from 'react'; +import { useRef, useState } from 'react'; import { Portal } from 'react-portal'; import { Bar, VictoryTooltip } from 'victory'; +interface PropsI { + datum?: {}; + onClickBarItem?: any; + getTooltipLabel: any; + popoverTriggerRef?: any; + x?: number; + y?: number; + theme: any; + centerTime?: boolean; +} + +const calculateMiddle = (datum) => { + return datum.beginDate + (datum.endDate - datum.beginDate) / 2; +}; + export const BarWithTooltip = ({ datum = {}, onClickBarItem, getTooltipLabel, + popoverTriggerRef = null, x = 0, y = 0, theme, + centerTime = false, ...rest -}) => { +}: PropsI) => { + const barRef = useRef(null); const [hover, setHover] = useState(false); const onMouseEnter = () => { @@ -24,17 +42,31 @@ export const BarWithTooltip = ({ const events = { onMouseEnter, onMouseLeave, - onClick: () => onClickBarItem(datum), + onClick: () => { + // Todo: Find a way to get barRef from Bar + + if (onClickBarItem && popoverTriggerRef) { + console.info('barRef.current', barRef.current); + // eslint-disable-next-line react-compiler/react-compiler + popoverTriggerRef.current = barRef.current; + onClickBarItem(datum); + } + }, }; + const midpoint = calculateMiddle(datum); + // @ts-ignore + const newX = rest.scale.y(midpoint); + return ( <> {} + {hover && ( )} diff --git a/client/src/components/Timeline/BrushHandle.tsx b/client/src/components/Timeline/BrushHandle.tsx new file mode 100644 index 00000000..5ca7c8b0 --- /dev/null +++ b/client/src/components/Timeline/BrushHandle.tsx @@ -0,0 +1,56 @@ +export const BrushHandle = ({ smaller = false, ...rest }) => { + const handleHeight = smaller ? 20 : 25; + const handleWidth = 8; + + const y = smaller ? 1 : 2; + + // Add functions to handle pointer capture + const handlePointerDown = (e) => { + // Set pointer capture on the handle + e.target.setPointerCapture(e.pointerId); + }; + + return ( + + {/* Simple rectangle handle */} + + + {/* Invisible larger hit area to make handle easier to grab */} + + + ); +}; + +// export const BrushHandle = (props) => ( +// +// +// +// +// +// +// ); diff --git a/client/src/components/Timeline/ChartTheme.ts b/client/src/components/Timeline/ChartTheme.ts index 5b52ff53..23f5f4f6 100644 --- a/client/src/components/Timeline/ChartTheme.ts +++ b/client/src/components/Timeline/ChartTheme.ts @@ -10,26 +10,28 @@ const lightGreen500 = '#8BC34A'; const teal700 = '#00796B'; const cyan900 = '#006064'; const colors = [deepOrange600, yellow200, lime300, lightGreen500, teal700, cyan900]; -const blueGrey50 = '#ECEFF1'; -const blueGrey300 = '#90A4AE'; -export const blueGrey700 = '#455A64'; -export const grey900 = '#212121'; -export const disabledGrey = '#e6e6e6'; +const bluegray300 = 'var(--chakra-colors-gray-300)'; + +export const bluegray700 = 'var(--chakra-colors-gray-700)'; +export const gray900 = 'var(--chakra-colors-gray-900)'; +export const disabledgray = 'var(--chakra-colors-gray-300)'; +const almostWhite = 'var(--chakra-colors-gray-100)'; +const gray = 'var(--chakra-colors-gray-500)'; export const getLabelColor = (isDark, isEnabled) => { if (isDark) { - return isEnabled ? almostWhite : blueGrey700; + return isEnabled ? almostWhite : bluegray700; } - return !isEnabled ? disabledGrey : disabledGrey; + return !isEnabled ? disabledgray : disabledgray; }; // * // * Typography // * const sansSerif = "'Roboto', 'Helvetica Neue', Helvetica, sans-serif"; const letterSpacing = 'normal'; -const fontSize = 10; +const fontSize = 12; // * // * Layout // * @@ -47,22 +49,15 @@ const baseLabelStyles = isDark => ({ fontSize, letterSpacing, padding, - fill: isDark ? almostWhite : blueGrey700, + fill: isDark ? almostWhite : bluegray700, stroke: 'transparent', strokeWidth: 0, }); -const almostWhite = '#c3c3c3'; -const lightGray = '#151515'; -const gray = '#212121'; - const centeredLabelStyles = isDark => assign({ textAnchor: 'middle' }, baseLabelStyles(isDark)); // * // * Strokes // * -const strokeDasharray = '10, 5'; -const strokeLinecap = 'round'; -const strokeLinejoin = 'round'; export const getChartTheme = isDark => ({ isDark, @@ -73,33 +68,23 @@ export const getChartTheme = isDark => ({ style: { axis: { fill: 'transparent', - stroke: isDark ? gray : blueGrey300, - strokeWidth: 1, - strokeLinecap, - strokeLinejoin, + strokeWidth: 0, }, axisLabel: assign({}, centeredLabelStyles(isDark), { padding, stroke: 'transparent', }), grid: { - fill: 'none', - stroke: isDark ? lightGray : blueGrey50, - strokeDasharray, - strokeLinecap, - strokeLinejoin, + stroke: isDark ? gray : bluegray300, pointerEvents: 'painted', }, ticks: { fill: 'transparent', size: 5, - stroke: isDark ? gray : blueGrey300, - strokeWidth: 1, - strokeLinecap, - strokeLinejoin, + strokeWidth: 0, }, tickLabels: assign({}, baseLabelStyles(isDark), { - fill: isDark ? almostWhite : blueGrey700, + fill: isDark ? almostWhite : bluegray700, }), }, }, @@ -109,7 +94,7 @@ export const getChartTheme = isDark => ({ { style: { data: { - fill: isDark ? almostWhite : blueGrey700, + fill: isDark ? almostWhite : bluegray700, padding, strokeWidth: 0, }, @@ -120,9 +105,12 @@ export const getChartTheme = isDark => ({ ), tooltip: { - style: assign({}, centeredLabelStyles(isDark), { padding: 5, pointerEvents: 'none' }), + style: assign({}, centeredLabelStyles(isDark), { + padding: 15, + pointerEvents: 'none', + }), flyoutStyle: { - stroke: isDark ? almostWhite : blueGrey300, + stroke: isDark ? almostWhite : bluegray300, strokeWidth: 0.5, fill: isDark ? '#000000' : '#ffffff', pointerEvents: 'none', @@ -137,7 +125,7 @@ export const getChartTheme = isDark => ({ style: { data: { padding, - stroke: blueGrey50, + stroke: bluegray300, strokeWidth: 1, }, labels: assign({}, baseLabelStyles(isDark), { padding: 20 }), @@ -150,7 +138,7 @@ export const getChartTheme = isDark => ({ { style: { data: { - fill: grey900, + fill: gray900, }, labels: centeredLabelStyles(isDark), }, @@ -160,15 +148,15 @@ export const getChartTheme = isDark => ({ boxplot: assign( { style: { - max: { padding, stroke: blueGrey700, strokeWidth: 1 }, + max: { padding, stroke: bluegray700, strokeWidth: 1 }, maxLabels: baseLabelStyles(isDark), - median: { padding, stroke: blueGrey700, strokeWidth: 1 }, + median: { padding, stroke: bluegray700, strokeWidth: 1 }, medianLabels: baseLabelStyles(isDark), - min: { padding, stroke: blueGrey700, strokeWidth: 1 }, + min: { padding, stroke: bluegray700, strokeWidth: 1 }, minLabels: baseLabelStyles(isDark), - q1: { padding, fill: blueGrey700 }, + q1: { padding, fill: bluegray700 }, q1Labels: baseLabelStyles(isDark), - q3: { padding, fill: blueGrey700 }, + q3: { padding, fill: bluegray700 }, q3Labels: baseLabelStyles(isDark), }, boxWidth: 20, @@ -179,13 +167,13 @@ export const getChartTheme = isDark => ({ { style: { data: { - stroke: blueGrey700, + stroke: bluegray700, }, labels: centeredLabelStyles(isDark), }, candleColors: { positive: '#ffffff', - negative: blueGrey700, + negative: bluegray700, }, }, baseProps, @@ -198,7 +186,7 @@ export const getChartTheme = isDark => ({ data: { fill: 'transparent', opacity: 1, - stroke: blueGrey700, + stroke: bluegray700, strokeWidth: 2, }, labels: centeredLabelStyles(isDark), @@ -231,7 +219,7 @@ export const getChartTheme = isDark => ({ data: { fill: 'transparent', opacity: 1, - stroke: blueGrey700, + stroke: bluegray700, strokeWidth: 2, }, labels: centeredLabelStyles(isDark), @@ -244,7 +232,7 @@ export const getChartTheme = isDark => ({ { style: { data: { - fill: blueGrey700, + fill: bluegray700, opacity: 1, stroke: 'transparent', strokeWidth: 0, @@ -274,7 +262,7 @@ export const getChartTheme = isDark => ({ pointerEvents: 'none', }), flyout: { - stroke: grey900, + stroke: gray900, strokeWidth: 1, fill: '#f0f0f0', pointerEvents: 'none', diff --git a/client/src/components/Timeline/ColorChangerModal.tsx b/client/src/components/Timeline/ColorChangerModal.tsx deleted file mode 100644 index 4e83ce36..00000000 --- a/client/src/components/Timeline/ColorChangerModal.tsx +++ /dev/null @@ -1,57 +0,0 @@ -import React from 'react'; - -import { Button, Modal } from 'antd'; -import { Logger } from '../../logger'; - -interface IProps { - modalVisible: boolean; - selectColorOption: any; -} - -const btnStyle = { width: '100%', marginBottom: 5 }; -export class ColorChangerModal extends React.PureComponent { - constructor(props) { - super(props); - Logger.debug('ColorChangerModal', props); - } - - public changeColorHandler = color => { - Logger.debug('Changed color:', color); - this.setState({ color }); - }; - - public saveItemHandler = opts => { - this.props.selectColorOption(opts); - }; - - public saveOnlyThis = () => this.saveItemHandler('ONLY_THIS'); - - public saveNew = () => this.saveItemHandler('NEW_ITEMS'); - - public saveAll = () => this.saveItemHandler('ALL_ITEMS'); - - public render() { - const { modalVisible }: IProps = this.props; - - return ( - - -
    - -
    - -
    - ); - } -} diff --git a/client/src/components/Timeline/ColorPicker.tsx b/client/src/components/Timeline/ColorPicker.tsx index 6b131c3e..1bd7e275 100644 --- a/client/src/components/Timeline/ColorPicker.tsx +++ b/client/src/components/Timeline/ColorPicker.tsx @@ -1,83 +1,63 @@ -import React, { useState, useEffect } from 'react'; -import { SketchPicker } from 'react-color'; -import reactCSS from 'reactcss'; +import { + Box, + Button, + Popover, + PopoverContent, + PopoverTrigger, + useColorMode, + useMultiStyleConfig, +} from '@chakra-ui/react'; +import { useEffect } from 'react'; +import { ColorPicker as ReactPicker, toColor, useColor } from 'react-color-palette'; +import 'react-color-palette/lib/css/styles.css'; +import { THEMES } from '../../store/theme.util'; interface IProps { color: any; onChange: any; + readOnly?: boolean; } const defaultColor = '#000000'; -export const ColorPicker = ({ color = defaultColor, onChange }: IProps) => { - const [pickerColor, setPickerColor] = useState(color); - const [displayColorPicker, setSisplayColorPicker] = useState(false); +export const ColorPicker = ({ color = defaultColor, onChange }: IProps) => { + const { colorMode } = useColorMode(); + const [pickerColor, setPickerColor] = useColor('hex', color || defaultColor); useEffect(() => { if (color) { - setPickerColor(color); + setPickerColor(toColor('hex', color)); } else { - setPickerColor(defaultColor); + setPickerColor(toColor('hex', defaultColor)); } - }, [color]); - - const handleClick = () => { - setSisplayColorPicker(!displayColorPicker); - }; - - const handleClose = () => { - setSisplayColorPicker(false); - }; + }, [setPickerColor, color]); - const handleChange = color => { - setPickerColor(color.hex); - onChange(color.hex); + const handleChange = (value) => { + setPickerColor(value); + onChange(value.hex); }; - const styles = reactCSS({ - default: { - color: { - width: '20px', - height: '20px', - borderRadius: '2px', - background: pickerColor, - }, - swatch: { - marginTop: '1px', - padding: '5px', - background: '#fff', - borderRadius: '3px', - boxShadow: '0 0 0 1px rgba(0,0,0,.1)', - display: 'inline-block', - cursor: 'pointer', - position: 'relative', - }, - popover: { - position: 'absolute', - zIndex: '2', - right: '0', - }, - cover: { - position: 'fixed', - top: '0px', - right: '0px', - bottom: '0px', - left: '0px', - }, - }, - }); + const styles = useMultiStyleConfig('ColorPicker', { bgColor: pickerColor.hex }); return ( -
    -
    -
    - {displayColorPicker ? ( -
    -
    - -
    - ) : null} -
    -
    + <> + + + + + + + + + ); }; diff --git a/client/src/components/Timeline/Loader.tsx b/client/src/components/Timeline/Loader.tsx new file mode 100644 index 00000000..9442166d --- /dev/null +++ b/client/src/components/Timeline/Loader.tsx @@ -0,0 +1,28 @@ +import { Spinner } from '@chakra-ui/react'; +import { useColorModeValue } from '@chakra-ui/react'; +import { chakra } from '@chakra-ui/react'; + +const SpinnerContainer = chakra('div', { + baseStyle: { + position: 'absolute', + textAlign: 'center', + + opacity: '75%', + borderRadius: 'md', + padding: 6, + width: '100%', + height: '100%', + minHeight: '100px', + + top: 0, + left: 0, + zIndex: 9, + margin: 'auto auto', + }, +}); + +export const Loader = () => ( + + + +); diff --git a/client/src/components/Timeline/MainTimelineChart.tsx b/client/src/components/Timeline/MainTimelineChart.tsx new file mode 100644 index 00000000..a1870119 --- /dev/null +++ b/client/src/components/Timeline/MainTimelineChart.tsx @@ -0,0 +1,271 @@ +import { memo, useRef } from 'react'; +import { + DomainPaddingPropType, + VictoryAxis, + VictoryBar, + VictoryBrushLine, + VictoryChart, + VictoryStyleInterface, +} from 'victory'; +import { convertDate, TIME_FORMAT } from '../../constants'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { Logger } from '../../logger'; +import { BarWithTooltip } from './BarWithTooltip'; + +import { Box, IconButton, Tooltip } from '@chakra-ui/react'; +import { RxZoomIn, RxZoomOut } from 'react-icons/rx'; +import { useDebouncedCallback } from 'use-debounce'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { useStoreActions, useStoreState } from '../../store/easyPeasy'; +import { rangeToDate } from '../../timeline.util'; +import { formatDurationInternal } from '../../utils'; +import { colorProp } from '../charts.utils'; +import { BrushHandle } from './BrushHandle'; +import { BAR_WIDTH, CHART_PADDING, CHART_SCALE } from './timeline.constants'; +import { getDynamicTimeFormat } from './timeline.format.utils'; +import { getTrackItemOrderFn } from './timeline.utils'; + +import { useMeasure } from '@uidotdev/usehooks'; +import { shortTime } from '../../time.util'; + +const domainPadding: DomainPaddingPropType = { y: 35, x: 10 }; + +export const barStyle = (isDark: boolean): VictoryStyleInterface => ({ + data: { + width: BAR_WIDTH, + fill: colorProp, + stroke: isDark ? 'black' : 'white', + strokeWidth: 0.5, + fillOpacity: 1, + clipPath: 'none', + }, +}); + +const EMPTY_ARRAY: ITrackItem[] = []; + +// Minimum timerange duration in milliseconds (5 minutes) +const MIN_TIMERANGE_DURATION_MS = 5 * 60 * 1000; + +export const MainTimelineChart = memo(() => { + const [ref, { width }] = useMeasure(); + + const { chartTheme } = useChartThemeState(); + const popoverTriggerRef = useRef(null); + + const timerange = useStoreState((state) => state.timerange); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + const timeItems = useStoreState((state) => state.timeItems); + + const setVisibleTimerange = useStoreActions((actions) => actions.setVisibleTimerange); + + const selectedTimelineItem = useStoreState((state) => state.selectedTimelineItem); + const setSelectedTimelineItem = useStoreActions((actions) => actions.setSelectedTimelineItem); + + const handleSelectionChanged = (item) => { + if (item) { + Logger.debug('Selected item:', item); + setSelectedTimelineItem(item); + } else { + Logger.error('No item selected'); + } + }; + + // Zoom handlers for manual zoom buttons + const zoomIn = () => { + if (visibleTimerange) { + const [start, end] = visibleTimerange; + const currentDuration = end.diff(start).milliseconds; + + // Calculate the new duration, but don't go below minimum + const newDuration = Math.max(currentDuration / 2, MIN_TIMERANGE_DURATION_MS); + + const midpoint = start.plus({ milliseconds: currentDuration / 2 }); + const newStart = midpoint.minus({ milliseconds: newDuration / 2 }); + const newEnd = midpoint.plus({ milliseconds: newDuration / 2 }); + + setVisibleTimerange([newStart, newEnd]); + } + }; + + const zoomOut = () => { + if (visibleTimerange && timerange) { + const [start, end] = visibleTimerange; + const midpoint = start.plus({ milliseconds: end.diff(start).milliseconds / 2 }); + const newDuration = end.diff(start).milliseconds * 2; + + // Constrain to original timerange + const [fullStart, fullEnd] = timerange; + const maxDuration = fullEnd.diff(fullStart).milliseconds; + const actualDuration = Math.min(newDuration, maxDuration); + + const newStart = midpoint.minus({ milliseconds: actualDuration / 2 }); + const newEnd = midpoint.plus({ milliseconds: actualDuration / 2 }); + + setVisibleTimerange([newStart, newEnd]); + } + }; + + const handleEditBrush = useDebouncedCallback((domain, brushProps) => { + if (domain) { + console.info('EditBrush event received:', domain, brushProps); + + const beginDate = convertDate(domain[0]).valueOf(); + const endDate = convertDate(domain[1]).valueOf(); + + Logger.debug('EditBrush changed:', beginDate, endDate); + + if (selectedTimelineItem) { + setSelectedTimelineItem({ ...selectedTimelineItem, beginDate, endDate }); + } else { + Logger.error('No item selected'); + } + } + }, 200); + + const getTooltipLabel = (d) => { + const diff = convertDate(d.endDate).diff(convertDate(d.beginDate)); + const now = convertDate(new Date()); + const ago = now.diff(convertDate(d.endDate)); + + const type = d.taskName === TrackItemType.StatusTrackItem ? 'STATUS' : d.app; + const beginTime = convertDate(d.beginDate).toFormat(TIME_FORMAT); + const endTime = convertDate(d.endDate).toFormat(TIME_FORMAT); + const agoText = `${shortTime(ago.milliseconds, { largest: 2 })} ago`; + + const url = d.url ? `${d.url}\r\n` : ''; + return `${type}\r\n${d.title}\r\n${url}${beginTime} - ${endTime}\r\n${formatDurationInternal( + diff.milliseconds, + )}\r\n${agoText}`; + }; + + const appItems = timeItems[TrackItemType.AppTrackItem] || EMPTY_ARRAY; + const logItems = timeItems[TrackItemType.LogTrackItem] || EMPTY_ARRAY; + const statusItems = timeItems[TrackItemType.StatusTrackItem] || EMPTY_ARRAY; + + if (!timerange && appItems.length === 0) { + return
    No data
    ; + } + + const timelineData = [...statusItems, ...logItems, ...appItems]; + + Logger.debug(`Rendering ${timelineData.length} items`); + + const axisStyle = { + grid: { strokeWidth: 0 }, + ticks: { stroke: 'gray', size: 5 }, + }; + + return ( +
    + + + } + onClick={zoomIn} + size="sm" + colorScheme="gray" + variant="ghost" + /> + + + } + onClick={zoomOut} + size="sm" + colorScheme="gray" + variant="ghost" + /> + + + + getDynamicTimeFormat(timestamp, visibleTimerange)} + /> + + d.beginDate} + y0={(d) => d.endDate} + data={timelineData} + barWidth={BAR_WIDTH} + horizontal={true} + dataComponent={ + + } + /> + (active ? 0.7 : 0.5), + cursor: 'move', + strokeWidth: 1.5, + }} + handleComponent={} + handleWidth={10} + brushAreaWidth={BAR_WIDTH * 2} + brushAreaStyle={{ + stroke: 'none', + fill: 'transparent', + opacity: 0.4, + cursor: 'move', + pointerEvents: 'all', + }} + allowDrag={true} + allowResize={true} + allowDraw={true} + /> + } + /> + +
    + ); +}); diff --git a/client/src/components/Timeline/NewLogButton.tsx b/client/src/components/Timeline/NewLogButton.tsx new file mode 100644 index 00000000..c02a2f92 --- /dev/null +++ b/client/src/components/Timeline/NewLogButton.tsx @@ -0,0 +1,31 @@ +import { Button, Tooltip } from '@chakra-ui/react'; +import randomcolor from 'randomcolor'; +import { memo } from 'react'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { useStoreActions, useStoreState } from '../../store/easyPeasy'; + +export const NewLogButton = memo(() => { + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + const selectedTimelineItem = useStoreState((state) => state.selectedTimelineItem); + + const setSelectedTimelineItem = useStoreActions((actions) => actions.setSelectedTimelineItem); + + const createNewItem = () => { + setSelectedTimelineItem({ + app: '', + title: '', + taskName: TrackItemType.LogTrackItem, + color: randomcolor(), + beginDate: selectedTimelineItem?.beginDate || visibleTimerange[0].valueOf(), + endDate: selectedTimelineItem?.endDate || visibleTimerange[1].valueOf(), + }); + }; + + return ( + + + + ); +}); diff --git a/client/src/components/Timeline/Search.tsx b/client/src/components/Timeline/Search.tsx index 10a52079..43a0a497 100644 --- a/client/src/components/Timeline/Search.tsx +++ b/client/src/components/Timeline/Search.tsx @@ -1,52 +1,66 @@ -import { Box, Flex } from 'reflexbox'; -import { Button, DatePicker, Tooltip } from 'antd'; -import { LeftOutlined, RightOutlined, PauseOutlined, CaretRightOutlined } from '@ant-design/icons'; -import moment from 'moment'; -import randomcolor from 'randomcolor'; -import React, { memo } from 'react'; -import { getTodayTimerange } from './timeline.utils'; +import { Box, Button, Tooltip, useToast } from '@chakra-ui/react'; +import { OnDatesChangeProps } from '@datepicker-react/hooks'; +import { DateTime } from 'luxon'; +import { memo, useEffect } from 'react'; +import { AiOutlineLeft, AiOutlineRight } from 'react-icons/ai'; +import { FaPlay, FaStop } from 'react-icons/fa'; import { Logger } from '../../logger'; import { useStoreActions, useStoreState } from '../../store/easyPeasy'; import { TIMERANGE_MODE_TODAY } from '../../store/mainStore'; +import { DateRangeInput } from '../Datepicker'; +import { getTodayTimerange } from './timeline.utils'; -const { RangePicker } = DatePicker; - -const getDayBefore = d => moment(d).subtract(1, 'days'); -const getDayAfter = d => moment(d).add(1, 'days'); +const getDayBefore = (d: DateTime) => d.minus({ days: 1 }); +const getDayAfter = (d: DateTime) => d.plus({ days: 1 }); export const Search = memo(() => { - const timerange = useStoreState(state => state.timerange); - const visibleTimerange = useStoreState(state => state.visibleTimerange); - const timerangeMode = useStoreState(state => state.timerangeMode); - const liveView = useStoreState(state => state.liveView); - - const setSelectedTimelineItem = useStoreActions(actions => actions.setSelectedTimelineItem); - const loadTimerange = useStoreActions(actions => actions.loadTimerange); - const setVisibleTimerange = useStoreActions(actions => actions.setVisibleTimerange); - const setLiveView = useStoreActions(actions => actions.setLiveView); - - const createNewItem = () => { - setSelectedTimelineItem({ - color: randomcolor(), - beginDate: visibleTimerange[0].valueOf(), - endDate: visibleTimerange[1].valueOf(), + const timerange = useStoreState((state) => state.timerange); + const toast = useToast(); + + const timerangeMode = useStoreState((state) => state.timerangeMode); + const liveView = useStoreState((state) => state.liveView); + const setLiveView = useStoreActions((actions) => actions.setLiveView); + const loadTimerange = useStoreActions((actions) => actions.loadTimerange); + + // Show a toast notification for live view status changes + const showLiveViewToast = (isEnabled: boolean) => { + toast({ + title: `Live view ${isEnabled ? 'enabled' : 'disabled'}`, + status: isEnabled ? 'success' : 'info', + duration: 2000, + isClosable: true, + position: 'top', }); }; + // Monitor liveView state changes and show toast + useEffect(() => { + if (timerangeMode === TIMERANGE_MODE_TODAY) { + showLiveViewToast(liveView); + } + }, [liveView, showLiveViewToast]); + const showLiveViewButton = timerangeMode === TIMERANGE_MODE_TODAY; + const toggleLiveView = () => { - setLiveView(!liveView); + const newLiveView = !liveView; + setLiveView(newLiveView); + + // Log the user action + Logger.debug(`User toggled live view to: ${newLiveView ? 'enabled' : 'disabled'}`); }; - const onChange = (dates: any) => { - Logger.debug('TIMERANGE:', dates); - if (dates != null) { - const beginDate = dates[0]; - const endDate = dates[1]; - const newTimerange = [beginDate, endDate]; - loadTimerange(newTimerange); - } else { - Logger.error('No dates selected'); + + const handleOnDatesChange = (data: OnDatesChangeProps) => { + Logger.debug('TIMERANGE:', data); + + const { startDate, endDate } = data; + + if (!startDate || !endDate) { + console.error('NO startDate or endDate'); + return; } + const newTimerange = [DateTime.fromJSDate(startDate).startOf('day'), DateTime.fromJSDate(endDate).endOf('day')]; + loadTimerange(newTimerange); }; const selectToday = () => { @@ -55,131 +69,65 @@ export const Search = memo(() => { }; const selectYesterday = () => { - const beginDate = getDayBefore(moment().startOf('day')); - const endDate = getDayBefore(moment().endOf('day')); + const beginDate = getDayBefore(DateTime.now().startOf('day')); + const endDate = getDayBefore(DateTime.now().endOf('day')); loadTimerange([beginDate, endDate]); }; const goBackOneDay = () => { - const beginDate = getDayBefore(moment(timerange[0])); - const endDate = getDayBefore(moment(timerange[1])); + const beginDate = getDayBefore(timerange[0]); + const endDate = getDayBefore(timerange[1]); loadTimerange([beginDate, endDate]); }; const goForwardOneDay = () => { - const beginDate = getDayAfter(moment(timerange[0])); - const endDate = getDayAfter(moment(timerange[1])); + const beginDate = getDayAfter(timerange[0]); + const endDate = getDayAfter(timerange[1]); loadTimerange([beginDate, endDate]); }; - const showDay = () => { - const beginDate = moment(timerange[0]).startOf('day'); - const endDate = moment(timerange[0]).endOf('day'); - setVisibleTimerange([beginDate, endDate]); - }; - - const showHour = () => { - const beginDate = moment(visibleTimerange[1]).startOf('hour'); - const endDate = moment(visibleTimerange[1]).endOf('hour'); - setVisibleTimerange([beginDate, endDate]); - }; - - const showAM = () => { - const beginDate = moment(timerange[0]).startOf('day'); - const endDate = moment(timerange[0]) - .startOf('day') - .hour(12); - setVisibleTimerange([beginDate, endDate]); - }; - - const showPM = () => { - const beginDate = moment(timerange[0]) - .startOf('day') - .hour(12); - const endDate = moment(timerange[0]).endOf('day'); - setVisibleTimerange([beginDate, endDate]); - }; - - const showEvening = () => { - const beginDate = moment(visibleTimerange[0]) - .startOf('day') - .hour(17); - const endDate = moment(visibleTimerange[0]).endOf('day'); - setVisibleTimerange([beginDate, endDate]); - }; + const isYesterday = DateTime.now().minus({ days: 1 }).hasSame(timerange[1], 'day'); - Logger.debug('Have timerange in Search:', timerange); return ( - + <> - + - - + - - - {showLiveViewButton && ( - - )} - - - - - - - - - - - - - - - - - - - - - - + ); }); diff --git a/client/src/components/Timeline/SmallTimelineChart.tsx b/client/src/components/Timeline/SmallTimelineChart.tsx new file mode 100644 index 00000000..17088db6 --- /dev/null +++ b/client/src/components/Timeline/SmallTimelineChart.tsx @@ -0,0 +1,133 @@ +import { debounce } from 'lodash'; +import { DateTime } from 'luxon'; +import { memo } from 'react'; +import { + DomainPaddingPropType, + DomainTuple, + ForAxes, + VictoryAxis, + VictoryBar, + VictoryBrushContainer, + VictoryChart, + VictoryStyleInterface, +} from 'victory'; + +import { Logger } from '../../logger'; + +import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { useStoreActions, useStoreState } from '../../store/easyPeasy'; +import { rangeToDate } from '../../timeline.util'; +import { colorProp } from '../charts.utils'; + +import { useMeasure } from '@uidotdev/usehooks'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { clampRange } from '../PieCharts/MetricTiles.utils'; +import { BrushHandle } from './BrushHandle'; +import { CHART_PADDING, CHART_SCALE } from './timeline.constants'; +import { getDynamicTimeFormat } from './timeline.format.utils'; +import { getTrackItemOrderFn } from './timeline.utils'; + +const domainPaddingBrush: DomainPaddingPropType = { y: 35, x: 5 }; + +const brushChartBarStyle = (isDark: boolean): VictoryStyleInterface => ({ + data: { + width: 7, + fill: colorProp, + stroke: isDark ? 'black' : 'white', + strokeWidth: 0.5, + fillOpacity: 1, + }, +}); + +const xDomain: DomainTuple = [1, 3]; + +const EMPTY_ARRAY: ITrackItem[] = []; + +export const SmallTimelineChart = memo(() => { + const { chartTheme } = useChartThemeState(); + + const [ref, { width }] = useMeasure(); + + const timerange = useStoreState((state) => state.timerange); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + const timeItems = useStoreState((state) => state.timeItems); + const setVisibleTimerange = useStoreActions((actions) => actions.setVisibleTimerange); + const setLiveView = useStoreActions((actions) => actions.setLiveView); + const changeVisibleTimerange = (range: [Date, Date]) => { + if (DateTime.now().hasSame(timerange[1], 'day')) { + setLiveView(false); + } + setVisibleTimerange(clampRange(timerange, [DateTime.fromJSDate(range[0]), DateTime.fromJSDate(range[1])])); + }; + + const handleBrush = (domain: { y: [Date, Date] }) => { + Logger.debug('Selected with brush:', domain.y); + + changeVisibleTimerange(domain.y); + }; + + const appTrackItems = timeItems[TrackItemType.AppTrackItem] || EMPTY_ARRAY; + const logTrackItems = timeItems[TrackItemType.LogTrackItem] || EMPTY_ARRAY; + const statusTrackItems = timeItems[TrackItemType.StatusTrackItem] || EMPTY_ARRAY; + + if (!timerange && appTrackItems.length === 0) { + return
    No data
    ; + } + + const brushData = [...statusTrackItems, ...logTrackItems]; + + const handleBrushDebounced = debounce(handleBrush, 300); + + const domain: ForAxes = { + y: [timerange[0].toMillis(), timerange[1].toMillis()], + x: xDomain, + }; + + return ( +
    + } + onBrushDomainChange={(domain) => { + // Convert domain.y from numbers to Dates before passing to handler + handleBrushDebounced({ y: [new Date(domain.y[0]), new Date(domain.y[1])] }); + }} + /> + } + > + getDynamicTimeFormat(timestamp, visibleTimerange)} + /> + + d.beginDate} + y0={(d) => d.endDate} + data={brushData} + /> + +
    + ); +}); diff --git a/client/src/components/Timeline/Timeline.styles.ts b/client/src/components/Timeline/Timeline.styles.ts deleted file mode 100644 index 9db8d468..00000000 --- a/client/src/components/Timeline/Timeline.styles.ts +++ /dev/null @@ -1,30 +0,0 @@ -import styled from 'styled-components'; - -import { Box } from 'reflexbox'; - -export const MainChart = styled(Box).attrs({ mb: 2, py: 2 })` - border-top: 1px solid ${({ theme: { variables } }) => variables['@normal-color']}; - - background-color: ${({ theme: { variables } }) => variables['@normal-color']}; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); -`; - -export const BrushChart = styled(Box).attrs({ mb: 2, py: 1 })` - border-top: 1px solid ${({ theme: { variables } }) => variables['@normal-color']}; - border-bottom: 1px solid ${({ theme: { variables } }) => variables['@normal-color']}; - background: ${({ theme: { variables } }) => variables['@component-background']}; - box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.1); -`; - -export const Spinner = styled.div` - position: absolute; - text-align: center; - background: ${({ theme: { variables } }) => variables['@normal-color']}; - opacity: 0.85; - border-radius: 4px; - padding: 50px; - width: 100%; - height: 100%; - z-index: 10000; - margin: auto auto; -`; diff --git a/client/src/components/Timeline/Timeline.tsx b/client/src/components/Timeline/Timeline.tsx index deb9e2f7..5b99498b 100644 --- a/client/src/components/Timeline/Timeline.tsx +++ b/client/src/components/Timeline/Timeline.tsx @@ -1,343 +1,57 @@ -import React, { memo, useState } from 'react'; - -import { useWindowWidth } from '@react-hook/window-size/throttled'; -import { Popover, Spin } from 'antd'; -import { debounce } from 'lodash'; -import moment from 'moment'; -import 'moment-duration-format'; import { - VictoryAxis, - VictoryBar, - VictoryBrushContainer, - VictoryChart, - VictoryZoomContainer, - VictoryBrushLine, -} from 'victory'; -import { convertDate, TIME_FORMAT } from '../../constants'; -import { TimelineRowType } from '../../enum/TimelineRowType'; -import { TrackItemType } from '../../enum/TrackItemType'; -import { BarWithTooltip } from './BarWithTooltip'; -import { getLabelColor } from './ChartTheme'; -import { BrushChart, MainChart, Spinner } from './Timeline.styles'; -import { TimelineItemEditContainer } from './TimelineItemEditContainer'; -import { Logger } from '../../logger'; -import { formatDuration } from '../SummaryCalendar/SummaryCalendar.util'; -import { colorProp } from '../charts.utils'; -import { useChartThemeState } from '../../routes/ChartThemeProvider'; -import { useStoreActions, useStoreState } from '../../store/easyPeasy'; -import { rangeToDate } from '../../timeline.util'; - -const getTrackItemOrder = (type: string) => { - if (type === TrackItemType.AppTrackItem) { - return 1; - } - if (type === TrackItemType.StatusTrackItem) { - return 2; - } - if (type === TrackItemType.LogTrackItem) { - return 3; - } - return 0; -}; - -const getTrackItemOrderFn = d => getTrackItemOrder(d.taskName); -const convertDateForY = d => convertDate(d.beginDate); -const convertDateForY0 = d => convertDate(d.endDate); -const brushChartBarStyle: any = { - data: { - width: 7, - fill: colorProp, - stroke: colorProp, - strokeWidth: 0.5, - fillOpacity: 0.75, - }, -}; - -const barWidth = 25; - -const scale: any = { y: 'time', x: 'linear' }; -const padding: any = { left: 50, top: 0, bottom: 20, right: 10 }; -const domainPadding: any = { y: 35, x: 10 }; -const domainPaddingBrush: any = { y: 35, x: 5 }; - -const barStyle: any = { - data: { - width: barWidth, - fill: colorProp, - stroke: colorProp, - strokeWidth: 0.5, - fillOpacity: 0.75, - }, -}; - -const rowEnabledDefaults = { - [TimelineRowType.App]: true, - [TimelineRowType.Log]: true, - [TimelineRowType.Status]: true, -}; + Box, + Popover, + PopoverArrow, + PopoverBody, + PopoverContent, + PopoverTrigger, + useColorModeValue, +} from '@chakra-ui/react'; +import { memo, useRef } from 'react'; +import { useStoreState } from '../../store/easyPeasy'; +import { BlackBox } from '../BlackBox'; +import { Loader } from './Loader'; +import { MainTimelineChart } from './MainTimelineChart'; +import { SmallTimelineChart } from './SmallTimelineChart'; +import { TimelineItemEdit } from './TimelineItemEdit'; export const Timeline = memo(() => { - const { chartTheme } = useChartThemeState(); - - const timerange = useStoreState(state => state.timerange); - const visibleTimerange = useStoreState(state => state.visibleTimerange); - const isLoading = useStoreState(state => state.isLoading); - const timeItems = useStoreState(state => state.timeItems); - - const setVisibleTimerange = useStoreActions(actions => actions.setVisibleTimerange); - - const selectedTimelineItem = useStoreState(state => state.selectedTimelineItem); - const setSelectedTimelineItem = useStoreActions(actions => actions.setSelectedTimelineItem); - const [isRowEnabled, setIsRowEnabled] = useState(rowEnabledDefaults); - - const chartWidth = useWindowWidth(); - const toggleRow = (rowId: any) => { - setIsRowEnabled({ ...isRowEnabled, [rowId - 1]: !isRowEnabled[rowId - 1] }); - }; - - const handleSelectionChanged = item => { - if (item) { - Logger.debug('Selected item:', item); - setSelectedTimelineItem(item); - } else { - Logger.error('No item selected'); - } - }; - - const changeVisibleTimerange = range => { - setVisibleTimerange([moment(range[0]), moment(range[1])]); - }; - - const handleZoom = domain => { - changeVisibleTimerange(domain.y); - }; - - const handleBrush = domain => { - Logger.debug('Selected with brush:', domain.y); - - changeVisibleTimerange(domain.y); - }; + const popoverTriggerRef = useRef(null); - const handleEditBrush = (domain, props) => { - if (domain) { - console.info('props', props); - if (props.index === TimelineRowType.Log) { - const beginDate = convertDate(domain[0]).valueOf(); - const endDate = convertDate(domain[1]).valueOf(); + const isLoading = useStoreState((state) => state.isLoading); - Logger.debug('EditBrush changed:', beginDate, endDate); - - setSelectedTimelineItem({ ...selectedTimelineItem, beginDate, endDate }); - } - } - }; - - const calcRowEnabledColor = ({ index }) => { - return getLabelColor(chartTheme.isDark, isRowEnabled[index]); - }; - - const calcRowEnabledColorFlipped = index => { - return getLabelColor(chartTheme.isDark, !isRowEnabled[index]); - }; - - const getTooltipLabel = d => { - const diff = convertDate(d.endDate).diff(convertDate(d.beginDate)); - - const type = d.taskName === TrackItemType.StatusTrackItem ? 'STATUS' : d.app; - const beginTime = convertDate(d.beginDate).format(TIME_FORMAT); - const endTime = convertDate(d.endDate).format(TIME_FORMAT); - - const url = d.url ? `${d.url}\r\n` : ''; - return `${type}\r\n${d.title}\r\n${url}${beginTime} - ${endTime}\r\n${formatDuration( - moment.duration(diff), - )}`; - }; - - const { appItems, logItems, statusItems } = timeItems; - - if (!timerange && !appItems && appItems.length === 0) { - return
    No data
    ; - } - - let timelineData = []; - let brushData = []; - if (isRowEnabled[TimelineRowType.Status]) { - // Logger.log('Adding statusItems:', statusItems); - timelineData = timelineData.concat(statusItems); - brushData = brushData.concat(statusItems); - } - if (isRowEnabled[TimelineRowType.Log]) { - // Logger.log('Adding logItems:', logItems); - timelineData = timelineData.concat(logItems); - brushData = brushData.concat(logItems); - } - if (isRowEnabled[TimelineRowType.App]) { - // Logger.log('Adding appItems:', appItems); - timelineData = timelineData.concat(appItems); - } - - Logger.debug(`Rendering ${timelineData.length} items`); - - const axisEvents: any = [ - { - target: 'tickLabels', - eventHandlers: { - onClick: () => { - return [ - { - target: 'tickLabels', - mutation: props => { - toggleRow(props.datum); - return { - style: { - ...props.style, - fill: calcRowEnabledColorFlipped(props.datum), - }, - }; - }, - }, - ]; - }, - }, - }, - ]; - - const axisStyle = { - grid: { strokeWidth: 0 }, - ticks: { stroke: 'grey', size: 5 }, - tickLabels: { - fill: calcRowEnabledColor, - }, - }; - - const handleBrushDebounced = debounce(handleBrush, 300); - const handleEditBrushDebounced = debounce(handleEditBrush, 300); - - const domain: any = { - y: [timerange[0], timerange[1]], - x: [1, 3], - }; + const selectedTimelineItem = useStoreState((state) => state.selectedTimelineItem); return ( -
    - - {isLoading && ( - - - - )} - } - visible={!!selectedTimelineItem} - trigger="click" - > - - } + + + + {isLoading && } + + + + +
    + + - - - - } - /> - (active ? 0.5 : 0.4), - }} - brushAreaStyle={{ - stroke: 'none', - fill: 'transparent', - opacity: 0, - }} - /> - } - /> - + + + + + - - - - } - > - - - - - -
    +
    + + + {isLoading && } + + + +
    ); }); diff --git a/client/src/components/Timeline/TimelineItemEdit.styles.ts b/client/src/components/Timeline/TimelineItemEdit.styles.ts deleted file mode 100644 index f6d83c4f..00000000 --- a/client/src/components/Timeline/TimelineItemEdit.styles.ts +++ /dev/null @@ -1,3 +0,0 @@ -import styled from 'styled-components'; - -export const EditForm = styled.div``; diff --git a/client/src/components/Timeline/TimelineItemEdit.tsx b/client/src/components/Timeline/TimelineItemEdit.tsx index a8ba6984..684ca67b 100644 --- a/client/src/components/Timeline/TimelineItemEdit.tsx +++ b/client/src/components/Timeline/TimelineItemEdit.tsx @@ -1,292 +1,264 @@ -import { Box, Flex } from 'reflexbox'; -import { Typography, Button, Divider, Input, Modal, Select, TimePicker, Tooltip } from 'antd'; -import { - PlayCircleOutlined, - SaveOutlined, - DeleteOutlined, - CloseOutlined, - ExclamationCircleOutlined, -} from '@ant-design/icons'; -import React, { useState, useEffect, memo } from 'react'; -import { ColorPicker } from './ColorPicker'; +import { Box, Button, Divider, Heading, Input, Select, Text, Tooltip } from '@chakra-ui/react'; +import { DateTime } from 'luxon'; +import randomcolor from 'randomcolor'; +import { memo, useEffect, useState } from 'react'; +import { AiOutlineClose, AiOutlineSave } from 'react-icons/ai'; +import { TIME_FORMAT_SHORT } from '../../constants'; import { Logger } from '../../logger'; -import moment from 'moment'; +import { ColorPicker } from './ColorPicker'; +import { TimelineItemEditDeleteButton } from './TimelineItemEditDeleteButton'; + +import { HStack, VStack } from '@chakra-ui/react'; +import { ITrackItem, SelectedTrackItem } from '../../@types/ITrackItem'; import { TrackItemType } from '../../enum/TrackItemType'; +import { changeColorForApp } from '../../services/appSettings.api'; +import { deleteByIds, saveTrackItem, updateTrackItemColor } from '../../services/trackItem.api'; +import { useStoreActions, useStoreState } from '../../store/easyPeasy'; +import { ITEM_TYPES } from '../../utils'; + +type ColorScope = 'ONLY_THIS' | 'NEW_ITEMS' | 'ALL_ITEMS'; + +const COLOR_SCOPE_ONLY_THIS: ColorScope = 'ONLY_THIS'; + +export const TimelineItemEdit = memo(() => { + const selectedTimelineItem = useStoreState((state) => state.selectedTimelineItem); + const setSelectedTimelineItem = useStoreActions((actions) => actions.setSelectedTimelineItem); + const fetchTimerange = useStoreActions((actions) => actions.fetchTimerange); + + const [state, setState] = useState<{ + trackItem: SelectedTrackItem | null; + colorScope: ColorScope; + }>({ + trackItem: selectedTimelineItem, + colorScope: COLOR_SCOPE_ONLY_THIS, + }); -const { Title } = Typography; - -interface IProps { - selectedTimelineItem: any; - saveTimelineItem: any; - changeColorForApp?: any; - trayEdit?: boolean; - clearTimelineItem?: any; - deleteTimelineItem?: any; -} - -const COLOR_SCOPE_ONLY_THIS = 'ONLY_THIS'; -/* -function propsAreEqual(prev, next) { - if (prev.selectedTimelineItem && next.selectedTimelineItem) { - const equalById = prev.selectedTimelineItem.id === next.selectedTimelineItem.id; - if (!next.selectedTimelineItem.id) { - return prev.selectedTimelineItem === next.selectedTimelineItem; + const { trackItem, colorScope } = state; + + const deleteTimelineItem = async () => { + const id = trackItem?.id; + Logger.debug('Delete timeline trackItem', id); + + if (id) { + await deleteByIds([id]); + Logger.debug('Deleted timeline items', id); + fetchTimerange(); + setSelectedTimelineItem(null); + } else { + Logger.error('No ids, not deleting from DB'); } + }; - return equalById; - } + const readOnly = selectedTimelineItem?.taskName !== TrackItemType.LogTrackItem; + + const saveTimelineItem = async () => { + Logger.debug('Updating color for trackItem', trackItem, colorScope); + if (!trackItem) { + Logger.error('No trackItem'); + return; + } + try { + const color = trackItem.color || randomcolor(); + if (colorScope === 'ALL_ITEMS') { + await changeColorForApp(trackItem.app, color); + await updateTrackItemColor(trackItem.app, color); + } else if (colorScope === 'NEW_ITEMS') { + await changeColorForApp(trackItem.app, color); + await saveTrackItem(trackItem as ITrackItem); + } else { + await saveTrackItem(trackItem as ITrackItem); + } + } catch (error) { + Logger.error('Saving track item failed', error); + } - return false; -}*/ - -const statusName = { - [TrackItemType.AppTrackItem]: 'App', - [TrackItemType.StatusTrackItem]: 'Status', - [TrackItemType.LogTrackItem]: 'Log', -}; - -export const TimelineItemEdit = memo( - ({ - selectedTimelineItem, - trayEdit, - clearTimelineItem, - saveTimelineItem, - deleteTimelineItem, - }) => { - const [state, setState] = useState({ + setSelectedTimelineItem(null); + fetchTimerange(); + }; + + const clearTimelineItem = () => setSelectedTimelineItem(null); + + useEffect(() => { + Logger.debug('Selected timelineitem changed:', selectedTimelineItem); + + setState({ trackItem: selectedTimelineItem, colorScope: COLOR_SCOPE_ONLY_THIS, }); + }, [selectedTimelineItem]); - const { trackItem, colorScope } = state; + const changeColorHandler = (color) => { + Logger.debug('Changed color:', color); - useEffect(() => { - Logger.debug('Selected timelineitem changed:', selectedTimelineItem); - if (selectedTimelineItem) { - setState({ - trackItem: selectedTimelineItem, - colorScope: COLOR_SCOPE_ONLY_THIS, - }); - } - }, [selectedTimelineItem]); - - const changeColorHandler = color => { - Logger.debug('Changed color:', color); - - setState({ - ...state, + setState((oldState) => { + if (!oldState.trackItem) return oldState; + return { + ...oldState, trackItem: { - ...state.trackItem, + ...oldState.trackItem, color, - }, - }); - }; + } as ITrackItem, + }; + }); + }; - const changeAppName = e => { - const { value } = e.target; - Logger.debug('Changed app name:', value); + const changeAppName = (e) => { + const { value }: { value: string } = e.target; + Logger.debug('Changed app name:', value); - setState({ - ...state, + setState((oldState) => { + if (!oldState.trackItem) return oldState; + return { + ...oldState, trackItem: { - ...state.trackItem, + ...oldState.trackItem, app: value, - }, - }); - }; - const changeTime = attr => value => { - Logger.debug('Changed app time:', value); - const oldDate = moment(state.trackItem[attr]); - const newDate = moment( - value - .toArray() - .slice(0, 4) - .concat(oldDate.toArray().slice(4)), - ); - setState({ - ...state, + } as ITrackItem, + }; + }); + }; + + const changeTime = (attr) => (timeStr: string) => { + Logger.debug('Changed app time:', timeStr); + const [hours, minutes] = timeStr.split(':').map(Number); + const oldDate = DateTime.fromJSDate(new Date(state.trackItem?.[attr] || 0)); + const newDate = oldDate.startOf('day').set({ hour: hours, minute: minutes }); + + setState((oldState) => { + if (!oldState.trackItem) return oldState; + return { + ...oldState, trackItem: { - ...state.trackItem, - [attr]: newDate.valueOf(), - }, - }); - }; - - const changeAppTitle = e => { - const { value } = e.target; - Logger.debug('Changed app title:', value); - - setState({ - ...state, + ...oldState.trackItem, + [attr]: newDate.toMillis(), + } as ITrackItem, + }; + }); + }; + + const changeAppTitle = (e) => { + const { value } = e.target; + Logger.debug('Changed app title:', value); + + setState((oldState) => { + if (!oldState.trackItem) return oldState; + return { + ...oldState, trackItem: { - ...state.trackItem, + ...oldState.trackItem, title: value, - }, - }); - }; - - const closeEdit = () => { - Logger.debug('Close TimelineItem'); - clearTimelineItem(); - }; - - const changeColorScopeHandler = colorScope => { - Logger.debug('Changed color scope:', colorScope); - - setState({ - ...state, - colorScope, - }); - }; - - const saveBasedOnColorOptionHandler = () => { - const { trackItem, colorScope } = state; - - saveTimelineItem(trackItem, colorScope); - }; - const deleteItem = () => { - const { trackItem } = state; - - deleteTimelineItem(trackItem); - }; - - const showDeleteConfirm = () => { - Modal.confirm({ - title: 'Delete', - icon: , - content: 'Sure you want to delete?', - okText: 'Delete', - cancelText: 'Cancel', - onOk: deleteItem, - zIndex: 10000, - }); - }; - - if (!selectedTimelineItem) { - Logger.debug('No trackItem'); - return null; - } + } as ITrackItem, + }; + }); + }; - const colorChanged = selectedTimelineItem.color !== trackItem.color; + const closeEdit = () => { + Logger.debug('Close TimelineItem'); + clearTimelineItem(); + }; - if (trayEdit) { - return ( - - - - - - - + const changeColorScopeHandler = (e) => { + const { value } = e.target; + Logger.debug('Changed color scope:', value); - - - + setState((oldState) => ({ + ...oldState, + colorScope: value, + })); + }; - - - - - - + ➜ + + changeTime('endDate')(e.target.value)} + readOnly={readOnly} + /> - - + + + + + + + - + {colorChanged && ( + + + + )} + + + + + - ); - }, -); + + {!isCreating && ( + + + + )} + + + + + + + + ); +}); diff --git a/client/src/components/Timeline/TimelineItemEditContainer.tsx b/client/src/components/Timeline/TimelineItemEditContainer.tsx deleted file mode 100644 index aa6b1d65..00000000 --- a/client/src/components/Timeline/TimelineItemEditContainer.tsx +++ /dev/null @@ -1,51 +0,0 @@ -import React, { memo } from 'react'; -import { changeColorForApp } from '../../services/appSettings.api'; -import { saveTrackItem, deleteByIds, updateTrackItemColor } from '../../services/trackItem.api'; -import { TimelineItemEdit } from './TimelineItemEdit'; -import { Logger } from '../../logger'; -import { useStoreActions, useStoreState } from '../../store/easyPeasy'; - -export const TimelineItemEditContainer = memo(() => { - const selectedTimelineItem = useStoreState(state => state.selectedTimelineItem); - const setSelectedTimelineItem = useStoreActions(actions => actions.setSelectedTimelineItem); - const fetchTimerange = useStoreActions(actions => actions.fetchTimerange); - - const deleteTimelineItem = async trackItem => { - const id = trackItem.id; - Logger.debug('Delete timeline trackItem', id); - - if (id) { - await deleteByIds([id]); - Logger.debug('Deleted timeline items', id); - fetchTimerange(); - setSelectedTimelineItem(null); - } else { - Logger.error('No ids, not deleting from DB'); - } - }; - - const saveTimelineItem = async (trackItem, colorScope) => { - Logger.debug('Updating color for trackItem', trackItem, colorScope); - if (colorScope === 'ALL_ITEMS') { - await changeColorForApp(trackItem.app, trackItem.color); - await updateTrackItemColor(trackItem.app, trackItem.color); - } else if (colorScope === 'NEW_ITEMS') { - await changeColorForApp(trackItem.app, trackItem.color); - await saveTrackItem(trackItem); - } else { - await saveTrackItem(trackItem); - } - - setSelectedTimelineItem(null); - fetchTimerange(); - }; - - const clearTimelineItem = () => setSelectedTimelineItem(null); - - const moreProps = { - deleteTimelineItem, - clearTimelineItem, - saveTimelineItem, - }; - return ; -}); diff --git a/client/src/components/Timeline/TimelineItemEditDeleteButton.tsx b/client/src/components/Timeline/TimelineItemEditDeleteButton.tsx new file mode 100644 index 00000000..123714bb --- /dev/null +++ b/client/src/components/Timeline/TimelineItemEditDeleteButton.tsx @@ -0,0 +1,50 @@ +import { Button } from '@chakra-ui/react'; +import { + AlertDialog, + AlertDialogBody, + AlertDialogContent, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogOverlay, +} from '@chakra-ui/react'; +import { useRef, useState } from 'react'; +import { AiOutlineDelete } from 'react-icons/ai'; + +export function TimelineItemEditDeleteButton({ deleteItem }) { + const [isOpen, setIsOpen] = useState(false); + const onClose = () => setIsOpen(false); + const onDelete = () => { + deleteItem(); + onClose(); + }; + const cancelRef = useRef(null!); + + return ( + <> + + + + + + + Delete Timeline Item + + + Are you sure? You can't undo this action afterwards. + + + + + + + + + + ); +} diff --git a/client/src/components/Timeline/VisibleRange.tsx b/client/src/components/Timeline/VisibleRange.tsx new file mode 100644 index 00000000..c6fbe25e --- /dev/null +++ b/client/src/components/Timeline/VisibleRange.tsx @@ -0,0 +1,219 @@ +import { Box, Button, Flex, HStack, Input, Text, useColorModeValue } from '@chakra-ui/react'; +import { memo, useEffect, useMemo, useState } from 'react'; +import { TIME_FORMAT_SHORT } from '../../constants'; +import { useStoreActions, useStoreState } from '../../store/easyPeasy'; + +// Range types to identify different visible range options +export enum RangeType { + ALL_DAY = 'ALL_DAY', + AM = 'AM', + PM = 'PM', + EVENING = 'EVENING', + HOUR = 'HOUR', + CUSTOM = 'CUSTOM', +} + +export const VisibleRange = memo(() => { + const timerange = useStoreState((state) => state.timerange); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + const setVisibleTimerange = useStoreActions((actions) => actions.setVisibleTimerange); + + // State for time inputs + const [startTime, setStartTime] = useState(''); + const [endTime, setEndTime] = useState(''); + + // Flag to prevent infinite update loops + const [updatingFromTimerange, setUpdatingFromTimerange] = useState(false); + + // Update time inputs when visibleTimerange changes + useEffect(() => { + if (visibleTimerange && visibleTimerange.length === 2) { + setUpdatingFromTimerange(true); + setStartTime(visibleTimerange[0].toFormat(TIME_FORMAT_SHORT)); + setEndTime(visibleTimerange[1].toFormat(TIME_FORMAT_SHORT)); + // Reset the flag after state updates + setTimeout(() => setUpdatingFromTimerange(false), 0); + } + }, [visibleTimerange]); + + // Determine which range type is currently active based on the visible timerange + const activeRange = useMemo(() => { + if (!visibleTimerange || visibleTimerange.length !== 2) { + return null; + } + + const [start, end] = visibleTimerange; + const dayStart = timerange[0].startOf('day'); + const dayEnd = timerange[0].endOf('day'); + const noon = dayStart.set({ hour: 12 }); + const evening = dayStart.set({ hour: 17 }); + + // Check if it's the whole day + if (start.hasSame(dayStart, 'minute') && end.hasSame(dayEnd, 'minute')) { + return RangeType.ALL_DAY; + } + + // Check if it's AM + if (start.hasSame(dayStart, 'minute') && end.hasSame(noon, 'minute')) { + return RangeType.AM; + } + + // Check if it's PM + if (start.hasSame(noon, 'minute') && end.hasSame(dayEnd, 'minute')) { + return RangeType.PM; + } + + // Check if it's Evening + if (start.hasSame(evening, 'minute') && end.hasSame(dayEnd, 'minute')) { + return RangeType.EVENING; + } + + const diff = end.diff(start); + + // Check if it's an hourly view (one hour duration) + if (Math.abs(diff.as('hours') - 1) < 0.05) { + return RangeType.HOUR; + } + + return RangeType.CUSTOM; + }, [visibleTimerange, timerange]); + + const showDay = () => { + const beginDate = timerange[0].startOf('day'); + const endDate = timerange[0].endOf('day'); + setVisibleTimerange([beginDate, endDate]); + }; + + const showHour = () => { + const beginDate = visibleTimerange[0].startOf('hour'); + const endDate = beginDate.plus({ hours: 1 }); + setVisibleTimerange([beginDate, endDate]); + }; + + const showAM = () => { + const beginDate = timerange[0].startOf('day'); + const endDate = timerange[0].startOf('day').set({ hour: 12 }); + setVisibleTimerange([beginDate, endDate]); + }; + + const showPM = () => { + const beginDate = timerange[0].startOf('day').set({ hour: 12 }); + const endDate = timerange[0].endOf('day'); + setVisibleTimerange([beginDate, endDate]); + }; + + const showEvening = () => { + const beginDate = visibleTimerange[0].startOf('day').set({ hour: 17 }); + const endDate = visibleTimerange[0].endOf('day'); + setVisibleTimerange([beginDate, endDate]); + }; + + // Apply the custom time range + const updateCustomTimeRange = (newStartTime, newEndTime) => { + if (!newStartTime || !newEndTime) return; + + try { + const [startHours, startMinutes] = newStartTime.split(':').map(Number); + const [endHours, endMinutes] = newEndTime.split(':').map(Number); + + if (isNaN(startHours) || isNaN(startMinutes) || isNaN(endHours) || isNaN(endMinutes)) { + return; + } + + const beginDate = timerange[0].startOf('day').set({ + hour: startHours, + minute: startMinutes || 0, + }); + + const endDate = timerange[0].startOf('day').set({ + hour: endHours, + minute: endMinutes || 0, + }); + + // If end time is earlier than start time, assume it's for the next day + const finalEndDate = endDate < beginDate ? endDate.plus({ days: 1 }) : endDate; + + setVisibleTimerange([beginDate, finalEndDate]); + } catch (err) { + console.error('Error parsing time inputs:', err); + } + }; + + // Handler for time input changes - directly updates the timerange + const handleTimeChange = (timeType) => (e) => { + const timeStr = e.target.value; + + // Don't update if we're currently syncing from timerange changes + if (updatingFromTimerange) return; + + if (timeType === 'start') { + setStartTime(timeStr); + updateCustomTimeRange(timeStr, endTime); + } else { + setEndTime(timeStr); + updateCustomTimeRange(startTime, timeStr); + } + }; + + return ( + + + + + + + ➜ + + + + + + + + Visible range + + + + + + + + + + + + + + + ); +}); diff --git a/client/src/components/Timeline/timeline.constants.ts b/client/src/components/Timeline/timeline.constants.ts new file mode 100644 index 00000000..ea049073 --- /dev/null +++ b/client/src/components/Timeline/timeline.constants.ts @@ -0,0 +1,10 @@ +import { D3Scale, Padding, ScalePropType } from 'victory'; + +export const BAR_WIDTH = 25; + +export const CHART_PADDING: Padding = { left: 0, top: 0, bottom: 20, right: 10 }; + +export const CHART_SCALE: { + x?: ScalePropType | D3Scale; + y?: ScalePropType | D3Scale; +} = { y: 'time', x: 'linear' }; diff --git a/client/src/components/Timeline/timeline.format.utils.ts b/client/src/components/Timeline/timeline.format.utils.ts new file mode 100644 index 00000000..304970bb --- /dev/null +++ b/client/src/components/Timeline/timeline.format.utils.ts @@ -0,0 +1,36 @@ +import { DateTime } from 'luxon'; +import { convertDate } from '../../constants'; + +/** + * Gets a dynamic time format function based on the visible time range + * + * @param timestamp - The timestamp to format + * @param visibleTimerange - The current visible time range (optional) + * @returns Formatted time string appropriate for the current zoom level + */ +export const getDynamicTimeFormat = (timestamp: number, visibleTimerange?: DateTime[]) => { + // Get the current system locale for date/time formatting + const locale = DateTime.local().resolvedLocaleOptions().locale; + const dateTime = convertDate(timestamp); + + // If no visible timerange is set yet, use the default format + if (!visibleTimerange || visibleTimerange.length !== 2) { + return dateTime.setLocale(locale).toLocaleString(DateTime.TIME_WITH_SECONDS); + } + + // Calculate the duration of the visible range in milliseconds + const [start, end] = visibleTimerange; + const rangeDuration = end.diff(start).milliseconds; + + // Adjust format based on zoom level + if (rangeDuration > 24 * 60 * 60 * 1000) { + // More than 24 hours - show date and time + return dateTime.setLocale(locale).toLocaleString({ ...DateTime.DATE_MED_WITH_WEEKDAY, year: undefined }); + } else if (rangeDuration > 60 * 60 * 1000) { + // More than 1 hour - show hours and minutes + return dateTime.setLocale(locale).toLocaleString(DateTime.TIME_SIMPLE); + } else { + // Zoomed in - show hours, minutes and seconds + return dateTime.setLocale(locale).toLocaleString(DateTime.TIME_WITH_SECONDS); + } +}; diff --git a/client/src/components/Timeline/timeline.utils.test.ts b/client/src/components/Timeline/timeline.utils.test.ts new file mode 100644 index 00000000..b25431c1 --- /dev/null +++ b/client/src/components/Timeline/timeline.utils.test.ts @@ -0,0 +1,99 @@ +import { DateTime } from 'luxon'; +import { describe, expect, it } from 'vitest'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { filterItems } from './timeline.utils'; + +describe('Timeline utils', () => { + it('filterItems in range items', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items: ITrackItem[] = [ + { + id: 1, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T17:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T17:10:00.000Z').toMillis(), + }, + { + id: 2, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + { + id: 3, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T18:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:00:00.000Z').toMillis(), + }, + ]; + const actual = filterItems(items, visibleTimerange); + expect(actual).toEqual(items); + }); + it('filterItems does not include out of range items', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items = [ + { + id: 1, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + ]; + const outOfRangeItems: ITrackItem[] = [ + { + id: 1, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T16:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T16:59:59.000Z').toMillis(), + }, + + { + id: 2, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T19:00:01.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:10:00.000Z').toMillis(), + }, + ]; + const actual = filterItems([...items, ...outOfRangeItems], visibleTimerange); + expect(actual).toEqual(items); + }); + + it('filterItems returns items that are partly in', () => { + const visibleTimerange = [ + DateTime.fromISO('2021-06-19T17:00:00.000Z'), + DateTime.fromISO('2021-06-19T19:00:00.000Z'), + ]; + const items = [ + { + id: 1, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T16:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T17:10:00.000Z').toMillis(), + }, + { + id: 2, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T18:00:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T18:10:00.000Z').toMillis(), + }, + { + id: 3, + app: 'app', + beginDate: DateTime.fromISO('2021-06-19T18:50:00.000Z').toMillis(), + endDate: DateTime.fromISO('2021-06-19T19:10:00.000Z').toMillis(), + }, + ]; + const actual = filterItems(items, visibleTimerange); + expect(actual).toEqual(items); + }); +}); + +export // Use an empty export to please Babel's single file emit. +// https://github.com/Microsoft/TypeScript/issues/15230 + {}; diff --git a/client/src/components/Timeline/timeline.utils.ts b/client/src/components/Timeline/timeline.utils.ts index 37113d69..789f2389 100644 --- a/client/src/components/Timeline/timeline.utils.ts +++ b/client/src/components/Timeline/timeline.utils.ts @@ -1,20 +1,28 @@ import _ from 'lodash'; -import moment from 'moment'; +import { DateTime } from 'luxon'; +import { ITrackItem } from '../../@types/ITrackItem'; import { convertDate } from '../../constants'; +import { TrackItemType } from '../../enum/TrackItemType'; -export const filterItems = (timeItems, visibleTimerange) => - timeItems.filter(item => { +export const filterItems = (timeItems: ITrackItem[], visibleTimerange: DateTime[]) => { + if (!timeItems) { + console.warn('No time items found'); + return [] as ITrackItem[]; + } + + return timeItems.filter((item) => { const itemBegin = convertDate(item.beginDate); const itemEnd = convertDate(item.endDate); - const visBegin = visibleTimerange[0]; - const visEnd = visibleTimerange[1]; - return itemBegin.isBetween(visBegin, visEnd) && itemEnd.isBetween(visBegin, visEnd); + const [visBegin, visEnd] = visibleTimerange; + + return (itemBegin >= visBegin && itemBegin <= visEnd) || (itemEnd >= visBegin && itemEnd <= visEnd); }); +}; -export const aggregateappItems = items => { +export const aggregateappItems = (items) => { _.reduce( items, - result => { + (result) => { const currVal = result; // result[value.id](result[value.id] || (result[value.id] = [])).push(key); return currVal; }, @@ -22,55 +30,74 @@ export const aggregateappItems = items => { ); }; -export const copyTime = (from, to) => - moment(from).set({ - hour: to.hour(), - minute: to.minute(), +export const copyTime = (from: DateTime, to: DateTime): DateTime => + DateTime.fromJSDate(from.toJSDate()).set({ + hour: to.hour, + minute: to.minute, }); -export const setDayFromTimerange = (visibleTimerange, timerange) => [ +export const setDayFromTimerange = (visibleTimerange: DateTime[], timerange: DateTime[]): DateTime[] => [ copyTime(timerange[0], visibleTimerange[0]), copyTime(timerange[1], visibleTimerange[1]), ]; -export const getTodayTimerange = () => [moment().startOf('day'), moment().endOf('day')]; +export const getTodayTimerange = (): DateTime[] => [DateTime.now().startOf('day'), DateTime.now().endOf('day')]; -export const getCenteredTimerange = (timerange, visibleTimerange, middleTime) => { - const timeBetweenMs = moment(visibleTimerange[1]).diff(visibleTimerange[0]); +export const getCenteredTimerange = ( + timerange: DateTime[], + visibleTimerange: DateTime[], + middleTime: DateTime, +): DateTime[] => { + const timeBetweenMs = visibleTimerange[1].diff(visibleTimerange[0]).milliseconds; const middlePoint = timeBetweenMs / 5; - let beginDate = moment(middleTime).subtract(timeBetweenMs - middlePoint, 'milliseconds'); - let endDate = moment(middleTime).add(middlePoint, 'milliseconds'); + let beginDate = middleTime.minus({ milliseconds: timeBetweenMs - middlePoint }); + let endDate = middleTime.plus({ milliseconds: middlePoint }); // if new beginDate is smaller than actual timerange, then cap it with timeranges beginDate - const underTime = moment(timerange[0]).diff(beginDate); + const underTime = timerange[0].diff(beginDate).milliseconds; if (underTime > 0) { - beginDate = moment(timerange[0]); - endDate = moment(endDate).add(underTime, 'milliseconds'); + beginDate = timerange[0]; + endDate = endDate.plus({ milliseconds: underTime }); } // if new endDate is bigger than actual timeranges endDate, then cap it with timeranges endDate - const overTime = moment(endDate).diff(timerange[1]); + const overTime = endDate.diff(timerange[1]).milliseconds; if (overTime > 0) { - endDate = moment(timerange[1]); - beginDate = moment(beginDate).subtract(overTime, 'milliseconds'); + endDate = timerange[1]; + beginDate = beginDate.minus({ milliseconds: overTime }); //edge case, if we have 23h visible timerange, then cap it with timeranges beginDate - if (moment(timerange[0]).diff(beginDate) > 0) { - beginDate = moment(timerange[0]); + if (timerange[0].diff(beginDate).milliseconds > 0) { + beginDate = timerange[0]; } } return [beginDate, endDate]; }; -export const getUniqueAppNames = appItems => +export const getUniqueAppNames = (appItems) => _(appItems) .map('app') .uniq() - .orderBy([app => app.toLowerCase()]) - .map(app => ({ + .orderBy([(app) => app.toLowerCase()]) + .map((app) => ({ text: app, value: app, })) .value(); + +export const getTrackItemOrder = (type: string) => { + if (type === TrackItemType.AppTrackItem) { + return 1; + } + if (type === TrackItemType.StatusTrackItem) { + return 2; + } + if (type === TrackItemType.LogTrackItem) { + return 3; + } + return 0; +}; + +export const getTrackItemOrderFn = (d) => getTrackItemOrder(d.taskName); diff --git a/client/src/components/TrackItemTable/DefaultColumnFilter.tsx b/client/src/components/TrackItemTable/DefaultColumnFilter.tsx new file mode 100644 index 00000000..4b7d14e9 --- /dev/null +++ b/client/src/components/TrackItemTable/DefaultColumnFilter.tsx @@ -0,0 +1,18 @@ +import { Input } from '@chakra-ui/react'; +import { ToggleColumnFilter } from './ToggleColumnFilter'; + +export function DefaultColumnFilter({ column }) { + const filterValue = column.getFilterValue() || ''; + + return ( + + { + column.setFilterValue(e.target.value || undefined); // Set undefined to remove the filter entirely + }} + placeholder={``} + /> + + ); +} diff --git a/client/src/components/TrackItemTable/IndeterminateCheckbox.tsx b/client/src/components/TrackItemTable/IndeterminateCheckbox.tsx new file mode 100644 index 00000000..f7c32896 --- /dev/null +++ b/client/src/components/TrackItemTable/IndeterminateCheckbox.tsx @@ -0,0 +1,43 @@ +import { Box } from '@chakra-ui/react'; +import React, { useEffect, useRef } from 'react'; + +interface IndeterminateCheckboxProps { + indeterminate?: boolean; + checked?: boolean; + disabled?: boolean; + onChange?: (e: React.ChangeEvent) => void; +} + +export const IndeterminateCheckbox: React.FC = ({ + indeterminate = false, + checked = false, + disabled = false, + onChange, + ...rest +}) => { + const ref = useRef(null); + + useEffect(() => { + if (ref.current) { + ref.current.indeterminate = !!indeterminate; + } + }, [indeterminate]); + + return ( + + + + ); +}; diff --git a/client/src/components/TrackItemTable/ItemsTable.tsx b/client/src/components/TrackItemTable/ItemsTable.tsx new file mode 100644 index 00000000..3059f665 --- /dev/null +++ b/client/src/components/TrackItemTable/ItemsTable.tsx @@ -0,0 +1,351 @@ +import React, { useEffect, useMemo, useState } from 'react'; +import { diffAndFormatShort, formatDurationInternal } from '../../utils'; + +import { TriangleDownIcon, TriangleUpIcon } from '@chakra-ui/icons'; +import { Box, Button, Flex, Table, Tbody, Td, Th, Thead, Tr } from '@chakra-ui/react'; +import { + ColumnDef, + ColumnFiltersState, + FilterFn, + flexRender, + getCoreRowModel, + getFacetedMinMaxValues, + getFacetedRowModel, + getFacetedUniqueValues, + getFilteredRowModel, + getPaginationRowModel, + getSortedRowModel, + PaginationState, + SortingState, + useReactTable, +} from '@tanstack/react-table'; + +import { Portal } from '@chakra-ui/react'; +import { DATE_TIME_FORMAT } from '../../constants'; +import { DefaultColumnFilter } from './DefaultColumnFilter'; +import { IndeterminateCheckbox } from './IndeterminateCheckbox'; +import { OverflowTextCell } from './OverflowText'; +import { SelectColumnFilter } from './SelectColumnFilter'; +import { fuzzyTextFilterFn, TableButtonsProps } from './TrackItemTable.utils'; +import { TrackItemTablePager } from './TrackItemTablePager'; + +import { differenceInMilliseconds, format } from 'date-fns'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { TIME_FORMAT } from '../../constants'; + +interface ItemsTableProps { + data: ITrackItem[]; + resetButtonsRef?: React.RefObject; + isOneDay: boolean; + isSearchTable: boolean; + pageCount?: number; + pageIndex?: number; + fetchData?: (options: { pageIndex: number; pageSize: number; sortBy: SortingState }) => void; + extraColumns?: ColumnDef[]; + sumTotal: number; + manualSortBy: boolean; + customTableButtons?: React.ReactElement; +} + +const defaultSorting: SortingState = [ + { + id: 'endDate', + desc: true, + }, +]; + +export const ItemsTable = ({ + data, + resetButtonsRef, + isSearchTable, + pageCount: controlledPageCount, + pageIndex: controlledPageIndex, + fetchData, + extraColumns = [], + sumTotal, + manualSortBy = false, + isOneDay, + customTableButtons, +}: ItemsTableProps) => { + const dateToValue = ({ cell }) => { + const value = cell.getValue() as number; + return format(value, isOneDay ? TIME_FORMAT : DATE_TIME_FORMAT); + }; + + const columns = useMemo[]>( + () => [ + { + id: 'selection', + header: ({ table }) => ( + table.toggleAllRowsSelected(e.target.checked)} + /> + ), + cell: ({ row }) => ( + row.toggleSelected(e.target.checked)} + /> + ), + enableSorting: false, + size: 10, + minSize: 10, + maxSize: 10, + }, + { + header: 'App', + accessorKey: 'app', + filterFn: 'includesString', + enableColumnFilter: !isSearchTable, + meta: { + Filter: SelectColumnFilter, + }, + size: 100, + minSize: 100, + maxSize: 120, + }, + { + header: 'Title', + accessorKey: 'title', + cell: (info) => , + enableColumnFilter: !isSearchTable, + size: 250, + minSize: 100, + maxSize: 500, + }, + { + header: 'URL', + accessorKey: 'url', + cell: (info) => , + enableColumnFilter: !isSearchTable, + size: 150, + minSize: 70, + maxSize: 400, + }, + { + header: 'Begin', + accessorKey: 'beginDate', + cell: dateToValue, + enableColumnFilter: false, + size: 80, + minSize: 80, + maxSize: 120, + }, + { + header: 'End', + accessorKey: 'endDate', + cell: dateToValue, + enableColumnFilter: false, + size: 80, + minSize: 80, + maxSize: 120, + }, + { + header: 'Duration', + accessorFn: (record: ITrackItem) => diffAndFormatShort(record.beginDate, record.endDate), + enableColumnFilter: false, + enableSorting: !manualSortBy, + size: 60, + minSize: 60, + maxSize: 80, + }, + ...extraColumns, + ], + [extraColumns, dateToValue, manualSortBy], + ); + + const [columnFilters, setColumnFilters] = useState([]); + const [sorting, setSorting] = useState(defaultSorting); + const [rowSelection, setRowSelection] = useState({}); + const [pagination, setPagination] = useState({ + pageIndex: controlledPageIndex || 0, + pageSize: 10, + }); + + // Use the state of the pagination when it is controlled from outside + useEffect(() => { + if (isSearchTable && typeof controlledPageIndex === 'number') { + setPagination((prev) => ({ + ...prev, + pageIndex: controlledPageIndex, + })); + } + }, [isSearchTable, controlledPageIndex]); + + // Configure the table + const table = useReactTable({ + data, + columns, + filterFns: { + fuzzyText: fuzzyTextFilterFn as FilterFn, + }, + state: { + sorting, + columnFilters, + rowSelection, + pagination, + }, + enableRowSelection: true, + enableMultiRowSelection: true, + getRowId: (row: ITrackItem) => row.id?.toString(), + onRowSelectionChange: setRowSelection, + onSortingChange: setSorting, + onColumnFiltersChange: setColumnFilters, + onPaginationChange: setPagination, + getCoreRowModel: getCoreRowModel(), + getFilteredRowModel: getFilteredRowModel(), + getSortedRowModel: getSortedRowModel(), + getPaginationRowModel: getPaginationRowModel(), + getFacetedRowModel: getFacetedRowModel(), //if you need a list of values for a column (other faceted row models depend on this one) + getFacetedMinMaxValues: getFacetedMinMaxValues(), //if you need min/max values + getFacetedUniqueValues: getFacetedUniqueValues(), //if you need a list o + manualPagination: isSearchTable, + manualSorting: manualSortBy, + manualFiltering: isSearchTable, + pageCount: isSearchTable + ? typeof controlledPageCount === 'number' && controlledPageCount > 0 + ? Math.ceil(controlledPageCount / pagination.pageSize) + : 0 + : undefined, + }); + + // Reset row selection when data changes + useEffect(() => { + setRowSelection({}); + }, [data]); + + // Handle server-side pagination + useEffect(() => { + if (isSearchTable) { + console.info('Change paging', { + pageIndex: pagination.pageIndex, + pageSize: pagination.pageSize, + sortBy: sorting, + }); + fetchData?.({ pageIndex: pagination.pageIndex, pageSize: pagination.pageSize, sortBy: sorting }); + } + }, [isSearchTable, fetchData, pagination, sorting]); + + // Handle server-side sorting + useEffect(() => { + if (manualSortBy && !isSearchTable) { + fetchData?.({ pageIndex: pagination.pageIndex, pageSize: pagination.pageSize, sortBy: sorting }); + } + }, [manualSortBy, fetchData, sorting, pagination, isSearchTable]); + + // Sum of all table data + const subTotal = table + .getFilteredRowModel() + .rows.map((row) => row.original) + .reduce((total, item) => total + differenceInMilliseconds(item.endDate, item.beginDate), 0); + + // Get the selected rows information for buttons/actions + const tableButtonsProps: TableButtonsProps = { + selectedFlatRows: table.getSelectedRowModel().rows, + selectedRowIds: table.getState().rowSelection, + setAllFilters: () => setColumnFilters([]), + setSortBy: (sortByState: SortingState) => setSorting(sortByState), + pageIndex: pagination.pageIndex, + pageSize: pagination.pageSize, + fetchData, + }; + + return ( + <> + + {customTableButtons && React.cloneElement(customTableButtons, tableButtonsProps)} + + +
    + + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => ( + + ))} + + ))} + + + {table.getRowModel().rows.map((row) => ( + + {row.getVisibleCells().map((cell) => ( + + ))} + + ))} + +
    + {header.column.id === 'selection' ? ( + flexRender(header.column.columnDef.header, header.getContext()) + ) : ( + + {header.column.getCanSort() ? ( + + ) : ( + + )} + + {header.column.getCanFilter() ? ( + // Use a safer type check and conditional rendering + // @ts-expect-error - We know this is correct based on our column definitions + header.column.columnDef.meta?.Filter ? ( + // @ts-expect-error - We know this component exists + + ) : ( + + ) + ) : null} + + )} +
    + {flexRender(cell.column.columnDef.cell, cell.getContext())} +
    + + + {formatDurationInternal(subTotal)} / {formatDurationInternal(sumTotal)} + + + + + + ); +}; diff --git a/client/src/components/TrackItemTable/ItemsTable.utils.ts b/client/src/components/TrackItemTable/ItemsTable.utils.ts new file mode 100644 index 00000000..1daa972a --- /dev/null +++ b/client/src/components/TrackItemTable/ItemsTable.utils.ts @@ -0,0 +1,8 @@ +import { SortingState } from '@tanstack/react-table'; + +export const defaultSorting: SortingState = [ + { + id: 'endDate', + desc: true, + }, +]; diff --git a/client/src/components/TrackItemTable/OverflowText.tsx b/client/src/components/TrackItemTable/OverflowText.tsx new file mode 100644 index 00000000..3a4a33ca --- /dev/null +++ b/client/src/components/TrackItemTable/OverflowText.tsx @@ -0,0 +1,23 @@ +import { Tooltip, Text, TextProps } from '@chakra-ui/react'; + +interface IProps extends TextProps { + value?: string; +} + +export const OverflowText = ({ children, ...props }: TextProps) => { + return ( + + + {children} + + + ); +}; + +export const OverflowTextCell = ({ value }: IProps) => { + return ( + + {value} + + ); +}; diff --git a/client/src/components/TrackItemTable/SelectColumnFilter.tsx b/client/src/components/TrackItemTable/SelectColumnFilter.tsx new file mode 100644 index 00000000..78789234 --- /dev/null +++ b/client/src/components/TrackItemTable/SelectColumnFilter.tsx @@ -0,0 +1,28 @@ +import { Select } from '@chakra-ui/react'; +import { Column } from '@tanstack/react-table'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { ToggleColumnFilter } from './ToggleColumnFilter'; + +export function SelectColumnFilter({ column }: { column: Column }) { + const uniqueValues = column.getFacetedUniqueValues(); + const options = Array.from(uniqueValues.keys()); + const filterValue = column.getFilterValue() || ''; + + return ( + + + + ); +} diff --git a/client/src/components/TrackItemTable/ToggleColumnFilter.tsx b/client/src/components/TrackItemTable/ToggleColumnFilter.tsx new file mode 100644 index 00000000..8daaf863 --- /dev/null +++ b/client/src/components/TrackItemTable/ToggleColumnFilter.tsx @@ -0,0 +1,30 @@ +import { cloneElement, useRef } from 'react'; +import { Popover, PopoverTrigger, useDisclosure, IconButton, PopoverContent, PopoverArrow } from '@chakra-ui/react'; +import { SearchIcon } from '@chakra-ui/icons'; + +export function ToggleColumnFilter({ children }) { + const { onOpen, onClose, isOpen } = useDisclosure(); + const firstFieldRef = useRef(null!); + + const form = cloneElement(children, { ref: firstFieldRef, onCancel: onClose }); + + return ( + } + onOpen={onOpen} + onClose={onClose} + placement="right" + closeOnBlur={true} + > + + } /> + + + + + {form} + + + ); +} diff --git a/client/src/components/TrackItemTable/TrackItemTable.styles.ts b/client/src/components/TrackItemTable/TrackItemTable.styles.ts deleted file mode 100644 index 30fd2d4f..00000000 --- a/client/src/components/TrackItemTable/TrackItemTable.styles.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Box, Flex } from 'reflexbox'; -import styled from 'styled-components'; - -export const FilterDropdown = styled(Flex).attrs({ p: 2 })` - border-radius: 6px; - background: #fff; - box-shadow: 0 1px 6px rgba(0, 0, 0, 0.2); -`; - -export const FilterInput = styled(Box).attrs({ mr: 1 })` - width: 130px; -`; -export const Highlight = styled.span` - color: #f50; -`; - -export const TotalCount = styled.div` - text-align: right; - padding-right: 10px; -`; diff --git a/client/src/components/TrackItemTable/TrackItemTable.tsx b/client/src/components/TrackItemTable/TrackItemTable.tsx index 52c62e8e..f1a4eaad 100644 --- a/client/src/components/TrackItemTable/TrackItemTable.tsx +++ b/client/src/components/TrackItemTable/TrackItemTable.tsx @@ -1,349 +1,51 @@ -import { Box, Flex } from 'reflexbox'; -import { Button, Input, Table } from 'antd'; -import { SearchOutlined } from '@ant-design/icons'; -// tslint:disable-next-line: no-submodule-imports - +import { Box } from '@chakra-ui/react'; +import { differenceInMilliseconds } from 'date-fns'; import { sumBy } from 'lodash'; -import moment from 'moment'; -import React, { useState, useRef, useEffect } from 'react'; -import Moment from 'react-moment'; -import { convertDate, DATE_TIME_FORMAT, TIME_FORMAT } from '../../constants'; -import { TrackItemType } from '../../enum/TrackItemType'; -import { diffAndFormatShort } from '../../utils'; -import { filterItems, getUniqueAppNames } from '../Timeline/timeline.utils'; -import { FilterDropdown, FilterInput, Highlight, TotalCount } from './TrackItemTable.styles'; -import { Logger } from '../../logger'; -import { deleteByIds } from '../../services/trackItem.api'; -import { checkIfOneDay } from '../../timeline.util'; +import { ITrackItem } from '../../@types/ITrackItem'; import { useStoreActions, useStoreState } from '../../store/easyPeasy'; - -const calculateTotal = filteredData => { - const totalMs = sumBy(filteredData, (c: any) => - convertDate(c.endDate).diff(convertDate(c.beginDate)), - ); - const dur = moment.duration(totalMs); - - return Total {dur.format()}; -}; - -const paginationConf = { - showSizeChanger: true, - pageSizeOptions: ['50', '100', '300', '500'], -}; - -export const TrackItemTable = () => { - const timeItems = useStoreState(state => state.timeItems); - const visibleTimerange = useStoreState(state => state.visibleTimerange); - - const fetchTimerange = useStoreActions(actions => actions.fetchTimerange); - - const [data, setData] = useState([]); - const [state, setState] = useState({ - filteredInfo: {}, - sortedInfo: {}, - filterTitleDropdownVisible: false, - filterUrlDropdownVisible: false, - activeType: TrackItemType.AppTrackItem, - searchText: '', - filtered: false, - selectedRowKeys: [], +import { TIMERANGE_MODE_TODAY } from '../../store/mainStore'; +import { checkIfOneDay } from '../../timeline.util'; +import { filterItems } from '../Timeline/timeline.utils'; +import { ItemsTable } from './ItemsTable'; +import { defaultTableButtonsProps } from './TrackItemTable.utils'; +import { TrackItemTableButtons } from './TrackItemTableButtons'; + +export const TrackItemTable = ({ type, resetButtonsRef }) => { + const timeItems = useStoreState((state) => state.timeItems); + const visibleTimerange = useStoreState((state) => state.visibleTimerange); + const timerangeMode = useStoreState((state) => state.timerangeMode); + const setLiveView = useStoreActions((actions) => actions.setLiveView); + + // Use the first 10 items for the current page (since we're not doing server-side pagination here) + const data = filterItems(timeItems[type], visibleTimerange); + + const isOneDay = checkIfOneDay(visibleTimerange); + const isToday = timerangeMode === TIMERANGE_MODE_TODAY; + + // Calculate total duration in milliseconds for all the data + const totalDuration = sumBy(timeItems[type] as ITrackItem[], (trackItem) => { + return differenceInMilliseconds(trackItem.endDate, trackItem.beginDate); }); - const deleteTimelineItems = async ids => { - Logger.debug('Delete timeline items', ids); - - if (ids) { - await deleteByIds(ids); - Logger.debug('Deleted timeline items', ids); - fetchTimerange(); - } else { - Logger.error('No ids, not deleting from DB'); - } - }; - - const searchInput = useRef(); - - const filterByAppType = type => - type === TrackItemType.AppTrackItem - ? filterItems(timeItems.appItems, visibleTimerange) - : filterItems(timeItems.logItems, visibleTimerange); - - useEffect(() => { - const { activeType } = state; - - const filteredData = filterByAppType(activeType); - setData(filteredData); - setState({ - ...state, - isOneDay: checkIfOneDay(visibleTimerange), - }); - - if ( - timeItems.appItems.length > 0 && - filteredData.length === 0 && - state.activeType === TrackItemType.AppTrackItem - ) { - const beginDate = timeItems.appItems[0].beginDate; - const endDate = timeItems.appItems[0].endDate; + const handleClick = (e) => { + e.stopPropagation(); - Logger.error('No items filtered for table', { - visibleTimerange, - beginDate, - endDate, - }); + if (isToday) { + setLiveView(false); } - }, [timeItems, visibleTimerange]); // eslint-disable-line react-hooks/exhaustive-deps - - useEffect(() => { - if (searchInput.current) { - searchInput.current.focus(); - } - }, [state.filterTitleDropdownVisible]); - - const handleChange = (pagination: any, filters: any, sorter: any) => { - setState({ ...state, filteredInfo: filters, sortedInfo: sorter }); - }; - - const clearFilters = () => { - setState({ ...state, filteredInfo: {} }); - }; - - const clearAll = () => { - setState({ ...state, filteredInfo: {}, sortedInfo: {} }); - }; - - const toggleTask = () => { - const { activeType } = state; - - clearAll(); - - const newActiveType = - activeType === TrackItemType.AppTrackItem - ? TrackItemType.LogTrackItem - : TrackItemType.AppTrackItem; - - setData(filterByAppType(newActiveType)); - setState({ - ...state, - - activeType: newActiveType, - isOneDay: checkIfOneDay(visibleTimerange), - }); - }; - - const onInputChange = e => { - setState({ ...state, searchText: e.target.value }); - }; - - const onSearch = () => { - const { searchText } = state; - const reg = new RegExp(searchText, 'gi'); - const filteredData = data - .map((record: any) => { - const match = record.title.match(reg); - if (!match) { - return null; - } - return { - ...record, - name: ( - - {record.title - .split(reg) - .map((text, i) => - i > 0 - ? [{match[0]}, text] - : text, - )} - - ), - }; - }) - .filter(record => !!record); - - setData(filteredData); - setState({ - ...state, - filterTitleDropdownVisible: false, - filterUrlDropdownVisible: false, - filtered: !!searchText, - }); - }; - - const onSelectChange = selectedRowKeys => { - Logger.debug('selectedRowKeys changed: ', selectedRowKeys); - setState({ ...state, selectedRowKeys }); - }; - - const deleteSelectedItems = () => { - const { selectedRowKeys } = state; - deleteTimelineItems(selectedRowKeys); - setState({ ...state, selectedRowKeys: [] }); }; - const { isOneDay, activeType, sortedInfo, filteredInfo } = state; - - const FilterDropdownComp = () => ( - - - - - - - ); - - const columns = [ - { - title: 'App', - dataIndex: 'app', - key: 'app', - width: 200, - filters: getUniqueAppNames(timeItems.appItems), - filteredValue: filteredInfo.app || null, - onFilter: (value: any, record: any) => record.app.includes(value), - sorter: (a: any, b: any) => a.app - b.app, - sortOrder: sortedInfo.columnKey === 'app' && sortedInfo.order, - }, - { - title: 'Title', - dataIndex: 'title', - key: 'title', - filterDropdown: FilterDropdownComp, - filterIcon: , - filterTitleDropdownVisible: state.filterTitleDropdownVisible, - onfilterTitleDropdownVisibleChange: visible => { - setState({ - ...state, - filterTitleDropdownVisible: visible, - }); - if (visible) { - setTimeout(() => (searchInput.current as any).select()); - } - }, - sorter: (a: any, b: any) => a.title.length - b.title.length, - sortOrder: sortedInfo.columnKey === 'title' && sortedInfo.order, - }, - - { - title: 'URL', - dataIndex: 'url', - key: 'url', - width: 300, - ellipsis: true, - filterDropdown: FilterDropdownComp, - filterIcon: , - filterUrlDropdownVisible: state.filterUrlDropdownVisible, - onFilterUrlDropdownVisibleChange: visible => { - setState({ - ...state, - filterUrlDropdownVisible: visible, - }); - if (visible) { - setTimeout(() => searchInput.current.select()); - } - }, - sorter: (a: any, b: any) => a.url.length - b.url.length, - sortOrder: sortedInfo.columnKey === 'url' && sortedInfo.order, - }, - { - title: 'Begin', - dataIndex: 'beginDate', - key: 'beginDate', - width: 170, - - onFilter: (value: any, record: any) => convertDate(record.beginDate) > value, - sorter: (a: any, b: any) => - convertDate(a.beginDate).valueOf() - convertDate(b.beginDate).valueOf(), - sortOrder: sortedInfo.columnKey === 'beginDate' && sortedInfo.order, - render: (text, record) => ( - - {record.beginDate} - - ), - }, - { - title: 'End', - dataIndex: 'endDate', - key: 'endDate', - width: 170, - onFilter: (value: any, record: any) => convertDate(record.endDate) > value, - sorter: (a: any, b: any) => - convertDate(a.endDate).valueOf() - convertDate(b.endDate).valueOf(), - sortOrder: sortedInfo.columnKey === 'endDate' && sortedInfo.order, - - render: (text, record) => ( - {record.endDate} - ), - }, - - { - title: 'Dur', - dataIndex: '', - key: 'duration', - width: 80, - sorter: (a: any, b: any) => - convertDate(a.endDate).diff(convertDate(a.beginDate)) - - convertDate(b.endDate).diff(convertDate(b.beginDate)), - sortOrder: sortedInfo.columnKey === 'duration' && sortedInfo.order, - - render: (text, record) => ( - {diffAndFormatShort(record.beginDate, record.endDate)} - ), - }, - ]; - - const { selectedRowKeys } = state; - const rowSelection = { - selectedRowKeys, - onChange: onSelectChange, - }; - const hasSelected = selectedRowKeys.length > 0; return ( -
    - - - {!hasSelected && ( - - )} - {hasSelected && ( - - )} - - - - - - - - - - - - `${record.id}`} - columns={columns} - pagination={paginationConf} - dataSource={data} - onChange={handleChange} - footer={calculateTotal} + + } /> - + ); }; diff --git a/client/src/components/TrackItemTable/TrackItemTable.utils.ts b/client/src/components/TrackItemTable/TrackItemTable.utils.ts new file mode 100644 index 00000000..0ac35b8f --- /dev/null +++ b/client/src/components/TrackItemTable/TrackItemTable.utils.ts @@ -0,0 +1,44 @@ +import { FilterFn, Row, SortingState } from '@tanstack/react-table'; +import { differenceInMilliseconds } from 'date-fns'; +import { sumBy } from 'lodash'; +import { matchSorter } from 'match-sorter'; +import { ITrackItem } from '../../@types/ITrackItem'; + +export const calculateTotal = (filteredData: ITrackItem[]) => { + const totalMs = sumBy(filteredData, (trackItem: ITrackItem) => { + return differenceInMilliseconds(trackItem.endDate, trackItem.beginDate); + }); + + return totalMs; +}; + +// Use matchSorter for fuzzy matching +export const fuzzyTextFilterFn: FilterFn = (row: Row, columnId: string, value: string) => { + // Rank the item + const itemRank = matchSorter([row.getValue(columnId)], value); + + return itemRank.length > 0; +}; + +// Let the table remove the filter if the string is empty +fuzzyTextFilterFn.autoRemove = (val: string) => !val; + +export interface TableButtonsProps { + selectedFlatRows: Row[]; + selectedRowIds: Record; + setAllFilters: () => void; + setSortBy: (sortBy: SortingState) => void; + pageIndex: number; + pageSize: number; + fetchData?: (options: { pageIndex: number; pageSize: number; sortBy: SortingState }) => void; +} + +export const defaultTableButtonsProps: TableButtonsProps = { + selectedFlatRows: [], + selectedRowIds: {}, + setAllFilters: () => {}, + setSortBy: () => {}, + pageIndex: 0, + pageSize: 10, + fetchData: () => {}, +}; diff --git a/client/src/components/TrackItemTable/TrackItemTableButtons.tsx b/client/src/components/TrackItemTable/TrackItemTableButtons.tsx new file mode 100644 index 00000000..b6125918 --- /dev/null +++ b/client/src/components/TrackItemTable/TrackItemTableButtons.tsx @@ -0,0 +1,63 @@ +import { Button, HStack, Text } from '@chakra-ui/react'; +import { SortingState } from '@tanstack/react-table'; +import { Logger } from '../../logger'; +import { deleteByIds } from '../../services/trackItem.api'; +import { useStoreActions } from '../../store/easyPeasy'; +import { defaultSorting } from './ItemsTable.utils'; +import { TableButtonsProps } from './TrackItemTable.utils'; + +interface Props extends TableButtonsProps { + fetchData?: (options: { pageIndex: number; pageSize: number; sortBy: SortingState }) => void; +} + +export const TrackItemTableButtons: React.FC = (props) => { + const { selectedFlatRows, selectedRowIds, setAllFilters, setSortBy } = props; + + const fetchTimerange = useStoreActions((actions) => actions.fetchTimerange); + + const deleteTimelineItems = async (ids: number[]) => { + Logger.debug('Delete timeline items', ids); + + if (ids) { + await deleteByIds(ids); + Logger.debug('Deleted timeline items', ids); + fetchTimerange(); + } else { + Logger.error('No ids, not deleting from DB'); + } + }; + + const deleteSelectedItems = () => { + deleteTimelineItems(selectedFlatRows.map(({ original }) => original.id)); + }; + + const hasSelected = Object.keys(selectedRowIds).length > 0; + + return ( + + {hasSelected && ( + + )} + + + + + + ); +}; diff --git a/client/src/components/TrackItemTable/TrackItemTablePager.tsx b/client/src/components/TrackItemTable/TrackItemTablePager.tsx new file mode 100644 index 00000000..e8a1b5a4 --- /dev/null +++ b/client/src/components/TrackItemTable/TrackItemTablePager.tsx @@ -0,0 +1,130 @@ +import { ArrowLeftIcon, ArrowRightIcon, ChevronLeftIcon, ChevronRightIcon } from '@chakra-ui/icons'; +import { + Flex, + IconButton, + NumberDecrementStepper, + NumberIncrementStepper, + NumberInput, + NumberInputField, + NumberInputStepper, + Select, + Text, + Tooltip, +} from '@chakra-ui/react'; + +interface TrackItemTablePagerProps { + gotoPage: (page: number) => void; + canPreviousPage: boolean; + previousPage: () => void; + pageIndex: number; + pageSize: number; + nextPage: () => void; + canNextPage: boolean; + pageCount: number; + setPageSize: (size: number) => void; +} + +export const TrackItemTablePager = ({ + gotoPage, + canPreviousPage, + previousPage, + pageIndex, + pageSize, + nextPage, + canNextPage, + pageCount, + setPageSize, +}: TrackItemTablePagerProps) => { + if (pageCount === 0) return null; + + return ( + + + + gotoPage(0)} + isDisabled={!canPreviousPage} + icon={} + mr={4} + /> + + + } + /> + + + + + + Page{' '} + + {pageIndex + 1} + {' '} + of{' '} + + {Math.max(pageCount, 1)} + + + Go to page:{' '} + { + const currentPage = Number(value); + const page = currentPage ? currentPage - 1 : 0; + gotoPage(page); + }} + defaultValue={pageIndex + 1} + value={pageIndex + 1} + > + + + + + + + + + + + + } + /> + + + gotoPage(Math.max(pageCount - 1, 0))} + isDisabled={!canNextPage} + icon={} + ml={4} + /> + + + + ); +}; diff --git a/client/src/components/TrackItemTable/TrackItemTabs.tsx b/client/src/components/TrackItemTable/TrackItemTabs.tsx new file mode 100644 index 00000000..afb5ebb7 --- /dev/null +++ b/client/src/components/TrackItemTable/TrackItemTabs.tsx @@ -0,0 +1,27 @@ +import { Box, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react'; +import { useRef } from 'react'; +import { TrackItemType } from '../../enum/TrackItemType'; +import { TrackItemTable } from './TrackItemTable'; + +export const TrackItemTabs = () => { + const resetButtonsRef = useRef(null); + + return ( + + + Apps + Logs + + + + + + + + + + + + + ); +}; diff --git a/client/src/components/TrayLayout/ChartCircles.tsx b/client/src/components/TrayLayout/ChartCircles.tsx new file mode 100644 index 00000000..1433a866 --- /dev/null +++ b/client/src/components/TrayLayout/ChartCircles.tsx @@ -0,0 +1,93 @@ +import { Box, Flex, Text, useColorModeValue } from '@chakra-ui/react'; +import { shortTime } from '../../time.util'; + +const NO_VALUE = '-'; + +export const ChartCircles = ({ width, innerWidth, onlineTimeMs, lastSessionMs, currentSession }) => { + const mainTextColor = useColorModeValue('gray.700', 'gray.300'); + + return ( + + + + + + + Session Time + + + {currentSession} + + + + Online Today + + + {onlineTimeMs} + + + Last Session + + + {lastSessionMs ? shortTime(lastSessionMs, { largest: 2, units: ['d', 'h', 'm', 's'] }) : NO_VALUE} + + + + ); +}; diff --git a/client/src/components/TrayLayout/OnlineChart.tsx b/client/src/components/TrayLayout/OnlineChart.tsx new file mode 100644 index 00000000..9f17c6bd --- /dev/null +++ b/client/src/components/TrayLayout/OnlineChart.tsx @@ -0,0 +1,156 @@ +import { Box, Button, HStack, Text, useColorModeValue, VStack } from '@chakra-ui/react'; +import { DateTime } from 'luxon'; +import { useContext, useEffect, useState } from 'react'; +import { VictoryContainer, VictoryPie, VictoryStyleInterface } from 'victory'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { RootContext } from '../../RootContext'; +import { useChartThemeState } from '../../routes/ChartThemeProvider'; +import { colorProp } from '../charts.utils'; +import { getOnlineTime } from '../PieCharts/MetricTiles.utils'; +import { ShortTimeInterval } from '../TrayList/ShortTimeInterval'; +import { ChartCircles } from './ChartCircles'; +import { CLOCK_MODE, getOnlineTimesForChart, getQuarters, getTotalOnlineDuration } from './OnlineChart.util'; +import { OnlineChartTooltipLabel } from './OnlineChartTooltipLabel'; + +const QuarterLabel = (props) => ( + + + +); + +const MINUTES = 60 * 1000; + +export const OnlineChart = ({ items }: { items: ITrackItem[] }) => { + const { workSettings } = useContext(RootContext); + const { chartTheme } = useChartThemeState(); + const [mode, setMode] = useState(CLOCK_MODE.HOURS_12); + const [currentSession, setCurrentSession] = useState(0); + const [lastSession, setLastSession] = useState(); + const onlineSinceColor = useColorModeValue('var(--chakra-colors-blue-500)', 'var(--chakra-colors-blue-500)'); + const overtimeColor = 'var(--chakra-colors-red-500)'; + + const { sessionLength, minBreakTime } = workSettings; + + const MAX_TIMER = sessionLength * MINUTES; + const sessionIsOvertime = currentSession > MAX_TIMER; + + useEffect(() => { + const grouped = getTotalOnlineDuration(DateTime.now(), items, minBreakTime); + const sessionTime = grouped[0]; + setCurrentSession(sessionTime); + + if (grouped.length > 1) { + setLastSession(grouped[1]); + } else { + setLastSession(undefined); + } + }, [items, minBreakTime]); + + const width = 300; + + const innerWidth = 230; + const [startDate, firstQuarter, secondQuarter, thirdQuarter, endDate] = getQuarters(DateTime.now(), mode); + + const onlineTimeMs = getOnlineTime(items, [startDate, endDate]); + + const pieData = getOnlineTimesForChart({ + beginClamp: startDate, + endClamp: endDate, + items, + mode, + }); + + const style: VictoryStyleInterface = { + data: { + fill: colorProp, + stroke: colorProp, + strokeWidth: 0, + fillOpacity: 0.75, + }, + }; + + const sessionLine = MAX_TIMER - currentSession; + + return ( + + {startDate.hour} + + + {thirdQuarter.hour} + + + } + lastSessionMs={lastSession} + currentSession={} + /> + } + style={style} + labelComponent={ + + } + y={(datum) => datum.diff} + data={pieData} + /> + + + + } + style={style} + y={(datum) => datum.diff} + labels={() => null} + data={[ + { x: 1, diff: sessionLine, color: 'transparent' }, + { + x: 3, + diff: currentSession, + color: sessionIsOvertime ? overtimeColor : onlineSinceColor, + }, + ]} + /> + + + + + {firstQuarter.hour} + + + {secondQuarter.hour} + + + ); +}; diff --git a/client/src/components/TrayLayout/OnlineChart.util.test.ts b/client/src/components/TrayLayout/OnlineChart.util.test.ts new file mode 100644 index 00000000..19b6a6e5 --- /dev/null +++ b/client/src/components/TrayLayout/OnlineChart.util.test.ts @@ -0,0 +1,736 @@ +import { last } from 'lodash'; +import { DateTime } from 'luxon'; +import { describe, expect, it, test } from 'vitest'; +import { + getClampHours, + getOnlineTimesForChart, + getTotalOnlineDuration, + groupByBreaks, + isBetweenHours, + isLessThanHours, +} from './OnlineChart.util'; + +const ONLINE = 'ONLINE'; +const OFFLINE = 'OFFLINE'; +const IDLE = 'IDLE'; + +const beginDate18_23_50 = DateTime.fromISO('2021-06-18T23:50:00').toMillis(); +const endDate19_00_10 = DateTime.fromISO('2021-06-19T00:10:00').toMillis(); + +const beginDate19_10_00 = DateTime.fromISO('2021-06-19T10:00:00').toMillis(); +const endDate19_10_10 = DateTime.fromISO('2021-06-19T10:10:00').toMillis(); + +const beginDate19_11_50 = DateTime.fromISO('2021-06-19T11:50:00').toMillis(); +const endDate_19_12_10 = DateTime.fromISO('2021-06-19T12:10:00').toMillis(); + +const beginDate19_18_50 = DateTime.fromISO('2021-06-19T18:50:00').toMillis(); +const endDate19_19_10 = DateTime.fromISO('2021-06-19T19:10:00').toMillis(); + +const beginDate_19_23_50 = DateTime.fromISO('2021-06-19T23:50:00').toMillis(); +const endDate20_00_10 = DateTime.fromISO('2021-06-20T00:10:00').toMillis(); + +const realDate = DateTime.fromISO('2021-06-19T10:10:00'); + +describe('OnlineChart getOnlineTimesForChart', () => { + it('uses only ONLINE items', () => { + const onlineItem = { + id: 1, + app: ONLINE, + beginDate: beginDate19_10_00, + endDate: endDate19_10_10, + }; + + const offlineItems = [ + { + id: 2, + app: OFFLINE, + beginDate: beginDate19_11_50, + endDate: endDate_19_12_10, + }, + { + id: 3, + app: OFFLINE, + beginDate: beginDate19_18_50, + endDate: endDate19_19_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 0, endHour: 24 }), + items: [onlineItem, ...offlineItems], + }); + + expect(actual).toEqual([ + { + beginDate: realDate.startOf('day').toMillis(), + endDate: beginDate19_10_00, + color: 'transparent', + diff: 600, + x: 0, + }, + { + id: 1, + app: ONLINE, + beginDate: beginDate19_10_00, + endDate: endDate19_10_10, + diff: 10, + x: 1, + color: 'transparent', + }, + { + beginDate: endDate19_10_10, + endDate: realDate.endOf('day').plus({ milliseconds: 1 }).toMillis(), + color: 'transparent', + diff: 830, + x: 2, + }, + ]); + }); + + it('Sets first, last and in between empty items hours 0 to 24', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate19_10_00, + endDate: endDate19_10_10, + }, + + { + id: 2, + app: ONLINE, + beginDate: beginDate19_18_50, + endDate: endDate19_19_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 0, endHour: 24 }), + items: [...items], + }); + expect(actual).toEqual([ + { + beginDate: DateTime.fromISO('2021-06-19T00:00:00').toMillis(), + endDate: beginDate19_10_00, + color: 'transparent', + diff: 600, + x: 0, + }, + { + app: ONLINE, + beginDate: beginDate19_10_00, + color: 'transparent', + endDate: endDate19_10_10, + diff: 10, + x: 1, + id: 1, + }, + + { + beginDate: endDate19_10_10, + endDate: beginDate19_18_50, + diff: 520, + color: 'transparent', + x: 2, + }, + + { + app: ONLINE, + beginDate: beginDate19_18_50, + endDate: endDate19_19_10, + diff: 20, + color: 'transparent', + x: 3, + id: 2, + }, + { + beginDate: endDate19_19_10, + endDate: DateTime.fromISO('2021-06-19T24:00:00').toMillis(), + color: 'transparent', + diff: 290, + x: 4, + }, + ]); + }); + + it('Sets first, last and in between empty items for hours 12 to 24', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate19_10_00, + endDate: endDate19_10_10, + }, + + { + id: 2, + app: ONLINE, + beginDate: beginDate19_18_50, + endDate: endDate19_19_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 12, endHour: 24 }), + + items: [...items], + }); + + expect(actual).toEqual([ + { + beginDate: DateTime.fromISO('2021-06-19T12:00:00').toMillis(), + endDate: beginDate19_18_50, + color: 'transparent', + diff: 410, + x: 0, + }, + + { + app: ONLINE, + beginDate: beginDate19_18_50, + endDate: endDate19_19_10, + color: 'transparent', + diff: 20, + x: 1, + id: 2, + }, + { + beginDate: endDate19_19_10, + endDate: DateTime.fromISO('2021-06-19T24:00:00').toMillis(), + color: 'transparent', + diff: 290, + x: 2, + }, + ]); + }); + + it('Clamps items for hours 12 to 24 beginDate', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate19_11_50, + endDate: endDate_19_12_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 12, endHour: 24 }), + + items: [...items], + }); + + expect(actual).toEqual([ + { + app: ONLINE, + beginDate: DateTime.fromISO('2021-06-19T12:00:00').toMillis(), + color: 'transparent', + endDate: endDate_19_12_10, + diff: 10, + x: 0, + id: 1, + }, + { + beginDate: endDate_19_12_10, + endDate: DateTime.fromISO('2021-06-19T24:00:00').toMillis(), + color: 'transparent', + diff: 710, + x: 1, + }, + ]); + }); + + it('Clamps items for hours 12 to 24 endDate', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate19_11_50, + endDate: endDate_19_12_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 0, endHour: 12 }), + items: [...items], + }); + + expect(actual).toEqual([ + { + beginDate: DateTime.fromISO('2021-06-19T00:00:00').toMillis(), + endDate: beginDate19_11_50, + color: 'transparent', + diff: 710, + x: 0, + }, + { + app: ONLINE, + beginDate: beginDate19_11_50, + color: 'transparent', + endDate: DateTime.fromISO('2021-06-19T12:00:00').toMillis(), + diff: 10, + id: 1, + x: 1, + }, + ]); + }); + it('Clamps items for hours 12 to 24 endDate next day', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate_19_23_50, + endDate: endDate20_00_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 12, endHour: 24 }), + items: [...items], + }); + + expect(actual).toEqual([ + { + beginDate: DateTime.fromISO('2021-06-19T12:00:00').toMillis(), + endDate: beginDate_19_23_50, + color: 'transparent', + diff: 710, + x: 0, + }, + { + app: ONLINE, + beginDate: beginDate_19_23_50, + color: 'transparent', + endDate: DateTime.fromISO('2021-06-19T24:00:00').toMillis(), + diff: 10, + id: 1, + x: 1, + }, + ]); + }); + + it('Clamps items for hours 0 to 12 beginDate previous day', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: beginDate18_23_50, + endDate: endDate19_00_10, + }, + ]; + + const actual = getOnlineTimesForChart({ + ...getClampHours({ realDate, startHour: 0, endHour: 12 }), + items: [...items], + }); + + expect(actual).toEqual([ + { + app: ONLINE, + beginDate: DateTime.fromISO('2021-06-19T00:00:00').toMillis(), + endDate: endDate19_00_10, + color: 'transparent', + diff: 10, + id: 1, + x: 0, + }, + { + beginDate: endDate19_00_10, + endDate: DateTime.fromISO('2021-06-19T12:00:00').toMillis(), + color: 'transparent', + diff: 710, + x: 1, + }, + ]); + }); +}); + +const getMillisFromTime = (time: string) => { + return DateTime.fromISO(`2021-06-19T${time}`).toMillis(); +}; +const getDateFromTime = (time: string) => { + return DateTime.fromISO(`2021-06-19T${time}`); +}; + +const MINUTES = 60 * 1000; +const minBreakTime = 5; + +describe('OnlineChart groupByBreaks', () => { + it('groupByBreaks take items until finds minimal break time.', () => { + const chunk1 = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:29:00'), + endDate: getMillisFromTime('08:39:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + color: 'transparent', + diff: 10, + x: 1, + }, + { + id: 3, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:14:00'), + color: 'transparent', + diff: 14, + x: 2, + }, + ]; + const chunk2 = [ + { + id: 4, + app: ONLINE, + beginDate: getMillisFromTime('07:00:00'), + endDate: getMillisFromTime('07:10:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + ]; + + const sorted = [...chunk1, ...chunk2]; + const grouped = groupByBreaks(sorted, minBreakTime); + + expect(grouped).toEqual([chunk1, chunk2]); + }); + + it('groupByBreaks groups all items', () => { + const chunk1 = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:29:00'), + endDate: getMillisFromTime('08:39:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + color: 'transparent', + diff: 10, + x: 1, + }, + { + id: 3, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:14:00'), + color: 'transparent', + diff: 14, + x: 2, + }, + ]; + const chunk2 = [ + { + id: 4, + app: ONLINE, + beginDate: getMillisFromTime('07:00:00'), + endDate: getMillisFromTime('07:10:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + ]; + + const chunk3 = [ + { + id: 5, + app: ONLINE, + beginDate: getMillisFromTime('06:50:00'), + endDate: getMillisFromTime('06:51:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + ]; + + const chunk4 = [ + { + id: 6, + app: ONLINE, + beginDate: getMillisFromTime('06:00:00'), + endDate: getMillisFromTime('06:10:00'), + color: 'transparent', + diff: 10, + x: 0, + }, + { + id: 7, + app: ONLINE, + beginDate: getMillisFromTime('05:00:00'), + endDate: getMillisFromTime('05:55:00'), + color: 'transparent', + diff: 55, + x: 1, + }, + ]; + + const sorted = [...chunk1, ...chunk2, ...chunk3, ...chunk4]; + const grouped = groupByBreaks(sorted, minBreakTime); + + expect(grouped).toEqual([chunk1, chunk2, chunk3, chunk4]); + }); +}); +describe('OnlineChart getTotalOnlineDuration', () => { + it('getTotalOnlineDuration sums diffs', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:15:00'), + }, + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + }, + ]; + const now = DateTime.fromMillis(last(items)?.endDate || 0); + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([25 * MINUTES]); + }); + + it('getTotalOnlineDuration returns 0 if no ONLINE items', () => { + const items = [ + { + id: 1, + app: OFFLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:15:00'), + }, + { + id: 2, + app: IDLE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + }, + ]; + const now = DateTime.fromMillis(last(items)?.endDate || 0); + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([0]); + }); + + it('getTotalOnlineDuration only sums ONLINE items', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:10:00'), + }, + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:11:00'), + endDate: getMillisFromTime('08:14:00'), + }, + ]; + const now = DateTime.fromMillis(last(items)?.endDate || 0); + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([13 * MINUTES]); + }); + + it('getTotalOnlineDuration take items until finds minimal break time.', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('07:00:00'), + endDate: getMillisFromTime('07:10:00'), + }, + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:14:00'), + }, + + { + id: 3, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + }, + { + id: 4, + app: ONLINE, + beginDate: getMillisFromTime('08:29:00'), + endDate: getMillisFromTime('08:39:00'), + }, + ]; + + const now = DateTime.fromMillis(last(items)?.endDate || 0); + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([34 * MINUTES, 10 * MINUTES]); + }); + it('getTotalOnlineDuration ignores items in creater then time specified', () => { + const items = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('07:00:00'), + endDate: getMillisFromTime('07:10:00'), + }, + { + id: 2, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:14:00'), + }, + + { + id: 3, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:25:00'), + }, + { + id: 4, + app: ONLINE, + beginDate: getMillisFromTime('08:29:00'), + endDate: getMillisFromTime('08:39:00'), + }, + ]; + + const now = getDateFromTime('08:15:00'); + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([14 * MINUTES, 10 * MINUTES]); + }); + + it('getTotalOnlineDuration returns [0] if just taken a break', () => { + const now = getDateFromTime('08:25:00'); + const items = [ + { + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:00:00'), + endDate: getMillisFromTime('08:20:00'), + }, + ]; + const duration = getTotalOnlineDuration(now, items, minBreakTime); + + expect(duration).toEqual([0]); + }); +}); + +describe('OnlineChart isBetweenHours', () => { + it('isBetweenHours returns correctly if partly out of range in end part', () => { + const startHour = 12; + const endHour = 24; + + const { beginClamp, endClamp } = getClampHours({ realDate, startHour, endHour }); + + expect( + isBetweenHours({ beginClamp, endClamp })({ + id: 1, + app: ONLINE, + beginDate: beginDate_19_23_50, + endDate: endDate20_00_10, + }), + ).toBeTruthy(); + }); + + it('isBetweenHours returns correctly if partly out of range in start part', () => { + const startHour = 0; + const endHour = 12; + + const { beginClamp, endClamp } = getClampHours({ realDate, startHour, endHour }); + + expect( + isBetweenHours({ beginClamp, endClamp })({ + id: 1, + app: ONLINE, + beginDate: beginDate19_11_50, + endDate: beginDate19_11_50, + }), + ).toBeTruthy(); + }); + + it('isBetweenHours returns correctly false if date is out of range ', () => { + const startHour = 0; + const endHour = 12; + + const { beginClamp, endClamp } = getClampHours({ realDate, startHour, endHour }); + + expect( + isBetweenHours({ beginClamp, endClamp })({ + id: 1, + app: ONLINE, + beginDate: beginDate_19_23_50, + endDate: endDate20_00_10, + }), + ).toBeFalsy(); + }); + + it('isBetweenHours returns correctly false if date is out of range in start part', () => { + const startHour = 12; + const endHour = 24; + + const { beginClamp, endClamp } = getClampHours({ realDate, startHour, endHour }); + + expect( + isBetweenHours({ beginClamp, endClamp })({ + id: 1, + app: ONLINE, + beginDate: beginDate19_11_50, + endDate: beginDate19_11_50, + }), + ).toBeFalsy(); + }); +}); + +test('isLessThanHours returns correctly', () => { + expect( + isLessThanHours(getDateFromTime('08:15:00'))({ + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:15:00'), + endDate: getMillisFromTime('08:15:00'), + }), + ).toBeTruthy(); + + expect( + isLessThanHours(getDateFromTime('08:15:00'))({ + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:14:00'), + endDate: getMillisFromTime('08:14:00'), + }), + ).toBeTruthy(); + + expect( + isLessThanHours(getDateFromTime('08:15:00'))({ + id: 1, + app: ONLINE, + beginDate: getMillisFromTime('08:14:00'), + endDate: getMillisFromTime('08:16:00'), + }), + ).not.toBeTruthy(); +}); + +export // Use an empty export to please Babel's single file emit. +// https://github.com/Microsoft/TypeScript/issues/15230 + {}; diff --git a/client/src/components/TrayLayout/OnlineChart.util.ts b/client/src/components/TrayLayout/OnlineChart.util.ts new file mode 100644 index 00000000..3af3652c --- /dev/null +++ b/client/src/components/TrayLayout/OnlineChart.util.ts @@ -0,0 +1,241 @@ +import { first, orderBy } from 'lodash'; +import { DateTime } from 'luxon'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { MAIN_THEME_COLOR } from '../../theme/theme.utils'; + +const clampItem = + ({ beginClamp, endClamp }: { beginClamp: DateTime; endClamp: DateTime }) => + (item: ITrackItem) => { + const beginDate = Math.max(beginClamp.toMillis(), item.beginDate); + const endDate = Math.min(endClamp.toMillis(), item.endDate); + + return { ...item, beginDate, endDate }; + }; + +export const roundTo = (start: DateTime) => { + const roundToMin = 3; + const remainder = roundToMin - (start.hour % roundToMin); + + return start.plus({ hours: remainder }); +}; + +export enum CLOCK_MODE { + HOURS_12 = 12, + HOURS_24 = 24, +} + +export const getQuarters = (date: DateTime, mode: CLOCK_MODE) => { + const startDate = + mode === CLOCK_MODE.HOURS_12 ? roundTo(date).minus({ hours: mode }).startOf('hour') : date.startOf('day'); + + const quarter = mode / 4; + return [ + startDate, + startDate.plus({ hours: quarter }), + startDate.plus({ hours: quarter * 2 }), + startDate.plus({ hours: quarter * 3 }), + startDate.plus({ hours: quarter * 4 }), + ]; +}; + +export const getClampHours = ({ + realDate, + startHour, + endHour, +}: { + realDate: DateTime; + startHour: number; + endHour: number; +}) => { + const beginClamp = realDate.startOf('day').set({ hour: startHour }); + const endClamp = realDate.startOf('day').set({ hour: endHour }); + return { beginClamp, endClamp }; +}; + +export const isBetweenHours = + ({ beginClamp, endClamp }: { beginClamp: DateTime; endClamp: DateTime }) => + (item: ITrackItem) => { + const itemBegin = DateTime.fromMillis(item.beginDate); + const itemEnd = DateTime.fromMillis(item.endDate); + + return (itemBegin >= beginClamp && itemBegin <= endClamp) || (itemEnd >= beginClamp && itemEnd <= endClamp); + }; + +export const isLessThanHours = (now: DateTime) => (item: ITrackItem) => { + return DateTime.fromMillis(item.endDate) <= now; +}; + +export interface IOnlineChartItem { + beginDate: number; + id?: number; + endDate: number; + color: string; + diff: number; + x: number; +} + +export const getOnlineTimesForChart = ({ + beginClamp, + endClamp, + items, + mode, +}: { + beginClamp: DateTime; + endClamp: DateTime; + items: ITrackItem[]; + mode?: CLOCK_MODE; +}) => { + const pieData: IOnlineChartItem[] = []; + const arr: { beginDate: number; endDate: number; diff: number; color?: string }[] = []; + + const filtered = items.filter((item) => item.app === 'ONLINE').filter(isBetweenHours({ beginClamp, endClamp })); + + if (filtered.length === 0) { + return []; + } + + filtered.forEach((item) => { + const clampedItem = clampItem({ beginClamp, endClamp })(item); + const itemBegin = DateTime.fromMillis(clampedItem.beginDate); + const itemEnd = DateTime.fromMillis(clampedItem.endDate); + const diff = itemEnd.diff(itemBegin).as('minutes'); + arr.push({ ...clampedItem, diff }); + }); + + let nr = 0; + arr.forEach((item, idx) => { + const prev = 0 !== idx ? arr[idx - 1] : null; + const next = arr.length - 1 !== idx ? arr[idx + 1] : null; + + if (!prev) { + const itemBegin = DateTime.fromMillis(item.beginDate); + const diff = itemBegin.diff(beginClamp).as('minutes'); + + if (diff > 0) { + pieData.push({ + beginDate: beginClamp.toMillis(), + endDate: itemBegin.toMillis(), + color: 'transparent', + diff, + x: nr++, + }); + } + } + + pieData.push({ ...item, x: nr++, color: item.color || 'transparent' }); + + if (next) { + const itemEnd = DateTime.fromMillis(item.endDate); + const nextBegin = DateTime.fromMillis(next.beginDate); + const diff = nextBegin.diff(itemEnd).as('minutes'); + + if (diff > 0) { + pieData.push({ + beginDate: itemEnd.toMillis(), + endDate: nextBegin.toMillis(), + color: 'transparent', + diff, + x: nr++, + }); + } + } + + if (!next) { + if (mode) { + const currentTimeItem: IOnlineChartItem = { + beginDate: DateTime.now().toMillis(), + endDate: DateTime.now().toMillis(), + color: MAIN_THEME_COLOR, + diff: mode === CLOCK_MODE.HOURS_12 ? 2 : 4, + x: nr++, + }; + pieData.push(currentTimeItem); + } + + const itemEnd = DateTime.fromMillis(item.endDate); + const diff = endClamp.diff(itemEnd).as('minutes'); + + if (diff > 0) { + pieData.push({ + beginDate: itemEnd.toMillis(), + endDate: endClamp.toMillis(), + color: 'transparent', + diff, + x: nr++, + }); + } + } + }); + + return pieData; +}; + +/* +-On20-Br1-On20-Br1-On20 = On60 +-On20-Br5-On20 = On20 +-On20-Br4-On20 = On40 +-On20-Br4-On20-Br4-0n-20 = On60 +*/ + +const getBeginEndDiff = (beginDate: DateTime, endDate: DateTime) => { + return endDate.diff(beginDate).milliseconds; +}; + +const MINUTES = 60 * 1000; + +export const groupByBreaks = (items: ITrackItem[], minBreakTime: number) => { + let newItems: ITrackItem[] = []; + let olderItem: ITrackItem; + + const groups: ITrackItem[][] = []; + + items.forEach((currentItem) => { + if (olderItem) { + const diff = getBeginEndDiff( + DateTime.fromMillis(currentItem.endDate), + DateTime.fromMillis(olderItem.beginDate), + ); + const hasHadBreak = diff / MINUTES > minBreakTime; + + if (hasHadBreak) { + groups.push(newItems); + newItems = []; + } + } + newItems.push(currentItem); + olderItem = currentItem; + }); + groups.push(newItems); + return groups; +}; + +export const getTotalOnlineDuration = (now: DateTime, items: ITrackItem[], minBreakTime: number) => { + const filtered = items.filter((item) => item.app === 'ONLINE').filter(isLessThanHours(now)); + + if (filtered.length === 0) { + return [0]; + } + + const sorted = orderBy(filtered, ['beginDate'], ['desc']); + + if (sorted.length === 0) { + return [0]; + } + + if (getBeginEndDiff(DateTime.fromMillis(first(sorted)?.endDate || 0), now) / MINUTES >= minBreakTime) { + return [0]; + } + + const onlyNeeded = groupByBreaks(sorted, minBreakTime); + + if (onlyNeeded.length === 0) { + return [0]; + } + + return onlyNeeded.map((group) => { + const diffs = group.map(({ beginDate, endDate }) => + getBeginEndDiff(DateTime.fromMillis(beginDate), DateTime.fromMillis(endDate)), + ); + return diffs.reduce((a, b) => a + b, 0); + }); +}; diff --git a/client/src/components/TrayLayout/OnlineChartTooltipLabel.tsx b/client/src/components/TrayLayout/OnlineChartTooltipLabel.tsx new file mode 100644 index 00000000..4c6b17f6 --- /dev/null +++ b/client/src/components/TrayLayout/OnlineChartTooltipLabel.tsx @@ -0,0 +1,98 @@ +import { DateTime } from 'luxon'; +import { PureComponent } from 'react'; +import { VictoryTooltip } from 'victory'; +import { shortTime } from '../../time.util'; +import { formatToTime } from '../LineCharts/LineChart.util'; +import { gray900 } from '../Timeline/ChartTheme'; + +interface IProps { + text?: string; + width: number; + innerWidth: number; + color?: string; + datum?: { beginDate: number; endDate: number; diff: number }; + theme: { tooltip: { style: { fontSize: number } }; isDark: boolean }; +} + +interface StyledLabelProps { + datum?: Record; + text?: string; + theme?: { isDark: boolean }; + x?: number; + y?: number; + [key: string]: unknown; +} + +// Custom label component for rich text formatting +class StyledLabel extends PureComponent { + render() { + const { datum, text, theme, x = 0, y = 0 } = this.props; + + if (!text || !datum) { + return null; + } + + const { beginDate, endDate, diff } = datum as { beginDate: number; endDate: number; diff: number }; + const now = DateTime.now(); + const end = DateTime.fromMillis(endDate); + const timeAgoMs = now.diff(end).milliseconds; + const timeAgo = shortTime(timeAgoMs, { largest: 2 }); + const timeText = `${formatToTime(beginDate)} - ${formatToTime(endDate)}`; + const diffText = shortTime(diff * 1000 * 60); + const timeAgoLabel = `${timeAgo} ago`; + + // Set colors based on theme + const textColor = theme?.isDark ? 'white' : 'black'; + const blueColor = 'var(--chakra-colors-blue-500)'; + + return ( + + {/* First line - large and bold */} + + {diffText} + + + {/* Second line - smaller */} + + {timeText} + + + {/* Third line - smaller and lighter */} + + {timeAgoLabel} + + + ); + } +} + +export class OnlineChartTooltipLabel extends PureComponent { + public static defaultEvents = VictoryTooltip.defaultEvents; + + public render() { + const { width, innerWidth, theme } = this.props; + + return ( + + } + text={`${this.props.text}`} + orientation="top" + pointerLength={0} + cornerRadius={innerWidth / 2} + flyoutWidth={innerWidth} + flyoutHeight={innerWidth} + style={{ ...theme.tooltip.style, fontSize: 26 }} + flyoutStyle={{ + fill: theme.isDark ? gray900 : 'white', + strokeWidth: 0, + fillOpacity: 1, + }} + /> + + ); + } +} diff --git a/client/src/components/TrayLayout/TrayLayout.tsx b/client/src/components/TrayLayout/TrayLayout.tsx index cdac5fdc..3838ad45 100644 --- a/client/src/components/TrayLayout/TrayLayout.tsx +++ b/client/src/components/TrayLayout/TrayLayout.tsx @@ -1,16 +1,17 @@ -import { Layout } from 'antd'; -import React from 'react'; +import { Box, Flex, useColorModeValue } from '@chakra-ui/react'; import { TrayMenu } from './TrayMenu'; -const { Content } = Layout; +interface TrayLayoutProps { + children: React.ReactNode; +} -export function TrayLayout({ children }: any) { +export function TrayLayout({ children }: TrayLayoutProps) { return ( -
    - - - {children} - -
    + + + + {children} + + ); } diff --git a/client/src/components/TrayLayout/TrayMenu.styles.ts b/client/src/components/TrayLayout/TrayMenu.styles.ts deleted file mode 100644 index 14ee90ba..00000000 --- a/client/src/components/TrayLayout/TrayMenu.styles.ts +++ /dev/null @@ -1,24 +0,0 @@ -import styled from 'styled-components'; - -import { Menu } from 'antd'; - -export const Brand = styled.div` - font-family: 'Berkshire Swash', cursive; - text-align: left; - font-size: 26px; -`; - -export const MenuItem = styled(Menu.Item)` - cursor: pointer; - - border-bottom: none !important; -`; - -export const RightMenuItem = styled(MenuItem)` - float: right !important; -`; - -export const Img = styled.img` - margin-right: 15px; - margin-bottom: 6px; -`; diff --git a/client/src/components/TrayLayout/TrayMenu.tsx b/client/src/components/TrayLayout/TrayMenu.tsx index 5ff451fe..4c532529 100644 --- a/client/src/components/TrayLayout/TrayMenu.tsx +++ b/client/src/components/TrayLayout/TrayMenu.tsx @@ -1,97 +1,45 @@ -import { Menu, Tooltip } from 'antd'; -import { ClockCircleOutlined, PoweroffOutlined, ArrowsAltOutlined } from '@ant-design/icons'; -import React, { useState, useEffect, memo } from 'react'; -import tocklerIcon from '../../assets/icons/tockler_icon.png'; -import { EventEmitter } from '../../services/EventEmitter'; -import { getOnlineStartTime } from '../../services/trackItem.api'; -import { Brand, Img, MenuItem, RightMenuItem } from './TrayMenu.styles'; -import moment from 'moment'; -import Moment from 'react-moment'; -import { Logger } from '../../logger'; -import { useWindowFocused } from '../../hooks/windowFocusedHook'; - -const getNow = () => moment().subtract(1, 'seconds'); +import { Box, HStack, IconButton, Tooltip } from '@chakra-ui/react'; +import { memo } from 'react'; +import { AiOutlineArrowsAlt, AiOutlinePoweroff } from 'react-icons/ai'; +import { ElectronEventEmitter } from '../../services/ElectronEventEmitter'; +import { Header } from '../Header/Header'; export const TrayMenuPlain = () => { - const { windowIsActive } = useWindowFocused(); - const [onlineSince, setOnlineSince] = useState(); const exitApp = () => { - EventEmitter.send('close-app'); + ElectronEventEmitter.send('close-app'); }; + const toggleMainWindow = () => { - EventEmitter.send('toggle-main-window'); + ElectronEventEmitter.send('toggle-main-window'); }; - useEffect(() => { - const systemIsOnline = () => { - Logger.debug('system-is-online'); - setOnlineSince(getNow()); - }; - const systemIsNotOnline = () => { - Logger.debug('system-is-not-online'); - setOnlineSince(null); - }; - - EventEmitter.on('system-is-online', systemIsOnline); - EventEmitter.on('system-is-not-online', systemIsNotOnline); - - return () => { - EventEmitter.off('system-is-online', systemIsOnline); - EventEmitter.off('system-is-not-online', systemIsNotOnline); - }; - }, []); - - useEffect(() => { - if (windowIsActive) { - const loadOnlineStartTime = async () => { - const onlineStartTime = await getOnlineStartTime(); - - setOnlineSince(onlineStartTime ? moment(onlineStartTime) : getNow()); - }; - - loadOnlineStartTime(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [windowIsActive]); - return ( - - - - - Tockler - - - - {onlineSince && ( - - <> - {' '} - - - - - - )} - - - - +
    + + + + + } + /> - - - - + + + } + /> - -
    + + ); }; -TrayMenuPlain.whyDidYouRender = true; - export const TrayMenu = memo(TrayMenuPlain); diff --git a/client/src/components/TrayList/ShortTimeInterval.tsx b/client/src/components/TrayList/ShortTimeInterval.tsx new file mode 100644 index 00000000..f4db6e01 --- /dev/null +++ b/client/src/components/TrayList/ShortTimeInterval.tsx @@ -0,0 +1,19 @@ +import { useEffect, useState } from 'react'; +import { useInterval } from '@chakra-ui/react'; +import { shortTime } from '../../time.util'; + +const NO_VALUE = '-'; + +export const ShortTimeInterval = ({ totalMs }) => { + const [time, setTime] = useState(totalMs); + + useEffect(() => { + setTime(totalMs); + }, [totalMs]); + + useInterval(() => { + setTime((oldTime) => oldTime + 1000); + }, 1000); + + return shortTime(time, { largest: 2, units: ['d', 'h', 'm', 's'] }) || NO_VALUE; +}; diff --git a/client/src/components/TrayList/TrayList.styles.ts b/client/src/components/TrayList/TrayList.styles.ts deleted file mode 100644 index 1433c913..00000000 --- a/client/src/components/TrayList/TrayList.styles.ts +++ /dev/null @@ -1,12 +0,0 @@ -import styled from 'styled-components'; - -export const Brand = styled.div` - font-family: 'Berkshire Swash', cursive; - text-align: left; - font-size: 26px; -`; - -export const Img = styled.img` - margin-right: 15px; - margin-bottom: 6px; -`; diff --git a/client/src/components/TrayList/TrayList.tsx b/client/src/components/TrayList/TrayList.tsx index aeb3389c..7b21bc46 100644 --- a/client/src/components/TrayList/TrayList.tsx +++ b/client/src/components/TrayList/TrayList.tsx @@ -1,62 +1,42 @@ -import { List } from 'antd'; -import { groupBy, map, sortBy, sumBy } from 'lodash'; -import React, { memo } from 'react'; -import { convertDate } from '../../constants'; -import { TrayListItem } from './TrayListItem'; - -const sumDiff = data => - sumBy(data, (c: any) => convertDate(c.endDate).diff(convertDate(c.beginDate))); +import { StackDivider, VStack } from '@chakra-ui/react'; +import { memo } from 'react'; -const aggregateSameAppAndName = lastLogItems => { - const grouped = groupBy(lastLogItems, item => `${item.app}_${item.title}`); +import { orderBy } from 'lodash'; +import { ITrackItem } from '../../@types/ITrackItem'; +import { TrayListItem } from './TrayListItem'; - const mapped = map(grouped, items => { - return { - app: items[0].app, - title: items[0].title, - color: items[0].color, - beginDate: sortBy(items, ['beginDate'])[0].beginDate, - endDate: sortBy(items, ['endDate'])[items.length - 1].endDate, - totalMs: sumDiff(items), - }; - }); +export interface AggregatedTrackItem extends ITrackItem { + totalDuration: number; +} - return mapped; -}; +const getKey = (item: ITrackItem) => `${item.app}_${item.title}`; export function TrayListPlain({ lastLogItems, - loading, runningLogItem, stopRunningLogItem, startNewLogItem, -}: any) { - // Remove runningLogItem from aggregated values and show it as running Item - let items; - if (runningLogItem) { - items = aggregateSameAppAndName(lastLogItems.filter(item => item.id !== runningLogItem.id)); - items.unshift(runningLogItem); - } else { - items = aggregateSameAppAndName(lastLogItems); - } +}: { + lastLogItems: AggregatedTrackItem[]; + runningLogItem: ITrackItem | undefined; + stopRunningLogItem: () => void; + startNewLogItem: (item: AggregatedTrackItem) => void; +}) { + const items: AggregatedTrackItem[] = orderBy(lastLogItems, ['endDate'], ['desc']); return ( - ( + } position="relative"> + {items.map((item, index) => ( - )} - /> + ))} + ); } -TrayListPlain.whyDidYouRender = true; - export const TrayList = memo(TrayListPlain); diff --git a/client/src/components/TrayList/TrayListItem.tsx b/client/src/components/TrayList/TrayListItem.tsx index d04bad5d..2cfd22b7 100644 --- a/client/src/components/TrayList/TrayListItem.tsx +++ b/client/src/components/TrayList/TrayListItem.tsx @@ -1,46 +1,24 @@ -import { Box, Flex } from 'reflexbox'; -import { Button, List } from 'antd'; -import { ClockCircleOutlined, PauseOutlined, CaretRightOutlined } from '@ant-design/icons'; +import { Box, Flex, HStack, IconButton, Text } from '@chakra-ui/react'; +import { memo } from 'react'; +import { FaPlay, FaStop } from 'react-icons/fa'; +import { convertDate, DATE_TIME_FORMAT } from '../../constants'; +import { shortTime } from '../../time.util'; +import { OverflowText } from '../TrackItemTable/OverflowText'; +import { ShortTimeInterval } from './ShortTimeInterval'; +import { AggregatedTrackItem } from './TrayList'; -import moment from 'moment'; -import React, { memo } from 'react'; -import Moment from 'react-moment'; -import TimeAgo from 'react-timeago'; -import styled from 'styled-components'; -import { convertDate } from '../../constants'; +const formatDate = (date: number) => convertDate(date).toFormat(DATE_TIME_FORMAT); -const CustomListItem = styled(List.Item)` - padding-left: 5px; - margin-top: 5px; - &:last-child { - margin-bottom: 5px; - } - background-color: ${({ theme: { variables } }) => variables['@component-background']}; - border-left: 5px solid ${props => props.color}; -`; - -const Small = styled(Box)` - font-size: 10px; -`; - -const Medium = styled(Box)` - font-size: 12px; -`; - -const ActionBtn = styled(Flex)` - margin: 2px 0; -`; - -const CustomBox = styled(Box)` - overflow: hidden; -`; - -const formatDate = date => convertDate(date).format('YYYY-MM-DD HH:mm:ss'); - -const FormattedTime = ({ item, isRunning }: any) => { - const full = isRunning - ? `${formatDate(item.beginDate)}` - : `${formatDate(item.beginDate)} - ${formatDate(item.endDate)}`; +const FormattedTime = ({ + beginDate, + endDate, + isRunning, +}: { + beginDate: number; + endDate: number; + isRunning: boolean; +}) => { + const full = isRunning ? `${formatDate(beginDate)}` : `${formatDate(beginDate)} - ${formatDate(endDate)}`; return {full}; }; @@ -50,78 +28,52 @@ export function TrayListItemPlain({ startNewLogItemFromOld, stopRunningLogItem, isRunning, -}: any) { +}: { + item: AggregatedTrackItem; + startNewLogItemFromOld: (item: AggregatedTrackItem) => void; + stopRunningLogItem: () => void; + isRunning: boolean; +}) { + const { totalDuration, title, app, color } = item; return ( - - - - - - {item.app} - - {item.title} - + + + + + - - - - - {' '} - - {' '} - - {!isRunning && ( - - {item.endDate} - - )} - {isRunning && ( - - {item.beginDate} - - )} - - - - - - {item.startDate && } - - - - - {item.totalMs > 1 && ( - - - Duration: {moment.duration(item.totalMs).format()} - - - )} + + {app} + + + + {title} + + + + + + + + + + {totalDuration > 1 && ( + <> + {!isRunning && shortTime(totalDuration)} + {isRunning && } + + )} + - - {isRunning && ( - - - - - - - - + + + + {isLoading && } + - - {isLoading && ( - - - - )} - + setTaskName(event.target.value)} /> + setSearchText(event.target.value)} /> - - - - + + + + + }> + Export + + + exportItems(searchText, 'csv')}>Export to CSV + exportItems(searchText, 'json')}>Export to JSON + + + + + + + + ); } diff --git a/client/src/routes/SettingsPage.tsx b/client/src/routes/SettingsPage.tsx index 67a1d73c..f1e4e00b 100644 --- a/client/src/routes/SettingsPage.tsx +++ b/client/src/routes/SettingsPage.tsx @@ -1,12 +1,5 @@ -import React from 'react'; - -import { MainLayout } from '../components/MainLayout/MainLayout'; import { SettingsForm } from '../components/Settings/SettingsForm'; -export function SettingsPage({ location }: any) { - return ( - - - - ); +export function SettingsPage() { + return ; } diff --git a/client/src/routes/SummaryPage.tsx b/client/src/routes/SummaryPage.tsx index f3621ae9..9a8ba89f 100644 --- a/client/src/routes/SummaryPage.tsx +++ b/client/src/routes/SummaryPage.tsx @@ -1,19 +1,20 @@ -import React from 'react'; -import { MainLayout } from '../components/MainLayout/MainLayout'; +import { VStack } from '@chakra-ui/react'; +import { CardBox } from '../components/CardBox'; +import { LineChart } from '../components/LineCharts/LineChart'; import { SummaryCalendar } from '../components/SummaryCalendar/SummaryCalendar'; import { SummaryProvider } from '../SummaryContext'; -import { LineChart } from '../components/LineCharts/LineChart'; -import { LineChartBox } from '../components/LineCharts/LineCharts.styles'; -export function SummaryPage({ location }: any) { +export function SummaryPage() { return ( - - - - + + + + + + - - - + + + ); } diff --git a/client/src/routes/SupportPage.tsx b/client/src/routes/SupportPage.tsx index f3c3477f..345ccdab 100644 --- a/client/src/routes/SupportPage.tsx +++ b/client/src/routes/SupportPage.tsx @@ -1,29 +1,35 @@ -import React, { useState } from 'react'; -import { MainLayout } from '../components/MainLayout/MainLayout'; -import { Box, Flex } from 'reflexbox'; -import emailjs from 'emailjs-com'; -import { Button, Input, Typography } from 'antd'; -const { Text, Title, Paragraph } = Typography; +import { Box, Button, Flex, HStack, Icon, Input, Text, Textarea, VStack } from '@chakra-ui/react'; +import { useState } from 'react'; +import { FaDonate, FaGithub } from 'react-icons/fa'; +import { CardBox } from '../components/CardBox'; +import { sendEmail } from '../services/email.service'; -const TEMPLATE_ID = process.env.REACT_APP_TEMPLATE_ID || ''; -const SERVICE_ID = process.env.REACT_APP_SERVICE_ID || ''; -const USER_ID = process.env.REACT_APP_USER_ID || ''; +const Paragraph = (props) => ( + + + +); -export function SupportPage({ location }: any) { +const errToString = (err) => (err.text ? err.text : err.toString()); + +export function SupportPage() { const [content, setContent] = useState(''); const [contentError, setContentError] = useState(false); const [emailSent, setEmailSent] = useState(false); const [isSending, setIsSending] = useState(false); const [email, setEmail] = useState(''); + const [sendError, setSendError] = useState(''); - const changeContent = e => { + const changeContent = (e) => { const { value } = e.target; setContent(value); + setSendError(''); }; - const changeEmail = e => { + const changeEmail = (e) => { const { value } = e.target; setEmail(value); + setSendError(''); }; const sendForm = async () => { @@ -31,112 +37,87 @@ export function SupportPage({ location }: any) { setContentError(true); return; } - const templateParams = { reply_to: email, message: content }; + try { setIsSending(true); - await emailjs.send(SERVICE_ID, TEMPLATE_ID, templateParams, USER_ID); + setSendError(''); + await sendEmail({ reply_to: email, message: content }); setEmailSent(true); setContent(''); setContentError(false); } catch (err) { - alert('Email send error! ' + (err.text ? err.text : err.toString())); + console.error('Email send error!', err); + setSendError('Email send error! ' + errToString(err)); } setIsSending(false); }; return ( - - - Contact Me - - Feel free to contact if you have any problems or feature requests. Or if you - have any feedback to give - good or bad. - - - + + + + Feel free to contact if you have any problems or feature requests. Or if you have any feedback + to give - good or bad. + + +