diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90ef20f..89f500a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,6 +4,21 @@ Thank you for your interest in contributing to NotifyChain! This document provid **Start here instead (recommended):** [`CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md`](CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md) +## Documentation conventions + +Use these names consistently in docs and PRs: + +| Concept | Standard form | +|---------|----------------| +| Product name (prose/titles) | **NotifyChain** | +| GitHub repository / clone directory | **Notify-Chain** (`Core-Foundry/Notify-Chain`) | +| Off-chain service | **Listener** (`listener/`) | +| React + Vite UI | **Dashboard** (`dashboard/`) | +| Legacy analytics app | **Frontend** (`frontend/`) | +| On-chain code | **Smart contracts** (`contract/`, `Documents/Task Bounty/`) | + +Canonical setup path: workflow guide → [`LOCAL_DEVELOPMENT.md`](LOCAL_DEVELOPMENT.md) (quick) → [`CONTRIBUTOR_SETUP.md`](CONTRIBUTOR_SETUP.md) (detailed). + ## Code of Conduct - Be respectful and inclusive diff --git a/CONTRIBUTOR_ARCHITECTURE_DEEP_DIVE.md b/CONTRIBUTOR_ARCHITECTURE_DEEP_DIVE.md index 5fcca83..d3f2c75 100644 --- a/CONTRIBUTOR_ARCHITECTURE_DEEP_DIVE.md +++ b/CONTRIBUTOR_ARCHITECTURE_DEEP_DIVE.md @@ -52,9 +52,9 @@ NotifyChain is split into three decoupled components, separated by network and t └────────────────────────────────────────────────────────────────────────┘ ``` -1. **Smart Contracts (On-Chain)**: Written in Rust for the Soroban smart contract platform. They run in a WebAssembly (WASM) sandbox, mutate ledger state, and emit structured events. Located in [contract/contracts/hello-world](file:///workspaces/Notify-Chain/contract/contracts/hello-world) and [Documents/Task Bounty](file:///workspaces/Notify-Chain/Documents/Task%20Bounty). -2. **Listener Service (Off-Chain Engine)**: Written in Node.js and TypeScript. It polls the Stellar RPC, parses, deduplicates, and stores events in SQLite, and dispatches real-time alerts. Located in [listener](file:///workspaces/Notify-Chain/listener). -3. **React Dashboard (Frontend)**: A standard Vite + React SPA that consumes the REST API exposed by the listener service to display events and schedule performance statistics. Located in [dashboard](file:///workspaces/Notify-Chain/dashboard). +1. **Smart Contracts (On-Chain)**: Written in Rust for the Soroban smart contract platform. They run in a WebAssembly (WASM) sandbox, mutate ledger state, and emit structured events. Located in [contract/contracts/hello-world](contract/contracts/hello-world) and [Documents/Task Bounty](Documents/Task%20Bounty). +2. **Listener Service (Off-Chain Engine)**: Written in Node.js and TypeScript. It polls the Stellar RPC, parses, deduplicates, and stores events in SQLite, and dispatches real-time alerts. Located in [listener](listener). +3. **React Dashboard (Frontend)**: A standard Vite + React SPA that consumes the REST API exposed by the listener service to display events and schedule performance statistics. Located in [dashboard](dashboard). --- @@ -63,14 +63,14 @@ NotifyChain is split into three decoupled components, separated by network and t NotifyChain supports two smart contract interaction patterns with different design structures: ### 2.1 Struct Event Pattern (AutoShare) -Implemented in [base/events.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/base/events.rs). The contract defines dedicated struct types decorated with `#[contractevent]`. Each event carries standard routing topics: +Implemented in [base/events.rs](contract/contracts/hello-world/src/base/events.rs). The contract defines dedicated struct types decorated with `#[contractevent]`. Each event carries standard routing topics: - **`NotificationCategory`**: A 4-variant enum mapping events to functional domains (`Group`, `Admin`, `Financial`, `Notification`). - **`NotificationPriority`**: A 4-variant enum detailing severity (`Low`, `Medium`, `High`, `Critical`). These are appended as the last two indexed topics to ensure backward compatibility for simpler indexers. ### 2.2 Subject-Action Event Pattern (TaskBounty) -Implemented in [src/events.rs](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/events.rs). The contract does not use routing metadata structures. Instead, it emits events as tuples of short symbols matching the `(Subject, Action)` schema: +Implemented in [src/events.rs](Documents/Task%20Bounty/src/events.rs). The contract does not use routing metadata structures. Instead, it emits events as tuples of short symbols matching the `(Subject, Action)` schema: - E.g., `(symbol_short!("task"), symbol_short!("created"))` or `(symbol_short!("sub"), symbol_short!("approved"))`. - Payload arguments (like task ID, amount, and creator) are passed as tuples in the event data field. @@ -116,15 +116,15 @@ sequenceDiagram ``` ### 3.1 Step-by-Step Processing Pipeline: -1. **Polling**: The [EventSubscriber](file:///workspaces/Notify-Chain/listener/src/services/event-subscriber.ts) wakes up at configured intervals (default: 30 seconds) and invokes `getEvents` on the Stellar RPC using the last persisted ledger sequence. -2. **Persistent Deduplication**: The [EventDeduplicationService](file:///workspaces/Notify-Chain/listener/src/services/event-deduplication-service.ts) checks each incoming event. It references the `processed_events` SQLite table to see if the event ID has already been indexed. +1. **Polling**: The [EventSubscriber](listener/src/services/event-subscriber.ts) wakes up at configured intervals (default: 30 seconds) and invokes `getEvents` on the Stellar RPC using the last persisted ledger sequence. +2. **Persistent Deduplication**: The [EventDeduplicationService](listener/src/services/event-deduplication-service.ts) checks each incoming event. It references the `processed_events` SQLite table to see if the event ID has already been indexed. 3. **Reorg Handling**: - If the RPC returns an event with a ledger number *lower* than the last processed ledger cursor, the system flags a blockchain reorganization. - It sets `is_reorg_duplicate = true` on the event. - The event is stored in SQLite for integrity, but the pipeline **skips sending Discord alerts or notifications** to prevent duplicate spam. 4. **In-Memory Cache (LRU)**: A secondary fast-path `NotificationDeduplicator` stores the last 60 seconds of event hashes in memory to prevent database roundtrips for duplicate frames. 5. **Persistence**: The event is formatted and saved to the `events` table. The `polling_cursors` table is updated with the new ledger index. -6. **Dispatch**: The [NotificationDispatcher](file:///workspaces/Notify-Chain/listener/src/services/notification-dispatcher.ts) formats the event and pushes it to active channels (e.g. Discord webhook). +6. **Dispatch**: The [NotificationDispatcher](listener/src/services/notification-dispatcher.ts) formats the event and pushes it to active channels (e.g. Discord webhook). --- @@ -206,19 +206,19 @@ Because SQLite executes writes sequentially and locks the database, only one wor Here are the critical paths and files that implement the core functionality of NotifyChain: ### 5.1 Smart Contracts -- [contract/contracts/hello-world/src/lib.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs): Entry point for the AutoShare contract. Declares the functions and maps calls to the logic module. -- [autoshare_logic.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/autoshare_logic.rs): Core business logic for AutoShare groups, members, subscriptions, withdrawals, and scheduled notification parameters. -- [base/events.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/base/events.rs): Structure definitions for category-priority routed events. -- [Documents/Task Bounty/src/lib.rs](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs): Entry point for the TaskBounty contract. -- [Documents/Task Bounty/src/events.rs](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/events.rs): Emits the unstructured subject-action events for tasks, submissions, and disputes. +- [contract/contracts/hello-world/src/lib.rs](contract/contracts/hello-world/src/lib.rs): Entry point for the AutoShare contract. Declares the functions and maps calls to the logic module. +- [autoshare_logic.rs](contract/contracts/hello-world/src/autoshare_logic.rs): Core business logic for AutoShare groups, members, subscriptions, withdrawals, and scheduled notification parameters. +- [base/events.rs](contract/contracts/hello-world/src/base/events.rs): Structure definitions for category-priority routed events. +- [Documents/Task Bounty/src/lib.rs](Documents/Task%20Bounty/src/lib.rs): Entry point for the TaskBounty contract. +- [Documents/Task Bounty/src/events.rs](Documents/Task%20Bounty/src/events.rs): Emits the unstructured subject-action events for tasks, submissions, and disputes. ### 5.2 Off-Chain Listener Service -- [listener/src/index.ts](file:///workspaces/Notify-Chain/listener/src/index.ts): Initializer script. Bootstraps the HTTP API server, SQLite store, subscriber, and scheduler loops. -- [listener/src/services/event-subscriber.ts](file:///workspaces/Notify-Chain/listener/src/services/event-subscriber.ts): Polls Stellar RPC logs and drives the ingestion loop. -- [listener/src/services/event-deduplication-service.ts](file:///workspaces/Notify-Chain/listener/src/services/event-deduplication-service.ts): SQLite-backed deduplication layer; houses reorg-detection safeguards. -- [listener/src/services/notification-scheduler.ts](file:///workspaces/Notify-Chain/listener/src/services/notification-scheduler.ts): Periodically queries SQLite for due scheduled notifications, acquires locks, dispatches alerts, and performs recovery. -- [listener/src/store/](file:///workspaces/Notify-Chain/listener/src/store/): Holds the repositories (`EventRepository`, `ScheduleRepository`) managing queries to SQLite. +- [listener/src/index.ts](listener/src/index.ts): Initializer script. Bootstraps the HTTP API server, SQLite store, subscriber, and scheduler loops. +- [listener/src/services/event-subscriber.ts](listener/src/services/event-subscriber.ts): Polls Stellar RPC logs and drives the ingestion loop. +- [listener/src/services/event-deduplication-service.ts](listener/src/services/event-deduplication-service.ts): SQLite-backed deduplication layer; houses reorg-detection safeguards. +- [listener/src/services/notification-scheduler.ts](listener/src/services/notification-scheduler.ts): Periodically queries SQLite for due scheduled notifications, acquires locks, dispatches alerts, and performs recovery. +- [listener/src/store/](listener/src/store/): Holds the repositories (`EventRepository`, `ScheduleRepository`) managing queries to SQLite. ### 5.3 Frontend Dashboard -- [dashboard/src/pages/](file:///workspaces/Notify-Chain/dashboard/src/pages/): Contains top-level dashboard pages: `Events` (real-time stream), `Schedules` (notification queue stats), and `Stats` (overview charts). -- [dashboard/src/hooks/](file:///workspaces/Notify-Chain/dashboard/src/hooks/): React hooks for fetching event feeds, managing poll intervals, and querying status counts from the listener. +- [dashboard/src/pages/](dashboard/src/pages/): Contains top-level dashboard pages: `Events` (real-time stream), `Schedules` (notification queue stats), and `Stats` (overview charts). +- [dashboard/src/hooks/](dashboard/src/hooks/): React hooks for fetching event feeds, managing poll intervals, and querying status counts from the listener. diff --git a/CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md b/CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md index 3fadfa7..c922dcc 100644 --- a/CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md +++ b/CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md @@ -21,7 +21,7 @@ A single, end-to-end workflow for local setup, branching, testing, and submittin - Rust (stable) with WebAssembly target: - `rustup target add wasm32-unknown-unknown` - Stellar CLI: - - `cargo install stellar-cli` + - `cargo install --locked stellar-cli --features opt` - Node.js: - Listener uses **Node 20** - Dashboard uses **Node 18** diff --git a/CONTRIBUTOR_SETUP.md b/CONTRIBUTOR_SETUP.md index 1ee2496..c44b451 100644 --- a/CONTRIBUTOR_SETUP.md +++ b/CONTRIBUTOR_SETUP.md @@ -7,7 +7,10 @@ This guide walks you through setting up a local development environment for NotifyChain. By the end, you will have the listener service, the dashboard, the frontend analytics app, and the smart contracts building and running on your machine. -This guide walks you through setting up a local development environment for NotifyChain. By the end, you will have the listener service, the dashboard, and the smart contracts building and running on your machine. + +For the canonical contribution workflow, start with +[`CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md`](CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md). +For a shorter setup path, see [`LOCAL_DEVELOPMENT.md`](LOCAL_DEVELOPMENT.md). --- @@ -24,11 +27,6 @@ This guide walks you through setting up a local development environment for Noti 9. [Running Tests](#9-running-tests) 10. [VS Code Setup (Recommended)](#10-vs-code-setup-recommended) 11. [Troubleshooting & FAQ](#11-troubleshooting--faq) -5. [Smart Contracts Setup](#5-smart-contracts-setup) -6. [Environment Variables Reference](#6-environment-variables-reference) -7. [Running Tests](#7-running-tests) -8. [VS Code Setup (Recommended)](#8-vs-code-setup-recommended) -9. [Troubleshooting & FAQ](#9-troubleshooting--faq) --- @@ -40,7 +38,7 @@ This guide walks you through setting up a local development environment for Noti |----------------|-----------------|-----------------------------------------|--------------------| | Rust | stable | [rustup.rs](https://rustup.rs) | Smart contracts | | `wasm32-unknown-unknown` | — | `rustup target add wasm32-unknown-unknown` | Soroban contracts | -| Stellar CLI | latest | `cargo install stellar-cli` | Contract build/deploy | +| Stellar CLI | latest | `cargo install --locked stellar-cli --features opt` | Contract build/deploy | | Node.js | **18** (dashboard), **20** (listener) | [nodejs.org](https://nodejs.org) or `nvm` | Listener, Dashboard | | npm | comes with Node | — | Package management | | Git | — | Your package manager or [git-scm.com](https://git-scm.com) | Version control | @@ -94,7 +92,6 @@ rustc --version && cargo --version && stellar --version ## 2. Clone the Repository ```bash -git clone https://github.com/CollinsC1O/Notify-Chain.git git clone https://github.com/Core-Foundry/Notify-Chain.git cd Notify-Chain ``` @@ -104,7 +101,6 @@ If you plan to contribute, fork the repository first, then clone your fork: ```bash git clone https://github.com/YOUR-USERNAME/Notify-Chain.git cd Notify-Chain -git remote add upstream https://github.com/CollinsC1O/Notify-Chain.git git remote add upstream https://github.com/Core-Foundry/Notify-Chain.git ``` @@ -786,7 +782,7 @@ cd frontend && npm install ### Still Stuck? -1. Search [open issues](https://github.com/CollinsC1O/Notify-Chain/issues) — your problem may already be reported. +1. Search [open issues](https://github.com/Core-Foundry/Notify-Chain/issues) — your problem may already be reported. 1. Search [open issues](https://github.com/Core-Foundry/Notify-Chain/issues) — your problem may already be reported. 2. Read the detailed [Troubleshooting Guide](TROUBLESHOOTING.md). 3. Open a new issue with: diff --git a/CREATE_PR_INSTRUCTIONS.md b/CREATE_PR_INSTRUCTIONS.md index f122d85..2c08376 100644 --- a/CREATE_PR_INSTRUCTIONS.md +++ b/CREATE_PR_INSTRUCTIONS.md @@ -21,7 +21,7 @@ You now have a complete, working notification template preview feature ready to 1. **Go to your fork on GitHub:** ``` - https://github.com/coderolisa/Notify-Chain + https://github.com/Core-Foundry/Notify-Chain ``` 2. **You should see a yellow banner** saying: @@ -122,7 +122,7 @@ gh pr create \ Click this link (replace YOUR_USERNAME): ``` -https://github.com/coderolisa/Notify-Chain/pull/new/feature/notification-template-preview +https://github.com/Core-Foundry/Notify-Chain/pull/new/feature/notification-template-preview ``` ## 📝 PR Checklist @@ -279,15 +279,15 @@ If you encounter any issues: ### Branch Info ``` -Repository: https://github.com/coderolisa/Notify-Chain +Repository: https://github.com/Core-Foundry/Notify-Chain Branch: feature/notification-template-preview Status: ✅ Ready for PR ``` ### Key URLs -- Your Fork: `https://github.com/coderolisa/Notify-Chain` -- Create PR: `https://github.com/coderolisa/Notify-Chain/pull/new/feature/notification-template-preview` -- Branch: `https://github.com/coderolisa/Notify-Chain/tree/feature/notification-template-preview` +- Your Fork: `https://github.com/Core-Foundry/Notify-Chain` +- Create PR: `https://github.com/Core-Foundry/Notify-Chain/pull/new/feature/notification-template-preview` +- Branch: `https://github.com/Core-Foundry/Notify-Chain/tree/feature/notification-template-preview` ## ✨ You're All Set! diff --git a/DEPLOYMENT_PLAYBOOK.md b/DEPLOYMENT_PLAYBOOK.md index c7bf490..af06bdc 100644 --- a/DEPLOYMENT_PLAYBOOK.md +++ b/DEPLOYMENT_PLAYBOOK.md @@ -81,7 +81,7 @@ These variables are commonly exported during CLI deployment scripting: - `DISPUTE_RESOLVER_ADDRESS`: The designated address authorized to resolve disputed tasks in `TaskBounty`. ### 2.2 Off-Chain Listener Configuration (`listener/.env`) -Once the contracts are deployed, their IDs must be registered in the listener's environment config [listener/.env.example](file:///workspaces/Notify-Chain/listener/.env.example): +Once the contracts are deployed, their IDs must be registered in the listener's environment config [listener/.env.example](listener/.env.example): - `STELLAR_NETWORK`: Set to `testnet` or `public` (mainnet). - `STELLAR_RPC_URL`: The Stellar RPC endpoint URL (e.g., `https://soroban-testnet.stellar.org:443`). - `CONTRACT_ADDRESSES`: A JSON array specifying the contract addresses and events to subscribe to. @@ -93,7 +93,7 @@ Once the contracts are deployed, their IDs must be registered in the listener's ``` ### 2.3 Frontend Dashboard Configuration (`dashboard/.env`) -Provide the frontend dashboard [dashboard/.env.example](file:///workspaces/Notify-Chain/dashboard/.env.example) with details to query the listener: +Provide the frontend dashboard [dashboard/.env.example](dashboard/.env.example) with details to query the listener: - `VITE_EVENTS_API_URL`: HTTP URL of the listener event feed (e.g., `http://localhost:8787/api/events`). - `VITE_STELLAR_NETWORK`: Network context (`TESTNET` or `PUBLIC`). @@ -102,8 +102,8 @@ Provide the frontend dashboard [dashboard/.env.example](file:///workspaces/Notif ## 3. Step-by-Step Deployment Examples NotifyChain contains two primary smart contracts that must be compiled and deployed: -1. `AutoShare` - Subscription and group management contract located in [contract/contracts/hello-world](file:///workspaces/Notify-Chain/contract/contracts/hello-world). -2. `TaskBounty` - Decentralized task and reward board contract located in [Documents/Task Bounty](file:///workspaces/Notify-Chain/Documents/Task%20Bounty). +1. `AutoShare` - Subscription and group management contract located in [contract/contracts/hello-world](contract/contracts/hello-world). +2. `TaskBounty` - Decentralized task and reward board contract located in [Documents/Task Bounty](Documents/Task%20Bounty). --- @@ -142,7 +142,7 @@ export AUTOSHARE_CONTRACT_ID= ``` #### Step A.4: Initialize the Contract -The `AutoShare` contract requires initializing the administrator identity before it can accept groups and payments. Call the [initialize_admin](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L38) function: +The `AutoShare` contract requires initializing the administrator identity before it can accept groups and payments. Call the [initialize_admin](contract/contracts/hello-world/src/lib.rs#L38) function: ```bash stellar contract invoke \ --id $AUTOSHARE_CONTRACT_ID \ @@ -186,7 +186,7 @@ export TASKBOUNTY_CONTRACT_ID= ``` #### Step B.4: Initialize the Contract -The `TaskBounty` contract requires setting up the admin address and a dispute resolver. Call the [initialize](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L38) function: +The `TaskBounty` contract requires setting up the admin address and a dispute resolver. Call the [initialize](Documents/Task%20Bounty/src/lib.rs#L38) function: ```bash stellar contract invoke \ --id $TASKBOUNTY_CONTRACT_ID \ diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index fcc2ebc..732406d 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -27,7 +27,7 @@ Before starting, ensure you have the following software installed on your machin | Tool | Minimum Version | Purpose | Installation Link | |------|----------------|---------|-------------------| -| **Node.js** | v18.0.0+ | JavaScript runtime for listener & dashboard | [nodejs.org](https://nodejs.org/) | +| **Node.js** | v18+ (v20 recommended for Listener) | JavaScript runtime for listener & dashboard | [nodejs.org](https://nodejs.org/) | | **npm** | v9.0.0+ | Package manager (bundled with Node.js) | Comes with Node.js | | **Rust** | Latest stable | Smart contract development | [rustup.rs](https://rustup.rs/) | | **Stellar CLI** | Latest | Deploy & interact with contracts | See [installation](#installing-stellar-cli) | @@ -48,7 +48,7 @@ Before starting, ensure you have the following software installed on your machin ``` NotifyChain/ -├── 📂 contract/ # Soroban smart contracts (Rust) +├── contract/ # Soroban smart contracts (Rust) │ ├── contracts/ │ │ └── hello-world/ # AutoShare contract │ │ ├── src/ @@ -61,7 +61,7 @@ NotifyChain/ │ │ └── Makefile │ └── Cargo.toml # Workspace configuration │ -├── 📂 listener/ # Off-chain event listener (Node.js/TypeScript) +├── listener/ # Off-chain event listener (Node.js/TypeScript) │ ├── src/ │ │ ├── api/ # REST API endpoints │ │ ├── database/ # SQLite database layer @@ -81,7 +81,7 @@ NotifyChain/ │ ├── tsconfig.json │ └── jest.config.js │ -├── 📂 dashboard/ # React frontend dashboard +├── dashboard/ # React frontend dashboard │ ├── src/ │ │ ├── components/ # React components │ │ ├── hooks/ # Custom React hooks @@ -95,7 +95,7 @@ NotifyChain/ │ ├── vite.config.ts │ └── tsconfig.json │ -├── 📂 Documents/ +├── Documents/ │ └── Task Bounty/ # TaskBounty contract (alternative example) │ ├── .github/ @@ -124,8 +124,8 @@ NotifyChain/ ### 1. Clone the Repository ```bash -git clone https://github.com/your-org/NotifyChain.git -cd NotifyChain +git clone https://github.com/Core-Foundry/Notify-Chain.git +cd Notify-Chain ``` ### 2. Install Node.js Dependencies @@ -739,6 +739,11 @@ test: Add tests for Discord service ### Documentation - [README.md](./README.md) - Project overview +- [LOCAL_DEVELOPMENT.md](./LOCAL_DEVELOPMENT.md) - Quick local setup +- [CONTRIBUTOR_SETUP.md](./CONTRIBUTOR_SETUP.md) - Detailed contributor setup +- [CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md](./CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md) - Canonical contribution workflow +- [docs/](./docs/) - Additional architecture and API docs +- [dashboard/STORYBOOK.md](./dashboard/STORYBOOK.md) - Dashboard component Storybook - [listener/INSTALLATION.md](./listener/INSTALLATION.md) - Detailed listener setup - [listener/README-SCHEDULER.md](./listener/README-SCHEDULER.md) - Scheduler documentation - [listener/TEST-FIXTURE-MIGRATION-GUIDE.md](./listener/TEST-FIXTURE-MIGRATION-GUIDE.md) - Testing guide @@ -753,8 +758,8 @@ test: Add tests for Discord service ### Community -- [GitHub Issues](https://github.com/your-org/NotifyChain/issues) -- [GitHub Discussions](https://github.com/your-org/NotifyChain/discussions) +- [GitHub Issues](https://github.com/Core-Foundry/Notify-Chain/issues) +- [GitHub Discussions](https://github.com/Core-Foundry/Notify-Chain/discussions) --- @@ -776,4 +781,4 @@ Before considering your setup complete, verify: **You're ready to contribute to NotifyChain!** 🚀 -For questions or issues, please open a [GitHub Issue](https://github.com/your-org/NotifyChain/issues). +For questions or issues, please open a [GitHub Issue](https://github.com/Core-Foundry/Notify-Chain/issues). diff --git a/EVENT_CATALOG.md b/EVENT_CATALOG.md index 74d9bdb..f12e535 100644 --- a/EVENT_CATALOG.md +++ b/EVENT_CATALOG.md @@ -11,9 +11,9 @@ NotifyChain leverages these on-chain events to feed the off-chain listener, inde NotifyChain contracts use a structured event design that allows off-chain services to quickly categorize and filter events without needing to parse the full event payload first. ### 1.1 Notification Category -Every event emitted by the [AutoShareContract](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L22) carries a `NotificationCategory` as one of its indexed topics. This allows listeners to filter for whole categories of events. +Every event emitted by the [AutoShareContract](contract/contracts/hello-world/src/lib.rs#L22) carries a `NotificationCategory` as one of its indexed topics. This allows listeners to filter for whole categories of events. -The enum is defined in [events.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/base/events.rs#L18): +The enum is defined in [events.rs](contract/contracts/hello-world/src/base/events.rs#L18): | Variant | Value (U32) | Description | | :--- | :--- | :--- | @@ -25,7 +25,7 @@ The enum is defined in [events.rs](file:///workspaces/Notify-Chain/contract/cont ### 1.2 Notification Priority Every event emitted by `AutoShareContract` also carries a `NotificationPriority` topic to help downstream routers filter or trigger alerts based on severity. -The enum is defined in [events.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/base/events.rs#L46): +The enum is defined in [events.rs](contract/contracts/hello-world/src/base/events.rs#L46): | Variant | Value (U32) | Description | | :--- | :--- | :--- | @@ -41,7 +41,7 @@ To prevent breaking changes in downstream indexers, category and priority topics ## 2. AutoShare Contract Events -These events are defined in [base/events.rs](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/base/events.rs) within the AutoShare contract. +These events are defined in [base/events.rs](contract/contracts/hello-world/src/base/events.rs) within the AutoShare contract. In Soroban, CamelCase struct names compile to snake_case symbols by default (e.g., `AutoshareCreated` is emitted on-chain with the first topic `Symbol("autoshare_created")`). @@ -50,7 +50,7 @@ In Soroban, CamelCase struct names compile to snake_case symbols by default (e.g ### 2.1 `autoshare_created` Emitted when a new AutoShare group is created. -- **Trigger Method**: [create](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L63) +- **Trigger Method**: [create](contract/contracts/hello-world/src/lib.rs#L63) - **Topics**: 1. `Symbol("autoshare_created")` 2. `creator: Address` (Indexed creator of the group) @@ -63,7 +63,7 @@ Emitted when a new AutoShare group is created. ### 2.2 `autoshare_updated` Emitted when the members list of an AutoShare group is updated. -- **Trigger Method**: [update_members](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L77) +- **Trigger Method**: [update_members](contract/contracts/hello-world/src/lib.rs#L77) - **Topics**: 1. `Symbol("autoshare_updated")` 2. `updater: Address` (Address that updated the members) @@ -76,7 +76,7 @@ Emitted when the members list of an AutoShare group is updated. ### 2.3 `group_deactivated` Emitted when an AutoShare group is deactivated by its creator. -- **Trigger Method**: [deactivate_group](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L123) +- **Trigger Method**: [deactivate_group](contract/contracts/hello-world/src/lib.rs#L123) - **Topics**: 1. `Symbol("group_deactivated")` 2. `creator: Address` (Creator performing deactivation) @@ -89,7 +89,7 @@ Emitted when an AutoShare group is deactivated by its creator. ### 2.4 `group_activated` Emitted when a deactivated group is reactivated. -- **Trigger Method**: [activate_group](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L128) +- **Trigger Method**: [activate_group](contract/contracts/hello-world/src/lib.rs#L128) - **Topics**: 1. `Symbol("group_activated")` 2. `creator: Address` (Creator performing reactivation) @@ -102,7 +102,7 @@ Emitted when a deactivated group is reactivated. ### 2.5 `contract_paused` Emitted when the contract is paused by the administrator. -- **Trigger Method**: [pause](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L43) +- **Trigger Method**: [pause](contract/contracts/hello-world/src/lib.rs#L43) - **Topics**: 1. `Symbol("contract_paused")` 2. `category: NotificationCategory` (Always `Admin` / `1`) @@ -114,7 +114,7 @@ Emitted when the contract is paused by the administrator. ### 2.6 `contract_unpaused` Emitted when the contract is unpaused by the administrator. -- **Trigger Method**: [unpause](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L48) +- **Trigger Method**: [unpause](contract/contracts/hello-world/src/lib.rs#L48) - **Topics**: 1. `Symbol("contract_unpaused")` 2. `category: NotificationCategory` (Always `Admin` / `1`) @@ -126,7 +126,7 @@ Emitted when the contract is unpaused by the administrator. ### 2.7 `admin_transferred` Emitted when admin privileges are transferred to a new account. -- **Trigger Method**: [transfer_admin](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L143) +- **Trigger Method**: [transfer_admin](contract/contracts/hello-world/src/lib.rs#L143) - **Topics**: 1. `Symbol("admin_transferred")` 2. `old_admin: Address` (Old admin address) @@ -139,7 +139,7 @@ Emitted when admin privileges are transferred to a new account. ### 2.8 `withdrawal` Emitted when the admin withdraws collected usage fees from the contract. -- **Trigger Method**: [withdraw](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L148) +- **Trigger Method**: [withdraw](contract/contracts/hello-world/src/lib.rs#L148) - **Topics**: 1. `Symbol("withdrawal")` 2. `token: Address` (Token withdrawn) @@ -165,7 +165,7 @@ Emitted when an unauthorized operation attempt is detected on-chain. ### 2.10 `scheduled_notification_cancelled` Emitted when a scheduled notification is cancelled on-chain. -- **Trigger Method**: [cancel_notification](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L253) +- **Trigger Method**: [cancel_notification](contract/contracts/hello-world/src/lib.rs#L253) - **Topics**: 1. `Symbol("scheduled_notification_cancelled")` 2. `caller: Address` (The user who triggered cancellation) @@ -178,7 +178,7 @@ Emitted when a scheduled notification is cancelled on-chain. ### 2.11 `notification_scheduled` Emitted when a notification is scheduled on-chain with a bounded lifetime. -- **Trigger Method**: [schedule_notification](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L265) +- **Trigger Method**: [schedule_notification](contract/contracts/hello-world/src/lib.rs#L265) - **Topics**: 1. `Symbol("notification_scheduled")` 2. `creator: Address` (The creator of the notification) @@ -191,7 +191,7 @@ Emitted when a notification is scheduled on-chain with a bounded lifetime. ### 2.12 `notification_expired` Emitted when a scheduled notification's lifetime elapses, marking it expired. -- **Trigger Method**: [expire_notification](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L289) +- **Trigger Method**: [expire_notification](contract/contracts/hello-world/src/lib.rs#L289) - **Topics**: 1. `Symbol("notification_expired")` 2. `notification_id: BytesN<32>` (ID of the expired notification) @@ -204,7 +204,7 @@ Emitted when a scheduled notification's lifetime elapses, marking it expired. ### 2.13 `notification_revoked` Emitted when a scheduled notification is revoked by its creator or admin. -- **Trigger Method**: [revoke_notification](file:///workspaces/Notify-Chain/contract/contracts/hello-world/src/lib.rs#L297) +- **Trigger Method**: [revoke_notification](contract/contracts/hello-world/src/lib.rs#L297) - **Topics**: 1. `Symbol("notification_revoked")` 2. `notification_id: BytesN<32>` (ID of the revoked notification) @@ -217,14 +217,14 @@ Emitted when a scheduled notification is revoked by its creator or admin. ## 3. TaskBounty Contract Events -These events are defined in [events.rs](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/events.rs) within the TaskBounty contract. They do not use the category/priority helper wrapper but emit multi-topic symbols directly. +These events are defined in [events.rs](Documents/Task%20Bounty/src/events.rs) within the TaskBounty contract. They do not use the category/priority helper wrapper but emit multi-topic symbols directly. --- ### 3.1 `task_created` Emitted when a new task is created and reward tokens are escrowed in the contract. -- **Trigger Method**: [create_task](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L58) +- **Trigger Method**: [create_task](Documents/Task%20Bounty/src/lib.rs#L58) - **Topics**: 1. `Symbol("task")` 2. `Symbol("created")` @@ -240,7 +240,7 @@ Emitted when a new task is created and reward tokens are escrowed in the contrac ### 3.2 `work_submitted` Emitted when a contributor submits work for a task. -- **Trigger Method**: [submit_work](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L92) +- **Trigger Method**: [submit_work](Documents/Task%20Bounty/src/lib.rs#L92) - **Topics**: 1. `Symbol("work")` 2. `Symbol("submit")` @@ -255,7 +255,7 @@ Emitted when a contributor submits work for a task. ### 3.3 `submission_approved` Emitted when the poster approves a work submission, releasing escrowed rewards. -- **Trigger Method**: [approve_submission](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L110) +- **Trigger Method**: [approve_submission](Documents/Task%20Bounty/src/lib.rs#L110) - **Topics**: 1. `Symbol("sub")` 2. `Symbol("approved")` @@ -270,7 +270,7 @@ Emitted when the poster approves a work submission, releasing escrowed rewards. ### 3.4 `submission_rejected` Emitted when the poster rejects a submission. -- **Trigger Method**: [reject_submission](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L128) +- **Trigger Method**: [reject_submission](Documents/Task%20Bounty/src/lib.rs#L128) - **Topics**: 1. `Symbol("sub")` 2. `Symbol("rejected")` @@ -284,7 +284,7 @@ Emitted when the poster rejects a submission. ### 3.5 `task_cancelled` Emitted when a task is cancelled and funds are refunded to the poster. -- **Trigger Method**: [cancel_task](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L145) +- **Trigger Method**: [cancel_task](Documents/Task%20Bounty/src/lib.rs#L145) - **Topics**: 1. `Symbol("task")` 2. `Symbol("cancel")` @@ -297,7 +297,7 @@ Emitted when a task is cancelled and funds are refunded to the poster. ### 3.6 `dispute_raised` Emitted when a poster or contributor raises a dispute over a work submission. -- **Trigger Method**: [raise_dispute](file:///workspaces/Notify-Chain/Documents/Task%20Bounty/src/lib.rs#L158) +- **Trigger Method**: [raise_dispute](Documents/Task%20Bounty/src/lib.rs#L158) - **Topics**: 1. `Symbol("dispute")` 2. `Symbol("raised")` diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md index 259858e..cca6a8c 100644 --- a/IMPLEMENTATION_SUMMARY.md +++ b/IMPLEMENTATION_SUMMARY.md @@ -501,7 +501,7 @@ The feature is: ### Branch Information ``` Branch: feature/notification-template-preview -Remote: https://github.com/coderolisa/Notify-Chain.git +Remote: https://github.com/Core-Foundry/Notify-Chain.git Status: Ready for Pull Request ``` diff --git a/LOCAL_DEVELOPMENT.md b/LOCAL_DEVELOPMENT.md index b2ac9b6..8e5a459 100644 --- a/LOCAL_DEVELOPMENT.md +++ b/LOCAL_DEVELOPMENT.md @@ -25,7 +25,7 @@ This guide walks you through setting up every component of NotifyChain on your l | Tool | Version | Install | |------|---------|---------| -| Node.js | ≥ 18 | [nodejs.org](https://nodejs.org) | +| Node.js | ≥ 18 (20 recommended for Listener) | [nodejs.org](https://nodejs.org) | | npm | ≥ 9 | Bundled with Node.js | | Rust | stable | `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \| sh` | | Stellar CLI | latest | `cargo install --locked stellar-cli --features opt` | @@ -146,6 +146,14 @@ EVENTS_API_PORT=8787 See [Environment Variables Reference](#environment-variables-reference) for all options. +Use `npm ci` when installing from the lockfile (CI / clean setups). Use `npm install` for local dependency updates. + +### Initialize database + +```bash +npm run migrate +``` + ### Run in development mode ```bash @@ -416,7 +424,7 @@ mkdir -p listener/data rustup target add wasm32-unknown-unknown ``` -### `cargo install stellar-cli` is slow or fails +### `cargo install --locked stellar-cli --features opt` is slow or fails Try with the `--locked` flag to use pinned dependency versions: diff --git a/README.md b/README.md index e68705b..8a6d279 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ The project enables developers to build reactive decentralized applications with > - [Notification Failure Recovery](NOTIFICATION_FAILURE_RECOVERY.md) — retry lifecycle, configuration, and troubleshooting. > > **Event reference**: [Smart Contract Event Reference Guide](CONTRACT_EVENT_REFERENCE.md) — all emitted events, parameters, data types, and usage recommendations for indexers and listeners. +> +> **Dashboard Storybook**: [dashboard/STORYBOOK.md](dashboard/STORYBOOK.md) — component documentation for design and development reviews. --- @@ -333,8 +335,8 @@ stellar --version 1. **Clone the repository**: ```bash - git clone https://github.com/your-org/notify-chain.git - cd notify-chain + git clone https://github.com/Core-Foundry/Notify-Chain.git + cd Notify-Chain ``` 2. **Building the AutoShare contract**: @@ -548,7 +550,7 @@ Common Freighter wallet issues and how to resolve them. ## Wallet UX States -The frontend models four wallet connection states. Every UI that depends on the wallet must handle all of them. +The frontend (legacy Next.js analytics app under `frontend/`) models four wallet connection states. Every UI that depends on the wallet must handle all of them. | State | Description | User-facing message | |-------|-------------|---------------------| @@ -649,7 +651,9 @@ Contributions are welcome! Please follow these steps (or start with the canonica Please follow the project's coding standards and include tests where applicable. For more detailed contribution guidelines, check: -- `Documents/Task Bounty/CONTRIBUTING.md` +- [`CONTRIBUTING.md`](CONTRIBUTING.md) +- [`CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md`](CONTRIBUTOR_DEVELOPMENT_WORKFLOW_GUIDE.md) +- `Documents/Task Bounty/CONTRIBUTING.md` (TaskBounty contract-specific) --- diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md index 0c9aa22..3c953e6 100644 --- a/TROUBLESHOOTING.md +++ b/TROUBLESHOOTING.md @@ -1,6 +1,6 @@ # Troubleshooting Guide — Local Development -This guide documents the most common setup issues contributors encounter and how to fix them. If your problem is not listed here, please open a [GitHub Issue](https://github.com/CollinsC1O/Notify-Chain/issues). +This guide documents the most common setup issues contributors encounter and how to fix them. If your problem is not listed here, please open a [GitHub Issue](https://github.com/Core-Foundry/Notify-Chain/issues). --- @@ -415,7 +415,7 @@ cd ../dashboard && npm install ### Still stuck? -1. Search [open issues](https://github.com/CollinsC1O/Notify-Chain/issues) — your problem may already be reported. +1. Search [open issues](https://github.com/Core-Foundry/Notify-Chain/issues) — your problem may already be reported. 2. Open a new issue with: - Your OS and version - Output of `rustc --version`, `node --version`, `stellar --version` diff --git a/contract/README.md b/contract/README.md index 557ea3d..b1eb38c 100644 --- a/contract/README.md +++ b/contract/README.md @@ -1,8 +1,10 @@ -# Soroban Project +# AutoShare Contract + +AutoShare lives under `contracts/hello-world` (directory name kept for historical Soroban scaffold layout). ## Project Structure -This repository uses the recommended structure for a Soroban project: +This package uses the recommended structure for a Soroban project: ```text . ├── contracts diff --git a/dashboard/.gitignore b/dashboard/.gitignore index 0ca39c0..a9927e7 100644 --- a/dashboard/.gitignore +++ b/dashboard/.gitignore @@ -1,3 +1,4 @@ node_modules dist +storybook-static .DS_Store diff --git a/dashboard/.storybook/main.ts b/dashboard/.storybook/main.ts new file mode 100644 index 0000000..ee0a2f5 --- /dev/null +++ b/dashboard/.storybook/main.ts @@ -0,0 +1,25 @@ +import type { StorybookConfig } from '@storybook/react-vite'; + +const config: StorybookConfig = { + stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|mjs|ts|tsx)'], + addons: ['@storybook/addon-essentials', '@storybook/addon-interactions'], + framework: { + name: '@storybook/react-vite', + options: {}, + }, + docs: { + autodocs: 'tag', + }, + async viteFinal(config) { + config.server = { + ...config.server, + fs: { + ...config.server?.fs, + strict: false, + }, + }; + return config; + }, +}; + +export default config; diff --git a/dashboard/.storybook/preview.tsx b/dashboard/.storybook/preview.tsx new file mode 100644 index 0000000..6d36869 --- /dev/null +++ b/dashboard/.storybook/preview.tsx @@ -0,0 +1,69 @@ +import type { Preview } from '@storybook/react'; +import React, { useEffect, type ReactNode } from 'react'; +import '../src/index.css'; + +function ThemeWrapper({ + theme, + children, +}: { + theme: 'dark' | 'light'; + children: ReactNode; +}) { + useEffect(() => { + document.documentElement.setAttribute('data-theme', theme); + document.body.style.background = theme === 'light' ? '#f5f7fb' : '#0b0d12'; + document.body.style.color = theme === 'light' ? '#0b0d12' : '#e8eaed'; + document.body.style.margin = '0'; + document.body.style.minHeight = '100vh'; + }, [theme]); + + return React.createElement( + 'div', + { className: 'app', style: { padding: '16px', minHeight: '100%' } }, + children + ); +} + +const preview: Preview = { + parameters: { + controls: { + matchers: { + color: /(background|color)$/i, + date: /Date$/i, + }, + }, + layout: 'padded', + backgrounds: { + default: 'dashboard-dark', + values: [ + { name: 'dashboard-dark', value: '#0b0d12' }, + { name: 'dashboard-light', value: '#f5f7fb' }, + ], + }, + }, + globalTypes: { + theme: { + description: 'Dashboard color theme', + defaultValue: 'dark', + toolbar: { + title: 'Theme', + icon: 'circlehollow', + items: [ + { value: 'dark', title: 'Dark' }, + { value: 'light', title: 'Light' }, + ], + dynamicTitle: true, + }, + }, + }, + decorators: [ + (Story, context) => + React.createElement( + ThemeWrapper, + { theme: (context.globals.theme as 'dark' | 'light') ?? 'dark' }, + React.createElement(Story) + ), + ], +}; + +export default preview; diff --git a/dashboard/STORYBOOK.md b/dashboard/STORYBOOK.md new file mode 100644 index 0000000..233aa5c --- /dev/null +++ b/dashboard/STORYBOOK.md @@ -0,0 +1,32 @@ +# Dashboard Storybook + +Storybook documents reusable NotifyChain dashboard UI components for development and design review. + +## Commands + +From `dashboard/`: + +```bash +npm install +npm run storybook +``` + +Open [http://localhost:6006](http://localhost:6006). + +Build a static Storybook site: + +```bash +npm run build-storybook +``` + +## Documented components + +- `Modal` — size and footer variations +- `ThemeToggle` — light / dark +- `PaginationControls` — first / middle / last page and custom page sizes +- `EventCard` — compact / expanded / loading and event-type variants +- `EventExplorerCard` — copied, paused, and clickable states +- `ExportHistoryTable` — mixed export statuses +- `WebhookSummaryCards` — loading and filled metrics + +Stories live next to components as `*.stories.tsx` and share fixtures under `src/stories/fixtures/`. diff --git a/dashboard/package-lock.json b/dashboard/package-lock.json index 758e0d8..4b1f5ff 100644 --- a/dashboard/package-lock.json +++ b/dashboard/package-lock.json @@ -14,6 +14,12 @@ "zustand": "^5.0.6" }, "devDependencies": { + "@storybook/addon-essentials": "^8.6.14", + "@storybook/addon-interactions": "^8.6.14", + "@storybook/blocks": "^8.6.14", + "@storybook/react": "^8.6.14", + "@storybook/react-vite": "^8.6.14", + "@storybook/test": "^8.6.14", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", @@ -30,6 +36,7 @@ "jest-axe": "^10.0.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^26.1.0", + "storybook": "^8.6.14", "ts-jest": "^29.2.5", "typescript": "^5.8.3", "vite": "^6.3.5" @@ -976,8 +983,6 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "extraneous": true, - "license": "Apache-2.0", "license": "Apache-2.0", "optional": true, "peer": true, @@ -1863,6 +1868,109 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", @@ -2466,6 +2574,78 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/@joshwooding/vite-plugin-react-docgen-typescript": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@joshwooding/vite-plugin-react-docgen-typescript/-/vite-plugin-react-docgen-typescript-0.5.0.tgz", + "integrity": "sha512-qYDdL7fPwLRI+bJNurVcis+tNgJmvWjH4YTBGXTA8xMuxFrnAz6E5o35iyzyKbq5J5Lr8mJGfrR5GXl+WGwhgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "magic-string": "^0.27.0", + "react-docgen-typescript": "^2.2.2" + }, + "peerDependencies": { + "typescript": ">= 4.3.x", + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@joshwooding/vite-plugin-react-docgen-typescript/node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@joshwooding/vite-plugin-react-docgen-typescript/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@joshwooding/vite-plugin-react-docgen-typescript/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -2606,6 +2786,24 @@ "integrity": "sha512-jwlVyzMFF296iaNgMWn1lu+EU6BeUD4mgPurEsy8EygYNCrjA8igLpsDlXhfvXhst9tX5w4wRuTDX+FZtpfCug==", "license": "GPL-3.0" }, + "node_modules/@mdx-js/react": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@mdx-js/react/-/react-3.1.1.tgz", + "integrity": "sha512-f++rKLQgUVYDAtECQ6fn/is15GkEH9+nZPM3MS0RcxVqoTfawHvDlSCH7JbMhAM6uJ32v3eXLvLmLvjGu7PTQw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/mdx": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/unified" + }, + "peerDependencies": { + "@types/react": ">=16", + "react": ">=16" + } + }, "node_modules/@mobily/ts-belt": { "version": "3.13.1", "resolved": "https://registry.npmjs.org/@mobily/ts-belt/-/ts-belt-3.13.1.tgz", @@ -3000,6 +3198,17 @@ "lit": "^3" } }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@preact/signals": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/@preact/signals/-/signals-2.9.0.tgz", @@ -3265,6 +3474,42 @@ "dev": true, "license": "MIT" }, + "node_modules/@rollup/pluginutils": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.4.0.tgz", + "integrity": "sha512-MfPp06CjRLfXQ3wY0R8vJDYBy/MvVcc9OulEfR0B8Iv9ko+GCNaRZ+EpJYFl27LhKsZK0o420sYCRHCjfCgeUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.62.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.62.2.tgz", @@ -4972,18 +5217,872 @@ "proxy-from-env": "^2.1.0" } }, - "node_modules/@stellar/stellar-sdk/node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "node_modules/@stellar/stellar-sdk/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "peer": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@storybook/addon-actions": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-actions/-/addon-actions-8.6.14.tgz", + "integrity": "sha512-mDQxylxGGCQSK7tJPkD144J8jWh9IU9ziJMHfB84PKpI/V5ZgqMDnpr2bssTrUaGDqU5e1/z8KcRF+Melhs9pQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@types/uuid": "^9.0.1", + "dequal": "^2.0.2", + "polished": "^4.2.2", + "uuid": "^9.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-actions/node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/addon-actions/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@storybook/addon-backgrounds": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-backgrounds/-/addon-backgrounds-8.6.14.tgz", + "integrity": "sha512-l9xS8qWe5n4tvMwth09QxH2PmJbCctEvBAc1tjjRasAfrd69f7/uFK4WhwJAstzBTNgTc8VXI4w8ZR97i1sFbg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "memoizerific": "^1.11.3", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-controls": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-controls/-/addon-controls-8.6.14.tgz", + "integrity": "sha512-IiQpkNJdiRyA4Mq9mzjZlvQugL/aE7hNgVxBBGPiIZG6wb6Ht9hNnBYpap5ZXXFKV9p2qVI0FZK445ONmAa+Cw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "dequal": "^2.0.2", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-docs": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-docs/-/addon-docs-8.6.14.tgz", + "integrity": "sha512-Obpd0OhAF99JyU5pp5ci17YmpcQtMNgqW2pTXV8jAiiipWpwO++hNDeQmLmlSXB399XjtRDOcDVkoc7rc6JzdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@mdx-js/react": "^3.0.0", + "@storybook/blocks": "8.6.14", + "@storybook/csf-plugin": "8.6.14", + "@storybook/react-dom-shim": "8.6.14", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-essentials": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-essentials/-/addon-essentials-8.6.14.tgz", + "integrity": "sha512-5ZZSHNaW9mXMOFkoPyc3QkoNGdJHETZydI62/OASR0lmPlJ1065TNigEo5dJddmZNn0/3bkE8eKMAzLnO5eIdA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/addon-actions": "8.6.14", + "@storybook/addon-backgrounds": "8.6.14", + "@storybook/addon-controls": "8.6.14", + "@storybook/addon-docs": "8.6.14", + "@storybook/addon-highlight": "8.6.14", + "@storybook/addon-measure": "8.6.14", + "@storybook/addon-outline": "8.6.14", + "@storybook/addon-toolbars": "8.6.14", + "@storybook/addon-viewport": "8.6.14", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-highlight": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-highlight/-/addon-highlight-8.6.14.tgz", + "integrity": "sha512-4H19OJlapkofiE9tM6K/vsepf4ir9jMm9T+zw5L85blJZxhKZIbJ6FO0TCG9PDc4iPt3L6+aq5B0X29s9zicNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-interactions": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-interactions/-/addon-interactions-8.6.14.tgz", + "integrity": "sha512-8VmElhm2XOjh22l/dO4UmXxNOolGhNiSpBcls2pqWSraVh4a670EyYBZsHpkXqfNHo2YgKyZN3C91+9zfH79qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.6.14", + "@storybook/test": "8.6.14", + "polished": "^4.2.2", + "ts-dedent": "^2.2.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/@storybook/test": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.6.14.tgz", + "integrity": "sha512-GkPNBbbZmz+XRdrhMtkxPotCLOQ1BaGNp/gFZYdGDk2KmUWBKmvc5JxxOhtoXM2703IzNFlQHSSNnhrDZYuLlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.6.14", + "@testing-library/dom": "10.4.0", + "@testing-library/jest-dom": "6.5.0", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "2.0.5", + "@vitest/spy": "2.0.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/@testing-library/jest-dom": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/addon-interactions/node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/addon-interactions/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/addon-measure": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-measure/-/addon-measure-8.6.14.tgz", + "integrity": "sha512-1Tlyb72NX8aAqm6I6OICsUuGOP6hgnXcuFlXucyhKomPa6j3Eu2vKu561t/f0oGtAK2nO93Z70kVaEh5X+vaGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "tiny-invariant": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-outline": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-outline/-/addon-outline-8.6.14.tgz", + "integrity": "sha512-CW857JvN6OxGWElqjlzJO2S69DHf+xO3WsEfT5mT3ZtIjmsvRDukdWfDU9bIYUFyA2lFvYjncBGjbK+I91XR7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-toolbars": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-toolbars/-/addon-toolbars-8.6.14.tgz", + "integrity": "sha512-W/wEXT8h3VyZTVfWK/84BAcjAxTdtRiAkT2KAN0nbSHxxB5KEM1MjKpKu2upyzzMa3EywITqbfy4dP6lpkVTwQ==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/addon-viewport": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/addon-viewport/-/addon-viewport-8.6.14.tgz", + "integrity": "sha512-gNzVQbMqRC+/4uQTPI2ZrWuRHGquTMZpdgB9DrD88VTEjNudP+J6r8myLfr2VvGksBbUMHkGHMXHuIhrBEnXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "memoizerific": "^1.11.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/blocks": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/blocks/-/blocks-8.6.14.tgz", + "integrity": "sha512-rBMHAfA39AGHgkrDze4RmsnQTMw1ND5fGWobr9pDcJdnDKWQWNRD7Nrlxj0gFlN3n4D9lEZhWGdFrCbku7FVAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/icons": "^1.2.12", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "storybook": "^8.6.14" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } + } + }, + "node_modules/@storybook/builder-vite": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/builder-vite/-/builder-vite-8.6.18.tgz", + "integrity": "sha512-XLqnOv4C36jlTd4uC8xpWBxv+7GV4/05zWJ0wAcU4qflorropUTirt4UQPGkwIzi+BVAhs9pJj+m4k0IWJtpHg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/csf-plugin": "8.6.18", + "browser-assert": "^1.2.1", + "ts-dedent": "^2.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.18", + "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" + } + }, + "node_modules/@storybook/builder-vite/node_modules/@storybook/csf-plugin": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.6.18.tgz", + "integrity": "sha512-x1ioz/L0CwaelCkHci3P31YtvwayN3FBftvwQOPbvRh9qeb4Cpz5IdVDmyvSxxYwXN66uAORNoqgjTi7B4/y5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.18" + } + }, + "node_modules/@storybook/components": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/components/-/components-8.6.18.tgz", + "integrity": "sha512-55yViiZzPS/cPBuOeW4QGxGqrusjXVyxuknmbYCIwDtFyyvI/CgbjXRHdxNBaIjz+IlftxvBmmSaOqFG5+/dkA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/core": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/core/-/core-8.6.18.tgz", + "integrity": "sha512-dRBP2TnX6fGdS0T2mXBHjkS/3Nlu1ra1huovZVFuM67CYMzrhM/3hX/zru1vWSC5rqY93ZaAhjMciPW4pK5mMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/theming": "8.6.18", + "better-opn": "^3.0.2", + "browser-assert": "^1.2.1", + "esbuild": "^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0 || ^0.25.0", + "esbuild-register": "^3.5.0", + "jsdoc-type-pratt-parser": "^4.0.0", + "process": "^0.11.10", + "recast": "^0.23.5", + "semver": "^7.6.2", + "util": "^0.12.5", + "ws": "^8.2.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, + "node_modules/@storybook/csf-plugin": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/csf-plugin/-/csf-plugin-8.6.14.tgz", + "integrity": "sha512-dErtc9teAuN+eelN8FojzFE635xlq9cNGGGEu0WEmMUQ4iJ8pingvBO1N8X3scz4Ry7KnxX++NNf3J3gpxS8qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "unplugin": "^1.3.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/global": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@storybook/global/-/global-5.0.0.tgz", + "integrity": "sha512-FcOqPAXACP0I3oJ/ws6/rrPT9WGhu915Cg8D02a9YxLo0DE9zI+a9A5gRGvmQ09fiWPukqI8ZAEoQEdWUKMQdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/icons": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@storybook/icons/-/icons-1.6.0.tgz", + "integrity": "sha512-hcFZIjW8yQz8O8//2WTIXylm5Xsgc+lW9ISLgUk1xGmptIJQRdlhVIXCpSyLrQaaRiyhQRaVg7l3BD9S216BHw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta" + } + }, + "node_modules/@storybook/instrumenter": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.6.14.tgz", + "integrity": "sha512-iG4MlWCcz1L7Yu8AwgsnfVAmMbvyRSk700Mfy2g4c8y5O+Cv1ejshE1LBBsCwHgkuqU0H4R0qu4g23+6UnUemQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^2.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/manager-api": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/manager-api/-/manager-api-8.6.18.tgz", + "integrity": "sha512-BjIp12gEMgzFkEsgKpDIbZdnSWTZpm2dlws8WiPJCpgJtG+HWSxZ0/Ms30Au9yfwzQEKRSbV/5zpsKMGc2SIJw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/preview-api": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/preview-api/-/preview-api-8.6.18.tgz", + "integrity": "sha512-joXRXh3GdVvzhbfIgmix1xs90p8Q/nja7AhEAC2egn5Pl7SKsIYZUCYI6UdrQANb2myg9P552LKXfPect8llKg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" + } + }, + "node_modules/@storybook/react": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/react/-/react-8.6.18.tgz", + "integrity": "sha512-BuLpzMkKtF+UCQCbi+lYVX9cdcAMG86Lu2dDn7UFkPi5HRNFq/zHPSvlz1XDgL0OYMtcqB1aoVzFzcyzUBhhjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/components": "8.6.18", + "@storybook/global": "^5.0.0", + "@storybook/manager-api": "8.6.18", + "@storybook/preview-api": "8.6.18", + "@storybook/react-dom-shim": "8.6.18", + "@storybook/theming": "8.6.18" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@storybook/test": "8.6.18", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.6.18", + "typescript": ">= 4.2.x" + }, + "peerDependenciesMeta": { + "@storybook/test": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@storybook/react-dom-shim": { + "version": "8.6.14", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.6.14.tgz", + "integrity": "sha512-0hixr3dOy3f3M+HBofp3jtMQMS+sqzjKNgl7Arfuj3fvjmyXOks/yGjDImySR4imPtEllvPZfhiQNlejheaInw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.6.14" + } + }, + "node_modules/@storybook/react-vite": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/react-vite/-/react-vite-8.6.18.tgz", + "integrity": "sha512-qpSYyH2IizlEsI95MJTdIL6xpLSgiNCMoJpHu+IEqLnyvmecRR/YEZvcHalgdtawuXlimH0bAYuwIu3l8Vo6FQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@joshwooding/vite-plugin-react-docgen-typescript": "0.5.0", + "@rollup/pluginutils": "^5.0.2", + "@storybook/builder-vite": "8.6.18", + "@storybook/react": "8.6.18", + "find-up": "^5.0.0", + "magic-string": "^0.30.0", + "react-docgen": "^7.0.0", + "resolve": "^1.22.8", + "tsconfig-paths": "^4.2.0" + }, + "engines": { + "node": ">=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "@storybook/test": "8.6.18", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.6.18", + "vite": "^4.0.0 || ^5.0.0 || ^6.0.0" + }, + "peerDependenciesMeta": { + "@storybook/test": { + "optional": true + } + } + }, + "node_modules/@storybook/react-vite/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/@storybook/react/node_modules/@storybook/react-dom-shim": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/react-dom-shim/-/react-dom-shim-8.6.18.tgz", + "integrity": "sha512-N4xULcAWZQTUv4jy1/d346Tyb4gufuC3UaLCuU/iVSZ1brYF4OW3ANr+096btbMxY8pR/65lmtoqr5CTGwnBvA==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta", + "storybook": "^8.6.18" + } + }, + "node_modules/@storybook/test": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/test/-/test-8.6.18.tgz", + "integrity": "sha512-u/RwfWMyHcH0N2hqfMTw2CoZ58IXdeED3b8NmcHc8bmERB3byI5vVAkwYbcD7+WeRHIiym38ZHi0SRn+IpkO3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@storybook/instrumenter": "8.6.18", + "@testing-library/dom": "10.4.0", + "@testing-library/jest-dom": "6.5.0", + "@testing-library/user-event": "14.5.2", + "@vitest/expect": "2.0.5", + "@vitest/spy": "2.0.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.18" + } + }, + "node_modules/@storybook/test/node_modules/@storybook/instrumenter": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/instrumenter/-/instrumenter-8.6.18.tgz", + "integrity": "sha512-viEC1BGlYyjAzi1Tv3LZjByh7Y3Oh04u6QKsujxdeUbr5rUOH4pa/wCKmxXmY6yWrD4WjcNtojmUvQZN/66FXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/global": "^5.0.0", + "@vitest/utils": "^2.1.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.6.18" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/dom": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz", + "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.10.4", + "@babel/runtime": "^7.12.5", + "@types/aria-query": "^5.0.1", + "aria-query": "5.3.0", + "chalk": "^4.1.0", + "dom-accessibility-api": "^0.5.9", + "lz-string": "^1.5.0", + "pretty-format": "^27.0.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.5.0.tgz", + "integrity": "sha512-xGGHpBXYSHUUr6XsKBfs85TWlYKpTc37cSBBVrXcib2MkHLboWlkClhWF37JKlDb9KEq3dHs+f2xR7XJEWGBxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@adobe/css-tools": "^4.4.0", + "aria-query": "^5.0.0", + "chalk": "^3.0.0", + "css.escape": "^1.5.1", + "dom-accessibility-api": "^0.6.3", + "lodash": "^4.17.21", + "redent": "^3.0.0" + }, + "engines": { + "node": ">=14", + "npm": ">=6", + "yarn": ">=1" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@storybook/test/node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz", + "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@storybook/test/node_modules/@testing-library/user-event": { + "version": "14.5.2", + "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz", + "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@testing-library/dom": ">=7.21.4" + } + }, + "node_modules/@storybook/test/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@storybook/test/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", - "peer": true, "dependencies": { - "agent-base": "6", - "debug": "4" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 6" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@storybook/theming": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/@storybook/theming/-/theming-8.6.18.tgz", + "integrity": "sha512-n6OEjEtHupa2PdTwWzRepr7cO8NkDd4rgF6BKLitRbujOspLxzMBEqdphs+QLcuiCIgf33SqmEA64QWnbSMhPw==", + "dev": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "storybook": "^8.2.0 || ^8.3.0-0 || ^8.4.0-0 || ^8.5.0-0 || ^8.6.0-0" } }, "node_modules/@swc/helpers": { @@ -7292,8 +8391,7 @@ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/@types/babel__core": { "version": "7.20.5", @@ -7349,6 +8447,13 @@ "@types/node": "*" } }, + "node_modules/@types/doctrine": { + "version": "0.0.9", + "resolved": "https://registry.npmjs.org/@types/doctrine/-/doctrine-0.0.9.tgz", + "integrity": "sha512-eOIHzCUSH7SMfonMG1LsC2f8vxBFtho6NGBznK41R84YzPuvSBzrhEps33IsQiOW9+VL6NQ9DbjQJznk/S4uRA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.9", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", @@ -7455,6 +8560,13 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "license": "MIT" }, + "node_modules/@types/mdx": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.14.tgz", + "integrity": "sha512-T48PeuJtvLosNTPVhfnIp3i/n3a4g4Bad7YCq5k64D4u7NwDrAotikQ+5+sjtUvBmxCMlbo3dVL+C2dP0rWHzg==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { "version": "26.0.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-26.0.1.tgz", @@ -7490,6 +8602,13 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/resolve": { + "version": "1.20.6", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.6.tgz", + "integrity": "sha512-A4STmOXPhMUtHH+S6ymgE2GiBSMqf4oTvcQZMcHzokuTLVYzXTB8ttjcgxOVaAp2lGwEdzZ0J+cRbbeevQj1UQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/semver": { "version": "7.7.1", "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.1.tgz", @@ -7789,6 +8908,102 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, + "node_modules/@vitest/expect": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.0.5.tgz", + "integrity": "sha512-yHZtwuP7JZivj65Gxoi8upUN2OzHTi3zVfjwdpu2WrvCZPLwsJ2Ey5ILIPccoW23dd/zQBlJ4/dhi7DWNyXCpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "2.0.5", + "@vitest/utils": "2.0.5", + "chai": "^5.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/@vitest/pretty-format": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.0.5.tgz", + "integrity": "sha512-h8k+1oWHfwTkyTkb9egzwNMfJAEx4veaPSnMeKbVSjp4euqGSbQlm5+6VHwTr7u4FJslVVsUG5nopCaAYdOmSQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/@vitest/utils": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.0.5.tgz", + "integrity": "sha512-d8HKbqIcya+GR67mkZbrzhS5kKhtp8dQLcmRZLGTscGVg7yImT82cIrhtn2L8+VujWcy6KZweApgNmPsTAO/UQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.0.5", + "estree-walker": "^3.0.3", + "loupe": "^3.1.1", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/expect/node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, + "node_modules/@vitest/pretty-format": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", + "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.0.5.tgz", + "integrity": "sha512-c/jdthAhvJdpfVuaexSrnawxZz6pywlTPe84LUB2m/4t3rl2fTo9NFGBG4oWgaD+FTgDDV8hJ/nibT7IfH3JfA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", + "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "2.1.9", + "loupe": "^3.1.2", + "tinyrainbow": "^1.2.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@wallet-standard/base": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@wallet-standard/base/-/base-1.1.1.tgz", @@ -7991,9 +9206,6 @@ "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "extraneous": true, - "hasInstallScript": true, - "license": "MIT", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -8985,6 +10197,29 @@ "license": "MIT", "peer": true }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/ast-types": { + "version": "0.16.1", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.16.1.tgz", + "integrity": "sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -9327,6 +10562,19 @@ "license": "MIT", "peer": true }, + "node_modules/better-opn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/better-opn/-/better-opn-3.0.2.tgz", + "integrity": "sha512-aVNobHnJqLiUelTaHat9DZ1qM2w0C0Eym4LPI/3JxOnSokGVdsl1T1kN7TFvsEAD8G47A6VKQ0TVHqbBnYMJlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "open": "^8.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/big-integer": { "version": "1.6.36", "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.36.tgz", @@ -9452,6 +10700,12 @@ "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", "license": "MIT" }, + "node_modules/browser-assert": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/browser-assert/-/browser-assert-1.2.1.tgz", + "integrity": "sha512-nfulgvOR6S4gt9UKCeGJOuSGBPGiFT6oQ/2UBnvTY/5aQ1PnksW72fhZkM30DzoRRv2WpwZf1vHHEr3mtuXIWQ==", + "dev": true + }, "node_modules/browserify-aes": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz", @@ -9821,6 +11075,23 @@ "node": ">=20" } }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "5.6.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", @@ -9852,6 +11123,16 @@ "node": "*" } }, + "node_modules/check-error": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", + "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 16" + } + }, "node_modules/chokidar": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", @@ -10338,6 +11619,16 @@ } } }, + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -10372,6 +11663,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/define-properties": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", @@ -10556,8 +11857,7 @@ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz", "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/domexception": { "version": "4.0.0", @@ -10587,6 +11887,13 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/ecdsa-sig-formatter": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", @@ -10935,6 +12242,19 @@ "@esbuild/win32-x64": "0.25.12" } }, + "node_modules/esbuild-register": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/esbuild-register/-/esbuild-register-3.6.0.tgz", + "integrity": "sha512-H2/S7Pm8a9CL1uhp9OvjwrBh5Pvx0H8qVOxNu8Wed9Y7qv56MPtq+GGM8RJpq6glYJn9Wspr8uw7l55uyinNeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, + "peerDependencies": { + "esbuild": ">=0.12 <1" + } + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -11272,6 +12592,13 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -11603,6 +12930,36 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/form-data": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", @@ -12435,6 +13792,23 @@ "url": "https://github.com/sponsors/brc-dd" } }, + "node_modules/is-arguments": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.2.0.tgz", + "integrity": "sha512-7bVbi0huj/wrIAOzb8U1aszg9kdi3KN/CyU19CTI7tAoZYEZoL9yCDXpbXN+uPsuWnP02cyug1gleqq+TU+YCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-array-buffer": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", @@ -12583,6 +13957,22 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "dev": true, + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-document.all": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", @@ -12966,6 +14356,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", @@ -13092,6 +14495,22 @@ "node": ">= 0.4" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, "node_modules/jayson": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/jayson/-/jayson-4.3.0.tgz", @@ -13134,9 +14553,6 @@ "version": "5.0.10", "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "extraneous": true, - "hasInstallScript": true, - "license": "MIT", "hasInstallScript": true, "license": "MIT", "optional": true, @@ -14844,6 +16260,16 @@ "js-yaml": "bin/js-yaml.js" } }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.8.0.tgz", + "integrity": "sha512-iZ8Bdb84lWRuGHamRXFyML07r21pcwBrLkHEuHgEY5UbCouBwv7ECknDRKzsQIXMiqpPymqtIf8TC/shYKB5rw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsdom": { "version": "26.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", @@ -15097,6 +16523,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -15131,6 +16564,13 @@ "loose-envify": "cli.js" } }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru_map": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/lru_map/-/lru_map-0.4.1.tgz", @@ -15154,11 +16594,20 @@ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==", "dev": true, "license": "MIT", - "peer": true, "bin": { "lz-string": "bin/bin.js" } }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-dir": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", @@ -15192,6 +16641,13 @@ "tmpl": "1.0.5" } }, + "node_modules/map-or-similar": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/map-or-similar/-/map-or-similar-1.5.0.tgz", + "integrity": "sha512-0aF7ZmVon1igznGI4VS30yugpduQW3y3GkcgGJOp7d8x8QrizhigUxjI/m2UojsXXto+jLAH3KSz+xOJTiORjg==", + "dev": true, + "license": "MIT" + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", @@ -15225,6 +16681,16 @@ "safe-buffer": "^5.1.2" } }, + "node_modules/memoizerific": { + "version": "1.11.3", + "resolved": "https://registry.npmjs.org/memoizerific/-/memoizerific-1.11.3.tgz", + "integrity": "sha512-/EuHYwAPdLtXwAwSZkh/Gutery6pD2KYd44oQLhAvQp/50mpyduZh8Q7PYHXTCJ+wuXxt7oij2LXyIJOOYFPog==", + "dev": true, + "license": "MIT", + "dependencies": { + "map-or-similar": "^1.5.0" + } + }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", @@ -15356,6 +16822,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -15820,6 +17296,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/open": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz", + "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-lazy-prop": "^2.0.0", + "is-docker": "^2.1.1", + "is-wsl": "^2.2.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -15927,6 +17421,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -16025,6 +17526,30 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -16035,6 +17560,16 @@ "node": ">=8" } }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/pbkdf2": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.6.tgz", @@ -16197,6 +17732,19 @@ "node": ">=10.13.0" } }, + "node_modules/polished": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/polished/-/polished-4.3.1.tgz", + "integrity": "sha512-OBatVyC/N7SCW/FaDHrSd+vn0o5cS855TOmYi4OkdWUMSJCET/xip//ch8xGUvtr3i44X9LVyWwQlRMTN3pwSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.17.8" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/possible-typed-array-names": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", @@ -16261,7 +17809,6 @@ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-regex": "^5.0.1", "ansi-styles": "^5.0.0", @@ -16271,6 +17818,16 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, + "node_modules/process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -16659,6 +18216,73 @@ "node": ">=0.10.0" } }, + "node_modules/react-docgen": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/react-docgen/-/react-docgen-7.1.1.tgz", + "integrity": "sha512-hlSJDQ2synMPKFZOsKo9Hi8WWZTC7POR8EmWvTSjow+VDgKzkmjQvFm2fk0tmRw+f0vTOIYKlarR0iL4996pdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.18.9", + "@babel/traverse": "^7.18.9", + "@babel/types": "^7.18.9", + "@types/babel__core": "^7.18.0", + "@types/babel__traverse": "^7.18.0", + "@types/doctrine": "^0.0.9", + "@types/resolve": "^1.20.2", + "doctrine": "^3.0.0", + "resolve": "^1.22.1", + "strip-indent": "^4.0.0" + }, + "engines": { + "node": ">=16.14.0" + } + }, + "node_modules/react-docgen-typescript": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/react-docgen-typescript/-/react-docgen-typescript-2.4.0.tgz", + "integrity": "sha512-ZtAp5XTO5HRzQctjPU0ybY0RRCQO19X/8fxn3w7y2VVTUbGHDKULPTL4ky3vB05euSgG5NpALhEhDPvQ56wvXg==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "typescript": ">= 4.3.x" + } + }, + "node_modules/react-docgen/node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/react-docgen/node_modules/strip-indent": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/react-dom": { "version": "19.2.7", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.7.tgz", @@ -16676,8 +18300,7 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/react-refresh": { "version": "0.17.0", @@ -16726,6 +18349,23 @@ "node": ">= 12.13.0" } }, + "node_modules/recast": { + "version": "0.23.12", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.23.12.tgz", + "integrity": "sha512-dEWRjcINDu/F4l2dYx57ugBtD7HV9KXESyxhzw/MqWLeglJrsjJKqACPyUPg+6AF8mIgm+Zi0dZ3ACoIg+QtpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ast-types": "^0.16.1", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tiny-invariant": "^1.3.3", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, "node_modules/redent": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", @@ -17654,6 +19294,33 @@ "node": ">= 0.4" } }, + "node_modules/storybook": { + "version": "8.6.18", + "resolved": "https://registry.npmjs.org/storybook/-/storybook-8.6.18.tgz", + "integrity": "sha512-p8seiSI6FiVY6P3V0pG+5v7c8pDMehMAFRWEhG5XqIBSQszzOjDnW2rNvm3odoLKfo3V3P6Cs6Hv9ILzymULyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@storybook/core": "8.6.18" + }, + "bin": { + "getstorybook": "bin/index.cjs", + "sb": "bin/index.cjs", + "storybook": "bin/index.cjs" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/storybook" + }, + "peerDependencies": { + "prettier": "^2 || ^3" + }, + "peerDependenciesMeta": { + "prettier": { + "optional": true + } + } + }, "node_modules/stream-browserify": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-3.0.0.tgz", @@ -17718,6 +19385,22 @@ "node": ">=8" } }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -17829,6 +19512,20 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", @@ -17983,6 +19680,13 @@ "real-require": "^0.2.0" } }, + "node_modules/tiny-invariant": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz", + "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==", + "dev": true, + "license": "MIT" + }, "node_modules/tiny-secp256k1": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz", @@ -18056,6 +19760,26 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinyrainbow": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", + "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", + "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/tldts": { "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", @@ -18167,6 +19891,16 @@ "typescript": ">=4.2.0" } }, + "node_modules/ts-dedent": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/ts-dedent/-/ts-dedent-2.3.0.tgz", + "integrity": "sha512-JfJeIHke7y2egdGGgRAvpCwYFUsHlM2gPcrVOxFkznt/4uzQ7HFmvE63iFHVLBJNDuyDOQgijDK/tXH/f6Msjg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.10" + } + }, "node_modules/ts-jest": { "version": "29.4.11", "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.4.11.tgz", @@ -18239,6 +19973,31 @@ "integrity": "sha512-ufKpbmrugz5Aou4wcr5Wc1UUFWOLhq+Fm6qa6P0w0K5Qw2yhaUoiWszhCVuNQyNwrlGiscHOmqYoAox1PtvgjA==", "license": "MIT" }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -18535,6 +20294,20 @@ "node": ">= 4.0.0" } }, + "node_modules/unplugin": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/unplugin/-/unplugin-1.16.1.tgz", + "integrity": "sha512-4/u/j4FrCKdi17jaxuJA0jClGxB1AvU2hw/IuayPc4ay1XGaJs/rbb4v5WKwAjNifjmXK9PIFyuPiaK8azyR9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.14.0", + "webpack-virtual-modules": "^0.6.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/unstorage": { "version": "1.17.5", "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.5.tgz", @@ -18739,6 +20512,20 @@ "node": ">=6.14.2" } }, + "node_modules/util": { + "version": "0.12.5", + "resolved": "https://registry.npmjs.org/util/-/util-0.12.5.tgz", + "integrity": "sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "is-arguments": "^1.0.4", + "is-generator-function": "^1.0.7", + "is-typed-array": "^1.1.3", + "which-typed-array": "^1.1.2" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19079,6 +20866,13 @@ "node": ">=12" } }, + "node_modules/webpack-virtual-modules": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.6.2.tgz", + "integrity": "sha512-66/V2i5hQanC51vBQKPH4aI8NMAcBW59FVBs+rC7eGHupMyfn34q7rZIE+ETlJ+XTevqfUhVVBgSUNSW2flEUQ==", + "dev": true, + "license": "MIT" + }, "node_modules/whatwg-encoding": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", @@ -19272,6 +21066,41 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/wrap-ansi/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", diff --git a/dashboard/package.json b/dashboard/package.json index b0433d9..a4b10e6 100644 --- a/dashboard/package.json +++ b/dashboard/package.json @@ -10,7 +10,9 @@ "lint": "node ./node_modules/eslint/bin/eslint.js \"src/**/*.{ts,tsx}\" --max-warnings=0", "test": "node ./node_modules/jest/bin/jest.js", "test:wallet": "node ./node_modules/jest/bin/jest.js src/__tests__/wallet-integration.test.tsx", - "benchmark": "node ./node_modules/jest/bin/jest.js src/benchmark" + "benchmark": "node ./node_modules/jest/bin/jest.js src/benchmark", + "storybook": "node ./node_modules/storybook/bin/index.cjs dev -p 6006", + "build-storybook": "node ./node_modules/storybook/bin/index.cjs build" }, "dependencies": { "@creit.tech/stellar-wallets-kit": "^2.3.0", @@ -19,13 +21,12 @@ "zustand": "^5.0.6" }, "devDependencies": { - "@typescript-eslint/eslint-plugin": "^6.10.0", - "@typescript-eslint/parser": "^6.10.0", - "eslint": "^8.46.0", - "eslint-plugin-react": "^7.33.0", - "@testing-library/react": "^16.3.0", - "@testing-library/user-event": "^14.6.1", - "@types/jest": "^29.5.14", + "@storybook/addon-essentials": "^8.6.14", + "@storybook/addon-interactions": "^8.6.14", + "@storybook/blocks": "^8.6.14", + "@storybook/react": "^8.6.14", + "@storybook/react-vite": "^8.6.14", + "@storybook/test": "^8.6.14", "@testing-library/jest-dom": "^6.9.1", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", @@ -33,11 +34,16 @@ "@types/jest-axe": "^3.5.9", "@types/react": "^19.1.8", "@types/react-dom": "^19.1.6", + "@typescript-eslint/eslint-plugin": "^6.10.0", + "@typescript-eslint/parser": "^6.10.0", "@vitejs/plugin-react": "^4.7.0", + "eslint": "^8.46.0", + "eslint-plugin-react": "^7.33.0", "jest": "^29.7.0", "jest-axe": "^10.0.0", "jest-environment-jsdom": "^29.7.0", "jsdom": "^26.1.0", + "storybook": "^8.6.14", "ts-jest": "^29.2.5", "typescript": "^5.8.3", "vite": "^6.3.5" diff --git a/dashboard/src/components/EventCard.stories.tsx b/dashboard/src/components/EventCard.stories.tsx new file mode 100644 index 0000000..d14a930 --- /dev/null +++ b/dashboard/src/components/EventCard.stories.tsx @@ -0,0 +1,63 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { EventCard } from './EventCard'; +import { + sampleEvent, + sampleSystemEvent, + sampleWithdrawalEvent, +} from '../stories/fixtures/events'; + +const meta: Meta = { + title: 'Components/EventCard', + component: EventCard, + tags: ['autodocs'], + args: { + event: sampleEvent, + variant: 'compact', + isLoading: false, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Compact: Story = {}; + +export const Expanded: Story = { + args: { + variant: 'expanded', + }, +}; + +export const LoadingCompact: Story = { + args: { + isLoading: true, + event: undefined, + }, +}; + +export const LoadingExpanded: Story = { + args: { + variant: 'expanded', + isLoading: true, + event: undefined, + }, +}; + +export const SystemEvent: Story = { + args: { + event: sampleSystemEvent, + }, +}; + +export const WithdrawalEvent: Story = { + args: { + event: sampleWithdrawalEvent, + variant: 'expanded', + }, +}; + +export const Clickable: Story = { + args: { + onClick: () => undefined, + }, +}; diff --git a/dashboard/src/components/EventExplorerCard.stories.tsx b/dashboard/src/components/EventExplorerCard.stories.tsx new file mode 100644 index 0000000..21c774a --- /dev/null +++ b/dashboard/src/components/EventExplorerCard.stories.tsx @@ -0,0 +1,58 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { EventExplorerCard } from './EventExplorerCard'; +import { sampleEvent, sampleSystemEvent } from '../stories/fixtures/events'; + +const meta: Meta = { + title: 'Components/EventExplorerCard', + component: EventExplorerCard, + tags: ['autodocs'], + args: { + event: sampleEvent, + onCopyContract: () => undefined, + isCopied: false, + contractStatuses: [], + }, + decorators: [ + (Story) => ( +
+
+ +
+
+ ), + ], +}; + +export default meta; +type Story = StoryObj; + +export const Default: Story = {}; + +export const Copied: Story = { + args: { + isCopied: true, + }, +}; + +export const PausedContract: Story = { + args: { + contractStatuses: [ + { + address: sampleEvent.contractAddress, + paused: true, + }, + ], + }, +}; + +export const SystemKind: Story = { + args: { + event: sampleSystemEvent, + }, +}; + +export const Clickable: Story = { + args: { + onSelect: () => undefined, + }, +}; diff --git a/dashboard/src/components/EventExplorerCard.tsx b/dashboard/src/components/EventExplorerCard.tsx index c837c72..ab1e5f9 100644 --- a/dashboard/src/components/EventExplorerCard.tsx +++ b/dashboard/src/components/EventExplorerCard.tsx @@ -71,7 +71,7 @@ export function EventExplorerCard({ aria-label={onSelect ? `View details for ${label} notification` : undefined} >
-
+

{shortenAddress(event.contractAddress)}

diff --git a/dashboard/src/components/ExportHistoryTable.stories.tsx b/dashboard/src/components/ExportHistoryTable.stories.tsx new file mode 100644 index 0000000..50446dd --- /dev/null +++ b/dashboard/src/components/ExportHistoryTable.stories.tsx @@ -0,0 +1,60 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { ExportHistoryTable } from './ExportHistoryTable'; +import type { NotificationExport } from '../utils/exportData'; + +const sampleExports: NotificationExport[] = [ + { + id: 'exp_1', + name: 'System alert notification logs', + format: 'CSV', + status: 'Completed', + createdAt: Date.UTC(2026, 6, 20, 9, 30), + recordCount: 1280, + fileSize: '240 KB', + }, + { + id: 'exp_2', + name: 'Monthly billing export', + format: 'JSON', + status: 'Processing', + createdAt: Date.UTC(2026, 6, 22, 14, 5), + recordCount: 420, + fileSize: '—', + }, + { + id: 'exp_3', + name: 'Webhook delivery metrics', + format: 'PDF', + status: 'Failed', + createdAt: Date.UTC(2026, 6, 23, 18, 40), + recordCount: 0, + fileSize: '—', + }, +]; + +const meta: Meta = { + title: 'Components/ExportHistoryTable', + component: ExportHistoryTable, + tags: ['autodocs'], + args: { + exports: sampleExports, + onDownload: () => undefined, + }, +}; + +export default meta; +type Story = StoryObj; + +export const MixedStatuses: Story = {}; + +export const CompletedOnly: Story = { + args: { + exports: sampleExports.filter((item) => item.status === 'Completed'), + }, +}; + +export const Empty: Story = { + args: { + exports: [], + }, +}; diff --git a/dashboard/src/components/Modal.stories.tsx b/dashboard/src/components/Modal.stories.tsx new file mode 100644 index 0000000..434fa38 --- /dev/null +++ b/dashboard/src/components/Modal.stories.tsx @@ -0,0 +1,76 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { useState } from 'react'; +import { Modal } from './Modal'; + +const meta: Meta = { + title: 'Components/Modal', + component: Modal, + tags: ['autodocs'], + args: { + isOpen: true, + title: 'Preview notification', + children: 'Modal body content for design review.', + size: 'medium', + }, + argTypes: { + onClose: { action: 'closed' }, + size: { + control: 'select', + options: ['small', 'medium', 'large'], + }, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Medium: Story = {}; + +export const Small: Story = { + args: { + size: 'small', + title: 'Confirm action', + children: 'This is a compact confirmation dialog.', + }, +}; + +export const Large: Story = { + args: { + size: 'large', + title: 'Notification template details', + children: + 'Large modal variation for richer previews, variable editors, and payload inspection.', + }, +}; + +export const WithFooter: Story = { + args: { + title: 'Send preview', + children: 'Review the rendered template before dispatching.', + footer: ( + <> + + + + ), + }, +}; + +export const Interactive: Story = { + render: function InteractiveModal(args) { + const [isOpen, setIsOpen] = useState(true); + + return ( +
+ + setIsOpen(false)} /> +
+ ); + }, +}; diff --git a/dashboard/src/components/PaginationControls.stories.tsx b/dashboard/src/components/PaginationControls.stories.tsx new file mode 100644 index 0000000..2563abf --- /dev/null +++ b/dashboard/src/components/PaginationControls.stories.tsx @@ -0,0 +1,64 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { useState } from 'react'; +import { PaginationControls } from './PaginationControls'; + +const meta: Meta = { + title: 'Components/PaginationControls', + component: PaginationControls, + tags: ['autodocs'], + args: { + page: 2, + pageCount: 8, + limit: 12, + totalCount: 96, + onPageChange: () => undefined, + onLimitChange: () => undefined, + }, +}; + +export default meta; +type Story = StoryObj; + +export const MiddlePage: Story = {}; + +export const FirstPage: Story = { + args: { + page: 1, + }, +}; + +export const LastPage: Story = { + args: { + page: 8, + }, +}; + +export const CustomPageSizes: Story = { + args: { + pageSizeOptions: [5, 10, 25], + limit: 10, + summaryLabel: 'exports', + }, +}; + +export const Interactive: Story = { + render: function InteractivePagination(args) { + const [page, setPage] = useState(args.page); + const [limit, setLimit] = useState(args.limit); + const pageCount = Math.max(1, Math.ceil(args.totalCount / limit)); + + return ( + { + setLimit(nextLimit); + setPage(1); + }} + /> + ); + }, +}; diff --git a/dashboard/src/components/ThemeToggle.stories.tsx b/dashboard/src/components/ThemeToggle.stories.tsx new file mode 100644 index 0000000..20e2518 --- /dev/null +++ b/dashboard/src/components/ThemeToggle.stories.tsx @@ -0,0 +1,40 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { useState } from 'react'; +import { ThemeToggle } from './ThemeToggle'; +import type { Theme } from '../hooks/useTheme'; + +const meta: Meta = { + title: 'Components/ThemeToggle', + component: ThemeToggle, + tags: ['autodocs'], +}; + +export default meta; +type Story = StoryObj; + +export const Dark: Story = { + args: { + theme: 'dark', + onToggle: () => undefined, + }, +}; + +export const Light: Story = { + args: { + theme: 'light', + onToggle: () => undefined, + }, +}; + +export const Interactive: Story = { + render: function InteractiveThemeToggle() { + const [theme, setTheme] = useState('dark'); + + return ( + setTheme((current) => (current === 'dark' ? 'light' : 'dark'))} + /> + ); + }, +}; diff --git a/dashboard/src/components/WebhookSummaryCards.stories.tsx b/dashboard/src/components/WebhookSummaryCards.stories.tsx new file mode 100644 index 0000000..3c88e04 --- /dev/null +++ b/dashboard/src/components/WebhookSummaryCards.stories.tsx @@ -0,0 +1,48 @@ +import type { Meta, StoryObj } from '@storybook/react'; +import { WebhookSummaryCards } from './WebhookSummaryCards'; +import type { WebhookSummaryMetrics } from '../types/webhook'; + +const filledSummary: WebhookSummaryMetrics = { + totalAttempts: 1842, + successCount: 1760, + failedCount: 82, + successRate: 95.55, + avgLatencyMs: 186, + p95LatencyMs: 412, +}; + +const strugglingSummary: WebhookSummaryMetrics = { + totalAttempts: 640, + successCount: 410, + failedCount: 230, + successRate: 64.06, + avgLatencyMs: 890, + p95LatencyMs: 2100, +}; + +const meta: Meta = { + title: 'Components/WebhookSummaryCards', + component: WebhookSummaryCards, + tags: ['autodocs'], + args: { + summary: filledSummary, + isLoading: false, + }, +}; + +export default meta; +type Story = StoryObj; + +export const Filled: Story = {}; + +export const Loading: Story = { + args: { + isLoading: true, + }, +}; + +export const DegradedPerformance: Story = { + args: { + summary: strugglingSummary, + }, +}; diff --git a/dashboard/src/index.css b/dashboard/src/index.css index 2cfb1ef..9ea732d 100644 --- a/dashboard/src/index.css +++ b/dashboard/src/index.css @@ -1662,6 +1662,7 @@ body { /* Compact layout */ .event-card--compact { padding: 12px 16px; + min-width: 0; } .event-card--compact .event-card__primary { @@ -1670,15 +1671,20 @@ body { align-items: center; gap: 12px; margin-bottom: 6px; + flex-wrap: wrap; + min-width: 0; } .event-card--compact .event-card__meta, .event-card--compact .event-card__details { display: flex; justify-content: space-between; + align-items: center; gap: 12px; font-size: 0.82rem; color: #9aa0a6; + flex-wrap: wrap; + min-width: 0; } .event-card--compact .event-card__details { @@ -1689,16 +1695,21 @@ body { color: #9aa0a6; font-size: 0.82rem; white-space: nowrap; + flex-shrink: 0; } .event-card__address, .event-card__time { font-family: 'Courier New', Courier, monospace; + min-width: 0; + overflow: hidden; + text-overflow: ellipsis; } /* Expanded layout */ .event-card--expanded { padding: 20px; + min-width: 0; } .event-card__header { @@ -1707,6 +1718,8 @@ body { align-items: flex-start; gap: 12px; margin-bottom: 16px; + flex-wrap: wrap; + min-width: 0; } .event-card__title { @@ -1714,6 +1727,8 @@ body { font-size: 1.1rem; font-weight: 600; line-height: 1.3; + min-width: 0; + overflow-wrap: anywhere; } .event-card__body { @@ -1732,6 +1747,7 @@ body { grid-template-columns: 88px 1fr; gap: 8px; align-items: baseline; + min-width: 0; } .event-card__field dt { @@ -1776,12 +1792,34 @@ body { /* Event type badge */ .event-card__badge { display: inline-block; + max-width: 100%; padding: 2px 10px; border-radius: 999px; font-size: 0.75rem; font-weight: 600; letter-spacing: 0.03em; white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + flex-shrink: 1; +} + +@media (max-width: 600px) { + .event-card--compact .event-card__primary, + .event-card--compact .event-card__meta, + .event-card--compact .event-card__details { + flex-direction: column; + align-items: flex-start; + } + + .event-card__field { + grid-template-columns: 1fr; + gap: 4px; + } + + .event-card__header { + align-items: flex-start; + } } .event-card__badge--green { @@ -1982,6 +2020,13 @@ body { } .drawer__eyebrow { + margin: 0 0 6px; + font-size: 0.75rem; + letter-spacing: 0.08em; + text-transform: uppercase; + color: #60a5fa; +} + .indexing-health { border: 1px solid rgba(255, 255, 255, 0.08); border-radius: 16px; @@ -2261,6 +2306,11 @@ body { } .drawer__error { + margin: 0; + color: #f87171; + font-size: 0.9rem; +} + .indexing-health__error { margin: 0; color: #f87171; @@ -2398,6 +2448,22 @@ body { min-width: 0; } +.event-explorer__contract-block { + display: flex; + flex-direction: column; + gap: 8px; + min-width: 0; + width: 100%; +} + +.event-explorer__contract-actions { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 8px; + min-width: 0; +} + .event-explorer__contract { margin: 0; font-family: 'Courier New', Courier, monospace; @@ -2630,14 +2696,17 @@ body { .event-explorer__row { padding: 18px; border-top: 1px solid rgba(255, 255, 255, 0.06); + align-items: stretch; } .event-explorer__cell { flex-direction: row; justify-content: space-between; - gap: 8px; + align-items: flex-start; + gap: 12px; margin-bottom: 12px; width: 100%; + min-width: 0; } .event-explorer__cell:last-child { @@ -2650,6 +2719,28 @@ body { font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; + flex-shrink: 0; + } + + .event-explorer__cell[data-label="Contract"] { + flex-direction: column; + align-items: stretch; + } + + .event-explorer__contract-block { + width: 100%; + } + + .event-explorer__contract-actions { + width: 100%; + } + + .event-explorer__event-name, + .event-explorer__cell > span, + .event-explorer__cell > time { + min-width: 0; + text-align: right; + overflow-wrap: anywhere; } .event-explorer__table-header { @@ -2675,6 +2766,12 @@ body { } .nav-tabs { + display: flex; + gap: 8px; + flex-wrap: wrap; + align-items: center; +} + /* ── Notification Delivery Timeline ─────────────────────────────────────── */ .timeline-view { @@ -3417,17 +3514,20 @@ body { gap: 12px; margin-bottom: 6px; flex-wrap: wrap; + padding-right: 16px; } .activity-event__type { font-weight: 600; font-size: 0.9rem; text-transform: capitalize; + min-width: 0; } .activity-event__time { font-size: 0.8rem; color: #9aa0a6; + flex-shrink: 0; } .activity-event__message { @@ -3675,6 +3775,16 @@ body { } .webhook-filters__select { + border: 1px solid rgba(255, 255, 255, 0.12); + border-radius: 8px; + padding: 8px 10px; + background: #12151c; + color: inherit; + font-size: 0.9rem; + min-width: 140px; + cursor: pointer; +} + /* ── Export History filters ─────────────────────────────────────────────── */ /* @@ -4194,6 +4304,7 @@ body { @media (max-width: 420px) { .webhook-summary-cards { grid-template-columns: 1fr; + } } /* ── Export table: action cell ──────────────────────────────────────────── */ @@ -4220,6 +4331,8 @@ body { max-width: 1100px; margin: 0 auto; padding: 24px; +} + @media (max-width: 600px) { /* Stack rows as definition lists on very small screens */ .export-table, diff --git a/dashboard/src/stories/fixtures/events.ts b/dashboard/src/stories/fixtures/events.ts new file mode 100644 index 0000000..041ed87 --- /dev/null +++ b/dashboard/src/stories/fixtures/events.ts @@ -0,0 +1,32 @@ +import type { BlockchainEvent } from '../../types/event'; + +export const sampleEvent: BlockchainEvent = { + eventId: 'evt_notify_001', + contractAddress: 'CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC', + eventName: 'TaskCreated', + ledger: 512_348, + type: 'contract', + topic: ['task', 'created'], + value: '10000000', + txHash: 'a1b2c3d4e5f60718293a4b5c6d7e8f901234567890abcdef1234567890abcd', + receivedAt: Date.UTC(2026, 6, 24, 12, 0, 0), + notificationStatus: 'active', + read: false, +}; + +export const sampleSystemEvent: BlockchainEvent = { + ...sampleEvent, + eventId: 'evt_sys_002', + eventName: 'NotificationExpired', + type: 'system', + notificationStatus: 'expired', + value: '0', +}; + +export const sampleWithdrawalEvent: BlockchainEvent = { + ...sampleEvent, + eventId: 'evt_fin_003', + eventName: 'Withdrawal', + type: 'contract', + value: '2500000', +}; diff --git a/docs/MONITORING_INTEGRATION.md b/docs/MONITORING_INTEGRATION.md index 57f57fa..f89d8b9 100644 --- a/docs/MONITORING_INTEGRATION.md +++ b/docs/MONITORING_INTEGRATION.md @@ -2,7 +2,7 @@ ## ⚠️ Critical: Avoiding Double-Counting in Metrics -This guide explains how to integrate with Notify-Chain's notification metrics **without double-counting retries**. +This guide explains how to integrate with NotifyChain's notification metrics **without double-counting retries**. --- @@ -29,7 +29,7 @@ Notification ID: 100 **Endpoint**: `GET /api/schedule/execution-metrics` ```bash -curl http://localhost:3000/api/schedule/execution-metrics +curl http://localhost:8787/api/schedule/execution-metrics ``` **Response**: @@ -86,7 +86,7 @@ But if you're counting all log entries for that notification, you might count 3 scrape_configs: - job_name: 'notify-chain' static_configs: - - targets: ['localhost:3000'] + - targets: ['localhost:8787'] metrics_path: '/api/schedule/execution-metrics' scrape_interval: 30s ``` @@ -196,7 +196,7 @@ import requests class NotifyChainCheck(AgentCheck): def check(self, instance): - url = instance.get('url', 'http://localhost:3000/api/schedule/execution-metrics') + url = instance.get('url', 'http://localhost:8787/api/schedule/execution-metrics') try: response = requests.get(url, timeout=5) @@ -228,7 +228,7 @@ class NotifyChainCheck(AgentCheck): init_config: instances: - - url: http://localhost:3000/api/schedule/execution-metrics + - url: http://localhost:8787/api/schedule/execution-metrics min_collection_interval: 30 ``` @@ -244,7 +244,7 @@ const cloudwatch = new AWS.CloudWatch(); exports.handler = async (event) => { try { - const metrics = await fetchMetrics('http://notify-chain:3000/api/schedule/execution-metrics'); + const metrics = await fetchMetrics('http://notify-chain:8787/api/schedule/execution-metrics'); const totalSuccess = metrics.successfulFirstAttempt + metrics.successfulAfterRetry; const successRate = metrics.totalNotifications > 0 @@ -318,7 +318,7 @@ function fetchMetrics(url) { ```json { "dashboard": { - "title": "Notify-Chain Metrics", + "title": "NotifyChain Metrics", "panels": [ { "title": "Success Rate", @@ -525,7 +525,7 @@ index=notify-chain "Notification marked as completed" ```bash # Create a notification that will succeed on first attempt -curl -X POST http://localhost:3000/api/schedule \ +curl -X POST http://localhost:8787/api/schedule \ -H "Content-Type: application/json" \ -d '{ "notificationType": "discord", @@ -542,7 +542,7 @@ curl -X POST http://localhost:3000/api/schedule \ ```bash # Fetch metrics -curl http://localhost:3000/api/schedule/execution-metrics | jq +curl http://localhost:8787/api/schedule/execution-metrics | jq # Expected output structure: # { @@ -563,7 +563,7 @@ curl http://localhost:3000/api/schedule/execution-metrics | jq # Stop Discord service to force failures # Then create notification - it will retry and eventually fail -curl -X POST http://localhost:3000/api/schedule \ +curl -X POST http://localhost:8787/api/schedule \ -H "Content-Type: application/json" \ -d '{ "notificationType": "discord", @@ -578,7 +578,7 @@ curl -X POST http://localhost:3000/api/schedule \ # Wait for retries to complete (2-3 minutes) # Check metrics again -curl http://localhost:3000/api/schedule/execution-metrics | jq +curl http://localhost:8787/api/schedule/execution-metrics | jq # Should show: # { diff --git a/docs/notifications/lifecycle.md b/docs/notifications/lifecycle.md index ec5fd02..1efe603 100644 --- a/docs/notifications/lifecycle.md +++ b/docs/notifications/lifecycle.md @@ -8,6 +8,8 @@ ## Overview +See also the root lifecycle guide: [`NOTIFICATION_LIFECYCLE.md`](../../NOTIFICATION_LIFECYCLE.md). + The NotifyChain notification system is a robust, multi-component system designed to capture events from Soroban smart contracts, deliver them to configured destinations, and track their entire lifecycle for auditing and debugging purposes. This document describes: