diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000000000000000000000000000000000..ce9a06efc528d1f61406c86cfdc2a2df40c40450 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,65 @@ +# Git +.git +.gitignore + +# Python +__pycache__ +*.py[cod] +*$py.class +*.so +.Python +.venv +venv +env +.env +*.egg-info +dist +build +.eggs + +# Node +node_modules +.npm +.pnpm-store + +# IDE +.idea +.vscode +*.swp +*.swo + +# Testing +.pytest_cache +.coverage +htmlcov +.tox + +# Documentation (not needed in image) +docs + +# Development files +*.log +.DS_Store +Thumbs.db + +# Notebooks (not needed for deployment) +notebooks +*.ipynb + +# POC code +poc + +# Local data +*.lancedb +data/ + +# Frontend build output (we build fresh) +frontend/out +frontend/.next +frontend/node_modules + +# hyper-scatter (built separately if present) +hyper-scatter + +# Assets (README images) +assets diff --git a/.github/workflows/devin-review.yml b/.github/workflows/devin-review.yml new file mode 100644 index 0000000000000000000000000000000000000000..5754ba553114442658c63d12274b5cb2ce8b0afd --- /dev/null +++ b/.github/workflows/devin-review.yml @@ -0,0 +1,23 @@ +name: Devin Review + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + devin-review: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + + - name: Run Devin Review + run: npx devin-review ${{ github.event.pull_request.html_url }} diff --git a/.github/workflows/require_frontend_export.yml b/.github/workflows/require_frontend_export.yml new file mode 100644 index 0000000000000000000000000000000000000000..00363fed53f7a60a8ca2cc598f530aebc8f36e8f --- /dev/null +++ b/.github/workflows/require_frontend_export.yml @@ -0,0 +1,53 @@ +name: Require Frontend Export + +on: + pull_request: + types: [opened, synchronize, reopened] + paths: + - "frontend/**" + - "scripts/export_frontend.sh" + - "src/hyperview/server/static/**" + +jobs: + require-frontend-export: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + ref: ${{ github.event.pull_request.head.sha }} + + - name: Verify static export updated when frontend changes + run: | + set -euo pipefail + + base_sha="${{ github.event.pull_request.base.sha }}" + head_sha="${{ github.event.pull_request.head.sha }}" + + changed_files="$(git diff --name-only "$base_sha" "$head_sha")" + + echo "Changed files:" + echo "$changed_files" + + frontend_changed="false" + static_changed="false" + + if echo "$changed_files" | grep -qE '^(frontend/|scripts/export_frontend\.sh$)'; then + frontend_changed="true" + fi + + if echo "$changed_files" | grep -q '^src/hyperview/server/static/'; then + static_changed="true" + fi + + if [[ "$frontend_changed" == "true" && "$static_changed" != "true" ]]; then + echo "" + echo "ERROR: frontend/ changed but src/hyperview/server/static/ was not updated." + echo "Run: bash scripts/export_frontend.sh" + echo "Then commit the updated src/hyperview/server/static/ output." + exit 1 + fi + + echo "OK: export requirements satisfied." diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5b94b3caacc9cabd4bf6357cec4f5b5804a4a441 --- /dev/null +++ b/.gitignore @@ -0,0 +1,74 @@ +# Python +__pycache__/ +*.pyc +*.pyo +*.pyd +.Python +env/ +venv/ +.venv/ +/uv.lock +*.egg-info/ +.pytest_cache/ +.coverage +htmlcov/ + +# Jupyter Notebooks +.ipynb_checkpoints + +# macOS +.DS_Store + +# VS Code +.vscode/ + +# Generated assets +assets/demo_animation_frames/ +*.gif + +# Frontend +frontend/node_modules/ +frontend/.next/ +frontend/out/ + +# Bundled frontend in Python package (built with scripts/export_frontend.sh) +# Not ignored - needed for pip install from git / sdist +# src/hyperview/server/static/ + +# Python package build +dist/ +build/ +*.egg-info/ + +# Data cache +*.hf/ +.cache/ + +# external repo (https://github.com/Hyper3Labs/hyper-scatter) +hyper-scatter/ + +# nohup +nohup.out +frontend/nohup.out + +# Local logs / tool artifacts +.hyperview-*.log +.hyperview-*.pid +.playwright-mcp/ +frontend/tsconfig.tsbuildinfo + +# Hyperbolic model zoo (kept as a separate repo) +hyper_model_zoo/ +hyper_models/ +scripts_ignored/ + +# AI Context (Agent files) +.claude/ +context/ +CLAUDE.md +TASKS.md +TESTS.md +AGENTS.md +**/AGENTS.md +.github/agents/ +.specstory/ \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..aba33680285c7d833a0180ffd1b5d43e7f3c4151 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,123 @@ +# ============================================================================= +# HyperView - Hugging Face Spaces Dockerfile +# ============================================================================= +# Multi-stage build for deploying HyperView to HuggingFace Spaces. +# +# Features: +# - CLIP embeddings (Euclidean) via embed-anything +# - HyCoCLIP embeddings (Hyperbolic) via hyper-models ONNX +# - Pre-computed demo dataset (300 CIFAR-10 samples) +# - Torch-free runtime for minimal image size +# +# Deploy: https://huggingface.co/spaces/Hyper3Labs/HyperView +# ============================================================================= + +# ----------------------------------------------------------------------------- +# Stage 1: Build Frontend (Next.js static export) +# ----------------------------------------------------------------------------- +FROM node:20-slim AS frontend-builder + +WORKDIR /app/frontend + +# Install dependencies first (better caching) +COPY frontend/package.json frontend/package-lock.json ./ +RUN npm ci --prefer-offline + +# Build hyper-scatter (installed from source tarball, dist-lib not prebuilt) +RUN cd node_modules/hyper-scatter \ + && npm install \ + && npm run build:lib + +# Copy frontend source and build +COPY frontend/ ./ +RUN npm run build + +# Verify output exists +RUN ls -la out/ && echo "Frontend build complete" + +# ----------------------------------------------------------------------------- +# Stage 2: Python Runtime +# ----------------------------------------------------------------------------- +FROM python:3.11-slim AS runtime + +# Install system dependencies +RUN apt-get update && apt-get install -y --no-install-recommends \ + build-essential \ + curl \ + git \ + libssl-dev \ + pkg-config \ + && rm -rf /var/lib/apt/lists/* + +# HuggingFace Spaces requirement: create user with UID 1000 +RUN useradd -m -u 1000 user + +# Switch to user +USER user + +# Set environment variables +ENV HOME=/home/user \ + PATH=/home/user/.local/bin:$PATH \ + HF_HOME=/home/user/.cache/huggingface \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 + +WORKDIR $HOME/app + +# Upgrade pip +RUN pip install --upgrade pip + +# Copy Python package files +COPY --chown=user pyproject.toml README.md LICENSE ./ +COPY --chown=user src/ ./src/ +COPY --chown=user scripts/ ./scripts/ + +# Install Python package (without ML extras - we use ONNX) +RUN pip install -e . + +# Copy built frontend to static directory +COPY --from=frontend-builder --chown=user /app/frontend/out ./src/hyperview/server/static/ + +# Verify frontend is in place +RUN ls -la src/hyperview/server/static/ && echo "Frontend copied successfully" + +# ----------------------------------------------------------------------------- +# Stage 3: Pre-compute Demo Dataset +# ----------------------------------------------------------------------------- +# Create output directories +RUN mkdir -p $HOME/app/demo_data/datasets $HOME/app/demo_data/media + +# Set environment for precomputation +ENV HYPERVIEW_DATASETS_DIR=/home/user/app/demo_data/datasets \ + HYPERVIEW_MEDIA_DIR=/home/user/app/demo_data/media \ + DEMO_SAMPLES=300 + +# Pre-download HuggingFace models and compute embeddings +# This runs during build to ensure fast startup +RUN python scripts/precompute_hf_demo.py + +# Verify dataset was created +RUN ls -la demo_data/ && echo "Demo dataset pre-computed successfully" + +# ----------------------------------------------------------------------------- +# Final Configuration +# ----------------------------------------------------------------------------- +# Copy entrypoint +COPY --chown=user app_hf.py ./ + +# Set runtime environment +ENV HOST=0.0.0.0 \ + PORT=7860 \ + DEMO_DATASET=cifar10_hf_demo \ + HYPERVIEW_DATASETS_DIR=/home/user/app/demo_data/datasets \ + HYPERVIEW_MEDIA_DIR=/home/user/app/demo_data/media + +# Expose port (HuggingFace Spaces default) +EXPOSE 7860 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD curl -f http://localhost:7860/__hyperview__/health || exit 1 + +# Start server +CMD ["python", "app_hf.py"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..10525a575ac979aefbca7e84e1c1e834dbf9be89 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Matin Mahmood + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index a9dd69fcfe17f9453e33a722b0426f19cb136d4f..8c59b2bac4bac672cc83a8f41f845fc8a57c1307 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,155 @@ --- title: HyperView -emoji: 😻 -colorFrom: blue -colorTo: indigo +emoji: 🔮 +colorFrom: purple +colorTo: blue sdk: docker +app_port: 7860 pinned: false -license: apache-2.0 -short_description: 'dataset curation + embedding visualization ' +tags: + - data-visualization + - embeddings + - hyperbolic + - poincare + - clip + - dataset-curation + - computer-vision + - umap +short_description: Dataset visualization with Euclidean & hyperbolic embeddings +models: + - openai/clip-vit-base-patch32 + - mnm-matin/hyperbolic-clip +datasets: + - uoft-cs/cifar10 --- -Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference +# HyperView + +> **Open-source dataset curation + embedding visualization (Euclidean + Poincaré disk)** + +[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Hyper3Labs/HyperView) [![Hugging Face Spaces](https://img.shields.io/badge/%F0%9F%A4%97%20Hugging%20Face-Spaces-blue)](https://huggingface.co/spaces/Hyper3Labs/HyperView) + +

+ + HyperView Screenshot + +
+ Watch the Demo Video +

+ +--- + +## Try it Online + +**[Launch HyperView on Hugging Face Spaces](https://huggingface.co/spaces/Hyper3Labs/HyperView)** - no installation required! + +The demo showcases: +- 300 CIFAR-10 images with pre-computed embeddings +- CLIP embeddings visualized in Euclidean space (UMAP) +- HyCoCLIP embeddings visualized on the Poincaré disk + +--- + +## Features + +- **Dual-Panel UI**: Image grid + scatter plot with bidirectional selection +- **Euclidean/Poincaré Toggle**: Switch between standard 2D UMAP and Poincaré disk visualization +- **HuggingFace Integration**: Load datasets directly from HuggingFace Hub +- **Fast Embeddings**: Uses EmbedAnything for CLIP-based image embeddings + +## Quick Start + +**Docs:** [docs/datasets.md](docs/datasets.md) · [docs/colab.md](docs/colab.md) · [CONTRIBUTING.md](CONTRIBUTING.md) · [TESTS.md](TESTS.md) + +### Installation + +```bash +git clone https://github.com/Hyper3Labs/HyperView.git +cd HyperView + +# Install with uv +uv venv .venv +source .venv/bin/activate +uv pip install -e ".[dev]" +``` + +### Run the Demo + +```bash +hyperview demo --samples 500 +``` + +This will: +1. Load 500 samples from CIFAR-100 +2. Compute CLIP embeddings +3. Generate Euclidean and Poincaré visualizations +4. Start the server at **http://127.0.0.1:6262** + +### Python API + +```python +import hyperview as hv + +# Create dataset +dataset = hv.Dataset("my_dataset") + +# Load from HuggingFace +dataset.add_from_huggingface( + "uoft-cs/cifar100", + split="train", + max_samples=1000 +) + +# Or load from local directory +# dataset.add_images_dir("/path/to/images", label_from_folder=True) + +# Compute embeddings and visualization +dataset.compute_embeddings() +dataset.compute_visualization() + +# Launch the UI +hv.launch(dataset) # Opens http://127.0.0.1:6262 +``` + +### Google Colab + +See [docs/colab.md](docs/colab.md) for a fast Colab smoke test and notebook-friendly launch behavior. + +### Save and Load Datasets + +```python +# Save dataset with embeddings +dataset.save("my_dataset.json") + +# Load later +dataset = hv.Dataset.load("my_dataset.json") +hv.launch(dataset) +``` + +## Why Hyperbolic? + +Traditional Euclidean embeddings struggle with hierarchical data. In Euclidean space, volume grows polynomially ($r^d$), causing **Representation Collapse** where minority classes get crushed together. + +**Hyperbolic space** (Poincaré disk) has exponential volume growth ($e^r$), naturally preserving hierarchical structure and keeping rare classes distinct. + +

+ Euclidean vs Hyperbolic +

+ +## Contributing + +Development setup, frontend hot-reload, and backend API notes live in [CONTRIBUTING.md](CONTRIBUTING.md). + +## Related projects + +- **hyper-scatter**: High-performance WebGL scatterplot engine (Euclidean + Poincaré) used by the frontend: https://github.com/Hyper3Labs/hyper-scatter +- **hyper-models**: Non-Euclidean model zoo + ONNX exports (e.g. for hyperbolic VLM experiments): https://github.com/Hyper3Labs/hyper-models + +## References + +- [Poincaré Embeddings for Learning Hierarchical Representations](https://arxiv.org/abs/1705.08039) (Nickel & Kiela, 2017) +- [Hyperbolic Neural Networks](https://arxiv.org/abs/1805.09112) (Ganea et al., 2018) + +## License + +MIT License - see [LICENSE](LICENSE) for details. diff --git a/app_hf.py b/app_hf.py new file mode 100644 index 0000000000000000000000000000000000000000..bff5ce62fa8345b2ff9fc5c11df75d7aba1de85d --- /dev/null +++ b/app_hf.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python +"""Hugging Face Spaces entrypoint for HyperView. + +This script serves a pre-computed demo dataset stored in LanceDB. +The dataset is computed at Docker build time by scripts/precompute_hf_demo.py. + +For HuggingFace Spaces deployment under Hyper3Labs/HyperView. +""" + +import os + +# Configuration from environment +HOST = os.environ.get("HOST", "0.0.0.0") +PORT = int(os.environ.get("PORT", 7860)) +DATASET_NAME = os.environ.get("DEMO_DATASET", "cifar10_hf_demo") + + +def main() -> None: + """Load pre-computed dataset and launch server.""" + import hyperview as hv + + dataset = hv.Dataset(DATASET_NAME) + + spaces = dataset.list_spaces() + layouts = dataset.list_layouts() + + if not spaces or not layouts: + print("Pre-computed embeddings not found in storage.") + print("Falling back to computing on startup (this will be slow)...") + + from scripts.precompute_hf_demo import create_demo_dataset + + dataset = create_demo_dataset() + else: + print(f"Loaded dataset '{DATASET_NAME}' with pre-computed embeddings") + + print(f"\nStarting HyperView server on {HOST}:{PORT}") + print("=" * 50) + + hv.launch( + dataset, + host=HOST, + port=PORT, + open_browser=False, + ) + + +if __name__ == "__main__": + main() diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000000000000000000000000000000000000..ff421e142bd24313b8be61ee69d76402275d52e2 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,54 @@ +# HyperView System Architecture + +## The Integrated Pipeline Approach + +HyperView is built as a three-stage pipeline that turns raw multimodal data into an interactive, fairness-aware view of a dataset. Each stage uses the tool best suited for the job: + +* **Ingestion – Python (PyTorch/Geoopt):** Differentiable manifold operations and training of the Hyperbolic Adapter. +* **Storage & Retrieval – Rust (Qdrant):** Low-latency vector search with a custom Poincaré distance metric. +* **Visualization – Browser (WebGL/Deck.gl):** GPU-accelerated rendering of the Poincaré disk in the browser. + +## System Diagram + +

+ HyperView System Architecture: The Integrated Pipeline Approach +

+ +## Component Breakdown + +### 1. Ingestion: Hyperbolic Adapter (Python) +* **Role:** The bridge between flat (Euclidean) model embeddings and curved (hyperbolic) space. +* **Input:** Raw data (images/text) → standard model embeddings (e.g. CLIP/ResNet vectors). +* **Tech:** PyTorch, Geoopt. +* **Function:** + * Learns a small Hyperbolic Adapter using differentiable manifold operations. + * Uses the exponential map (`expmap0`) to project Euclidean vectors into the Poincaré ball. + * This is where minority and rare cases are expanded away from the crowded center so they remain distinguishable. + +### 2. Storage & Retrieval: Vector Engine (Rust / Qdrant) +* **Role:** The memory that stores and retrieves hyperbolic embeddings at scale. +* **Tech:** Qdrant (forked/extended in Rust). +* **Challenge:** Standard vector DBs only support dot, cosine, or Euclidean distance. +* **Solution:** + * Implement a custom `PoincareDistance` metric in Rust: + $$d(u, v) = \text{arccosh}\left(1 + 2 \frac{\lVert u - v\rVert^2}{(1 - \lVert u\rVert^2)(1 - \lVert v\rVert^2)}\right)$$ + * Plug this metric into Qdrant’s HNSW index for fast nearest-neighbor search in hyperbolic space. + * This allows search results to respect the hierarchy in the data instead of collapsing the long tail. + +### 3. Visualization: Poincaré Disk Viewer (WebGL) +* **Role:** The lens that lets humans explore the structure of the dataset. +* **Tech:** React, Deck.gl, custom WebGL shaders. +* **Challenge:** Rendering 1M points in non-Euclidean geometry directly in the browser. +* **Solution:** + * Send raw hyperbolic coordinates to the GPU and render them directly onto the Poincaré disk using a custom shader (no CPU-side projection). + * Provide pan/zoom/selection so curators can inspect minority clusters, isolate rare subgroups at the boundary, and export curated subsets. + +## Data Flow: The Fairness Pipeline + +1. **Ingest:** User uploads a dataset (e.g. medical images, biodiversity data). +2. **Embed:** Standard models (CLIP/ResNet/Whisper) produce Euclidean embeddings. +3. **Expand:** The Hyperbolic Adapter projects them into the Poincaré ball; rare cases move towards the boundary instead of being crushed. +4. **Index:** Qdrant stores these hyperbolic vectors with the custom Poincaré distance metric. +5. **Query:** A user clicks on a minority example or defines a region of interest. +6. **Search:** Qdrant returns semantic neighbors according to Poincaré distance, preserving the hierarchy between majority, minority, and rare subgroups. +7. **Visualize & Curate:** The browser renders the Poincaré disk, highlighting clusters and long-tail regions so users can see gaps, remove duplicates, and build fairer training sets. diff --git a/docs/colab.md b/docs/colab.md new file mode 100644 index 0000000000000000000000000000000000000000..eef4e27920ac939b547a28bca7bfd98f7036ade7 --- /dev/null +++ b/docs/colab.md @@ -0,0 +1,37 @@ +# Running HyperView in Google Colab + +HyperView works natively in Google Colab. Because Colab runs on a remote VM, you cannot access `localhost` directly. HyperView handles this automatically. + +## Usage + +### 1. Install HyperView + +```bash +!pip install -q git+https://github.com/Hyper3Labs/HyperView.git +``` + +### 2. Launch the visualizer + +When you run `hv.launch()`, a button labeled **“Open HyperView in a new tab”** will appear in the output. Click it to open the visualization. + +```python +# Minimal example +import numpy as np +import hyperview as hv +from hyperview.core.sample import SampleFromArray + +dataset = hv.Dataset("colab_smoke", persist=False) + +rng = np.random.default_rng(0) +for i in range(200): + img = (rng.random((64, 64, 3)) * 255).astype(np.uint8) + sample = SampleFromArray.from_array(id=f"s{i}", image_array=img, label="demo") + sample.embedding_2d = [float(rng.normal()), float(rng.normal())] # Dummy 2D points + dataset.add_sample(sample) + +hv.launch(dataset) +``` + +## Technical Details + +To support Colab, HyperView uses `google.colab.kernel.proxyPort` to expose the backend server. The UI is opened via a specially constructed "launcher" page that embeds the proxied application in a full-page iframe. This workaround ensures compatibility with modern browser security policies (like third-party cookie blocking) that often break direct proxy URLs. diff --git a/docs/datasets.md b/docs/datasets.md new file mode 100644 index 0000000000000000000000000000000000000000..f147fe5a247c7645a4f7a7141c5e0577be771c8c --- /dev/null +++ b/docs/datasets.md @@ -0,0 +1,96 @@ +# Datasets + +## Creating a Dataset + +```python +import hyperview as hv + +# Persistent dataset (default) - survives restarts +dataset = hv.Dataset("my_dataset") + +# In-memory dataset - lost when process exits +dataset = hv.Dataset("my_dataset", persist=False) +``` + +**Storage location:** `~/.hyperview/datasets/` (configurable via `HYPERVIEW_DATABASE_DIR`) + +Internally, each dataset is stored as two Lance tables (directories) inside that folder: +- `hyperview_{dataset_name}.lance/` (samples) +- `hyperview_{dataset_name}_meta.lance/` (metadata like label colors) + +## Adding Samples + +### From HuggingFace +```python +dataset.add_from_huggingface( + "uoft-cs/cifar100", + split="train", + image_key="img", + label_key="fine_label", + max_samples=1000, +) +``` + +### From Directory +```python +dataset.add_images_dir("/path/to/images", label_from_folder=True) +``` + +## Persistence Model: Additive + +HyperView uses an **additive** persistence model: + +| Action | Behavior | +|--------|----------| +| Add samples | New samples inserted, existing skipped by ID | +| Request fewer than exist | Existing samples preserved (no deletion) | +| Request more than exist | Only new samples added | +| Embeddings | Cached per-sample, reused across sessions | +| Projections | Recomputed when new samples added (UMAP requires refit) | + +**Example:** +```python +dataset = hv.Dataset("my_dataset") + +dataset.add_from_huggingface(..., max_samples=200) # 200 samples +dataset.add_from_huggingface(..., max_samples=400) # +200 new → 400 total +dataset.add_from_huggingface(..., max_samples=300) # no change → 400 total +dataset.add_from_huggingface(..., max_samples=500) # +100 new → 500 total +``` + +Samples are **never implicitly deleted**. Use `hv.Dataset.delete("name")` for explicit removal. + +## Computing Embeddings + +```python +# High-dimensional embeddings (CLIP/ResNet) +dataset.compute_embeddings(model="clip", show_progress=True) + +# 2D projections for visualization +dataset.compute_visualization() # UMAP to Euclidean + Hyperbolic +``` + +Embeddings are stored per-sample. If a sample already has embeddings, it's skipped. + +## Listing & Deleting Datasets + +```python +# List all persistent datasets +hv.Dataset.list_datasets() # ['cifar100_demo', 'my_dataset', ...] + +# Delete a dataset +hv.Dataset.delete("my_dataset") + +# Check existence +hv.Dataset.exists("my_dataset") # True/False +``` + +## Dataset Info + +```python +len(dataset) # Number of samples +dataset.name # Dataset name +dataset.labels # Unique labels +dataset.samples # Iterator over all samples +dataset[sample_id] # Get sample by ID +``` diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000000000000000000000000000000000000..9d2f633d3a64e5906ec2410b302f593e7c3794a1 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,465 @@ + + + + + + HyperView: Interactive Poincaré Disk + + + + + +
+
+ +

Why HyperView?

+

+ Modern AI curation tools rely on Euclidean geometry (flat space). + But real-world data—like biological taxonomies, social hierarchies, and medical diagnoses—is + complex and hierarchical. +

+

+ When you force this complex data into a flat box, you run out of room. + To fit the "Majority," the math crushes the "Minority" and "Rare" cases together. + We call this Representation Collapse. +

+ +

The Solution: Hyperbolic Space

+

+ HyperView uses the Poincaré disk, a model of hyperbolic geometry where space expands exponentially towards the edge. + This gives "infinite" room for outliers, ensuring they remain distinct and visible. +

+ +

FAQ: Why does this matter?

+ +
+

The "Hidden Diagnosis" Problem

+

+ Imagine training an AI doctor on 10,000 chest X-rays: +
9,000 Healthy (Majority) +
900 Common Pneumonia (Minority) +
100 Rare Early-Stage Tuberculosis (Rare Subgroup) +

+

+ In Euclidean Space: The model runs out of room. It crushes the 100 Tuberculosis cases into the Pneumonia cluster. To the AI, they look like noise. The patient is misdiagnosed. +

+

+ In HyperView: The Tuberculosis cases are pushed to the edge. They form a distinct, visible island. You can see them, select them, and ensure the AI learns to save those patients. +

+
+
+
+ +
+

HyperView Interactive Demo

+

+ Drag to Pan. Experience the "infinite" space. + Notice how the red "Rare" points expand and separate as you bring them towards the center. +

+
+
Majority
+
Minority
+
Rare
+
+ +
+ Hyperbolic Mode:
+ Space expands exponentially.
+ Rare items are distinct. +
+ +
+ + + + + diff --git a/frontend/components.json b/frontend/components.json new file mode 100644 index 0000000000000000000000000000000000000000..f826c543ed2815d3258fd024fad38d04df76c7ee --- /dev/null +++ b/frontend/components.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://ui.shadcn.com/schema.json", + "style": "new-york", + "rsc": true, + "tsx": true, + "tailwind": { + "config": "tailwind.config.ts", + "css": "src/app/globals.css", + "baseColor": "neutral", + "cssVariables": true, + "prefix": "" + }, + "iconLibrary": "lucide", + "aliases": { + "components": "@/components", + "utils": "@/lib/utils", + "ui": "@/components/ui", + "lib": "@/lib", + "hooks": "@/hooks" + }, + "registries": {} +} diff --git a/frontend/eslint.config.mjs b/frontend/eslint.config.mjs new file mode 100644 index 0000000000000000000000000000000000000000..4c89b74ddde41d7e46ee0169c860a37aa5d081c2 --- /dev/null +++ b/frontend/eslint.config.mjs @@ -0,0 +1,22 @@ +import path from "path"; +import { fileURLToPath } from "url"; + +import { FlatCompat } from "@eslint/eslintrc"; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +// Bridge legacy shareable configs (like `next/core-web-vitals`) into ESLint v9 flat config. +const compat = new FlatCompat({ + baseDirectory: __dirname, +}); + +const config = [ + { + // Mirror Next.js defaults: never lint build artifacts. + ignores: ["**/.next/**", "**/out/**", "**/node_modules/**"], + }, + ...compat.extends("next/core-web-vitals"), +]; + +export default config; diff --git a/frontend/next-env.d.ts b/frontend/next-env.d.ts new file mode 100644 index 0000000000000000000000000000000000000000..c4b7818fbb2c2c34c24feb1b627ee824507c5600 --- /dev/null +++ b/frontend/next-env.d.ts @@ -0,0 +1,6 @@ +/// +/// +import "./.next/dev/types/routes.d.ts"; + +// NOTE: This file should not be edited +// see https://nextjs.org/docs/app/api-reference/config/typescript for more information. diff --git a/frontend/next.config.ts b/frontend/next.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..7dbfdbd98cbe72518880bcdb6857e7c5363f9338 --- /dev/null +++ b/frontend/next.config.ts @@ -0,0 +1,24 @@ +import type { NextConfig } from "next"; +import path from "path"; + +const nextConfig: NextConfig = { + output: "export", + trailingSlash: true, + // Needed for Turbopack to resolve local linked/file dependencies in a monorepo. + outputFileTracingRoot: path.join(__dirname, ".."), + transpilePackages: ["hyper-scatter"], + images: { + unoptimized: true, + }, + // Proxy API calls to backend during development + async rewrites() { + return [ + { + source: "/api/:path*", + destination: "http://127.0.0.1:6262/api/:path*", + }, + ]; + }, +}; + +export default nextConfig; diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 0000000000000000000000000000000000000000..b1ccb5db3fc05387bdca7e4d905340ad21a88832 --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,7445 @@ +{ + "name": "hyperview-frontend", + "version": "0.1.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hyperview-frontend", + "version": "0.1.0", + "dependencies": { + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@tanstack/react-virtual": "^3.10.9", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "dockview": "^4.13.1", + "hyper-scatter": "https://github.com/Hyper3Labs/hyper-scatter/archive/14421d24ccf128392444175a23e74627c120905c.tar.gz", + "justified-layout": "^4.1.0", + "lucide-react": "^0.562.0", + "next": "^16.0.7", + "react": "18.3.1", + "react-dom": "18.3.1", + "tailwind-merge": "^3.4.0", + "tailwindcss-animate": "^1.0.7", + "zustand": "^5.0.1" + }, + "devDependencies": { + "@types/justified-layout": "^4.1.4", + "@types/node": "^22.9.0", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "autoprefixer": "^10.4.20", + "eslint": "^9.14.0", + "eslint-config-next": "15.0.3", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.15", + "typescript": "^5.6.3" + } + }, + "../viz_impl": { + "name": "hyper-scatter", + "version": "0.1.0", + "extraneous": true, + "devDependencies": { + "@types/node": "^20.10.0", + "puppeteer": "^24.34.0", + "tsx": "^4.7.0", + "typescript": "^5.3.0", + "vite": "^5.0.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@emnapi/core": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.7.1.tgz", + "integrity": "sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz", + "integrity": "sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", + "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.1.tgz", + "integrity": "sha512-S26Stp4zCy88tH94QbBv3XCuzRQiZ9yXofEILmglYTh/Ug/a9/umqvgFtYBAo3Lp0nsI/5/qH1CCrbdK3AP1Tw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@img/colour": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", + "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", + "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-darwin-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", + "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", + "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", + "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "darwin" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", + "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", + "cpu": [ + "arm" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", + "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-ppc64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", + "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", + "cpu": [ + "ppc64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-riscv64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", + "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", + "cpu": [ + "riscv64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", + "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", + "cpu": [ + "s390x" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", + "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", + "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", + "cpu": [ + "arm64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", + "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", + "cpu": [ + "x64" + ], + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-linux-arm": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", + "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", + "cpu": [ + "arm" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", + "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-ppc64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", + "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", + "cpu": [ + "ppc64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-ppc64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-riscv64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", + "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", + "cpu": [ + "riscv64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-riscv64": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-s390x": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", + "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", + "cpu": [ + "s390x" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.2.4" + } + }, + "node_modules/@img/sharp-linux-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", + "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", + "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" + } + }, + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", + "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.2.4" + } + }, + "node_modules/@img/sharp-wasm32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", + "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", + "cpu": [ + "wasm32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, + "dependencies": { + "@emnapi/runtime": "^1.7.0" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-arm64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", + "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-ia32": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", + "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@img/sharp-win32-x64": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", + "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@napi-rs/wasm-runtime": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz", + "integrity": "sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.3", + "@emnapi/runtime": "^1.4.3", + "@tybys/wasm-util": "^0.10.0" + } + }, + "node_modules/@next/env": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/env/-/env-16.0.7.tgz", + "integrity": "sha512-gpaNgUh5nftFKRkRQGnVi5dpcYSKGcZZkQffZ172OrG/XkrnS7UBTQ648YY+8ME92cC4IojpI2LqTC8sTDhAaw==", + "license": "MIT" + }, + "node_modules/@next/eslint-plugin-next": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/@next/eslint-plugin-next/-/eslint-plugin-next-15.0.3.tgz", + "integrity": "sha512-3Ln/nHq2V+v8uIaxCR6YfYo7ceRgZNXfTd3yW1ukTaFbO+/I8jNakrjYWODvG9BuR2v5kgVtH/C8r0i11quOgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "3.3.1" + } + }, + "node_modules/@next/swc-darwin-arm64": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-arm64/-/swc-darwin-arm64-16.0.7.tgz", + "integrity": "sha512-LlDtCYOEj/rfSnEn/Idi+j1QKHxY9BJFmxx7108A6D8K0SB+bNgfYQATPk/4LqOl4C0Wo3LACg2ie6s7xqMpJg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-darwin-x64": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-darwin-x64/-/swc-darwin-x64-16.0.7.tgz", + "integrity": "sha512-rtZ7BhnVvO1ICf3QzfW9H3aPz7GhBrnSIMZyr4Qy6boXF0b5E3QLs+cvJmg3PsTCG2M1PBoC+DANUi4wCOKXpA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-gnu": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-16.0.7.tgz", + "integrity": "sha512-mloD5WcPIeIeeZqAIP5c2kdaTa6StwP4/2EGy1mUw8HiexSHGK/jcM7lFuS3u3i2zn+xH9+wXJs6njO7VrAqww==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-arm64-musl": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-16.0.7.tgz", + "integrity": "sha512-+ksWNrZrthisXuo9gd1XnjHRowCbMtl/YgMpbRvFeDEqEBd523YHPWpBuDjomod88U8Xliw5DHhekBC3EOOd9g==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-gnu": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-16.0.7.tgz", + "integrity": "sha512-4WtJU5cRDxpEE44Ana2Xro1284hnyVpBb62lIpU5k85D8xXxatT+rXxBgPkc7C1XwkZMWpK5rXLXTh9PFipWsA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-linux-x64-musl": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-16.0.7.tgz", + "integrity": "sha512-HYlhqIP6kBPXalW2dbMTSuB4+8fe+j9juyxwfMwCe9kQPPeiyFn7NMjNfoFOfJ2eXkeQsoUGXg+O2SE3m4Qg2w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-arm64-msvc": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-16.0.7.tgz", + "integrity": "sha512-EviG+43iOoBRZg9deGauXExjRphhuYmIOJ12b9sAPy0eQ6iwcPxfED2asb/s2/yiLYOdm37kPaiZu8uXSYPs0Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@next/swc-win32-x64-msvc": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-16.0.7.tgz", + "integrity": "sha512-gniPjy55zp5Eg0896qSrf3yB1dw4F/3s8VK1ephdsZZ129j2n6e1WqCbE2YgcKhW9hPB9TVZENugquWJD5x0ug==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nolyfill/is-core-module": { + "version": "1.0.39", + "resolved": "https://registry.npmjs.org/@nolyfill/is-core-module/-/is-core-module-1.0.39.tgz", + "integrity": "sha512-nn5ozdjYQpUCZlWGuxcJY/KpxkWQs4DcbMCmKojjyrYDEAGy4Ce19NN4v5MduafTwJlbKc99UA8YhSVqq9yPZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.4.0" + } + }, + "node_modules/@radix-ui/number": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/number/-/number-1.1.1.tgz", + "integrity": "sha512-MkKCwxlXTgz6CFoJx3pCwn07GKp36+aZyu/u2Ln2VrA5DcdyCZkASEDBTd8x5whTQQL5CiYf4prXKLcgQdv29g==", + "license": "MIT" + }, + "node_modules/@radix-ui/primitive": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz", + "integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==", + "license": "MIT" + }, + "node_modules/@radix-ui/react-arrow": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz", + "integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collapsible": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collapsible/-/react-collapsible-1.1.12.tgz", + "integrity": "sha512-Uu+mSh4agx2ib1uIGPP4/CKNULyajb3p92LsVXmH2EHVMTfZWpll88XJ0j4W0z3f8NK1eYl1+Mf/szHPmcHzyA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-collection/-/react-collection-1.1.7.tgz", + "integrity": "sha512-Fh9rGN0MoI4ZFUNyfFVNU4y9LUz93u9/0K+yLgA2bwRojxM8JU1DyvvMBabnZPBgMWREAJvU2jjVzq+LrFUglw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-collection/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz", + "integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", + "integrity": "sha512-TCglVRtzlffRNxRMEyR36DGBLJpeusFcgMVD9PZEzAKnUs1lKCgX5u9BmC2Yg+LL9MgZDugFFs1Vl+Jp4t/PGw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dialog/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-direction": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-direction/-/react-direction-1.1.1.tgz", + "integrity": "sha512-1UEWRX6jnOA2y4H5WczZ44gOOjTEmlqv1uNW4GAJEO5+bauCBhv8snY65Iw5/VOS/ghKN9gr2KjnLKxrsvoMVw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz", + "integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-escape-keydown": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-dropdown-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.16.tgz", + "integrity": "sha512-1PLGQEynI/3OX/ftV54COn+3Sud/Mn8vALg2rWnBLnRaGtJDduNW/22XjlGgPdpcIbiQxjKtb7BkcjP00nqfJw==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-guards": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz", + "integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-focus-scope": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz", + "integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-id": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", + "integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu": { + "version": "2.1.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-menu/-/react-menu-2.1.16.tgz", + "integrity": "sha512-72F2T+PLlphrqLcAotYPp0uJMr5SjP5SL01wfEspJbru5Zs5vQaSHb4VB3ZMJPimgHHCHG7gMOeOB9H3Hdmtxg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz", + "integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-focus-guards": "1.1.3", + "@radix-ui/react-focus-scope": "1.1.7", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "aria-hidden": "^1.2.4", + "react-remove-scroll": "^2.6.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popover/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-popper": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz", + "integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1", + "@radix-ui/react-use-rect": "1.1.1", + "@radix-ui/react-use-size": "1.1.1", + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-portal": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz", + "integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-presence": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz", + "integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-primitive/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-radio-group": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-radio-group/-/react-radio-group-1.3.8.tgz", + "integrity": "sha512-VBKYIYImA5zsxACdisNQ3BjCBfmbGH3kQlnFVqlWU4tXwjy7cGX8ta80BcrO+WJXIn5iBylEH3K6ZTlee//lgQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-use-previous": "1.1.1", + "@radix-ui/react-use-size": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-roving-focus": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.11.tgz", + "integrity": "sha512-7A6S9jSgm/S+7MdtNDSb+IU859vQqJ/QAtcYQcfFC6W8RS4IxIZDldLR0xqCFZ6DCyrQLjLPsxtTNch5jVA4lA==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-collection": "1.1.7", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-scroll-area": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-scroll-area/-/react-scroll-area-1.2.10.tgz", + "integrity": "sha512-tAXIa1g3sM5CGpVT0uIbUx/U3Gs5N8T52IICuCtObaos1S8fzsrPXG5WObkQN3S6NVl6wKgPhAIiBGbWnvc97A==", + "license": "MIT", + "dependencies": { + "@radix-ui/number": "1.1.1", + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-separator/-/react-separator-1.1.8.tgz", + "integrity": "sha512-sDvqVY4itsKwwSMEe0jtKgfTh+72Sy3gPmQpjqcQneqQ4PFmr/1I0YA+2/puilhggCe2gJcx5EBAYFkWkdpa5g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-separator/node_modules/@radix-ui/react-primitive": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.4.tgz", + "integrity": "sha512-9hQc4+GNVtJAIEPEqlYqW5RiYdrr8ea5XQ0ZOnD6fgru+83kqT15mq2OCcbe8KnjRZl5vF3ks69AKz3kh1jrhg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.4" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-slot": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.4.tgz", + "integrity": "sha512-Jl+bCv8HxKnlTLVrcDE8zTMJ09R9/ukw4qBs/oZClOfoQk/cOTbDn+NceXfV7j09YPVQUryJPHurafcSg6EVKA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle": { + "version": "1.1.10", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle/-/react-toggle-1.1.10.tgz", + "integrity": "sha512-lS1odchhFTeZv3xwHH31YPObmJn8gOg7Lq12inrr0+BH/l3Tsq32VfjqH1oh80ARM3mlkfMic15n0kg4sD1poQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-toggle-group": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/@radix-ui/react-toggle-group/-/react-toggle-group-1.1.11.tgz", + "integrity": "sha512-5umnS0T8JQzQT6HbPyO7Hh9dgd82NmS36DQr+X/YJ9ctFNCiiQd6IJAYYZ33LUwm8M+taCz5t2ui29fHZc4Y6Q==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-direction": "1.1.1", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-roving-focus": "1.1.11", + "@radix-ui/react-toggle": "1.1.10", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz", + "integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-compose-refs": "1.1.2", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-dismissable-layer": "1.1.11", + "@radix-ui/react-id": "1.1.1", + "@radix-ui/react-popper": "1.2.8", + "@radix-ui/react-portal": "1.1.9", + "@radix-ui/react-presence": "1.1.5", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-slot": "1.2.3", + "@radix-ui/react-use-controllable-state": "1.2.2", + "@radix-ui/react-visually-hidden": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz", + "integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz", + "integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-effect-event": "0.0.2", + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-effect-event": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz", + "integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz", + "integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz", + "integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-previous": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-previous/-/react-use-previous-1.1.1.tgz", + "integrity": "sha512-2dHfToCj/pzca2Ck724OZ5L0EVrr3eHRNsG/b3xQJLA2hZpVCS99bLAX+hm1IHXDEnzU6by5z/5MIY794/a8NQ==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz", + "integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==", + "license": "MIT", + "dependencies": { + "@radix-ui/rect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-use-size": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz", + "integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.1" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-visually-hidden": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", + "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-primitive": "2.1.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/rect": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz", + "integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==", + "license": "MIT" + }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rushstack/eslint-patch": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/@rushstack/eslint-patch/-/eslint-patch-1.15.0.tgz", + "integrity": "sha512-ojSshQPKwVvSMR8yT2L/QtUkV5SXi/IfDiJ4/8d6UbTPjiHVmxZzUAzGD8Tzks1b9+qQkZa0isUOvYObedITaw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@swc/helpers": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.15.tgz", + "integrity": "sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.8.0" + } + }, + "node_modules/@tanstack/react-virtual": { + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.13.12.tgz", + "integrity": "sha512-Gd13QdxPSukP8ZrkbgS2RwoZseTTbQPLnQEn7HY/rqtM+8Zt95f7xKC7N0EsKs7aoz0WzZ+fditZux+F8EzYxA==", + "license": "MIT", + "dependencies": { + "@tanstack/virtual-core": "3.13.12" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tanstack/virtual-core": { + "version": "3.13.12", + "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.13.12.tgz", + "integrity": "sha512-1YBOJfRHV4sXUmWsFSf5rQor4Ss82G8dQWLRbnk3GA4jeP8hQt1hxXh0tmflpC0dz3VgEv/1+qwPyLeWkQuPFA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", + "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json5": { + "version": "0.0.29", + "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", + "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/justified-layout": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/@types/justified-layout/-/justified-layout-4.1.4.tgz", + "integrity": "sha512-q2ybP0u0NVj87oMnGZOGxY2iUN8ddr48zPOBHBdbOLpsMTA/keGj+93ou+OMCnJk0xewzlNIaVEkxM6VBD3E2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "22.19.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.1.tgz", + "integrity": "sha512-LCCV0HdSZZZb34qifBsyWlUmok6W7ouER+oQIGBScS8EsZsQbrtFTUrDX4hOl+CS6p7cnNC4td+qrSVGSCTUfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.27", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", + "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", + "devOptional": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "devOptional": true, + "license": "MIT", + "peer": true, + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.48.1.tgz", + "integrity": "sha512-X63hI1bxl5ohelzr0LY5coufyl0LJNthld+abwxpCoo6Gq+hSqhKwci7MUWkXo67mzgUK6YFByhmaHmUcuBJmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/type-utils": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "graphemer": "^1.4.0", + "ignore": "^7.0.0", + "natural-compare": "^1.4.0", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^8.48.1", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.48.1.tgz", + "integrity": "sha512-PC0PDZfJg8sP7cmKe6L3QIL8GZwU5aRvUFedqSIpw3B+QjRSUZeeITC2M5XKeMXEzL6wccN196iy3JLwKNvDVA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.48.1.tgz", + "integrity": "sha512-HQWSicah4s9z2/HifRPQ6b6R7G+SBx64JlFQpgSSHWPKdvCZX57XCbszg/bapbRsOEv42q5tayTYcEFpACcX1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.48.1", + "@typescript-eslint/types": "^8.48.1", + "debug": "^4.3.4" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.48.1.tgz", + "integrity": "sha512-rj4vWQsytQbLxC5Bf4XwZ0/CKd362DkWMUkviT7DCS057SK64D5lH74sSGzhI6PDD2HCEq02xAP9cX68dYyg1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.48.1.tgz", + "integrity": "sha512-k0Jhs4CpEffIBm6wPaCXBAD7jxBtrHjrSgtfCjUvPp9AZ78lXKdTR8fxyZO5y4vWNlOvYXRtngSZNSn+H53Jkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.48.1.tgz", + "integrity": "sha512-1jEop81a3LrJQLTf/1VfPQdhIY4PlGDBc/i67EVWObrtvcziysbLN3oReexHOM6N3jyXgCrkBsZpqwH0hiDOQg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1", + "@typescript-eslint/utils": "8.48.1", + "debug": "^4.3.4", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/types": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.48.1.tgz", + "integrity": "sha512-+fZ3LZNeiELGmimrujsDCT4CRIbq5oXdHe7chLiW8qzqyPMnn1puNstCrMNVAqwcl2FdIxkuJ4tOs/RFDBVc/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.48.1.tgz", + "integrity": "sha512-/9wQ4PqaefTK6POVTjJaYS0bynCgzh6ClJHGSBj06XEHjkfylzB+A3qvyaXnErEZSaxhIo4YdyBgq6j4RysxDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/project-service": "8.48.1", + "@typescript-eslint/tsconfig-utils": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/visitor-keys": "8.48.1", + "debug": "^4.3.4", + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.1.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.48.1.tgz", + "integrity": "sha512-fAnhLrDjiVfey5wwFRwrweyRlCmdz5ZxXz2G/4cLn0YDLjTapmN4gcCsTBR1N2rWnZSDeWpYtgLDsJt+FpmcwA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.48.1", + "@typescript-eslint/types": "8.48.1", + "@typescript-eslint/typescript-estree": "8.48.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "8.48.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.48.1.tgz", + "integrity": "sha512-BmxxndzEWhE4TIEEMBs8lP3MBWN3jFPs/p6gPm/wkv02o41hI6cq9AuSmGAaTTHPtA1FTi2jBre4A9rm5ZmX+Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "8.48.1", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@unrs/resolver-binding-android-arm-eabi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm-eabi/-/resolver-binding-android-arm-eabi-1.11.1.tgz", + "integrity": "sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-android-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-android-arm64/-/resolver-binding-android-arm64-1.11.1.tgz", + "integrity": "sha512-lCxkVtb4wp1v+EoN+HjIG9cIIzPkX5OtM03pQYkG+U5O/wL53LC4QbIeazgiKqluGeVEeBlZahHalCaBvU1a2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-arm64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-arm64/-/resolver-binding-darwin-arm64-1.11.1.tgz", + "integrity": "sha512-gPVA1UjRu1Y/IsB/dQEsp2V1pm44Of6+LWvbLc9SDk1c2KhhDRDBUkQCYVWe6f26uJb3fOK8saWMgtX8IrMk3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-darwin-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-darwin-x64/-/resolver-binding-darwin-x64-1.11.1.tgz", + "integrity": "sha512-cFzP7rWKd3lZaCsDze07QX1SC24lO8mPty9vdP+YVa3MGdVgPmFc59317b2ioXtgCMKGiCLxJ4HQs62oz6GfRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@unrs/resolver-binding-freebsd-x64": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-freebsd-x64/-/resolver-binding-freebsd-x64-1.11.1.tgz", + "integrity": "sha512-fqtGgak3zX4DCB6PFpsH5+Kmt/8CIi4Bry4rb1ho6Av2QHTREM+47y282Uqiu3ZRF5IQioJQ5qWRV6jduA+iGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-gnueabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-gnueabihf/-/resolver-binding-linux-arm-gnueabihf-1.11.1.tgz", + "integrity": "sha512-u92mvlcYtp9MRKmP+ZvMmtPN34+/3lMHlyMj7wXJDeXxuM0Vgzz0+PPJNsro1m3IZPYChIkn944wW8TYgGKFHw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm-musleabihf": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm-musleabihf/-/resolver-binding-linux-arm-musleabihf-1.11.1.tgz", + "integrity": "sha512-cINaoY2z7LVCrfHkIcmvj7osTOtm6VVT16b5oQdS4beibX2SYBwgYLmqhBjA1t51CarSaBuX5YNsWLjsqfW5Cw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-gnu/-/resolver-binding-linux-arm64-gnu-1.11.1.tgz", + "integrity": "sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-arm64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-arm64-musl/-/resolver-binding-linux-arm64-musl-1.11.1.tgz", + "integrity": "sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-ppc64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-ppc64-gnu/-/resolver-binding-linux-ppc64-gnu-1.11.1.tgz", + "integrity": "sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-gnu/-/resolver-binding-linux-riscv64-gnu-1.11.1.tgz", + "integrity": "sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-riscv64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-riscv64-musl/-/resolver-binding-linux-riscv64-musl-1.11.1.tgz", + "integrity": "sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-s390x-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-s390x-gnu/-/resolver-binding-linux-s390x-gnu-1.11.1.tgz", + "integrity": "sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-gnu": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-gnu/-/resolver-binding-linux-x64-gnu-1.11.1.tgz", + "integrity": "sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-linux-x64-musl": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-linux-x64-musl/-/resolver-binding-linux-x64-musl-1.11.1.tgz", + "integrity": "sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@unrs/resolver-binding-wasm32-wasi": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-wasm32-wasi/-/resolver-binding-wasm32-wasi-1.11.1.tgz", + "integrity": "sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==", + "cpu": [ + "wasm32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@napi-rs/wasm-runtime": "^0.2.11" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@unrs/resolver-binding-win32-arm64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-arm64-msvc/-/resolver-binding-win32-arm64-msvc-1.11.1.tgz", + "integrity": "sha512-nRcz5Il4ln0kMhfL8S3hLkxI85BXs3o8EYoattsJNdsX4YUU89iOkVn7g0VHSRxFuVMdM4Q1jEpIId1Ihim/Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-ia32-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-ia32-msvc/-/resolver-binding-win32-ia32-msvc-1.11.1.tgz", + "integrity": "sha512-DCEI6t5i1NmAZp6pFonpD5m7i6aFrpofcp4LA2i8IIq60Jyo28hamKBxNrZcyOwVOZkgsRp9O2sXWBWP8MnvIQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@unrs/resolver-binding-win32-x64-msvc": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/@unrs/resolver-binding-win32-x64-msvc/-/resolver-binding-win32-x64-msvc-1.11.1.tgz", + "integrity": "sha512-lrW200hZdbfRtztbygyaq/6jP6AKE8qQN2KvPcJ+x7wiD038YtnYtZ82IMNJ69GJibV7bwL3y9FgK+5w/pYt6g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "dev": true, + "license": "MIT", + "peer": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/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/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/aria-hidden": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz", + "integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.findlastindex": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ast-types-flow": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/ast-types-flow/-/ast-types-flow-0.0.8.tgz", + "integrity": "sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/autoprefixer": { + "version": "10.4.22", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", + "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.27.0", + "caniuse-lite": "^1.0.30001754", + "fraction.js": "^5.3.4", + "normalize-range": "^0.1.2", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axe-core": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/axe-core/-/axe-core-4.11.0.tgz", + "integrity": "sha512-ilYanEU8vxxBexpJd8cWM4ElSQq4QctCLKih0TSfjIfCQTeyH/6zVrmIJfLPrKTKJRbiG+cfnZbQIjAlJmF1jQ==", + "dev": true, + "license": "MPL-2.0", + "engines": { + "node": ">=4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.2.tgz", + "integrity": "sha512-PxSsosKQjI38iXkmb3d0Y32efqyA0uW4s41u4IVBsLlWLhCiYNpH/AfNOVWRqCQBlD8TFJTz6OUWNd4DFJCnmw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001759", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", + "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/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/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/class-variance-authority": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz", + "integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==", + "license": "Apache-2.0", + "dependencies": { + "clsx": "^2.1.1" + }, + "funding": { + "url": "https://polar.sh/cva" + } + }, + "node_modules/client-only": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", + "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", + "license": "MIT" + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/cmdk": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cmdk/-/cmdk-1.1.1.tgz", + "integrity": "sha512-Vsv7kFaXm+ptHDMZ7izaRsP70GgrW9NBNGswt9OZaVBLlE0SNpDq8eu/VGXyF9r7M0azK3Wy7OlYXsuyYLFzHg==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "^1.1.1", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-id": "^1.1.0", + "@radix-ui/react-primitive": "^2.0.2" + }, + "peerDependencies": { + "react": "^18 || ^19 || ^19.0.0-rc", + "react-dom": "^18 || ^19 || ^19.0.0-rc" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/damerau-levenshtein": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", + "integrity": "sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node-es": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz", + "integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "license": "Apache-2.0" + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "license": "MIT" + }, + "node_modules/dockview": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/dockview/-/dockview-4.13.1.tgz", + "integrity": "sha512-K8xnYt3Rvkx8MYKHaEsb8aFaPyQclKRRkXS9JcpQPZUgqxumTLnSidgdd6uIfzEps6yJsXoZGQGJ9PtcaKyDcQ==", + "license": "MIT", + "dependencies": { + "dockview-core": "^4.13.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/dockview-core": { + "version": "4.13.1", + "resolved": "https://registry.npmjs.org/dockview-core/-/dockview-core-4.13.1.tgz", + "integrity": "sha512-+7vR0ZEoL8CNck6NqDVUMqBT22niwBu5CMMI137dZ3c8NDc7c5Si+3dGEqQgM4lNtHBLAtvypo1C4p21J2wkiQ==", + "license": "MIT" + }, + "node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.265", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.265.tgz", + "integrity": "sha512-B7IkLR1/AE+9jR2LtVF/1/6PFhY5TlnEHnlrKmGk7PvkJibg5jr+mLXLLzq3QYl6PA1T/vLDthQPqIPAlS/PPA==", + "dev": true, + "license": "ISC" + }, + "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/es-abstract": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", + "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.39.1", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-config-next": { + "version": "15.0.3", + "resolved": "https://registry.npmjs.org/eslint-config-next/-/eslint-config-next-15.0.3.tgz", + "integrity": "sha512-IGP2DdQQrgjcr4mwFPve4DrCqo7CVVez1WoYY47XwKSrYO4hC0Dlb+iJA60i0YfICOzgNADIb8r28BpQ5Zs0wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@next/eslint-plugin-next": "15.0.3", + "@rushstack/eslint-patch": "^1.10.3", + "@typescript-eslint/eslint-plugin": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "@typescript-eslint/parser": "^5.4.2 || ^6.0.0 || ^7.0.0 || ^8.0.0", + "eslint-import-resolver-node": "^0.3.6", + "eslint-import-resolver-typescript": "^3.5.2", + "eslint-plugin-import": "^2.31.0", + "eslint-plugin-jsx-a11y": "^6.10.0", + "eslint-plugin-react": "^7.35.0", + "eslint-plugin-react-hooks": "^5.0.0" + }, + "peerDependencies": { + "eslint": "^7.23.0 || ^8.0.0 || ^9.0.0", + "typescript": ">=3.3.1" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-import-resolver-node": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7", + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" + } + }, + "node_modules/eslint-import-resolver-node/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-import-resolver-typescript": { + "version": "3.10.1", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.10.1.tgz", + "integrity": "sha512-A1rHYb06zjMGAxdLSkN2fXPBwuSaQ0iO5M/hdyS0Ajj1VBaRp0sPD3dn1FhME3c/JluGFbwSxyCfqdSbtQLAHQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "@nolyfill/is-core-module": "1.0.39", + "debug": "^4.4.0", + "get-tsconfig": "^4.10.0", + "is-bun-module": "^2.0.0", + "stable-hash": "^0.0.5", + "tinyglobby": "^0.2.13", + "unrs-resolver": "^1.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint-import-resolver-typescript" + }, + "peerDependencies": { + "eslint": "*", + "eslint-plugin-import": "*", + "eslint-plugin-import-x": "*" + }, + "peerDependenciesMeta": { + "eslint-plugin-import": { + "optional": true + }, + "eslint-plugin-import-x": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils": { + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^3.2.7" + }, + "engines": { + "node": ">=4" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/eslint-module-utils/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import": { + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", + "debug": "^3.2.7", + "doctrine": "^2.1.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", + "is-glob": "^4.0.3", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", + "semver": "^6.3.1", + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-import/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/eslint-plugin-import/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-jsx-a11y": { + "version": "6.10.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.10.2.tgz", + "integrity": "sha512-scB3nz4WmG75pV8+3eRUQOHZlNSUhFNq37xnpgRkCCELU3XMvXAxLk1eqWWyE22Ki4Q01Fnsw9BA3cJHDPgn2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "aria-query": "^5.3.2", + "array-includes": "^3.1.8", + "array.prototype.flatmap": "^1.3.2", + "ast-types-flow": "^0.0.8", + "axe-core": "^4.10.0", + "axobject-query": "^4.1.0", + "damerau-levenshtein": "^1.0.8", + "emoji-regex": "^9.2.2", + "hasown": "^2.0.2", + "jsx-ast-utils": "^3.3.5", + "language-tags": "^1.0.9", + "minimatch": "^3.1.2", + "object.fromentries": "^2.0.8", + "safe-regex-test": "^1.0.3", + "string.prototype.includes": "^2.0.1" + }, + "engines": { + "node": ">=4.0" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9" + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.2.0.tgz", + "integrity": "sha512-+f15FfK64YQwZdJNELETdn5ibXEUQmW1DZL6KXhNnc2heoy/sg9VJJeT7n8TlMWouzWqSWavFkIhHyIbIAEapg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-glob": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", + "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-nonce": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz", + "integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hyper-scatter": { + "version": "0.1.0", + "resolved": "https://github.com/Hyper3Labs/hyper-scatter/archive/14421d24ccf128392444175a23e74627c120905c.tar.gz", + "integrity": "sha512-pZ7bgI1Bo0kE/VaQu8Vwm7lpJ8FMCtmcouDU0wMkin7NvVi0BKBl4NlDNFAEKdP+0HIIZUQaAKuE0uplxp1UaQ==", + "license": "MIT" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bun-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-bun-module/-/is-bun-module-2.0.0.tgz", + "integrity": "sha512-gNCGbnnnnFAUGKeZ9PdbyeGYJqewpmc2aKHUEMO5nQPWU9lOmv7jcmQIv+qHD8fXW6W7qfuCwX4rY9LNRjXrkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.7.1" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "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-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", + "peer": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/justified-layout": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/justified-layout/-/justified-layout-4.1.0.tgz", + "integrity": "sha512-M5FimNMXgiOYerVRGsXZ2YK9YNCaTtwtYp7Hb2308U1Q9TXXHx5G0p08mcVR5O53qf8bWY4NJcPBxE6zuayXSg==", + "license": "ISC" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/language-subtag-registry": { + "version": "0.3.23", + "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", + "integrity": "sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/language-tags": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/language-tags/-/language-tags-1.0.9.tgz", + "integrity": "sha512-MbjN408fEndfiQXbFQ1vnd+1NoLDsnQW41410oQBXiyXDMYH5z505juWa4KUE1LqxRC7DgOgZDbKLxHIwm27hA==", + "dev": true, + "license": "MIT", + "dependencies": { + "language-subtag-registry": "^0.3.20" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lucide-react": { + "version": "0.562.0", + "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.562.0.tgz", + "integrity": "sha512-82hOAu7y0dbVuFfmO4bYF1XEwYk/mEbM5E+b1jgci/udUBEE/R7LF5Ip0CCEmXe8AybRM8L+04eP+LGZeDvkiw==", + "license": "ISC", + "peerDependencies": { + "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/napi-postinstall": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/napi-postinstall/-/napi-postinstall-0.3.4.tgz", + "integrity": "sha512-PHI5f1O0EP5xJ9gQmFGMS6IZcrVvTjpXjz7Na41gTE7eE2hK11lg04CECCYEEjdc17EV4DO+fkGEtt7TpTaTiQ==", + "dev": true, + "license": "MIT", + "bin": { + "napi-postinstall": "lib/cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/napi-postinstall" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/next": { + "version": "16.0.7", + "resolved": "https://registry.npmjs.org/next/-/next-16.0.7.tgz", + "integrity": "sha512-3mBRJyPxT4LOxAJI6IsXeFtKfiJUbjCLgvXO02fV8Wy/lIhPvP94Fe7dGhUgHXcQy4sSuYwQNcOLhIfOm0rL0A==", + "license": "MIT", + "dependencies": { + "@next/env": "16.0.7", + "@swc/helpers": "0.5.15", + "caniuse-lite": "^1.0.30001579", + "postcss": "8.4.31", + "styled-jsx": "5.1.6" + }, + "bin": { + "next": "dist/bin/next" + }, + "engines": { + "node": ">=20.9.0" + }, + "optionalDependencies": { + "@next/swc-darwin-arm64": "16.0.7", + "@next/swc-darwin-x64": "16.0.7", + "@next/swc-linux-arm64-gnu": "16.0.7", + "@next/swc-linux-arm64-musl": "16.0.7", + "@next/swc-linux-x64-gnu": "16.0.7", + "@next/swc-linux-x64-musl": "16.0.7", + "@next/swc-win32-arm64-msvc": "16.0.7", + "@next/swc-win32-x64-msvc": "16.0.7", + "sharp": "^0.34.4" + }, + "peerDependencies": { + "@opentelemetry/api": "^1.1.0", + "@playwright/test": "^1.51.1", + "babel-plugin-react-compiler": "*", + "react": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "react-dom": "^18.2.0 || 19.0.0-rc-de68d2f4-20241204 || ^19.0.0", + "sass": "^1.3.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "@playwright/test": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "sass": { + "optional": true + } + } + }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.groupby": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/react-remove-scroll": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.2.tgz", + "integrity": "sha512-Iqb9NjCCTt6Hf+vOdNIZGdTiH1QSqr27H/Ek9sv/a97gfueI/5h1s3yRi1nngzMUaOOToin5dI1dXKdXiF+u0Q==", + "license": "MIT", + "dependencies": { + "react-remove-scroll-bar": "^2.3.7", + "react-style-singleton": "^2.2.3", + "tslib": "^2.1.0", + "use-callback-ref": "^1.3.3", + "use-sidecar": "^1.1.3" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-remove-scroll-bar": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz", + "integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==", + "license": "MIT", + "dependencies": { + "react-style-singleton": "^2.2.2", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/react-style-singleton": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz", + "integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==", + "license": "MIT", + "dependencies": { + "get-nonce": "^1.0.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "license": "MIT", + "dependencies": { + "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/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "devOptional": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/sharp": { + "version": "0.34.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", + "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", + "hasInstallScript": true, + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@img/colour": "^1.0.0", + "detect-libc": "^2.1.2", + "semver": "^7.7.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.34.5", + "@img/sharp-darwin-x64": "0.34.5", + "@img/sharp-libvips-darwin-arm64": "1.2.4", + "@img/sharp-libvips-darwin-x64": "1.2.4", + "@img/sharp-libvips-linux-arm": "1.2.4", + "@img/sharp-libvips-linux-arm64": "1.2.4", + "@img/sharp-libvips-linux-ppc64": "1.2.4", + "@img/sharp-libvips-linux-riscv64": "1.2.4", + "@img/sharp-libvips-linux-s390x": "1.2.4", + "@img/sharp-libvips-linux-x64": "1.2.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", + "@img/sharp-libvips-linuxmusl-x64": "1.2.4", + "@img/sharp-linux-arm": "0.34.5", + "@img/sharp-linux-arm64": "0.34.5", + "@img/sharp-linux-ppc64": "0.34.5", + "@img/sharp-linux-riscv64": "0.34.5", + "@img/sharp-linux-s390x": "0.34.5", + "@img/sharp-linux-x64": "0.34.5", + "@img/sharp-linuxmusl-arm64": "0.34.5", + "@img/sharp-linuxmusl-x64": "0.34.5", + "@img/sharp-wasm32": "0.34.5", + "@img/sharp-win32-arm64": "0.34.5", + "@img/sharp-win32-ia32": "0.34.5", + "@img/sharp-win32-x64": "0.34.5" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stable-hash": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/stable-hash/-/stable-hash-0.0.5.tgz", + "integrity": "sha512-+L3ccpzibovGXFK+Ap/f8LOS0ahMrHTf3xu7mMLSpEGU0EO9ucaysSylKo9eRDFNhWve/y275iPmIZ4z39a9iA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.includes": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", + "integrity": "sha512-o7+c9bW6zpAdJHTtujeePODAhkuicdAryFsfVKwA+wGw89wJ4GTY484WTucM9hLtDEOpOvI+aHnzqnC5lHp4Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/styled-jsx": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/styled-jsx/-/styled-jsx-5.1.6.tgz", + "integrity": "sha512-qSVyDTeMotdvQYoHWLNGwRFJHC+i+ZvdBRYosOFgC+Wg1vx4frN2/RG/NA7SYqqvKNLf39P2LSRA2pu6n0XYZA==", + "license": "MIT", + "dependencies": { + "client-only": "0.0.1" + }, + "engines": { + "node": ">= 12.0.0" + }, + "peerDependencies": { + "react": ">= 16.8.0 || 17.x.x || ^18.0.0-0 || ^19.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/tailwind-merge": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", + "integrity": "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/dcastil" + } + }, + "node_modules/tailwindcss": { + "version": "3.4.18", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", + "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss-animate": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz", + "integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==", + "license": "MIT", + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/tailwindcss/node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/ts-api-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.12" + }, + "peerDependencies": { + "typescript": ">=4.8.4" + } + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "license": "Apache-2.0" + }, + "node_modules/tsconfig-paths": { + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json5": "^0.0.29", + "json5": "^1.0.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/unrs-resolver": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/unrs-resolver/-/unrs-resolver-1.11.1.tgz", + "integrity": "sha512-bSjt9pjaEBnNiGgc9rUiHGKv5l4/TGzDmYw3RhnkJGtLhbnnA/5qJj7x3dNDCRx/PJxu774LlH8lCOlB4hEfKg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "napi-postinstall": "^0.3.0" + }, + "funding": { + "url": "https://opencollective.com/unrs-resolver" + }, + "optionalDependencies": { + "@unrs/resolver-binding-android-arm-eabi": "1.11.1", + "@unrs/resolver-binding-android-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-arm64": "1.11.1", + "@unrs/resolver-binding-darwin-x64": "1.11.1", + "@unrs/resolver-binding-freebsd-x64": "1.11.1", + "@unrs/resolver-binding-linux-arm-gnueabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm-musleabihf": "1.11.1", + "@unrs/resolver-binding-linux-arm64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-arm64-musl": "1.11.1", + "@unrs/resolver-binding-linux-ppc64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-riscv64-musl": "1.11.1", + "@unrs/resolver-binding-linux-s390x-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-gnu": "1.11.1", + "@unrs/resolver-binding-linux-x64-musl": "1.11.1", + "@unrs/resolver-binding-wasm32-wasi": "1.11.1", + "@unrs/resolver-binding-win32-arm64-msvc": "1.11.1", + "@unrs/resolver-binding-win32-ia32-msvc": "1.11.1", + "@unrs/resolver-binding-win32-x64-msvc": "1.11.1" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-callback-ref": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz", + "integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/use-sidecar": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz", + "integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==", + "license": "MIT", + "dependencies": { + "detect-node-es": "^1.1.0", + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.9.tgz", + "integrity": "sha512-ALBtUj0AfjJt3uNRQoL1tL2tMvj6Gp/6e39dnfT6uzpelGru8v1tPOGBzayOWbPJvujM8JojDk3E1LxeFisBNg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + } + } +} diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000000000000000000000000000000000000..e37e61803bc985edadc87e8b2de04e376d36688c --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,51 @@ +{ + "name": "hyperview-frontend", + "version": "0.1.0", + "private": true, + "scripts": { + "dev": "next dev", + "build": "next build", + "start": "next start", + "lint": "eslint .", + "export": "next build && cp -r out/* ../src/hyperview/server/static/" + }, + "dependencies": { + "@radix-ui/react-collapsible": "^1.1.12", + "@radix-ui/react-dialog": "^1.1.15", + "@radix-ui/react-dropdown-menu": "^2.1.16", + "@radix-ui/react-popover": "^1.1.15", + "@radix-ui/react-radio-group": "^1.3.8", + "@radix-ui/react-scroll-area": "^1.2.10", + "@radix-ui/react-separator": "^1.1.8", + "@radix-ui/react-slot": "^1.2.4", + "@radix-ui/react-toggle": "^1.1.10", + "@radix-ui/react-toggle-group": "^1.1.11", + "@radix-ui/react-tooltip": "^1.2.8", + "@tanstack/react-virtual": "^3.10.9", + "class-variance-authority": "^0.7.1", + "clsx": "^2.1.1", + "cmdk": "^1.1.1", + "dockview": "^4.13.1", + "hyper-scatter": "https://github.com/Hyper3Labs/hyper-scatter/archive/14421d24ccf128392444175a23e74627c120905c.tar.gz", + "justified-layout": "^4.1.0", + "lucide-react": "^0.562.0", + "next": "^16.0.7", + "react": "18.3.1", + "react-dom": "18.3.1", + "tailwind-merge": "^3.4.0", + "tailwindcss-animate": "^1.0.7", + "zustand": "^5.0.1" + }, + "devDependencies": { + "@types/justified-layout": "^4.1.4", + "@types/node": "^22.9.0", + "@types/react": "^18.3.12", + "@types/react-dom": "^18.3.1", + "autoprefixer": "^10.4.20", + "eslint": "^9.14.0", + "eslint-config-next": "15.0.3", + "postcss": "^8.4.49", + "tailwindcss": "^3.4.15", + "typescript": "^5.6.3" + } +} diff --git a/frontend/postcss.config.mjs b/frontend/postcss.config.mjs new file mode 100644 index 0000000000000000000000000000000000000000..2ef30fcf4272e19cf6a23d07b0544027954f9627 --- /dev/null +++ b/frontend/postcss.config.mjs @@ -0,0 +1,9 @@ +/** @type {import('postcss-load-config').Config} */ +const config = { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +}; + +export default config; diff --git a/frontend/src/app/globals.css b/frontend/src/app/globals.css new file mode 100644 index 0000000000000000000000000000000000000000..4272f94be17d2c4c917e8cf170c9ac6ba95115d3 --- /dev/null +++ b/frontend/src/app/globals.css @@ -0,0 +1,224 @@ +@import "dockview/dist/styles/dockview.css"; + +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + html, + body { + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + } + + :root { + /* Rerun-inspired dark theme as default (dark-first) */ + --background: 215 28% 7%; /* #0d1117 */ + --foreground: 213 27% 92%; /* #e6edf3 */ + + --card: 215 21% 11%; /* #161b22 */ + --card-foreground: 213 27% 92%; + + --popover: 215 21% 11%; + --popover-foreground: 213 27% 92%; + + --primary: 212 100% 67%; /* #58a6ff */ + --primary-foreground: 215 28% 7%; + + --secondary: 215 14% 17%; /* #21262d */ + --secondary-foreground: 213 27% 92%; + + --muted: 215 14% 17%; + --muted-foreground: 213 12% 58%; /* #8b949e */ + + --accent: 215 14% 17%; + --accent-foreground: 213 27% 92%; + + --destructive: 0 62% 50%; + --destructive-foreground: 0 0% 98%; + + --border: 215 14% 22%; /* #30363d */ + --input: 215 14% 22%; + --ring: 212 100% 67%; + + --radius: 0.375rem; + + /* Custom Rerun-specific tokens */ + --surface: 215 21% 11%; /* #161b22 */ + --surface-light: 215 14% 17%; /* #21262d */ + --surface-elevated: 215 14% 22%; /* #30363d */ + --border-subtle: 215 14% 17%; + --text: 213 27% 92%; /* #e6edf3 */ + --text-muted: 213 12% 58%; /* #8b949e */ + --text-subtle: 215 10% 46%; /* #6e7681 */ + --accent-cyan: 176 60% 53%; /* #39d3cc */ + --accent-orange: 27 86% 59%; /* #f0883e */ + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground; + font-size: 12px; + line-height: 16px; + letter-spacing: -0.15px; + font-weight: 500; + font-feature-settings: "liga" 1, "calt" 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + } +} + +/* Custom scrollbar - Rerun style: 6px bar, 2px inner margin, 2px outer margin */ +::-webkit-scrollbar { + width: 10px; /* 6px bar + 2px inner margin on each side */ + height: 10px; +} + +::-webkit-scrollbar-track { + background: transparent; +} + +::-webkit-scrollbar-thumb { + background: hsl(var(--muted-foreground) / 0.2); + border-radius: 3px; + border: 2px solid transparent; + background-clip: padding-box; +} + +::-webkit-scrollbar-thumb:hover { + background: hsl(var(--muted-foreground) / 0.35); + border: 2px solid transparent; + background-clip: padding-box; +} + +/* Firefox scrollbar */ +* { + scrollbar-width: thin; + scrollbar-color: hsl(var(--muted-foreground) / 0.25) transparent; +} + +/* Hide scrollbar for some elements */ +.hide-scrollbar::-webkit-scrollbar { + display: none; +} + +.hide-scrollbar { + -ms-overflow-style: none; + scrollbar-width: none; +} + +/* Scroll containers inside panels should keep scrollbars inset */ +.panel-scroll { + scrollbar-gutter: stable; +} + +/* Dockview theme overrides (match HyperView tokens) */ +.hyperview-dockview { + --dv-background-color: hsl(var(--background)); + --dv-group-view-background-color: hsl(var(--card)); + --dv-tabs-and-actions-container-background-color: hsl(var(--secondary)); + --dv-activegroup-visiblepanel-tab-background-color: hsl(var(--card)); + --dv-activegroup-hiddenpanel-tab-background-color: hsl(var(--secondary)); + --dv-inactivegroup-visiblepanel-tab-background-color: hsl(var(--secondary)); + --dv-inactivegroup-hiddenpanel-tab-background-color: hsl(var(--secondary)); + --dv-activegroup-visiblepanel-tab-color: hsl(var(--foreground)); + --dv-activegroup-hiddenpanel-tab-color: hsl(var(--muted-foreground)); + --dv-inactivegroup-visiblepanel-tab-color: hsl(var(--muted-foreground)); + --dv-inactivegroup-hiddenpanel-tab-color: hsl(var(--muted-foreground)); + --dv-tabs-and-actions-container-font-size: 12px; + --dv-tabs-and-actions-container-height: 24px; + --dv-tab-font-size: 12px; + --dv-tabs-container-scrollbar-color: hsl(var(--muted-foreground) / 0.25); + --dv-scrollbar-background-color: hsl(var(--muted-foreground) / 0.25); + --dv-tab-divider-color: hsl(var(--border)); + --dv-separator-border: transparent; + --dv-paneview-header-border-color: hsl(var(--border)); + --dv-sash-color: hsl(var(--border)); + --dv-icon-hover-background-color: hsl(var(--accent)); + --dv-active-sash-color: hsl(var(--primary)); + --dv-drag-over-background-color: hsl(var(--primary) / 0.15); + --dv-drag-over-border-color: hsl(var(--primary) / 0.6); + /* Remove tab margins for flush appearance */ + --dv-tab-margin: 0; +} + +/* Remove any gaps between panels - Rerun-style flush layout */ +.hyperview-dockview .dv-groupview { + border: none; +} + +.hyperview-dockview .dv-tabs-and-actions-container { + border-bottom: 1px solid hsl(var(--border)); +} + +.hyperview-dockview .dv-tab { + padding: 0 8px; + height: 100%; + display: flex; + align-items: center; + line-height: 16px; +} + +.hyperview-dockview .dv-scrollable .dv-scrollbar-horizontal { + height: 6px; + border-radius: 3px; +} + +/* Hide Dockview tab scrollbars (avoid extra bar under tabs) */ +.hyperview-dockview .dv-tabs-container { + scrollbar-width: none; +} + +.hyperview-dockview .dv-tabs-container::-webkit-scrollbar { + height: 0; +} + +.hyperview-dockview .dv-scrollable .dv-scrollbar-horizontal { + display: none; +} + +/* Sash styling: transparent hit area with centered 1px visible line via pseudo-element */ +.hyperview-dockview .dv-split-view-container > .dv-sash-container > .dv-sash { + /* Keep the sash itself transparent - we'll draw the line with ::after */ + background-color: transparent !important; +} + +/* Horizontal sash (vertical divider line) */ +.hyperview-dockview .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash::after { + content: ""; + position: absolute; + top: 0; + bottom: 0; + left: 50%; + transform: translateX(-50%); + width: 1px; + background-color: hsl(var(--border)); + pointer-events: none; +} + +.hyperview-dockview .dv-split-view-container.dv-horizontal > .dv-sash-container > .dv-sash.dv-enabled:hover::after { + background-color: hsl(var(--primary)); +} + +/* Vertical sash (horizontal divider line) */ +.hyperview-dockview .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash::after { + content: ""; + position: absolute; + left: 0; + right: 0; + top: 50%; + transform: translateY(-50%); + height: 1px; + background-color: hsl(var(--border)); + pointer-events: none; +} + +.hyperview-dockview .dv-split-view-container.dv-vertical > .dv-sash-container > .dv-sash.dv-enabled:hover::after { + background-color: hsl(var(--primary)); +} diff --git a/frontend/src/app/layout.tsx b/frontend/src/app/layout.tsx new file mode 100644 index 0000000000000000000000000000000000000000..6af29dfb6eac948f47f5238c0ff22440343da254 --- /dev/null +++ b/frontend/src/app/layout.tsx @@ -0,0 +1,26 @@ +import type { Metadata } from "next"; +import { Inter } from "next/font/google"; +import "./globals.css"; + +const inter = Inter({ + subsets: ["latin"], + display: "swap", + weight: ["400", "500"], +}); + +export const metadata: Metadata = { + title: "HyperView", + description: "Dataset visualization with hyperbolic embeddings", +}; + +export default function RootLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + return ( + + {children} + + ); +} diff --git a/frontend/src/app/page.tsx b/frontend/src/app/page.tsx new file mode 100644 index 0000000000000000000000000000000000000000..a04d1881b2df42bc324a153ca566818811307bd3 --- /dev/null +++ b/frontend/src/app/page.tsx @@ -0,0 +1,277 @@ +"use client"; + +import { useEffect, useCallback, useMemo, useRef, useState } from "react"; +import { Header } from "@/components"; +import { DockviewWorkspace, DockviewProvider } from "@/components/DockviewWorkspace"; +import { useStore } from "@/store/useStore"; +import type { Sample } from "@/types"; +import { + fetchDataset, + fetchSamples, + fetchSamplesBatch, + fetchLassoSelection, +} from "@/lib/api"; + +const SAMPLES_PER_PAGE = 100; + +export default function Home() { + const { + samples, + totalSamples, + samplesLoaded, + setSamples, + appendSamples, + addSamplesIfMissing, + setDatasetInfo, + setIsLoading, + isLoading, + error, + setError, + selectedIds, + isLassoSelection, + selectionSource, + lassoQuery, + lassoSamples, + lassoTotal, + lassoIsLoading, + setLassoResults, + labelFilter, + } = useStore(); + + const [loadingMore, setLoadingMore] = useState(false); + const labelFilterRef = useRef(labelFilter ?? null); + + // Initial data load - runs once on mount + // Store setters are stable and don't need to be in deps + useEffect(() => { + const loadData = async () => { + setIsLoading(true); + setError(null); + + try { + // Fetch dataset info and samples in parallel + const [datasetInfo, samplesRes] = await Promise.all([ + fetchDataset(), + fetchSamples(0, SAMPLES_PER_PAGE), + ]); + + setDatasetInfo(datasetInfo); + setSamples(samplesRes.samples, samplesRes.total); + } catch (err) { + console.error("Failed to load data:", err); + setError(err instanceof Error ? err.message : "Failed to load data"); + } finally { + setIsLoading(false); + } + }; + + loadData(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + // Fetch selected samples that aren't already loaded + useEffect(() => { + const fetchSelectedSamples = async () => { + if (isLassoSelection) return; + if (selectedIds.size === 0) return; + if (selectionSource === "label") return; + + // Find IDs that are selected but not in our samples array + const loadedIds = new Set(samples.map((s) => s.id)); + const missingIds = Array.from(selectedIds).filter((id) => !loadedIds.has(id)); + + if (missingIds.length === 0) return; + + try { + const fetchedSamples = await fetchSamplesBatch(missingIds); + addSamplesIfMissing(fetchedSamples); + } catch (err) { + console.error("Failed to fetch selected samples:", err); + } + }; + + fetchSelectedSamples(); + }, [selectedIds, samples, addSamplesIfMissing, isLassoSelection, selectionSource]); + + // Refetch samples when label filter changes (non-lasso mode) + useEffect(() => { + if (labelFilterRef.current === labelFilter) return; + if (isLassoSelection) return; + + labelFilterRef.current = labelFilter ?? null; + + let cancelled = false; + const run = async () => { + try { + const res = await fetchSamples(0, SAMPLES_PER_PAGE, labelFilter ?? undefined); + if (cancelled) return; + setSamples(res.samples, res.total); + } catch (err) { + if (cancelled) return; + console.error("Failed to load filtered samples:", err); + } + }; + + run(); + return () => { + cancelled = true; + }; + }, [isLassoSelection, labelFilter, setSamples]); + + // Fetch initial lasso selection page when a new lasso query begins. + useEffect(() => { + if (!isLassoSelection) return; + if (!lassoQuery) return; + if (!lassoIsLoading) return; + + const abort = new AbortController(); + + const run = async () => { + try { + const res = await fetchLassoSelection({ + layoutKey: lassoQuery.layoutKey, + polygon: lassoQuery.polygon, + offset: 0, + limit: SAMPLES_PER_PAGE, + signal: abort.signal, + }); + if (abort.signal.aborted) return; + setLassoResults(res.samples, res.total, false); + } catch (err) { + if (err instanceof DOMException && err.name === "AbortError") return; + console.error("Failed to fetch lasso selection:", err); + setLassoResults([], 0, false); + } + }; + + run(); + + return () => abort.abort(); + }, [isLassoSelection, lassoIsLoading, lassoQuery, setLassoResults]); + + // Load more samples + const loadMore = useCallback(async () => { + if (loadingMore) return; + + if (isLassoSelection) { + if (!lassoQuery) return; + if (lassoIsLoading) return; + if (!lassoIsLoading && lassoSamples.length >= lassoTotal) return; + + setLoadingMore(true); + try { + const res = await fetchLassoSelection({ + layoutKey: lassoQuery.layoutKey, + polygon: lassoQuery.polygon, + offset: lassoSamples.length, + limit: SAMPLES_PER_PAGE, + }); + setLassoResults(res.samples, res.total, true); + } catch (err) { + console.error("Failed to load more lasso samples:", err); + } finally { + setLoadingMore(false); + } + return; + } + + if (samplesLoaded >= totalSamples) return; + + setLoadingMore(true); + try { + const res = await fetchSamples(samplesLoaded, SAMPLES_PER_PAGE, labelFilter ?? undefined); + appendSamples(res.samples); + } catch (err) { + console.error("Failed to load more samples:", err); + } finally { + setLoadingMore(false); + } + }, [ + loadingMore, + appendSamples, + isLassoSelection, + lassoIsLoading, + lassoQuery, + lassoSamples.length, + lassoTotal, + samplesLoaded, + totalSamples, + setLassoResults, + labelFilter, + ]); + + const displayedSamples = useMemo(() => { + if (isLassoSelection) return lassoSamples; + + // When a selection comes from the scatter plot, bring selected samples to the top + // so the user immediately sees what they clicked. + if (selectionSource === "scatter" && selectedIds.size > 0) { + const byId = new Map(); + for (const s of samples) byId.set(s.id, s); + + const pinned: Sample[] = []; + for (const id of selectedIds) { + const s = byId.get(id); + if (s) pinned.push(s); + } + + if (pinned.length > 0) { + const rest = samples.filter((s) => !selectedIds.has(s.id)); + return [...pinned, ...rest]; + } + } + + return samples; + }, [isLassoSelection, lassoSamples, samples, selectedIds, selectionSource]); + + const displayedTotal = isLassoSelection ? lassoTotal : totalSamples; + const displayedHasMore = isLassoSelection ? displayedSamples.length < displayedTotal : samplesLoaded < totalSamples; + + if (error) { + return ( +
+
+
+
+
Error
+
{error}
+

+ Make sure the HyperView backend is running on port 6262. +

+
+
+
+ ); + } + + if (isLoading) { + return ( +
+
+
+
+
+
Loading dataset...
+
+
+
+ ); + } + + return ( + +
+
+ + {/* Main content - dockable panels */} +
+ +
+
+
+ ); +} diff --git a/frontend/src/components/DockviewWorkspace.tsx b/frontend/src/components/DockviewWorkspace.tsx new file mode 100644 index 0000000000000000000000000000000000000000..42d3f41d0787e16d72b03a77171496a44531e36c --- /dev/null +++ b/frontend/src/components/DockviewWorkspace.tsx @@ -0,0 +1,765 @@ +"use client"; + +import React, { + useCallback, + useEffect, + useMemo, + useState, + createContext, + useContext, + type ReactNode, +} from "react"; +import { + DockviewReact, + type DockviewApi, + type DockviewReadyEvent, + type IDockviewPanelProps, + type IDockviewPanelHeaderProps, + type IWatermarkPanelProps, + themeAbyss, +} from "dockview"; +import { Circle, Disc, Grid3X3 } from "lucide-react"; + +import type { Geometry, Sample } from "@/types"; +import { useStore } from "@/store/useStore"; +import { findLayoutByGeometry } from "@/lib/layouts"; +import { ImageGrid } from "./ImageGrid"; +import { ScatterPanel } from "./ScatterPanel"; +import { ExplorerPanel } from "./ExplorerPanel"; +import { PlaceholderPanel } from "./PlaceholderPanel"; +import { HyperViewLogo } from "./icons"; + +const LAYOUT_STORAGE_KEY = "hyperview:dockview-layout:v4"; + +// Panel IDs +const PANEL = { + EXPLORER: "explorer", + GRID: "grid", + SCATTER_EUCLIDEAN: "scatter-euclidean", + SCATTER_POINCARE: "scatter-poincare", + SCATTER_DEFAULT: "scatter-default", + RIGHT_PLACEHOLDER: "right-placeholder", + BOTTOM_PLACEHOLDER: "bottom-placeholder", +} as const; + +const CENTER_PANEL_IDS = [ + PANEL.GRID, + PANEL.SCATTER_EUCLIDEAN, + PANEL.SCATTER_POINCARE, + PANEL.SCATTER_DEFAULT, +] as const; + +export const CENTER_PANEL_DEFS = [ + { id: PANEL.GRID, label: "Samples", icon: Grid3X3 }, + { id: PANEL.SCATTER_EUCLIDEAN, label: "Euclidean", icon: Circle }, + { id: PANEL.SCATTER_POINCARE, label: "Hyperbolic", icon: Disc }, +] as const; + +const NON_ANCHOR_PANEL_IDS = new Set([ + PANEL.EXPLORER, + PANEL.RIGHT_PLACEHOLDER, + PANEL.BOTTOM_PLACEHOLDER, +]); + +const DRAG_LOCKED_PANEL_IDS = new Set([PANEL.EXPLORER]); + +const DEFAULT_CONTAINER_WIDTH = 1200; +const DEFAULT_CONTAINER_HEIGHT = 800; +const MIN_SIDE_PANEL_WIDTH = 120; +const MIN_BOTTOM_PANEL_HEIGHT = 150; + +const getContainerWidth = (api?: DockviewApi | null) => + api?.width ?? + (typeof window === "undefined" ? DEFAULT_CONTAINER_WIDTH : window.innerWidth); +const getContainerHeight = (api?: DockviewApi | null) => + api?.height ?? + (typeof window === "undefined" ? DEFAULT_CONTAINER_HEIGHT : window.innerHeight); + +const getDefaultLeftPanelWidth = (screenWidth: number) => + Math.round(Math.min(0.35 * screenWidth, 200)); +const getDefaultRightPanelWidth = (screenWidth: number) => + Math.round(Math.min(0.45 * screenWidth, 300)); +const getDefaultBottomPanelHeight = (containerHeight: number) => + Math.round( + Math.min(Math.max(0.25 * containerHeight, MIN_BOTTOM_PANEL_HEIGHT), 250) + ); +const getBottomPanelMaxHeight = (containerHeight: number) => + Math.round( + Math.max(containerHeight - MIN_BOTTOM_PANEL_HEIGHT, MIN_BOTTOM_PANEL_HEIGHT) + ); + +function getCenterAnchorPanel(api: DockviewApi) { + for (const id of CENTER_PANEL_IDS) { + const panel = api.getPanel(id); + if (panel) return panel; + } + + const fallback = api.panels.find((panel) => !NON_ANCHOR_PANEL_IDS.has(panel.id)); + return fallback ?? api.activePanel; +} + +function getZonePosition(zone: "left" | "right" | "bottom") { + return { direction: zone === "bottom" ? "below" : zone }; +} + +function getCenterTabPosition(api: DockviewApi) { + const anchor = getCenterAnchorPanel(api); + if (!anchor) return undefined; + return { referencePanel: anchor, direction: "within" as const }; +} + +// ----------------------------------------------------------------------------- +// Context for sharing dockview API across components +// ----------------------------------------------------------------------------- +interface DockviewContextValue { + api: DockviewApi | null; + setApi: (api: DockviewApi) => void; + samples: Sample[]; + onLoadMore: () => void; + hasMore: boolean; +} + +const DockviewContext = createContext(null); + +function useDockviewContext() { + const ctx = useContext(DockviewContext); + if (!ctx) throw new Error("useDockviewContext must be used within DockviewProvider"); + return ctx; +} + +// Public hook for components like Header +export function useDockviewApi() { + const ctx = useContext(DockviewContext); + const datasetInfo = useStore((state) => state.datasetInfo); + const { + leftPanelOpen, + rightPanelOpen, + bottomPanelOpen, + setLeftPanelOpen, + setRightPanelOpen, + setBottomPanelOpen, + } = useStore(); + + const addPanel = useCallback( + (panelId: string) => { + if (!ctx?.api) return; + + const api = ctx.api; + const position = getCenterTabPosition(api); + const baseOptions = position ? { position } : {}; + + const layouts = datasetInfo?.layouts ?? []; + const euclideanLayout = findLayoutByGeometry(layouts, "euclidean"); + const poincareLayout = findLayoutByGeometry(layouts, "poincare"); + + // Don't add if already exists - just focus it + if (api.getPanel(panelId)) { + api.getPanel(panelId)?.focus(); + return; + } + + switch (panelId) { + case PANEL.GRID: + api.addPanel({ + id: PANEL.GRID, + component: "grid", + title: "Samples", + tabComponent: "samplesTab", + renderer: "always", + ...baseOptions, + }); + break; + + case PANEL.SCATTER_EUCLIDEAN: + api.addPanel({ + id: PANEL.SCATTER_EUCLIDEAN, + component: "scatter", + title: "Euclidean", + tabComponent: "euclideanTab", + params: { + layoutKey: euclideanLayout?.layout_key, + geometry: "euclidean" as Geometry, + }, + renderer: "always", + ...baseOptions, + }); + break; + + case PANEL.SCATTER_POINCARE: + api.addPanel({ + id: PANEL.SCATTER_POINCARE, + component: "scatter", + title: "Hyperbolic", + tabComponent: "hyperbolicTab", + params: { + layoutKey: poincareLayout?.layout_key, + geometry: "poincare" as Geometry, + }, + renderer: "always", + ...baseOptions, + }); + break; + } + }, + [ctx?.api, datasetInfo] + ); + + const resetLayout = useCallback(() => { + localStorage.removeItem(LAYOUT_STORAGE_KEY); + window.location.reload(); + }, []); + + // Toggle zone visibility + const toggleZone = useCallback( + (zone: "left" | "right" | "bottom") => { + if (!ctx?.api) return; + + const api = ctx.api; + const panelId = + zone === "left" + ? PANEL.EXPLORER + : zone === "right" + ? PANEL.RIGHT_PLACEHOLDER + : PANEL.BOTTOM_PLACEHOLDER; + const setOpen = + zone === "left" + ? setLeftPanelOpen + : zone === "right" + ? setRightPanelOpen + : setBottomPanelOpen; + const isOpen = + zone === "left" + ? leftPanelOpen + : zone === "right" + ? rightPanelOpen + : bottomPanelOpen; + + const existingPanel = api.getPanel(panelId); + + if (isOpen && existingPanel) { + existingPanel.api.close(); + setOpen(false); + return; + } + + if (isOpen) return; + + const containerWidth = getContainerWidth(api); + const containerHeight = getContainerHeight(api); + const position = getZonePosition(zone); + + let newPanel; + if (zone === "left") { + const targetWidth = getDefaultLeftPanelWidth(containerWidth); + newPanel = api.addPanel({ + id: panelId, + component: "explorer", + title: "Explorer", + position, + initialWidth: targetWidth, + minimumWidth: MIN_SIDE_PANEL_WIDTH, + maximumWidth: targetWidth, + }); + + if (newPanel) { + newPanel.group.locked = true; + newPanel.group.header.hidden = true; + // Explicitly set the width to ensure it's applied + newPanel.api.setSize({ width: targetWidth }); + } + } else if (zone === "right") { + newPanel = api.addPanel({ + id: panelId, + component: "placeholder", + title: "Blank", + position, + initialWidth: getDefaultRightPanelWidth(containerWidth), + minimumWidth: MIN_SIDE_PANEL_WIDTH, + maximumWidth: Math.round(containerWidth * 0.65), + }); + } else { + newPanel = api.addPanel({ + id: panelId, + component: "placeholder", + title: "Blank", + position, + initialHeight: getDefaultBottomPanelHeight(containerHeight), + minimumHeight: MIN_BOTTOM_PANEL_HEIGHT, + maximumHeight: getBottomPanelMaxHeight(containerHeight), + }); + } + + if (newPanel) { + setOpen(true); + // Activate the panel so its content renders immediately + newPanel.api.setActive(); + } + }, + [ + ctx?.api, + leftPanelOpen, + rightPanelOpen, + bottomPanelOpen, + setLeftPanelOpen, + setRightPanelOpen, + setBottomPanelOpen, + ] + ); + + if (!ctx) return null; + + return { + api: ctx.api, + addPanel, + resetLayout, + toggleZone, + }; +} + +// ----------------------------------------------------------------------------- +// Panel Components - stable references defined outside component +// ----------------------------------------------------------------------------- +type ScatterPanelParams = { + layoutKey?: string; + geometry?: Geometry; +}; + +const ScatterDockPanel = React.memo(function ScatterDockPanel( + props: IDockviewPanelProps +) { + const params = props.params ?? {}; + return ( + + ); +}); + +// Custom tab component with icon (like Rerun's "Image and segmentation mask" tab) +type TabWithIconProps = IDockviewPanelHeaderProps & { + icon: React.ReactNode; +}; + +const TabWithIcon = React.memo(function TabWithIcon({ api, icon }: TabWithIconProps) { + return ( +
+ {icon} + {api.title} +
+ ); +}); + +// Tab components for different panel types +const EuclideanTab = React.memo(function EuclideanTab(props: IDockviewPanelHeaderProps) { + return } />; +}); + +const HyperbolicTab = React.memo(function HyperbolicTab(props: IDockviewPanelHeaderProps) { + return } />; +}); + +const SamplesTab = React.memo(function SamplesTab(props: IDockviewPanelHeaderProps) { + return } />; +}); + +// Grid panel uses context to get samples +const GridDockPanel = React.memo(function GridDockPanel() { + const ctx = useDockviewContext(); + return ( + + ); +}); + +// Explorer panel for left zone +const ExplorerDockPanel = React.memo(function ExplorerDockPanel() { + return ; +}); + +// Placeholder panel for right/bottom zones +const PlaceholderDockPanel = React.memo(function PlaceholderDockPanel( + props: IDockviewPanelProps +) { + const handleClose = React.useCallback(() => { + props.api.close(); + }, [props.api]); + + return ; +}); + +// Watermark shown when dock is empty - just the logo, no text +const Watermark = React.memo(function Watermark(_props: IWatermarkPanelProps) { + return ( +
+
+ +
+
+ ); +}); + +// Stable components object - never changes +const COMPONENTS = { + grid: GridDockPanel, + scatter: ScatterDockPanel, + explorer: ExplorerDockPanel, + placeholder: PlaceholderDockPanel, +}; + +// Tab components with icons +const TAB_COMPONENTS = { + euclideanTab: EuclideanTab, + hyperbolicTab: HyperbolicTab, + samplesTab: SamplesTab, +}; + +// ----------------------------------------------------------------------------- +// Provider Component +// ----------------------------------------------------------------------------- +interface DockviewProviderProps { + children: ReactNode; + samples: Sample[]; + onLoadMore: () => void; + hasMore: boolean; +} + +export function DockviewProvider({ + children, + samples, + onLoadMore, + hasMore, +}: DockviewProviderProps) { + const [api, setApi] = useState(null); + + const contextValue = useMemo( + () => ({ + api, + setApi, + samples, + onLoadMore, + hasMore, + }), + [api, samples, onLoadMore, hasMore] + ); + + return ( + + {children} + + ); +} + +function applyZonePolicies(api: DockviewApi) { + const explorer = api.getPanel(PANEL.EXPLORER); + if (explorer) { + explorer.group.locked = true; + explorer.group.header.hidden = true; + } + + // Hide tab headers for placeholder panels + const rightPlaceholder = api.getPanel(PANEL.RIGHT_PLACEHOLDER); + if (rightPlaceholder) { + rightPlaceholder.group.header.hidden = true; + } + + const bottomPlaceholder = api.getPanel(PANEL.BOTTOM_PLACEHOLDER); + if (bottomPlaceholder) { + bottomPlaceholder.group.header.hidden = true; + } +} + +// ----------------------------------------------------------------------------- +// Workspace Component - the actual dockview renderer +// ----------------------------------------------------------------------------- +export function DockviewWorkspace() { + const ctx = useDockviewContext(); + const datasetInfo = useStore((state) => state.datasetInfo); + const { setLeftPanelOpen, setRightPanelOpen, setBottomPanelOpen } = useStore(); + + const buildDefaultLayout = useCallback( + (api: DockviewApi) => { + const layouts = datasetInfo?.layouts ?? []; + const euclideanLayout = findLayoutByGeometry(layouts, "euclidean"); + const poincareLayout = findLayoutByGeometry(layouts, "poincare"); + const fallbackLayout = !euclideanLayout && !poincareLayout ? layouts[0] : null; + const hasLayouts = layouts.length > 0; + + // Create the grid panel first (center zone) + const gridPanel = + api.getPanel(PANEL.GRID) ?? + api.addPanel({ + id: PANEL.GRID, + component: "grid", + title: "Samples", + tabComponent: "samplesTab", + renderer: "always", + }); + + let scatterPanel: typeof gridPanel | null = null; + + if (hasLayouts && euclideanLayout) { + scatterPanel = + api.getPanel(PANEL.SCATTER_EUCLIDEAN) ?? + api.addPanel({ + id: PANEL.SCATTER_EUCLIDEAN, + component: "scatter", + title: "Euclidean", + tabComponent: "euclideanTab", + params: { + layoutKey: euclideanLayout.layout_key, + geometry: "euclidean" as Geometry, + }, + position: { + referencePanel: gridPanel.id, + direction: "right", + }, + renderer: "always", + }); + } + + if (hasLayouts && poincareLayout) { + const position = scatterPanel + ? { referencePanel: scatterPanel.id, direction: "within" as const } + : { referencePanel: gridPanel.id, direction: "right" as const }; + + const poincarePanel = + api.getPanel(PANEL.SCATTER_POINCARE) ?? + api.addPanel({ + id: PANEL.SCATTER_POINCARE, + component: "scatter", + title: "Hyperbolic", + tabComponent: "hyperbolicTab", + params: { + layoutKey: poincareLayout.layout_key, + geometry: "poincare" as Geometry, + }, + position, + renderer: "always", + }); + + if (!scatterPanel) { + scatterPanel = poincarePanel; + } + } + + if (!hasLayouts) { + const euclideanPanel = + api.getPanel(PANEL.SCATTER_EUCLIDEAN) ?? + api.addPanel({ + id: PANEL.SCATTER_EUCLIDEAN, + component: "scatter", + title: "Euclidean", + tabComponent: "euclideanTab", + params: { + geometry: "euclidean" as Geometry, + }, + position: { + referencePanel: gridPanel.id, + direction: "right", + }, + renderer: "always", + }); + + api.getPanel(PANEL.SCATTER_POINCARE) ?? + api.addPanel({ + id: PANEL.SCATTER_POINCARE, + component: "scatter", + title: "Hyperbolic", + tabComponent: "hyperbolicTab", + params: { + geometry: "poincare" as Geometry, + }, + position: { + referencePanel: euclideanPanel.id, + direction: "within" as const, + }, + renderer: "always", + }); + + scatterPanel = euclideanPanel; + } + + if (fallbackLayout && !scatterPanel) { + api.getPanel(PANEL.SCATTER_DEFAULT) ?? + api.addPanel({ + id: PANEL.SCATTER_DEFAULT, + component: "scatter", + title: "Embeddings", + params: { + layoutKey: fallbackLayout.layout_key, + }, + position: { + referencePanel: gridPanel.id, + direction: "right", + }, + renderer: "always", + }); + } + + const containerWidth = getContainerWidth(api); + const explorerPanel = + api.getPanel(PANEL.EXPLORER) ?? + api.addPanel({ + id: PANEL.EXPLORER, + component: "explorer", + title: "Explorer", + position: getZonePosition("left"), + initialWidth: getDefaultLeftPanelWidth(containerWidth), + minimumWidth: MIN_SIDE_PANEL_WIDTH, + maximumWidth: getDefaultLeftPanelWidth(containerWidth), + inactive: true, + }); + + if (explorerPanel) { + explorerPanel.group.locked = true; + explorerPanel.group.header.hidden = true; + } + + setLeftPanelOpen(!!explorerPanel); + setRightPanelOpen(false); + setBottomPanelOpen(false); + }, + [datasetInfo, setLeftPanelOpen, setRightPanelOpen, setBottomPanelOpen] + ); + + const onReady = useCallback( + (event: DockviewReadyEvent) => { + ctx.setApi(event.api); + + const stored = localStorage.getItem(LAYOUT_STORAGE_KEY); + if (stored) { + try { + event.api.fromJSON(JSON.parse(stored)); + if (event.api.totalPanels === 0) { + localStorage.removeItem(LAYOUT_STORAGE_KEY); + buildDefaultLayout(event.api); + } + + // Re-apply side-zone policies after restore (header hidden, no-drop targets, etc) + applyZonePolicies(event.api); + + // Sync store state with restored layout + setLeftPanelOpen(!!event.api.getPanel(PANEL.EXPLORER)); + setRightPanelOpen(!!event.api.getPanel(PANEL.RIGHT_PLACEHOLDER)); + setBottomPanelOpen(!!event.api.getPanel(PANEL.BOTTOM_PLACEHOLDER)); + return; + } catch (err) { + console.warn("Failed to restore dock layout, resetting.", err); + localStorage.removeItem(LAYOUT_STORAGE_KEY); + } + } + + if (event.api.totalPanels === 0) { + buildDefaultLayout(event.api); + } + }, + [buildDefaultLayout, ctx, setLeftPanelOpen, setRightPanelOpen, setBottomPanelOpen] + ); + + // Save layout on changes + useEffect(() => { + const api = ctx.api; + if (!api) return; + + const disposable = api.onDidLayoutChange(() => { + if (api.totalPanels === 0) return; + const layout = api.toJSON(); + localStorage.setItem(LAYOUT_STORAGE_KEY, JSON.stringify(layout)); + }); + + return () => disposable.dispose(); + }, [ctx.api]); + + // Sync panel state when panels are closed + useEffect(() => { + const api = ctx.api; + if (!api) return; + + const disposable = api.onDidRemovePanel((e) => { + if (e.id === PANEL.EXPLORER) setLeftPanelOpen(false); + if (e.id === PANEL.RIGHT_PLACEHOLDER) setRightPanelOpen(false); + if (e.id === PANEL.BOTTOM_PLACEHOLDER) setBottomPanelOpen(false); + }); + + return () => disposable.dispose(); + }, [ctx.api, setLeftPanelOpen, setRightPanelOpen, setBottomPanelOpen]); + + // When a real panel is dropped into a placeholder group, close the placeholder + useEffect(() => { + const api = ctx.api; + if (!api) return; + + const disposable = api.onDidAddPanel((e) => { + // Skip if the added panel is a placeholder itself + if (e.id === PANEL.RIGHT_PLACEHOLDER || e.id === PANEL.BOTTOM_PLACEHOLDER) { + return; + } + + // Check if this panel was added to the same group as a placeholder + const group = e.group; + if (!group) return; + + // Find and close any placeholder panels in the same group + const rightPlaceholder = api.getPanel(PANEL.RIGHT_PLACEHOLDER); + const bottomPlaceholder = api.getPanel(PANEL.BOTTOM_PLACEHOLDER); + + if (rightPlaceholder && rightPlaceholder.group?.id === group.id) { + rightPlaceholder.api.close(); + } + if (bottomPlaceholder && bottomPlaceholder.group?.id === group.id) { + bottomPlaceholder.api.close(); + } + }); + + return () => disposable.dispose(); + }, [ctx.api]); + + // Prevent dragging locked panels (explorer only) + useEffect(() => { + const api = ctx.api; + if (!api) return; + + const disposable = api.onWillDragPanel((event) => { + if (DRAG_LOCKED_PANEL_IDS.has(event.panel.id)) { + event.nativeEvent.preventDefault(); + } + }); + + return () => disposable.dispose(); + }, [ctx.api]); + + // Rebuild layout when dataset info changes + useEffect(() => { + if (!ctx.api) return; + if (!datasetInfo) return; + + const hasScatter = + ctx.api.getPanel(PANEL.SCATTER_EUCLIDEAN) || + ctx.api.getPanel(PANEL.SCATTER_POINCARE) || + ctx.api.getPanel(PANEL.SCATTER_DEFAULT); + + if (!hasScatter) { + buildDefaultLayout(ctx.api); + } + }, [buildDefaultLayout, datasetInfo, ctx.api]); + + return ( +
+ +
+ ); +} diff --git a/frontend/src/components/ExplorerPanel.tsx b/frontend/src/components/ExplorerPanel.tsx new file mode 100644 index 0000000000000000000000000000000000000000..4942f725c44655970bd2d2c53656041a19cbf122 --- /dev/null +++ b/frontend/src/components/ExplorerPanel.tsx @@ -0,0 +1,181 @@ +"use client"; + +import React from "react"; +import { useStore } from "@/store/useStore"; +import { Panel } from "./Panel"; +import { PanelHeader } from "./PanelHeader"; +import { Tag, Search, ChevronDown, ChevronRight } from "lucide-react"; +import { cn } from "@/lib/utils"; +import { FALLBACK_LABEL_COLOR, MISSING_LABEL_COLOR, normalizeLabel } from "@/lib/labelColors"; +import { useLabelLegend } from "./useLabelLegend"; + +interface ExplorerPanelProps { + className?: string; +} + +export function ExplorerPanel({ className }: ExplorerPanelProps) { + const { + datasetInfo, + embeddingsByLayoutKey, + activeLayoutKey, + labelFilter, + setLabelFilter, + } = useStore(); + const [labelSearch, setLabelSearch] = React.useState(""); + const [isSearchOpen, setIsSearchOpen] = React.useState(false); + const [isLabelsExpanded, setIsLabelsExpanded] = React.useState(true); + const searchInputRef = React.useRef(null); + + const resolvedLayoutKey = + activeLayoutKey ?? datasetInfo?.layouts?.[0]?.layout_key ?? null; + const embeddings = resolvedLayoutKey + ? embeddingsByLayoutKey[resolvedLayoutKey] ?? null + : null; + + const { + labelCounts, + labelUniverse, + distinctLabelCount, + distinctColoringDisabled, + labelColorMap, + legendLabels, + } = useLabelLegend({ datasetInfo, embeddings, labelSearch, labelFilter }); + + const hasCounts = labelCounts.size > 0; + const baseLabelCount = labelUniverse.length > 0 + ? labelUniverse.filter((label) => label !== "undefined").length + : distinctLabelCount; + const displayCount = labelSearch.trim().length > 0 + ? legendLabels.length + : baseLabelCount; + + const activeLabel = labelFilter ? normalizeLabel(labelFilter) : null; + + // Focus search input when opened + React.useEffect(() => { + if (isSearchOpen && searchInputRef.current) { + searchInputRef.current.focus(); + } + }, [isSearchOpen]); + + const handleSearchToggle = () => { + setIsSearchOpen(!isSearchOpen); + if (isSearchOpen) { + setLabelSearch(""); + } + }; + + return ( + + + + {/* Scrollable content area */} +
+ {/* Labels section */} +
+ {/* Section header - collapsible with search icon */} +
+ + + {/* Search toggle button */} + +
+ + {/* Search input - shown when search is toggled */} + {isSearchOpen && ( +
+ setLabelSearch(e.target.value)} + placeholder="Filter labels..." + className="w-full h-6 px-2 rounded bg-background border border-border text-[12px] leading-[16px] text-foreground placeholder:text-muted-foreground/50 outline-none focus:ring-1 focus:ring-ring focus:border-ring" + /> +
+ )} + + {/* Labels list - collapsible */} + {isLabelsExpanded && ( +
+ {distinctColoringDisabled && ( +
+ Too many labels ({distinctLabelCount}) to color distinctly; using one color. +
+ )} + + {legendLabels.length === 0 ? ( +
+ No labels available +
+ ) : ( +
+ {legendLabels.map((label) => { + const color = + label === "undefined" + ? MISSING_LABEL_COLOR + : labelColorMap[label] ?? FALLBACK_LABEL_COLOR; + const normalized = normalizeLabel(label); + const isActive = activeLabel === normalized; + const isDimmed = activeLabel && !isActive; + + return ( + + ); + })} +
+ )} +
+ )} +
+
+
+ ); +} diff --git a/frontend/src/components/Header.tsx b/frontend/src/components/Header.tsx new file mode 100644 index 0000000000000000000000000000000000000000..59709696847254c35c1e2a1e41cca9af85fd1614 --- /dev/null +++ b/frontend/src/components/Header.tsx @@ -0,0 +1,244 @@ +"use client"; + +import { useStore } from "@/store/useStore"; +import { Button } from "@/components/ui/button"; +import { HyperViewLogo, DiscordIcon } from "./icons"; +import { CENTER_PANEL_DEFS, useDockviewApi } from "./DockviewWorkspace"; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from "@/components/ui/command"; +import { + ChevronDown, + RotateCcw, + Check, + PanelLeft, + PanelBottom, + PanelRight, + Settings, + Search, +} from "lucide-react"; +import { useState } from "react"; +import { cn } from "@/lib/utils"; + +const PANEL_CONFIG = CENTER_PANEL_DEFS; +const DISCORD_URL = process.env.NEXT_PUBLIC_DISCORD_URL ?? "https://discord.gg/Qf2pXtY4Vf"; + +export function Header() { + const { datasetInfo, leftPanelOpen, rightPanelOpen, bottomPanelOpen } = useStore(); + const dockview = useDockviewApi(); + const [datasetPickerOpen, setDatasetPickerOpen] = useState(false); + + const handlePanelToggle = (panelId: string) => { + if (!dockview?.api) return; + const panel = dockview.api.getPanel(panelId); + if (panel) { + panel.api.close(); + return; + } + dockview.addPanel(panelId); + }; + + // Check which panels are currently open + const openPanels = new Set( + PANEL_CONFIG.map((p) => p.id).filter((id) => dockview?.api?.getPanel(id)) + ); + + return ( +
+ {/* Left side: Logo + View menu */} +
+ {/* Logo */} +
+ +
+ + {/* View dropdown */} + {dockview && ( + + + + + + {/* Panel toggles - no section header, similar to Rerun */} + {PANEL_CONFIG.map((panel) => { + const Icon = panel.icon; + const isOpen = openPanels.has(panel.id); + return ( + handlePanelToggle(panel.id)} + className="flex items-center justify-between h-7 text-[12px] leading-[16px]" + > + + + {panel.label} + + {isOpen && } + + ); + })} + + {/* Spacer */} +
+ + {/* Reset layout */} + dockview.resetLayout()} + className="flex items-center gap-2 h-7 text-[12px] leading-[16px]" + > + + Reset Layout + + + + )} +
+ + {/* Center: Dataset picker (VS Code style command palette trigger) */} +
+ + + + + + + + + + No datasets found. + + + {/* Currently only show the loaded dataset */} + {datasetInfo && ( + setDatasetPickerOpen(false)} + className="text-[12px] leading-[16px]" + > + {datasetInfo.name} + + {datasetInfo.num_samples.toLocaleString()} samples + + + + )} + + + + + +
+ + {/* Right side: Discord + Panel toggles + Settings */} +
+ {/* Discord link */} + + + + + {/* Separator */} +
+ + {/* Left panel toggle */} + + + {/* Bottom panel toggle */} + + + {/* Right panel toggle */} + + + {/* Separator */} +
+ + {/* Settings button */} + +
+
+ ); +} diff --git a/frontend/src/components/ImageGrid.tsx b/frontend/src/components/ImageGrid.tsx new file mode 100644 index 0000000000000000000000000000000000000000..7e1e45771435463039fbc93cb16e9731e84ac116 --- /dev/null +++ b/frontend/src/components/ImageGrid.tsx @@ -0,0 +1,338 @@ +"use client"; + +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; +import { useVirtualizer } from "@tanstack/react-virtual"; +import justifiedLayout from "justified-layout"; +import { useStore } from "@/store/useStore"; +import { Panel } from "./Panel"; +import { CheckIcon } from "./icons"; +import type { Sample } from "@/types"; + +interface ImageGridProps { + samples: Sample[]; + onLoadMore?: () => void; + hasMore?: boolean; +} + +// Justified layout config +const BOX_SPACING = 2; // Tight spacing between images +const TARGET_ROW_HEIGHT = 180; // Target height for rows +const DEFAULT_ASPECT_RATIO = 1; // Fallback for samples without dimensions + +/** + * Get aspect ratio from sample, with fallback + */ +function getAspectRatio(sample: Sample): number { + if (sample.width && sample.height && sample.height > 0) { + return sample.width / sample.height; + } + return DEFAULT_ASPECT_RATIO; +} + +/** + * Compute justified layout geometry for samples + */ +function computeLayout( + samples: Sample[], + containerWidth: number +): { boxes: Array<{ width: number; height: number; top: number; left: number }>; containerHeight: number } { + if (samples.length === 0 || containerWidth <= 0) { + return { boxes: [], containerHeight: 0 }; + } + + const aspectRatios = samples.map(getAspectRatio); + + const geometry = justifiedLayout(aspectRatios, { + containerWidth, + containerPadding: 0, + boxSpacing: BOX_SPACING, + targetRowHeight: TARGET_ROW_HEIGHT, + targetRowHeightTolerance: 0.25, + showWidows: true, // Always show last row even if incomplete + }); + + return { + boxes: geometry.boxes, + containerHeight: geometry.containerHeight, + }; +} + +/** + * Group boxes into rows for virtualization + */ +interface RowData { + startIndex: number; + endIndex: number; // exclusive + top: number; + height: number; +} + +function groupIntoRows( + boxes: Array<{ width: number; height: number; top: number; left: number }> +): RowData[] { + if (boxes.length === 0) return []; + + const rows: RowData[] = []; + let currentRowTop = boxes[0].top; + let currentRowStart = 0; + let currentRowHeight = boxes[0].height; + + for (let i = 1; i < boxes.length; i++) { + const box = boxes[i]; + // New row if top position changes significantly + if (Math.abs(box.top - currentRowTop) > 1) { + rows.push({ + startIndex: currentRowStart, + endIndex: i, + top: currentRowTop, + height: currentRowHeight, + }); + currentRowStart = i; + currentRowTop = box.top; + currentRowHeight = box.height; + } else { + // Same row - take max height in case of slight variations + currentRowHeight = Math.max(currentRowHeight, box.height); + } + } + + // Push final row + rows.push({ + startIndex: currentRowStart, + endIndex: boxes.length, + top: currentRowTop, + height: currentRowHeight, + }); + + return rows; +} + +export function ImageGrid({ samples, onLoadMore, hasMore }: ImageGridProps) { + const containerRef = useRef(null); + const [containerWidth, setContainerWidth] = useState(0); + + const { + selectedIds, + isLassoSelection, + selectionSource, + toggleSelection, + addToSelection, + setHoveredId, + hoveredId, + labelFilter, + } = useStore(); + + // Track container width for layout computation + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const updateWidth = () => { + const width = container.clientWidth; + if (width > 0 && width !== containerWidth) { + setContainerWidth(width); + } + }; + + updateWidth(); + + const resizeObserver = new ResizeObserver(() => { + requestAnimationFrame(updateWidth); + }); + resizeObserver.observe(container); + + return () => resizeObserver.disconnect(); + }, [containerWidth]); + + // Compute justified layout + const { boxes, containerHeight } = useMemo( + () => computeLayout(samples, containerWidth), + [samples, containerWidth] + ); + + // Group into rows for virtualization + const rows = useMemo(() => groupIntoRows(boxes), [boxes]); + + // Virtualizer for rows + const virtualizer = useVirtualizer({ + count: rows.length, + getScrollElement: () => containerRef.current, + estimateSize: (index) => rows[index]?.height ?? TARGET_ROW_HEIGHT, + overscan: 3, + getItemKey: (index) => { + const row = rows[index]; + if (!row) return `row-${index}`; + // Create stable key from sample IDs in this row + const rowSamples = samples.slice(row.startIndex, row.endIndex); + return rowSamples.map((s) => s.id).join("-") || `row-${index}`; + }, + }); + + // Load more when scrolling near bottom + useEffect(() => { + const container = containerRef.current; + if (!container || !onLoadMore || !hasMore) return; + + const handleScroll = () => { + const { scrollTop, scrollHeight, clientHeight } = container; + if (scrollHeight - scrollTop - clientHeight < 500) { + onLoadMore(); + } + }; + + container.addEventListener("scroll", handleScroll); + return () => container.removeEventListener("scroll", handleScroll); + }, [onLoadMore, hasMore]); + + // Reset scroll on filter change + useEffect(() => { + containerRef.current?.scrollTo({ top: 0 }); + }, [labelFilter]); + + // Scroll to top when scatter selection made + useEffect(() => { + if (isLassoSelection) return; + if (selectionSource !== "scatter") return; + if (selectedIds.size === 0) return; + + try { + virtualizer.scrollToIndex(0, { align: "start" }); + } catch { + containerRef.current?.scrollTo({ top: 0 }); + } + }, [isLassoSelection, selectedIds, selectionSource, virtualizer]); + + // Handle click with selection logic + const handleClick = useCallback( + (sample: Sample, event: React.MouseEvent) => { + if (event.metaKey || event.ctrlKey) { + toggleSelection(sample.id); + } else if (event.shiftKey && selectedIds.size > 0) { + const selectedArray = Array.from(selectedIds); + const lastSelected = selectedArray[selectedArray.length - 1]; + const lastIndex = samples.findIndex((s) => s.id === lastSelected); + const currentIndex = samples.findIndex((s) => s.id === sample.id); + + if (lastIndex !== -1 && currentIndex !== -1) { + const start = Math.min(lastIndex, currentIndex); + const end = Math.max(lastIndex, currentIndex); + const rangeIds = samples.slice(start, end + 1).map((s) => s.id); + addToSelection(rangeIds); + } + } else { + const newSet = new Set(); + newSet.add(sample.id); + useStore.getState().setSelectedIds(newSet, "grid"); + } + }, + [samples, selectedIds, toggleSelection, addToSelection] + ); + + const virtualRows = virtualizer.getVirtualItems(); + + return ( + +
+
+
+ {virtualRows.map((virtualRow) => { + const row = rows[virtualRow.index]; + if (!row) return null; + + const rowSamples = samples.slice(row.startIndex, row.endIndex); + const rowBoxes = boxes.slice(row.startIndex, row.endIndex); + + return ( +
+ {rowSamples.map((sample, i) => { + const box = rowBoxes[i]; + if (!box) return null; + + const isSelected = isLassoSelection ? true : selectedIds.has(sample.id); + const isHovered = hoveredId === sample.id; + + return ( +
handleClick(sample, e)} + onMouseEnter={() => setHoveredId(sample.id)} + onMouseLeave={() => setHoveredId(null)} + > + {/* Image container - justified layout sizes tile to preserve aspect ratio */} + {/* Future: overlays (segmentations, bboxes) will be absolutely positioned here */} + {sample.thumbnail ? ( + // eslint-disable-next-line @next/next/no-img-element + {sample.filename} + ) : ( +
+ No image +
+ )} + + {/* Label badge */} + {sample.label && ( +
+ + {sample.label} + +
+ )} + + {/* Selection indicator */} + {isSelected && ( +
+ +
+ )} +
+ ); + })} +
+ ); + })} +
+
+
+
+ ); +} diff --git a/frontend/src/components/Panel.tsx b/frontend/src/components/Panel.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5058fa5262238a2140eda945c1beaada35e07d6b --- /dev/null +++ b/frontend/src/components/Panel.tsx @@ -0,0 +1,43 @@ +"use client"; + +import { ReactNode } from "react"; +import { cn } from "@/lib/utils"; + +interface PanelProps { + children: ReactNode; + className?: string; +} + +/** + * Base panel container with consistent Rerun-style appearance. + * No borders or rounded corners - panels should be flush against each other. + */ +export function Panel({ children, className }: PanelProps) { + return ( +
+ {children} +
+ ); +} + +interface PanelFooterProps { + children: ReactNode; + className?: string; +} + +/** + * Panel footer for keyboard shortcuts/hints. + */ +export function PanelFooter({ children, className }: PanelFooterProps) { + return ( +
+ {children} +
+ ); +} diff --git a/frontend/src/components/PanelHeader.tsx b/frontend/src/components/PanelHeader.tsx new file mode 100644 index 0000000000000000000000000000000000000000..78201c45d32e6b6acfb512d001d7061ed024eab6 --- /dev/null +++ b/frontend/src/components/PanelHeader.tsx @@ -0,0 +1,47 @@ +"use client"; + +import { ReactNode } from "react"; +import { cn } from "@/lib/utils"; + +interface PanelHeaderProps { + icon?: ReactNode; + title: string; + subtitle?: string; + children?: ReactNode; // Toolbar actions slot + className?: string; +} + +/** + * Rerun-style panel header with icon, title, and optional toolbar. + * + * Design tokens (from Rerun): + * - Title bar height: 24px + * - Icon size: 14px (3.5 tailwind units) + * - Icon-to-text gap: 4px (gap-1) + * - Font size: 12px with -0.15px tracking + * - Section header font: 11px uppercase + */ +export function PanelHeader({ icon, title, subtitle, children, className }: PanelHeaderProps) { + return ( +
+
+ {icon && ( + // 14px icon (3.5 tailwind units) with 4px gap to text + {icon} + )} + {/* 12px font, medium weight, tight tracking */} + {title} + {subtitle && ( + {subtitle} + )} +
+ {children && ( +
{children}
+ )} +
+ ); +} diff --git a/frontend/src/components/PlaceholderPanel.tsx b/frontend/src/components/PlaceholderPanel.tsx new file mode 100644 index 0000000000000000000000000000000000000000..bf760facad3c605563141d83205b52f6321fd4c2 --- /dev/null +++ b/frontend/src/components/PlaceholderPanel.tsx @@ -0,0 +1,39 @@ +"use client"; + +import React from "react"; +import { HyperViewLogo } from "./icons"; +import { Panel } from "./Panel"; +import { cn } from "@/lib/utils"; +import { X } from "lucide-react"; + +interface PlaceholderPanelProps { + className?: string; + onClose?: () => void; +} + +/** + * Empty placeholder panel with centered HyperView logo and a close button. + * Used for right and bottom zones that are reserved for future features. + * The close button is always visible in the top-right corner of the panel content. + */ +export function PlaceholderPanel({ className, onClose }: PlaceholderPanelProps) { + return ( + + {/* Close button always visible in top right */} + {onClose && ( + + )} +
+
+ +
+
+
+ ); +} diff --git a/frontend/src/components/ScatterPanel.tsx b/frontend/src/components/ScatterPanel.tsx new file mode 100644 index 0000000000000000000000000000000000000000..fc68cd6f00e24eabc8c317d30978218a3c393b74 --- /dev/null +++ b/frontend/src/components/ScatterPanel.tsx @@ -0,0 +1,174 @@ +"use client"; + +import { useCallback, useEffect, useMemo, useState } from "react"; +import { useStore } from "@/store/useStore"; +import { Panel } from "./Panel"; +import { useHyperScatter } from "./useHyperScatter"; +import { useLabelLegend } from "./useLabelLegend"; +import type { Geometry } from "@/types"; +import { findLayoutByGeometry, listAvailableGeometries } from "@/lib/layouts"; +import { fetchEmbeddings } from "@/lib/api"; + +interface ScatterPanelProps { + className?: string; + layoutKey?: string; + geometry?: Geometry; +} + +export function ScatterPanel({ + className = "", + layoutKey, + geometry, +}: ScatterPanelProps) { + const { + datasetInfo, + embeddingsByLayoutKey, + setEmbeddingsForLayout, + selectedIds, + setSelectedIds, + beginLassoSelection, + hoveredId, + setHoveredId, + setActiveLayoutKey, + labelFilter, + } = useStore(); + + const [localGeometry, setLocalGeometry] = useState("euclidean"); + + // Check which geometries are available + const availableGeometries = useMemo(() => { + return listAvailableGeometries(datasetInfo?.layouts ?? []); + }, [datasetInfo?.layouts]); + + useEffect(() => { + if (geometry) return; + if (availableGeometries.length === 0) return; + if (!availableGeometries.includes(localGeometry)) { + setLocalGeometry(availableGeometries[0]); + } + }, [availableGeometries, geometry, localGeometry]); + + const resolvedGeometry = geometry ?? localGeometry; + + const resolvedLayoutKey = useMemo(() => { + if (!datasetInfo) return layoutKey ?? null; + + if (layoutKey) { + const exists = datasetInfo.layouts.some((layout) => layout.layout_key === layoutKey); + if (exists) return layoutKey; + } + + const layout = findLayoutByGeometry(datasetInfo.layouts, resolvedGeometry); + return layout?.layout_key ?? datasetInfo.layouts[0]?.layout_key ?? null; + }, [datasetInfo, layoutKey, resolvedGeometry]); + + const embeddings = resolvedLayoutKey ? embeddingsByLayoutKey[resolvedLayoutKey] ?? null : null; + + useEffect(() => { + if (!resolvedLayoutKey) return; + setActiveLayoutKey(resolvedLayoutKey); + }, [resolvedLayoutKey, setActiveLayoutKey]); + + useEffect(() => { + if (!resolvedLayoutKey) return; + if (embeddingsByLayoutKey[resolvedLayoutKey]) return; + + let cancelled = false; + + fetchEmbeddings(resolvedLayoutKey) + .then((data) => { + if (cancelled) return; + setEmbeddingsForLayout(resolvedLayoutKey, data); + }) + .catch((err) => { + if (cancelled) return; + console.error("Failed to load embeddings:", err); + }) + + return () => { + cancelled = true; + }; + }, [embeddingsByLayoutKey, resolvedLayoutKey, setEmbeddingsForLayout]); + + const { labelsInfo } = useLabelLegend({ datasetInfo, embeddings, labelFilter }); + + const { + canvasRef, + overlayCanvasRef, + containerRef, + handlePointerDown, + handlePointerMove, + handlePointerUp, + handlePointerLeave, + handleDoubleClick, + rendererError, + } = useHyperScatter({ + embeddings, + labelsInfo, + selectedIds, + hoveredId, + setSelectedIds, + beginLassoSelection, + setHoveredId, + hoverEnabled: !labelFilter, + }); + + const focusLayout = useCallback(() => { + if (!resolvedLayoutKey) return; + setActiveLayoutKey(resolvedLayoutKey); + }, [resolvedLayoutKey, setActiveLayoutKey]); + + const loadingLabel = resolvedLayoutKey + ? "Loading embeddings..." + : "No embeddings layout available"; + + return ( + + {/* Main content area - min-h-0 prevents flex overflow */} +
+ {/* Canvas container */} +
+ { + focusLayout(); + handlePointerDown(e); + }} + onPointerMove={handlePointerMove} + onPointerUp={handlePointerUp} + onPointerCancel={handlePointerUp} + onPointerLeave={handlePointerLeave} + onDoubleClick={handleDoubleClick} + onPointerEnter={focusLayout} + /> + + {/* Lasso overlay (screen-space) */} + + + {/* Loading overlay */} + {rendererError ? ( +
+
+
Browser not supported
+
{rendererError}
+
+
+ ) : ( + !embeddings && ( +
+
{loadingLabel}
+
+ ) + )} +
+ +
+
+ ); +} diff --git a/frontend/src/components/icons.tsx b/frontend/src/components/icons.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2d385614eb7c2ec7110bb3127ebec44abddca6b0 --- /dev/null +++ b/frontend/src/components/icons.tsx @@ -0,0 +1,73 @@ +"use client"; + +/** + * Shared icons for HyperView UI. + * Using inline SVGs for simplicity (no extra icon library dependency). + */ + +export const GridIcon = () => ( + + + + + + +); + +export const ScatterIcon = () => ( + + + + + + + +); + +export const HyperViewLogo = ({ className = "w-5 h-5" }: { className?: string }) => ( + + + + + +); + +export const CheckIcon = () => ( + + + +); + +/** Euclidean geometry icon - flat grid */ +export const EuclideanIcon = () => ( + + + + + +); + +/** Poincaré disk icon - hyperbolic geometry */ +export const PoincareIcon = () => ( + + + + + +); + +/** Spherical geometry icon - for future use */ +export const SphericalIcon = () => ( + + + + + +); + +/** Discord icon - official simplified logo */ +export const DiscordIcon = ({ className = "w-4 h-4" }: { className?: string }) => ( + + + +); diff --git a/frontend/src/components/index.ts b/frontend/src/components/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..f17848313aee2485521a6b2a29f7423982cf2dab --- /dev/null +++ b/frontend/src/components/index.ts @@ -0,0 +1,9 @@ +export { ImageGrid } from "./ImageGrid"; +export { ScatterPanel } from "./ScatterPanel"; +export { DockviewWorkspace } from "./DockviewWorkspace"; +export { Header } from "./Header"; +export { Panel, PanelFooter } from "./Panel"; +export { PanelHeader } from "./PanelHeader"; +export { ExplorerPanel } from "./ExplorerPanel"; +export { PlaceholderPanel } from "./PlaceholderPanel"; +export * from "./icons"; diff --git a/frontend/src/components/ui/button.tsx b/frontend/src/components/ui/button.tsx new file mode 100644 index 0000000000000000000000000000000000000000..65d4fcd9ca74240125c5f72cf84c873781141fea --- /dev/null +++ b/frontend/src/components/ui/button.tsx @@ -0,0 +1,57 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button" + return ( + + ) + } +) +Button.displayName = "Button" + +export { Button, buttonVariants } diff --git a/frontend/src/components/ui/collapsible.tsx b/frontend/src/components/ui/collapsible.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9fa48946afd1eb56bd932377fd888e3986304676 --- /dev/null +++ b/frontend/src/components/ui/collapsible.tsx @@ -0,0 +1,11 @@ +"use client" + +import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" + +const Collapsible = CollapsiblePrimitive.Root + +const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger + +const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent + +export { Collapsible, CollapsibleTrigger, CollapsibleContent } diff --git a/frontend/src/components/ui/command.tsx b/frontend/src/components/ui/command.tsx new file mode 100644 index 0000000000000000000000000000000000000000..2cecd9104b27be82d238aa2f1cbb351e05446af7 --- /dev/null +++ b/frontend/src/components/ui/command.tsx @@ -0,0 +1,153 @@ +"use client" + +import * as React from "react" +import { type DialogProps } from "@radix-ui/react-dialog" +import { Command as CommandPrimitive } from "cmdk" +import { Search } from "lucide-react" + +import { cn } from "@/lib/utils" +import { Dialog, DialogContent } from "@/components/ui/dialog" + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Command.displayName = CommandPrimitive.displayName + +const CommandDialog = ({ children, ...props }: DialogProps) => { + return ( + + + + {children} + + + + ) +} + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)) + +CommandInput.displayName = CommandPrimitive.Input.displayName + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandList.displayName = CommandPrimitive.List.displayName + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)) + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandGroup.displayName = CommandPrimitive.Group.displayName + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +CommandSeparator.displayName = CommandPrimitive.Separator.displayName + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) + +CommandItem.displayName = CommandPrimitive.Item.displayName + +const CommandShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +CommandShortcut.displayName = "CommandShortcut" + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +} diff --git a/frontend/src/components/ui/dialog.tsx b/frontend/src/components/ui/dialog.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1647513eced8f9e788c0e8b63c99654d3a542a9c --- /dev/null +++ b/frontend/src/components/ui/dialog.tsx @@ -0,0 +1,122 @@ +"use client" + +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { X } from "lucide-react" + +import { cn } from "@/lib/utils" + +const Dialog = DialogPrimitive.Root + +const DialogTrigger = DialogPrimitive.Trigger + +const DialogPortal = DialogPrimitive.Portal + +const DialogClose = DialogPrimitive.Close + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)) +DialogContent.displayName = DialogPrimitive.Content.displayName + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogHeader.displayName = "DialogHeader" + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+) +DialogFooter.displayName = "DialogFooter" + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +} diff --git a/frontend/src/components/ui/dropdown-menu.tsx b/frontend/src/components/ui/dropdown-menu.tsx new file mode 100644 index 0000000000000000000000000000000000000000..5a20503b547ea0e4e467d63fe1ae78e4171afb52 --- /dev/null +++ b/frontend/src/components/ui/dropdown-menu.tsx @@ -0,0 +1,201 @@ +"use client" + +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/frontend/src/components/ui/popover.tsx b/frontend/src/components/ui/popover.tsx new file mode 100644 index 0000000000000000000000000000000000000000..70a28f6610b5e331769e14ca0f77072789899ff7 --- /dev/null +++ b/frontend/src/components/ui/popover.tsx @@ -0,0 +1,33 @@ +"use client" + +import * as React from "react" +import * as PopoverPrimitive from "@radix-ui/react-popover" + +import { cn } from "@/lib/utils" + +const Popover = PopoverPrimitive.Root + +const PopoverTrigger = PopoverPrimitive.Trigger + +const PopoverAnchor = PopoverPrimitive.Anchor + +const PopoverContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, align = "center", sideOffset = 4, ...props }, ref) => ( + + + +)) +PopoverContent.displayName = PopoverPrimitive.Content.displayName + +export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor } diff --git a/frontend/src/components/ui/radio-group.tsx b/frontend/src/components/ui/radio-group.tsx new file mode 100644 index 0000000000000000000000000000000000000000..0bdf6853fccc6ba250ce89d78a4f5b72b7347279 --- /dev/null +++ b/frontend/src/components/ui/radio-group.tsx @@ -0,0 +1,44 @@ +"use client" + +import * as React from "react" +import * as RadioGroupPrimitive from "@radix-ui/react-radio-group" +import { Circle } from "lucide-react" + +import { cn } from "@/lib/utils" + +const RadioGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + ) +}) +RadioGroup.displayName = RadioGroupPrimitive.Root.displayName + +const RadioGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => { + return ( + + + + + + ) +}) +RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName + +export { RadioGroup, RadioGroupItem } diff --git a/frontend/src/components/ui/scroll-area.tsx b/frontend/src/components/ui/scroll-area.tsx new file mode 100644 index 0000000000000000000000000000000000000000..b1e223f9cd7254e90bf9b50470c574a6a8a9103b --- /dev/null +++ b/frontend/src/components/ui/scroll-area.tsx @@ -0,0 +1,49 @@ +"use client" + +import * as React from "react" +import * as ScrollAreaPrimitive from "@radix-ui/react-scroll-area" + +import { cn } from "@/lib/utils" + +const ScrollArea = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + {children} + + + + +)) +ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName + +const ScrollBar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, orientation = "vertical", ...props }, ref) => ( + + + +)) +ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName + +export { ScrollArea, ScrollBar } diff --git a/frontend/src/components/ui/separator.tsx b/frontend/src/components/ui/separator.tsx new file mode 100644 index 0000000000000000000000000000000000000000..12d81c4a853472948b6dd2e85eff99b5d12fe60b --- /dev/null +++ b/frontend/src/components/ui/separator.tsx @@ -0,0 +1,31 @@ +"use client" + +import * as React from "react" +import * as SeparatorPrimitive from "@radix-ui/react-separator" + +import { cn } from "@/lib/utils" + +const Separator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>( + ( + { className, orientation = "horizontal", decorative = true, ...props }, + ref + ) => ( + + ) +) +Separator.displayName = SeparatorPrimitive.Root.displayName + +export { Separator } diff --git a/frontend/src/components/ui/toggle-group.tsx b/frontend/src/components/ui/toggle-group.tsx new file mode 100644 index 0000000000000000000000000000000000000000..1c876bbeecabe59b684719afe58e684f34cdecbf --- /dev/null +++ b/frontend/src/components/ui/toggle-group.tsx @@ -0,0 +1,61 @@ +"use client" + +import * as React from "react" +import * as ToggleGroupPrimitive from "@radix-ui/react-toggle-group" +import { type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +import { toggleVariants } from "@/components/ui/toggle" + +const ToggleGroupContext = React.createContext< + VariantProps +>({ + size: "default", + variant: "default", +}) + +const ToggleGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, children, ...props }, ref) => ( + + + {children} + + +)) + +ToggleGroup.displayName = ToggleGroupPrimitive.Root.displayName + +const ToggleGroupItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, children, variant, size, ...props }, ref) => { + const context = React.useContext(ToggleGroupContext) + + return ( + + {children} + + ) +}) + +ToggleGroupItem.displayName = ToggleGroupPrimitive.Item.displayName + +export { ToggleGroup, ToggleGroupItem } diff --git a/frontend/src/components/ui/toggle.tsx b/frontend/src/components/ui/toggle.tsx new file mode 100644 index 0000000000000000000000000000000000000000..e516f21cf9e578e75f423367fbd20f8cdd1e6a87 --- /dev/null +++ b/frontend/src/components/ui/toggle.tsx @@ -0,0 +1,45 @@ +"use client" + +import * as React from "react" +import * as TogglePrimitive from "@radix-ui/react-toggle" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" + +const toggleVariants = cva( + "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-transparent", + outline: + "border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground data-[state=on]:border-primary", + }, + size: { + default: "h-9 px-2 min-w-9", + sm: "h-8 px-1.5 min-w-8", + lg: "h-10 px-2.5 min-w-10", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + } +) + +const Toggle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & + VariantProps +>(({ className, variant, size, ...props }, ref) => ( + +)) + +Toggle.displayName = TogglePrimitive.Root.displayName + +export { Toggle, toggleVariants } diff --git a/frontend/src/components/ui/tooltip.tsx b/frontend/src/components/ui/tooltip.tsx new file mode 100644 index 0000000000000000000000000000000000000000..28e19183f4d9dfbb73c82928190556b69575eb2b --- /dev/null +++ b/frontend/src/components/ui/tooltip.tsx @@ -0,0 +1,32 @@ +"use client" + +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" + +import { cn } from "@/lib/utils" + +const TooltipProvider = TooltipPrimitive.Provider + +const Tooltip = TooltipPrimitive.Root + +const TooltipTrigger = TooltipPrimitive.Trigger + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/frontend/src/components/useHyperScatter.ts b/frontend/src/components/useHyperScatter.ts new file mode 100644 index 0000000000000000000000000000000000000000..3801a701e492707a345a94f859feabb7c70ed585 --- /dev/null +++ b/frontend/src/components/useHyperScatter.ts @@ -0,0 +1,614 @@ +import type React from "react"; +import { useCallback, useEffect, useMemo, useRef, useState } from "react"; + +import type { EmbeddingsData } from "@/types"; +import type { ScatterLabelsInfo } from "@/lib/labelLegend"; +import type { Dataset, GeometryMode, Modifiers, Renderer } from "hyper-scatter"; + +type HyperScatterModule = typeof import("hyper-scatter"); + +const MAX_LASSO_VERTS = 512; + +function supportsWebGL2(): boolean { + try { + if (typeof document === "undefined") return false; + const canvas = document.createElement("canvas"); + return !!canvas.getContext("webgl2"); + } catch { + return false; + } +} + +function capInterleavedXY(points: ArrayLike, maxVerts: number): number[] { + const n = Math.floor(points.length / 2); + if (n <= maxVerts) return Array.from(points as ArrayLike); + + const out = new Array(maxVerts * 2); + for (let i = 0; i < maxVerts; i++) { + const src = Math.floor((i * n) / maxVerts); + out[i * 2] = points[src * 2]; + out[i * 2 + 1] = points[src * 2 + 1]; + } + return out; +} + + +interface UseHyperScatterArgs { + embeddings: EmbeddingsData | null; + labelsInfo: ScatterLabelsInfo | null; + selectedIds: Set; + hoveredId: string | null; + setSelectedIds: (ids: Set, source?: "scatter" | "grid") => void; + beginLassoSelection: (query: { layoutKey: string; polygon: number[] }) => void; + setHoveredId: (id: string | null) => void; + hoverEnabled?: boolean; +} + +function toModifiers(e: { shiftKey: boolean; ctrlKey: boolean; altKey: boolean; metaKey: boolean }): Modifiers { + return { + shift: e.shiftKey, + ctrl: e.ctrlKey, + alt: e.altKey, + meta: e.metaKey, + }; +} + +function clearOverlay(canvas: HTMLCanvasElement | null): void { + if (!canvas) return; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + ctx.setTransform(1, 0, 0, 1, 0, 0); + ctx.clearRect(0, 0, canvas.width, canvas.height); +} + +function drawLassoOverlay(canvas: HTMLCanvasElement | null, points: number[]): void { + if (!canvas) return; + const ctx = canvas.getContext("2d"); + if (!ctx) return; + + clearOverlay(canvas); + if (points.length < 6) return; + + ctx.save(); + ctx.lineWidth = 2; + ctx.strokeStyle = "rgba(79,70,229,0.9)"; // indigo-ish + ctx.fillStyle = "rgba(79,70,229,0.15)"; + + ctx.beginPath(); + ctx.moveTo(points[0], points[1]); + for (let i = 2; i < points.length; i += 2) { + ctx.lineTo(points[i], points[i + 1]); + } + ctx.closePath(); + ctx.fill(); + ctx.stroke(); + ctx.restore(); +} + +export function useHyperScatter({ + embeddings, + labelsInfo, + selectedIds, + hoveredId, + setSelectedIds, + beginLassoSelection, + setHoveredId, + hoverEnabled = true, +}: UseHyperScatterArgs) { + const canvasRef = useRef(null); + const overlayCanvasRef = useRef(null); + const containerRef = useRef(null); + + const rendererRef = useRef(null); + + const [rendererError, setRendererError] = useState(null); + + const rafPendingRef = useRef(false); + + // Interaction state (refs to avoid rerender churn) + const isPanningRef = useRef(false); + const isLassoingRef = useRef(false); + const pointerDownXRef = useRef(0); + const pointerDownYRef = useRef(0); + const lastPointerXRef = useRef(0); + const lastPointerYRef = useRef(0); + const lassoPointsRef = useRef([]); + const persistentLassoRef = useRef(null); + + const hoveredIndexRef = useRef(-1); + + const idToIndex = useMemo(() => { + if (!embeddings) return null; + const m = new Map(); + for (let i = 0; i < embeddings.ids.length; i++) { + m.set(embeddings.ids[i], i); + } + return m; + }, [embeddings]); + + const requestRender = useCallback(() => { + if (rafPendingRef.current) return; + rafPendingRef.current = true; + + requestAnimationFrame(() => { + rafPendingRef.current = false; + const renderer = rendererRef.current; + if (!renderer) return; + + try { + renderer.render(); + } catch (err) { + // Avoid an exception storm that would permanently prevent the UI from updating. + console.error("hyper-scatter renderer.render() failed:", err); + try { + renderer.destroy(); + } catch { + // ignore + } + rendererRef.current = null; + setRendererError( + "This browser can't render the scatter plot (WebGL2 is required). Please use Chrome/Edge/Firefox." + ); + clearOverlay(overlayCanvasRef.current); + return; + } + + if (isLassoingRef.current) { + drawLassoOverlay(overlayCanvasRef.current, lassoPointsRef.current); + } + }); + }, []); + + const getCanvasPos = useCallback((e: { clientX: number; clientY: number }) => { + const canvas = canvasRef.current; + if (!canvas) return { x: 0, y: 0 }; + const rect = canvas.getBoundingClientRect(); + return { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + }; + }, []); + + const redrawOverlay = useCallback(() => { + if (!overlayCanvasRef.current) return; + clearOverlay(overlayCanvasRef.current); + const persistent = persistentLassoRef.current; + if (persistent && persistent.length >= 6) { + drawLassoOverlay(overlayCanvasRef.current, persistent); + } + }, []); + + const clearPersistentLasso = useCallback(() => { + persistentLassoRef.current = null; + clearOverlay(overlayCanvasRef.current); + }, []); + + const stopInteraction = useCallback(() => { + isPanningRef.current = false; + isLassoingRef.current = false; + lassoPointsRef.current = []; + if (persistentLassoRef.current) { + redrawOverlay(); + return; + } + clearOverlay(overlayCanvasRef.current); + }, [redrawOverlay]); + + // Initialize renderer when embeddings change. + useEffect(() => { + if (!embeddings || !labelsInfo) return; + if (!canvasRef.current || !containerRef.current) return; + + let cancelled = false; + + const init = async () => { + // Clear any previous renderer errors when we attempt to re-init. + setRendererError(null); + + if (!supportsWebGL2()) { + setRendererError( + "This browser doesn't support WebGL2, so the scatter plot can't be displayed. Please use Chrome/Edge/Firefox." + ); + return; + } + + try { + const viz = (await import("hyper-scatter")) as HyperScatterModule; + if (cancelled) return; + + const container = containerRef.current; + const canvas = canvasRef.current; + if (!container || !canvas) return; + + // Destroy existing renderer (if any) + if (rendererRef.current) { + rendererRef.current.destroy(); + rendererRef.current = null; + } + + const rect = container.getBoundingClientRect(); + const width = Math.floor(rect.width); + const height = Math.floor(rect.height); + if (overlayCanvasRef.current) { + overlayCanvasRef.current.width = Math.max(1, width); + overlayCanvasRef.current.height = Math.max(1, height); + overlayCanvasRef.current.style.width = `${width}px`; + overlayCanvasRef.current.style.height = `${height}px`; + redrawOverlay(); + } + + // Use coords from embeddings response directly + const coords = embeddings.coords; + const positions = new Float32Array(coords.length * 2); + for (let i = 0; i < coords.length; i++) { + positions[i * 2] = coords[i][0]; + positions[i * 2 + 1] = coords[i][1]; + } + + const geometry = embeddings.geometry as GeometryMode; + const dataset: Dataset = viz.createDataset(geometry, positions, labelsInfo.categories); + + const opts = { + width, + height, + devicePixelRatio: window.devicePixelRatio, + pointRadius: 4, + colors: labelsInfo.palette, + backgroundColor: "#161b22", // Match HyperView theme: --card is #161b22 + }; + + const renderer: Renderer = + geometry === "euclidean" ? new viz.EuclideanWebGLCandidate() : new viz.HyperbolicWebGLCandidate(); + + renderer.init(canvas, opts); + + renderer.setDataset(dataset); + rendererRef.current = renderer; + + // Force a first render to surface WebGL2 context creation failures early. + try { + renderer.render(); + } catch (err) { + console.error("hyper-scatter initial render failed:", err); + rendererRef.current = null; + try { + renderer.destroy(); + } catch { + // ignore + } + setRendererError( + "This browser can't render the scatter plot (WebGL2 is required). Please use Chrome/Edge/Firefox." + ); + return; + } + + hoveredIndexRef.current = -1; + renderer.setHovered(-1); + + requestRender(); + } catch (err) { + console.error("Failed to initialize hyper-scatter renderer:", err); + setRendererError( + "Failed to initialize the scatter renderer in this browser. Please use Chrome/Edge/Firefox." + ); + } + }; + + init(); + + return () => { + cancelled = true; + stopInteraction(); + if (rendererRef.current) { + rendererRef.current.destroy(); + rendererRef.current = null; + } + }; + }, [embeddings, labelsInfo, redrawOverlay, requestRender, stopInteraction]); + + // Store -> renderer sync + useEffect(() => { + const renderer = rendererRef.current; + if (!renderer || !embeddings || !idToIndex) return; + + const indices = new Set(); + for (const id of selectedIds) { + const idx = idToIndex.get(id); + if (typeof idx === "number") indices.add(idx); + } + + renderer.setSelection(indices); + + if (!hoverEnabled) { + renderer.setHovered(-1); + hoveredIndexRef.current = -1; + requestRender(); + return; + } + + const hoveredIdx = hoveredId ? (idToIndex.get(hoveredId) ?? -1) : -1; + renderer.setHovered(hoveredIdx); + hoveredIndexRef.current = hoveredIdx; + + requestRender(); + }, [embeddings, hoveredId, hoverEnabled, idToIndex, requestRender, selectedIds]); + + // Resize handling + useEffect(() => { + const container = containerRef.current; + if (!container) return; + + const resize = () => { + const rect = container.getBoundingClientRect(); + const width = Math.floor(rect.width); + const height = Math.floor(rect.height); + if (!(width > 0) || !(height > 0)) return; + + if (overlayCanvasRef.current) { + overlayCanvasRef.current.width = Math.max(1, width); + overlayCanvasRef.current.height = Math.max(1, height); + overlayCanvasRef.current.style.width = `${width}px`; + overlayCanvasRef.current.style.height = `${height}px`; + redrawOverlay(); + } + + const renderer = rendererRef.current; + if (renderer) { + renderer.resize(width, height); + requestRender(); + } + }; + + resize(); + + const ro = new ResizeObserver(resize); + ro.observe(container); + return () => ro.disconnect(); + }, [redrawOverlay, requestRender]); + + // Wheel zoom (native listener so we can set passive:false) + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const onWheel = (e: WheelEvent) => { + const renderer = rendererRef.current; + if (!renderer) return; + e.preventDefault(); + + const pos = getCanvasPos(e); + const delta = -e.deltaY / 100; + renderer.zoom(pos.x, pos.y, delta, toModifiers(e)); + requestRender(); + }; + + canvas.addEventListener("wheel", onWheel, { passive: false }); + return () => canvas.removeEventListener("wheel", onWheel); + }, [getCanvasPos, requestRender]); + + // Pointer interactions + const handlePointerDown = useCallback( + (e: React.PointerEvent) => { + const renderer = rendererRef.current; + if (!renderer) return; + + // Left button only + if (typeof e.button === "number" && e.button !== 0) return; + + const pos = getCanvasPos(e); + pointerDownXRef.current = pos.x; + pointerDownYRef.current = pos.y; + lastPointerXRef.current = pos.x; + lastPointerYRef.current = pos.y; + + if (persistentLassoRef.current) { + clearPersistentLasso(); + } + + // Shift-drag = lasso, otherwise pan. + if (e.shiftKey) { + isLassoingRef.current = true; + isPanningRef.current = false; + lassoPointsRef.current = [pos.x, pos.y]; + drawLassoOverlay(overlayCanvasRef.current, lassoPointsRef.current); + } else { + isPanningRef.current = true; + isLassoingRef.current = false; + } + + try { + e.currentTarget.setPointerCapture(e.pointerId); + } catch { + // ignore + } + + e.preventDefault(); + }, + [clearPersistentLasso, getCanvasPos] + ); + + const handlePointerMove = useCallback( + (e: React.PointerEvent) => { + const renderer = rendererRef.current; + if (!renderer) return; + + const pos = getCanvasPos(e); + + if (isPanningRef.current) { + const dx = pos.x - lastPointerXRef.current; + const dy = pos.y - lastPointerYRef.current; + lastPointerXRef.current = pos.x; + lastPointerYRef.current = pos.y; + + renderer.pan(dx, dy, toModifiers(e)); + requestRender(); + return; + } + + if (isLassoingRef.current) { + const pts = lassoPointsRef.current; + const lastX = pts[pts.length - 2] ?? pos.x; + const lastY = pts[pts.length - 1] ?? pos.y; + const ddx = pos.x - lastX; + const ddy = pos.y - lastY; + const distSq = ddx * ddx + ddy * ddy; + + // Sample at ~2px spacing + if (distSq >= 4) { + pts.push(pos.x, pos.y); + drawLassoOverlay(overlayCanvasRef.current, pts); + } + return; + } + + if (!hoverEnabled) { + if (hoveredIndexRef.current !== -1) { + hoveredIndexRef.current = -1; + renderer.setHovered(-1); + requestRender(); + } + return; + } + + // Hover + const hit = renderer.hitTest(pos.x, pos.y); + const nextIndex = hit ? hit.index : -1; + if (nextIndex === hoveredIndexRef.current) return; + hoveredIndexRef.current = nextIndex; + renderer.setHovered(nextIndex); + + if (!embeddings) return; + if (nextIndex >= 0 && nextIndex < embeddings.ids.length) { + setHoveredId(embeddings.ids[nextIndex]); + } else { + setHoveredId(null); + } + + requestRender(); + }, + [embeddings, getCanvasPos, hoverEnabled, requestRender, setHoveredId] + ); + + const handlePointerUp = useCallback( + async (e: React.PointerEvent) => { + const renderer = rendererRef.current; + if (!renderer || !embeddings) { + stopInteraction(); + return; + } + + if (isLassoingRef.current) { + const pts = lassoPointsRef.current.slice(); + persistentLassoRef.current = pts.length >= 6 ? pts : null; + stopInteraction(); + redrawOverlay(); + + if (pts.length >= 6) { + try { + const polyline = new Float32Array(pts); + const result = renderer.lassoSelect(polyline); + + // Enter server-driven lasso mode by sending a data-space polygon. + // Backend selection runs in the same coordinate system returned by /api/embeddings. + const dataCoords = result.geometry?.coords; + if (!dataCoords || dataCoords.length < 6) return; + + // Clear any existing manual selection highlights immediately. + renderer.setSelection(new Set()); + + // Cap vertex count to keep request payload + backend runtime bounded. + const polygon = capInterleavedXY(dataCoords, MAX_LASSO_VERTS); + if (polygon.length < 6) return; + + beginLassoSelection({ layoutKey: embeddings.layout_key, polygon }); + } catch (err) { + console.error("Lasso selection failed:", err); + } + } + + requestRender(); + return; + } + + // Click-to-select (scatter -> image grid) + // Only treat as a click if the pointer didn't move much (otherwise it's a pan). + const pos = getCanvasPos(e); + const dx = pos.x - pointerDownXRef.current; + const dy = pos.y - pointerDownYRef.current; + const CLICK_MAX_DIST_SQ = 36; // ~6px + const isClick = dx * dx + dy * dy <= CLICK_MAX_DIST_SQ; + + if (isClick) { + const hit = renderer.hitTest(pos.x, pos.y); + const idx = hit ? hit.index : -1; + + if (idx >= 0 && idx < embeddings.ids.length) { + const id = embeddings.ids[idx]; + + if (e.metaKey || e.ctrlKey) { + const next = new Set(selectedIds); + if (next.has(id)) next.delete(id); + else next.add(id); + setSelectedIds(next, "scatter"); + } else { + setSelectedIds(new Set([id]), "scatter"); + } + } + } + + stopInteraction(); + requestRender(); + }, + [ + beginLassoSelection, + embeddings, + getCanvasPos, + redrawOverlay, + requestRender, + selectedIds, + setSelectedIds, + stopInteraction, + ] + ); + + const handlePointerLeave = useCallback( + (_e: React.PointerEvent) => { + const renderer = rendererRef.current; + if (renderer) { + hoveredIndexRef.current = -1; + setHoveredId(null); + renderer.setHovered(-1); + requestRender(); + } + stopInteraction(); + }, + [requestRender, setHoveredId, stopInteraction] + ); + + const handleDoubleClick = useCallback( + (_e: React.MouseEvent) => { + const renderer = rendererRef.current; + if (!renderer) return; + clearPersistentLasso(); + stopInteraction(); + + renderer.setSelection(new Set()); + setSelectedIds(new Set(), "scatter"); + + requestRender(); + }, + [clearPersistentLasso, requestRender, setSelectedIds, stopInteraction] + ); + + return { + canvasRef, + overlayCanvasRef, + containerRef, + handlePointerDown, + handlePointerMove, + handlePointerUp, + handlePointerLeave, + handleDoubleClick, + rendererError, + }; +} diff --git a/frontend/src/components/useLabelLegend.ts b/frontend/src/components/useLabelLegend.ts new file mode 100644 index 0000000000000000000000000000000000000000..9c58da0133b1476e19162e9d7bffc3de1d062c2e --- /dev/null +++ b/frontend/src/components/useLabelLegend.ts @@ -0,0 +1,85 @@ +import { useMemo } from "react"; + +import type { DatasetInfo, EmbeddingsData } from "@/types"; +import { + MAX_DISTINCT_LABEL_COLORS, + buildLabelColorMap, + buildLabelCounts, + buildLabelUniverse, + buildLabelsInfo, + buildLegendLabels, + getDistinctLabelCount, +} from "@/lib/labelLegend"; + +interface UseLabelLegendArgs { + datasetInfo: DatasetInfo | null; + embeddings: EmbeddingsData | null; + labelSearch?: string; + labelFilter?: string | null; +} + +export function useLabelLegend({ + datasetInfo, + embeddings, + labelSearch = "", + labelFilter = null, +}: UseLabelLegendArgs) { + const labelCounts = useMemo(() => buildLabelCounts(embeddings), [embeddings]); + + const labelUniverse = useMemo( + () => buildLabelUniverse(datasetInfo?.labels ?? [], embeddings?.labels ?? null), + [datasetInfo?.labels, embeddings?.labels] + ); + + const distinctLabelCount = useMemo(() => { + const fromCounts = getDistinctLabelCount(labelCounts); + if (fromCounts > 0) return fromCounts; + let n = labelUniverse.length; + if (labelUniverse.includes("undefined")) n -= 1; + return n; + }, [labelCounts, labelUniverse]); + + const distinctColoringDisabled = distinctLabelCount > MAX_DISTINCT_LABEL_COLORS; + + const labelsInfo = useMemo( + () => + buildLabelsInfo({ + datasetLabels: datasetInfo?.labels ?? [], + embeddings, + distinctColoringDisabled, + labelFilter, + }), + [datasetInfo?.labels, embeddings, distinctColoringDisabled, labelFilter] + ); + + const labelColorMap = useMemo( + () => + buildLabelColorMap({ + labelsInfo, + labelUniverse, + distinctColoringDisabled, + labelFilter, + }), + [labelsInfo, labelUniverse, distinctColoringDisabled, labelFilter] + ); + + const legendLabels = useMemo( + () => + buildLegendLabels({ + labelUniverse, + labelCounts, + query: labelSearch, + }), + [labelUniverse, labelCounts, labelSearch] + ); + + return { + labelCounts, + labelUniverse, + distinctLabelCount, + distinctColoringDisabled, + labelsInfo, + labelColorMap, + legendLabels, + }; +} diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts new file mode 100644 index 0000000000000000000000000000000000000000..e340b003a1551c201159c4c904b9baaabc621d9d --- /dev/null +++ b/frontend/src/lib/api.ts @@ -0,0 +1,103 @@ +import type { DatasetInfo, EmbeddingsData, Sample, SamplesResponse } from "@/types"; + +const API_BASE = process.env.NODE_ENV === "development" ? "http://127.0.0.1:6262" : ""; + +export async function fetchDataset(): Promise { + const res = await fetch(`${API_BASE}/api/dataset`); + if (!res.ok) { + throw new Error(`Failed to fetch dataset: ${res.statusText}`); + } + return res.json(); +} + +export async function fetchSamples( + offset: number = 0, + limit: number = 100, + label?: string +): Promise { + const params = new URLSearchParams({ + offset: offset.toString(), + limit: limit.toString(), + }); + if (label) { + params.set("label", label); + } + + const res = await fetch(`${API_BASE}/api/samples?${params}`); + if (!res.ok) { + throw new Error(`Failed to fetch samples: ${res.statusText}`); + } + return res.json(); +} + +export async function fetchEmbeddings(layoutKey?: string): Promise { + const params = new URLSearchParams(); + if (layoutKey) { + params.set("layout_key", layoutKey); + } + const query = params.toString(); + const res = await fetch(`${API_BASE}/api/embeddings${query ? `?${query}` : ""}`); + if (!res.ok) { + throw new Error(`Failed to fetch embeddings: ${res.statusText}`); + } + return res.json(); +} + +export async function fetchSample(sampleId: string): Promise { + const res = await fetch(`${API_BASE}/api/samples/${sampleId}`); + if (!res.ok) { + throw new Error(`Failed to fetch sample: ${res.statusText}`); + } + return res.json(); +} + +export async function fetchSamplesBatch(sampleIds: string[]): Promise { + const res = await fetch(`${API_BASE}/api/samples/batch`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ sample_ids: sampleIds }), + }); + if (!res.ok) { + throw new Error(`Failed to fetch samples batch: ${res.statusText}`); + } + const data = await res.json(); + return data.samples; +} + +export interface LassoSelectionResponse { + total: number; + offset: number; + limit: number; + sample_ids: string[]; + samples: Sample[]; +} + +export async function fetchLassoSelection(args: { + layoutKey: string; + polygon: ArrayLike; + offset?: number; + limit?: number; + includeThumbnails?: boolean; + signal?: AbortSignal; +}): Promise { + const res = await fetch(`${API_BASE}/api/selection/lasso`, { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + layout_key: args.layoutKey, + polygon: Array.from(args.polygon), + offset: args.offset ?? 0, + limit: args.limit ?? 100, + include_thumbnails: args.includeThumbnails ?? true, + }), + signal: args.signal, + }); + if (!res.ok) { + throw new Error(`Failed to fetch lasso selection: ${res.statusText}`); + } + return res.json(); +} diff --git a/frontend/src/lib/labelColors.ts b/frontend/src/lib/labelColors.ts new file mode 100644 index 0000000000000000000000000000000000000000..273b5191a33fa495078a51c617c43dde7bc8dd74 --- /dev/null +++ b/frontend/src/lib/labelColors.ts @@ -0,0 +1,153 @@ +const MISSING_LABEL_SENTINEL = "undefined"; + +export const MISSING_LABEL_COLOR = "#39d3cc"; // matches --accent-cyan +export const FALLBACK_LABEL_COLOR = "#8b949e"; // matches --muted-foreground + +// Rerun-style auto colors: distribute hues by golden ratio conjugate. +// See: context/repos/rerun/crates/viewer/re_viewer_context/src/utils/color.rs +const GOLDEN_RATIO_CONJUGATE = (Math.sqrt(5) - 1) / 2; // ~0.61803398875 + +function fnv1a32(input: string): number { + // 32-bit FNV-1a hash + let hash = 0x811c9dc5; + for (let i = 0; i < input.length; i++) { + hash ^= input.charCodeAt(i); + hash = Math.imul(hash, 0x01000193); + } + return hash >>> 0; +} + +function clamp01(v: number): number { + if (v < 0) return 0; + if (v > 1) return 1; + return v; +} + +function hsvToHex(h: number, s: number, v: number): string { + // h/s/v in [0, 1] + const hh = ((h % 1) + 1) % 1; + const ss = clamp01(s); + const vv = clamp01(v); + + const x = hh * 6; + const i = Math.floor(x); + const f = x - i; + + const p = vv * (1 - ss); + const q = vv * (1 - ss * f); + const t = vv * (1 - ss * (1 - f)); + + let r = 0; + let g = 0; + let b = 0; + + switch (i % 6) { + case 0: + r = vv; + g = t; + b = p; + break; + case 1: + r = q; + g = vv; + b = p; + break; + case 2: + r = p; + g = vv; + b = t; + break; + case 3: + r = p; + g = q; + b = vv; + break; + case 4: + r = t; + g = p; + b = vv; + break; + case 5: + r = vv; + g = p; + b = q; + break; + } + + const toHex = (x: number) => { + const n = Math.round(clamp01(x) * 255); + return n.toString(16).padStart(2, "0"); + }; + + return `#${toHex(r)}${toHex(g)}${toHex(b)}`; +} + +export function labelToColor(label: string): string { + if (!label) return FALLBACK_LABEL_COLOR; + if (label === MISSING_LABEL_SENTINEL) return MISSING_LABEL_COLOR; + + return colorForKey(label); +} + +function colorForKey(key: string): string { + const seed = fnv1a32(key); + const val = seed & 0xffff; // map to u16 + const h = (val * GOLDEN_RATIO_CONJUGATE) % 1; + + // Match Rerun's defaults: saturation 0.85, value 0.5 + return hsvToHex(h, 0.85, 0.5); +} + +function stableLabelSort(a: string, b: string): number { + if (a === MISSING_LABEL_SENTINEL && b !== MISSING_LABEL_SENTINEL) return 1; + if (b === MISSING_LABEL_SENTINEL && a !== MISSING_LABEL_SENTINEL) return -1; + return a.localeCompare(b); +} + +/** + * Builds a deterministic, collision-free label → color mapping for the given + * label universe. + * + * Notes: + * - No modulo/cycling: if there are N labels, we produce N colors. + * - Deterministic: same input set yields same mapping. + * - Collision-free within the provided set via deterministic rehashing. + */ +export function createLabelColorMap(labels: string[]): Record { + const unique = Array.from(new Set(labels.map((l) => normalizeLabel(l)))).sort(stableLabelSort); + + const colors: Record = {}; + const used = new Set(); + + for (const label of unique) { + if (label === MISSING_LABEL_SENTINEL) { + colors[label] = MISSING_LABEL_COLOR; + used.add(MISSING_LABEL_COLOR.toLowerCase()); + continue; + } + + let attempt = 0; + // Deterministic collision resolution (should be extremely rare). + while (attempt < 32) { + const candidate = colorForKey(attempt === 0 ? label : `${label}#${attempt}`); + const normalized = candidate.toLowerCase(); + if (!used.has(normalized)) { + colors[label] = candidate; + used.add(normalized); + break; + } + attempt++; + } + + if (!colors[label]) { + // Should never happen, but keep UI resilient. + colors[label] = FALLBACK_LABEL_COLOR; + } + } + + return colors; +} + +export function normalizeLabel(label: string | null | undefined): string { + return label && label.length > 0 ? label : MISSING_LABEL_SENTINEL; +} diff --git a/frontend/src/lib/labelLegend.ts b/frontend/src/lib/labelLegend.ts new file mode 100644 index 0000000000000000000000000000000000000000..2d43e939e8a426ba1fabef4f9f22d1dca73bc815 --- /dev/null +++ b/frontend/src/lib/labelLegend.ts @@ -0,0 +1,248 @@ +import type { EmbeddingsData } from "@/types"; +import { + FALLBACK_LABEL_COLOR, + MISSING_LABEL_COLOR, + createLabelColorMap, + normalizeLabel, +} from "@/lib/labelColors"; + +// Past ~20-30 categories, color-as-encoding becomes unreliable for most users. +// We choose a conservative upper bound and fall back to a single color. +export const MAX_DISTINCT_LABEL_COLORS = 20; +export const UNSELECTED_LABEL_ALPHA = 0.12; + +export interface ScatterLabelsInfo { + uniqueLabels: string[]; + categories: Uint16Array; + palette: string[]; +} + +function clamp01(v: number): number { + if (v < 0) return 0; + if (v > 1) return 1; + return v; +} + +function applyAlphaToHex(color: string, alpha: number): string { + if (!color.startsWith("#")) return color; + const hex = Math.round(clamp01(alpha) * 255) + .toString(16) + .padStart(2, "0"); + + if (color.length === 7) { + return `${color}${hex}`; + } + + if (color.length === 9) { + return `${color.slice(0, 7)}${hex}`; + } + + return color; +} + +function applyLabelFilterToPalette(params: { + palette: string[]; + labels: string[]; + labelFilter: string | null; + unselectedAlpha: number; +}): string[] { + const { palette, labels, labelFilter, unselectedAlpha } = params; + if (!labelFilter) return palette; + if (!labels.includes(labelFilter)) return palette; + + return palette.map((color, idx) => + labels[idx] === labelFilter ? color : applyAlphaToHex(color, unselectedAlpha) + ); +} + +export function buildLabelCounts(embeddings: EmbeddingsData | null): Map { + const counts = new Map(); + if (!embeddings) return counts; + for (const raw of embeddings.labels) { + const l = normalizeLabel(raw); + counts.set(l, (counts.get(l) ?? 0) + 1); + } + return counts; +} + +export function getDistinctLabelCount(labelCounts: Map): number { + let n = labelCounts.size; + if (labelCounts.has("undefined")) n -= 1; + return n; +} + +export function buildLabelUniverse( + datasetLabels: string[], + embeddingsLabels: (string | null)[] | null +): string[] { + const universe: string[] = []; + const seen = new Set(); + let hasMissing = false; + + const baseLabels = datasetLabels.map((l) => normalizeLabel(l)); + for (const l of baseLabels) { + if (l === "undefined") { + hasMissing = true; + continue; + } + if (seen.has(l)) continue; + seen.add(l); + universe.push(l); + } + + if (embeddingsLabels) { + const extras = new Set(); + for (const raw of embeddingsLabels) { + const l = normalizeLabel(raw); + if (l === "undefined") { + hasMissing = true; + continue; + } + if (!seen.has(l)) extras.add(l); + } + + if (extras.size > 0) { + const extraSorted = Array.from(extras).sort((a, b) => a.localeCompare(b)); + for (const l of extraSorted) { + seen.add(l); + universe.push(l); + } + } + } + + if (hasMissing) universe.push("undefined"); + return universe; +} + +export function buildLabelsInfo(params: { + datasetLabels: string[]; + embeddings: EmbeddingsData | null; + distinctColoringDisabled: boolean; + labelFilter?: string | null; + unselectedAlpha?: number; +}): ScatterLabelsInfo | null { + const { + datasetLabels, + embeddings, + distinctColoringDisabled, + labelFilter = null, + unselectedAlpha = UNSELECTED_LABEL_ALPHA, + } = params; + if (!embeddings) return null; + + const universe = buildLabelUniverse(datasetLabels, embeddings.labels); + + // Guard: hyper-scatter categories are Uint16. + if (universe.length > 65535) { + console.warn( + `Too many labels (${universe.length}) for uint16 categories; collapsing to a single color.` + ); + return { + uniqueLabels: ["undefined"], + categories: new Uint16Array(embeddings.labels.length), + palette: [FALLBACK_LABEL_COLOR], + }; + } + + const labelToCategory: Record = {}; + for (let i = 0; i < universe.length; i++) { + labelToCategory[universe[i]] = i; + } + + const undefinedIndex = labelToCategory["undefined"] ?? 0; + const categories = new Uint16Array(embeddings.labels.length); + for (let i = 0; i < embeddings.labels.length; i++) { + const key = normalizeLabel(embeddings.labels[i]); + categories[i] = labelToCategory[key] ?? undefinedIndex; + } + + let palette: string[]; + if (distinctColoringDisabled) { + palette = universe.map((l) => (l === "undefined" ? MISSING_LABEL_COLOR : FALLBACK_LABEL_COLOR)); + } else { + const colors = createLabelColorMap(universe); + palette = universe.map((l) => colors[l] ?? FALLBACK_LABEL_COLOR); + } + + const filteredPalette = applyLabelFilterToPalette({ + palette, + labels: universe, + labelFilter, + unselectedAlpha, + }); + + return { uniqueLabels: universe, categories, palette: filteredPalette }; +} + +export function buildLabelColorMap(params: { + labelsInfo: ScatterLabelsInfo | null; + labelUniverse: string[]; + distinctColoringDisabled: boolean; + labelFilter?: string | null; + unselectedAlpha?: number; +}): Record { + const { + labelsInfo, + labelUniverse, + distinctColoringDisabled, + labelFilter = null, + unselectedAlpha = UNSELECTED_LABEL_ALPHA, + } = params; + const map: Record = {}; + + if (labelsInfo) { + for (let i = 0; i < labelsInfo.uniqueLabels.length; i++) { + map[labelsInfo.uniqueLabels[i]] = labelsInfo.palette[i] ?? FALLBACK_LABEL_COLOR; + } + return map; + } + + if (labelUniverse.length === 0) return map; + + if (distinctColoringDisabled) { + for (const label of labelUniverse) { + map[label] = label === "undefined" ? MISSING_LABEL_COLOR : FALLBACK_LABEL_COLOR; + } + return map; + } + + const colors = createLabelColorMap(labelUniverse); + for (const label of labelUniverse) { + map[label] = colors[label] ?? FALLBACK_LABEL_COLOR; + } + + if (!labelFilter || !labelUniverse.includes(labelFilter)) return map; + + for (const label of labelUniverse) { + if (label !== labelFilter) { + map[label] = applyAlphaToHex(map[label], unselectedAlpha); + } + } + + return map; +} + +export function buildLegendLabels(params: { + labelUniverse: string[]; + labelCounts: Map; + query: string; +}): string[] { + const { labelUniverse, labelCounts, query } = params; + const all = labelUniverse.length > 0 ? [...labelUniverse] : Array.from(labelCounts.keys()); + const q = query.trim().toLowerCase(); + const filtered = q ? all.filter((l) => l.toLowerCase().includes(q)) : all; + const hasCounts = labelCounts.size > 0; + + return filtered.sort((a, b) => { + if (a === "undefined" && b !== "undefined") return 1; + if (b === "undefined" && a !== "undefined") return -1; + + if (hasCounts) { + const ca = labelCounts.get(a) ?? 0; + const cb = labelCounts.get(b) ?? 0; + if (cb !== ca) return cb - ca; + } + + return a.localeCompare(b); + }); +} diff --git a/frontend/src/lib/layouts.ts b/frontend/src/lib/layouts.ts new file mode 100644 index 0000000000000000000000000000000000000000..2f02e92767775cace17376c87decd61ce1d2f1ba --- /dev/null +++ b/frontend/src/lib/layouts.ts @@ -0,0 +1,17 @@ +import type { Geometry, LayoutInfo } from "@/types"; + +export function listAvailableGeometries(layouts: LayoutInfo[]): Geometry[] { + const geometries = new Set(); + for (const layout of layouts) { + geometries.add(layout.geometry); + } + return Array.from(geometries); +} + +export function findLayoutByGeometry(layouts: LayoutInfo[], geometry: Geometry): LayoutInfo | undefined { + return layouts.find((l) => l.geometry === geometry); +} + +export function findLayoutByKey(layouts: LayoutInfo[], layoutKey: string): LayoutInfo | undefined { + return layouts.find((l) => l.layout_key === layoutKey); +} diff --git a/frontend/src/lib/utils.ts b/frontend/src/lib/utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..bd0c391ddd1088e9067844c48835bf4abcd61783 --- /dev/null +++ b/frontend/src/lib/utils.ts @@ -0,0 +1,6 @@ +import { clsx, type ClassValue } from "clsx" +import { twMerge } from "tailwind-merge" + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)) +} diff --git a/frontend/src/store/useStore.ts b/frontend/src/store/useStore.ts new file mode 100644 index 0000000000000000000000000000000000000000..c440b103e42995f26eb0831be071ee3fb966e67d --- /dev/null +++ b/frontend/src/store/useStore.ts @@ -0,0 +1,289 @@ +import { create } from "zustand"; +import type { DatasetInfo, EmbeddingsData, Sample } from "@/types"; +import { normalizeLabel } from "@/lib/labelColors"; + +function computeLabelSelection(embeddings: EmbeddingsData, label: string): Set { + const target = normalizeLabel(label); + const ids = new Set(); + for (let i = 0; i < embeddings.labels.length; i++) { + if (normalizeLabel(embeddings.labels[i]) === target) { + ids.add(embeddings.ids[i]); + } + } + return ids; +} + +interface AppState { + // Panel visibility (for header toggles) + leftPanelOpen: boolean; + rightPanelOpen: boolean; + bottomPanelOpen: boolean; + setLeftPanelOpen: (open: boolean) => void; + setRightPanelOpen: (open: boolean) => void; + setBottomPanelOpen: (open: boolean) => void; + + // Dataset info + datasetInfo: DatasetInfo | null; + setDatasetInfo: (info: DatasetInfo) => void; + + // Samples + samples: Sample[]; + totalSamples: number; + // Number of samples loaded via offset/limit pagination (excludes ad-hoc fetched samples) + samplesLoaded: number; + setSamples: (samples: Sample[], total: number) => void; + appendSamples: (samples: Sample[]) => void; + addSamplesIfMissing: (samples: Sample[]) => void; + + // Embeddings (cached per layout key) + embeddingsByLayoutKey: Record; + setEmbeddingsForLayout: (layoutKey: string, data: EmbeddingsData) => void; + + // Active layout (for sidebar context) + activeLayoutKey: string | null; + setActiveLayoutKey: (layoutKey: string | null) => void; + + // Label filter (sidebar-driven) + labelFilter: string | null; + setLabelFilter: (label: string | null) => void; + + // Selection + selectedIds: Set; + isLassoSelection: boolean; + selectionSource: "scatter" | "grid" | "lasso" | "label" | null; + setSelectedIds: (ids: Set, source?: "scatter" | "grid" | "label") => void; + toggleSelection: (id: string) => void; + addToSelection: (ids: string[]) => void; + clearSelection: () => void; + + // Lasso selection (server-driven) + lassoQuery: { layoutKey: string; polygon: number[] } | null; + lassoSamples: Sample[]; + lassoTotal: number; + lassoIsLoading: boolean; + beginLassoSelection: (query: { layoutKey: string; polygon: number[] }) => void; + setLassoResults: (samples: Sample[], total: number, append?: boolean) => void; + clearLassoSelection: () => void; + + // Hover state + hoveredId: string | null; + setHoveredId: (id: string | null) => void; + + // Loading states + isLoading: boolean; + setIsLoading: (loading: boolean) => void; + + // Error state + error: string | null; + setError: (error: string | null) => void; +} + +export const useStore = create((set, get) => ({ + // Panel visibility (for header toggles) + leftPanelOpen: false, + rightPanelOpen: false, + bottomPanelOpen: false, + setLeftPanelOpen: (open) => set({ leftPanelOpen: open }), + setRightPanelOpen: (open) => set({ rightPanelOpen: open }), + setBottomPanelOpen: (open) => set({ bottomPanelOpen: open }), + + // Dataset info + datasetInfo: null, + setDatasetInfo: (info) => set({ datasetInfo: info }), + + // Samples + samples: [], + totalSamples: 0, + samplesLoaded: 0, + setSamples: (samples, total) => set({ samples, totalSamples: total, samplesLoaded: samples.length }), + appendSamples: (newSamples) => + set((state) => { + const existingIds = new Set(state.samples.map((s) => s.id)); + const toAdd = newSamples.filter((s) => !existingIds.has(s.id)); + + // Advance pagination cursor by what the API returned (even if some IDs were prefetched). + const samplesLoaded = state.samplesLoaded + newSamples.length; + + if (toAdd.length === 0) return { samplesLoaded }; + return { samples: [...state.samples, ...toAdd], samplesLoaded }; + }), + addSamplesIfMissing: (newSamples) => + set((state) => { + const existingIds = new Set(state.samples.map((s) => s.id)); + const toAdd = newSamples.filter((s) => !existingIds.has(s.id)); + if (toAdd.length === 0) return state; + return { samples: [...state.samples, ...toAdd] }; + }), + + // Embeddings + embeddingsByLayoutKey: {}, + setEmbeddingsForLayout: (layoutKey, data) => + set((state) => { + const selectionUpdate = + state.labelFilter && + state.selectionSource === "label" && + state.activeLayoutKey === layoutKey + ? { + selectedIds: computeLabelSelection(data, state.labelFilter), + selectionSource: "label" as const, + } + : {}; + + return { + embeddingsByLayoutKey: { ...state.embeddingsByLayoutKey, [layoutKey]: data }, + ...selectionUpdate, + }; + }), + + // Active layout + activeLayoutKey: null, + setActiveLayoutKey: (layoutKey) => + set((state) => { + if (!layoutKey) return { activeLayoutKey: null }; + if (!state.labelFilter || state.selectionSource !== "label") { + return { activeLayoutKey: layoutKey }; + } + + const embeddings = state.embeddingsByLayoutKey[layoutKey]; + if (!embeddings) { + return { + activeLayoutKey: layoutKey, + selectedIds: new Set(), + selectionSource: "label", + }; + } + + return { + activeLayoutKey: layoutKey, + selectedIds: computeLabelSelection(embeddings, state.labelFilter), + selectionSource: "label", + }; + }), + + // Label filter + labelFilter: null, + setLabelFilter: (label) => + set((state) => { + const nextLabel = label ? normalizeLabel(label) : null; + const nextState: Partial = { labelFilter: nextLabel }; + + if (nextLabel) { + const layoutKey = state.activeLayoutKey; + const embeddings = layoutKey ? state.embeddingsByLayoutKey[layoutKey] : null; + nextState.selectedIds = embeddings ? computeLabelSelection(embeddings, nextLabel) : new Set(); + nextState.selectionSource = "label"; + nextState.isLassoSelection = false; + nextState.lassoQuery = null; + nextState.lassoSamples = []; + nextState.lassoTotal = 0; + nextState.lassoIsLoading = false; + } else if (state.selectionSource === "label") { + nextState.selectedIds = new Set(); + nextState.selectionSource = null; + } + + return nextState; + }), + + // Selection + selectedIds: new Set(), + isLassoSelection: false, + selectionSource: null, + setSelectedIds: (ids, source = "grid") => + set({ + selectedIds: ids, + selectionSource: ids.size > 0 ? source : null, + isLassoSelection: false, + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + }), + toggleSelection: (id) => + set((state) => { + const newSet = new Set(state.selectedIds); + if (newSet.has(id)) { + newSet.delete(id); + } else { + newSet.add(id); + } + // Manual selection from image grid, not lasso + return { + selectedIds: newSet, + selectionSource: newSet.size > 0 ? "grid" : null, + isLassoSelection: false, + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + }; + }), + addToSelection: (ids) => + set((state) => { + const newSet = new Set(state.selectedIds); + ids.forEach((id) => newSet.add(id)); + // Manual selection from image grid, not lasso + return { + selectedIds: newSet, + selectionSource: newSet.size > 0 ? "grid" : null, + isLassoSelection: false, + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + }; + }), + clearSelection: () => + set({ + selectedIds: new Set(), + selectionSource: null, + isLassoSelection: false, + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + }), + + // Lasso selection (server-driven) + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + beginLassoSelection: (query) => + set({ + isLassoSelection: true, + selectedIds: new Set(), + selectionSource: "lasso", + lassoQuery: query, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: true, + }), + setLassoResults: (samples, total, append = false) => + set((state) => ({ + lassoSamples: append ? [...state.lassoSamples, ...samples] : samples, + lassoTotal: total, + lassoIsLoading: false, + })), + clearLassoSelection: () => + set({ + isLassoSelection: false, + selectionSource: null, + lassoQuery: null, + lassoSamples: [], + lassoTotal: 0, + lassoIsLoading: false, + }), + + // Hover + hoveredId: null, + setHoveredId: (id) => set({ hoveredId: id }), + + // Loading + isLoading: false, + setIsLoading: (loading) => set({ isLoading: loading }), + + // Error + error: null, + setError: (error) => set({ error }), +})); diff --git a/frontend/src/types/index.ts b/frontend/src/types/index.ts new file mode 100644 index 0000000000000000000000000000000000000000..2cd5560d25db1883ffd83b07ebddd889204a0e09 --- /dev/null +++ b/frontend/src/types/index.ts @@ -0,0 +1,56 @@ +export interface Sample { + id: string; + filepath: string; + filename: string; + label: string | null; + thumbnail: string | null; + metadata: Record; + width: number | null; + height: number | null; +} + +export type Geometry = "euclidean" | "poincare"; + +export interface SpaceInfo { + space_key: string; + model_id: string; + dim: number; + count: number; + provider: string; + geometry: Geometry | string; + config: Record | null; +} + +export interface LayoutInfo { + layout_key: string; + space_key: string; + method: string; + geometry: Geometry; + count: number; + params: Record | null; +} + +export interface DatasetInfo { + name: string; + num_samples: number; + labels: string[]; + label_colors?: Record; + spaces: SpaceInfo[]; + layouts: LayoutInfo[]; +} + +export interface EmbeddingsData { + layout_key: string; + geometry: Geometry; + ids: string[]; + labels: (string | null)[]; + coords: [number, number][]; + label_colors?: Record; +} + +export interface SamplesResponse { + total: number; + offset: number; + limit: number; + samples: Sample[]; +} diff --git a/frontend/tailwind.config.ts b/frontend/tailwind.config.ts new file mode 100644 index 0000000000000000000000000000000000000000..9ebc9b5225ca019c78a7823b7e2d7a3653ce358d --- /dev/null +++ b/frontend/tailwind.config.ts @@ -0,0 +1,67 @@ +import type { Config } from "tailwindcss"; + +export default { + darkMode: ["class"], + content: [ + "./src/pages/**/*.{js,ts,jsx,tsx,mdx}", + "./src/components/**/*.{js,ts,jsx,tsx,mdx}", + "./src/app/**/*.{js,ts,jsx,tsx,mdx}", + ], + theme: { + extend: { + colors: { + // shadcn semantic colors (HSL-based) + background: "hsl(var(--background))", + foreground: "hsl(var(--foreground))", + card: { + DEFAULT: "hsl(var(--card))", + foreground: "hsl(var(--card-foreground))", + }, + popover: { + DEFAULT: "hsl(var(--popover))", + foreground: "hsl(var(--popover-foreground))", + }, + primary: { + DEFAULT: "hsl(var(--primary))", + foreground: "hsl(var(--primary-foreground))", + }, + secondary: { + DEFAULT: "hsl(var(--secondary))", + foreground: "hsl(var(--secondary-foreground))", + }, + muted: { + DEFAULT: "hsl(var(--muted))", + foreground: "hsl(var(--muted-foreground))", + }, + accent: { + DEFAULT: "hsl(var(--accent))", + foreground: "hsl(var(--accent-foreground))", + }, + destructive: { + DEFAULT: "hsl(var(--destructive))", + foreground: "hsl(var(--destructive-foreground))", + }, + border: "hsl(var(--border))", + input: "hsl(var(--input))", + ring: "hsl(var(--ring))", + + // Rerun-specific aliases + surface: "hsl(var(--surface))", + "surface-light": "hsl(var(--surface-light))", + "surface-elevated": "hsl(var(--surface-elevated))", + "border-subtle": "hsl(var(--border-subtle))", + text: "hsl(var(--text))", + "text-muted": "hsl(var(--text-muted))", + "text-subtle": "hsl(var(--text-subtle))", + "accent-cyan": "hsl(var(--accent-cyan))", + "accent-orange": "hsl(var(--accent-orange))", + }, + borderRadius: { + lg: "var(--radius)", + md: "calc(var(--radius) - 2px)", + sm: "calc(var(--radius) - 4px)", + }, + }, + }, + plugins: [require("tailwindcss-animate")], +} satisfies Config; diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000000000000000000000000000000000000..b575f7dac742447c79dd92f8b471b7d5e18c32cc --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,41 @@ +{ + "compilerOptions": { + "target": "ES2017", + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "noEmit": true, + "esModuleInterop": true, + "module": "esnext", + "moduleResolution": "bundler", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "react-jsx", + "incremental": true, + "plugins": [ + { + "name": "next" + } + ], + "paths": { + "@/*": [ + "./src/*" + ] + } + }, + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts", + ".next/dev/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] +} diff --git a/notebooks/colab_smoke_test.ipynb b/notebooks/colab_smoke_test.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..b60a470cbedb43d34c55e9f67bf993e5d61d6d06 --- /dev/null +++ b/notebooks/colab_smoke_test.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "47ee06e6", + "metadata": {}, + "source": [ + "# HyperView — Colab Smoke Test\n", + "\n", + "This notebook verifies that HyperView can launch inside Google Colab and open the UI in a new browser tab.\n", + "\n", + "The smoke test uses a synthetic dataset (random images + precomputed 2D coordinates), so it does not download models or run embedding computation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "945a1017", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "zsh:1: command not found: pip\n", + "Cloning into 'HyperView'...\n", + "remote: Enumerating objects: 577, done.\u001b[K\n", + "remote: Counting objects: 100% (577/577), done.\u001b[K\n", + "remote: Compressing objects: 100% (328/328), done.\u001b[K\n", + "remote: Total 577 (delta 240), reused 518 (delta 193), pack-reused 0 (from 0)\u001b[K\n", + "Receiving objects: 100% (577/577), 4.29 MiB | 8.76 MiB/s, done.\n", + "Resolving deltas: 100% (240/240), done.\n", + "/Users/matin/hyperview_org/HyperView/notebooks/HyperView\n", + "\u001b[2mUsing Python 3.12.8 environment at: /Users/matin/hyperview_org/HyperView/.venv\u001b[0m\n", + "\u001b[2K\u001b[1m\u001b[31merror\u001b[39m\u001b[0m: /Users/matin/hyperview_org/HyperView/notebooks/HyperView does not appear to be a Python project, as neither `pyproject.toml` nor `setup.py` are present in the directory\n" + ] + } + ], + "source": [ + "%pip install -q git+https://github.com/HackerRoomAI/HyperView.git@hyperview-base" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "58b82256", + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "\n", + "import hyperview as hv\n", + "from hyperview.core.sample import SampleFromArray\n", + "\n", + "dataset = hv.Dataset(\"colab_smoke\", persist=False)\n", + "\n", + "rng = np.random.default_rng(0)\n", + "num_samples = 200\n", + "\n", + "for i in range(num_samples):\n", + " img = (rng.random((64, 64, 3)) * 255).astype(np.uint8)\n", + "\n", + " sample = SampleFromArray.from_array(\n", + " id=f\"s{i}\",\n", + " image_array=img,\n", + " label=f\"class_{i % 10}\",\n", + " metadata={\"i\": i},\n", + " )\n", + "\n", + " # Precomputed 2D Euclidean projection\n", + " sample.embedding_2d = [float(rng.normal()), float(rng.normal())]\n", + "\n", + " # Precomputed 2D hyperbolic projection (inside unit disk)\n", + " r = float(rng.random() * 0.95)\n", + " theta = float(rng.random() * 2 * np.pi)\n", + " sample.embedding_2d_hyperbolic = [float(r * np.cos(theta)), float(r * np.sin(theta))]\n", + "\n", + " dataset.add_sample(sample)\n", + "\n", + "hv.launch(dataset, port=6262)" + ] + }, + { + "cell_type": "markdown", + "id": "b1cb3148", + "metadata": {}, + "source": [ + "Click the link printed above to open HyperView in a new tab. If needed, copy/paste the URL." + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/notebooks/demo.ipynb b/notebooks/demo.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..20b5343af3936af6a681b17cccd98838c1b1ec59 --- /dev/null +++ b/notebooks/demo.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e26a6a66", + "metadata": {}, + "source": [ + "# HyperView Demo\n", + "This notebook demonstrates how to use HyperView to visualize embeddings in both Euclidean and Hyperbolic spaces.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0aba0ed9", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:47.867950Z", + "iopub.status.busy": "2025-12-21T23:01:47.867881Z", + "iopub.status.idle": "2025-12-21T23:01:48.736348Z", + "shell.execute_reply": "2025-12-21T23:01:48.735942Z" + } + }, + "outputs": [], + "source": [ + "import sys\n", + "from pathlib import Path\n", + "\n", + "# Add src to path for development\n", + "sys.path.insert(0, str(Path.cwd().parent / \"src\"))\n", + "\n", + "import hyperview as hv\n", + "print(f\"HyperView version: {hv.__version__}\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "00becfad", + "metadata": {}, + "source": [ + "## Initialize Dataset\n", + "We'll create a new dataset named `cifar100_demo`.\n" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "3e5e93d5", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:48.738083Z", + "iopub.status.busy": "2025-12-21T23:01:48.737879Z", + "iopub.status.idle": "2025-12-21T23:01:49.297549Z", + "shell.execute_reply": "2025-12-21T23:01:49.296797Z" + } + }, + "outputs": [], + "source": [ + "dataset = hv.Dataset(\"cifar100_demo\")\n" + ] + }, + { + "cell_type": "markdown", + "id": "2248602f", + "metadata": {}, + "source": [ + "## Load CIFAR-100 Data\n", + "We'll load 500 samples from the CIFAR-100 dataset using Hugging Face Datasets.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0666b39a", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:49.299289Z", + "iopub.status.busy": "2025-12-21T23:01:49.299171Z", + "iopub.status.idle": "2025-12-21T23:01:51.732573Z", + "shell.execute_reply": "2025-12-21T23:01:51.732008Z" + } + }, + "outputs": [], + "source": [ + "dataset.add_from_huggingface(\n", + " \"uoft-cs/cifar100\",\n", + " split=\"train\",\n", + " image_key=\"img\",\n", + " label_key=\"fine_label\",\n", + " max_samples=500,\n", + ")\n" + ] + }, + { + "cell_type": "markdown", + "id": "5e119424", + "metadata": {}, + "source": [ + "## Compute Embeddings\n", + "This will use a pre-trained model to compute high-dimensional embeddings for our images.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d4e2c71f", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:51.734082Z", + "iopub.status.busy": "2025-12-21T23:01:51.733890Z", + "iopub.status.idle": "2025-12-21T23:01:55.876495Z", + "shell.execute_reply": "2025-12-21T23:01:55.875932Z" + } + }, + "outputs": [], + "source": [ + "dataset.compute_embeddings(show_progress=True)\n" + ] + }, + { + "cell_type": "markdown", + "id": "6f552a59", + "metadata": {}, + "source": [ + "## Compute Visualization Layout\n", + "This step performs dimensionality reduction to project the high-dimensional embeddings into 2D Euclidean and Hyperbolic spaces.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "b357847f", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:55.880223Z", + "iopub.status.busy": "2025-12-21T23:01:55.879935Z", + "iopub.status.idle": "2025-12-21T23:01:56.272742Z", + "shell.execute_reply": "2025-12-21T23:01:56.272238Z" + } + }, + "outputs": [], + "source": [ + "dataset.compute_visualization()\n" + ] + }, + { + "cell_type": "markdown", + "id": "54af1ea2", + "metadata": {}, + "source": [ + "## Launch Interactive Visualizer\n", + "Finally, we launch the visualizer. In a notebook environment, this will display an interactive iframe.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "0acef7dc", + "metadata": { + "execution": { + "iopub.execute_input": "2025-12-21T23:01:56.274506Z", + "iopub.status.busy": "2025-12-21T23:01:56.274369Z", + "iopub.status.idle": "2025-12-21T23:01:56.356551Z", + "shell.execute_reply": "2025-12-21T23:01:56.355551Z" + } + }, + "outputs": [], + "source": [ + "session = hv.launch(dataset)\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv (3.12.8)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.8" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/poc/bias_demonstration.py b/poc/bias_demonstration.py new file mode 100644 index 0000000000000000000000000000000000000000..6d343a980b4ae08fd4f42ed7261b36bae27d4320 --- /dev/null +++ b/poc/bias_demonstration.py @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +import matplotlib.pyplot as plt +import matplotlib.patches as mpatches +import numpy as np +import geomstats.backend as gs # type: ignore +from geomstats.geometry.poincare_ball import PoincareBall + +def generate_data(n_samples, center_r, center_theta, spread, label): + """Generates points in polar coordinates, then converts to Cartesian.""" + # Random noise in polar coordinates + r_noise = np.random.normal(0, spread, n_samples) + theta_noise = np.random.normal(0, spread, n_samples) + + r = np.clip(center_r + r_noise, 0, 0.99) # Keep within unit disk + theta = center_theta + theta_noise + + # Convert to Cartesian for plotting + x = r * np.cos(theta) + y = r * np.sin(theta) + + return np.column_stack([x, y]), label + +def main(): + print("Generating synthetic hierarchical data...") + + # 1. Define the Hierarchy + # Majority: Center of the space + # Minority: Periphery + # Rare: Deep Periphery (Sub-group of Minority) + + # Parameters + majority_n = 500 + minority_n = 50 + rare_n = 10 + + # Angle for the minority group + theta_minority = np.pi / 4 # 45 degrees + + # --- Euclidean Simulation --- + # In Euclidean space, we simulate "crowding" by placing them close together + # because the space doesn't expand. + + # Majority at (0,0) + maj_euc, _ = generate_data(majority_n, 0.0, 0.0, 0.1, "Majority") + + # Minority at distance 0.5 + min_euc, _ = generate_data(minority_n, 0.5, theta_minority, 0.08, "Minority") + + # Rare at distance 0.52 (Buried inside the Minority cluster in Euclidean terms) + rare_euc, _ = generate_data(rare_n, 0.52, theta_minority, 0.04, "Rare") + + + # --- Hyperbolic Simulation --- + # In Hyperbolic space, we map these same "conceptual" positions to the Poincaré disk. + # The "Rare" group is pushed further out to the edge (r=0.95). + # The "Minority" group is at r=0.8. + # The "Majority" is at r=0.0. + + # Majority at center + maj_hyp, _ = generate_data(majority_n, 0.0, 0.0, 0.1, "Majority") + + # Minority at r=0.8 + min_hyp, _ = generate_data(minority_n, 0.8, theta_minority, 0.05, "Minority") + + # Rare at r=0.95 (Deep in the hyperbolic tail) + rare_hyp, _ = generate_data(rare_n, 0.95, theta_minority, 0.01, "Rare") + + + # --- Visualization --- + fig, axes = plt.subplots(1, 2, figsize=(16, 8)) + + # Plot 1: Euclidean View + ax = axes[0] + ax.set_title("Euclidean Space (Standard AI)\n'Representation Collapse'", fontsize=14, fontweight='bold') + + # Draw Unit Circle for reference + circle = mpatches.Circle((0, 0), 1, color='black', fill=False, linestyle='--', alpha=0.3) + ax.add_artist(circle) + + ax.scatter(maj_euc[:, 0], maj_euc[:, 1], c='gray', alpha=0.3, label='Majority (Head)', s=20) + ax.scatter(min_euc[:, 0], min_euc[:, 1], c='blue', alpha=0.6, label='Minority (Tail)', s=40) + ax.scatter(rare_euc[:, 0], rare_euc[:, 1], c='red', alpha=0.9, label='Rare Subgroup (Long Tail)', s=40) + + # Annotate the "Crush" + ax.annotate('Indistinguishable\nCluster', xy=(0.55, 0.55), xytext=(0.2, 0.7), + arrowprops=dict(facecolor='black', shrink=0.05), fontsize=12) + + ax.set_xlim(-1.1, 1.1) + ax.set_ylim(-1.1, 1.1) + ax.set_aspect('equal') + ax.legend(loc='lower right') + ax.grid(True, alpha=0.2) + + + # Plot 2: Hyperbolic View + ax = axes[1] + ax.set_title("Hyperbolic Space (HyperView)\n'Hierarchical Expansion'", fontsize=14, fontweight='bold') + + # Draw Poincaré Disk Boundary + circle = mpatches.Circle((0, 0), 1, color='black', fill=False, linewidth=2) + ax.add_artist(circle) + + ax.scatter(maj_hyp[:, 0], maj_hyp[:, 1], c='gray', alpha=0.3, label='Majority', s=20) + ax.scatter(min_hyp[:, 0], min_hyp[:, 1], c='blue', alpha=0.6, label='Minority', s=40) + ax.scatter(rare_hyp[:, 0], rare_hyp[:, 1], c='red', alpha=0.9, label='Rare Subgroup', s=40) + + # Calculate Geodesic Distance (Visual representation) + # We use geomstats to calculate the actual hyperbolic distance between the centers + manifold = PoincareBall(2) + p_min = gs.array([0.8 * np.cos(theta_minority), 0.8 * np.sin(theta_minority)]) + p_rare = gs.array([0.95 * np.cos(theta_minority), 0.95 * np.sin(theta_minority)]) + dist = manifold.metric.dist(p_min, p_rare) + + # Annotate the Expansion + ax.annotate(f'Hyperbolic Dist: {dist:.2f}\n(Distinct & Separable)', + xy=(0.85, 0.85), xytext=(0.2, 0.8), + arrowprops=dict(facecolor='black', shrink=0.05), fontsize=12) + + ax.set_xlim(-1.1, 1.1) + ax.set_ylim(-1.1, 1.1) + ax.set_aspect('equal') + ax.legend(loc='lower right') + ax.axis('off') # Hide grid for cleaner Poincaré look + + plt.tight_layout() + output_path = 'assets/bias_collapse.png' + plt.savefig(output_path, dpi=300) + print(f"Visualization saved to {output_path}") + +if __name__ == "__main__": + main() diff --git a/poc/hyperbolic_adapter.py b/poc/hyperbolic_adapter.py new file mode 100644 index 0000000000000000000000000000000000000000..c7128506161e54ce46c8fab522fd2cc910ed2134 --- /dev/null +++ b/poc/hyperbolic_adapter.py @@ -0,0 +1,79 @@ +import torch +import torch.nn as nn +import geoopt + +class HyperbolicAdapter(nn.Module): + """ + A lightweight adapter that maps Euclidean embeddings (e.g., from CLIP/ResNet) + into the Poincaré ball. + + This solves the "Representation Collapse" by projecting crowded Euclidean + vectors into a space with exponentially growing volume. + """ + def __init__(self, input_dim=512, output_dim=128, c=1.0): + super().__init__() + self.c = c # Curvature of the manifold + self.manifold = geoopt.PoincareBall(c=self.c) + + # 1. Linear Layer (Euclidean transformation) + # We first compress/transform the features in Euclidean space + self.encoder = nn.Linear(input_dim, output_dim) + + # 2. Mobius Linear (Hyperbolic transformation - Optional but powerful) + # For a simple adapter, we can just project the output of the linear layer. + # But a true hyperbolic layer operates on the manifold. + # self.hyp_layer = geoopt.MobiusLinear(output_dim, output_dim, c=self.c) + + def forward(self, x): + """ + Args: + x: Euclidean input tensor (Batch, Input_Dim) + Returns: + x_hyp: Hyperbolic output tensor (Batch, Output_Dim) on the Poincaré ball + """ + # Step 1: Standard Euclidean processing + x_euc = self.encoder(x) + + # Step 2: Exponential Map (The "Bridge") + # This projects the Euclidean vector onto the Hyperbolic manifold. + # Ideally, we map to the tangent space at the origin (which is Euclidean-like) + # and then use expmap0 to project to the manifold. + + # expmap0(v) maps a vector v in the tangent space at 0 to the manifold. + x_hyp = self.manifold.expmap0(x_euc) + + return x_hyp + +def demo(): + print("--- Hyperbolic Adapter Demo ---") + + # Simulate CLIP embeddings (Batch=32, Dim=512) + # These represent our "crowded" Euclidean data + batch_size = 32 + input_dim = 512 + clip_embeddings = torch.randn(batch_size, input_dim) + print(f"Input (Euclidean): {clip_embeddings.shape}") + + # Initialize Adapter + # We project to a lower dimension (128) which is common for hyperbolic spaces + # as they are more efficient (can capture hierarchy in fewer dimensions). + adapter = HyperbolicAdapter(input_dim=input_dim, output_dim=128) + + # Forward Pass + hyp_embeddings = adapter(clip_embeddings) + + print(f"Output (Hyperbolic): {hyp_embeddings.shape}") + + # Verify they are on the manifold + # In Poincaré ball, norm must be < 1/sqrt(c) (usually < 1) + norms = hyp_embeddings.norm(dim=-1) + max_norm = norms.max().item() + print(f"Max Norm of embeddings: {max_norm:.4f} (Should be < 1.0)") + + if max_norm < 1.0: + print("SUCCESS: All points are validly projected onto the Poincaré disk.") + else: + print("FAILURE: Points escaped the manifold!") + +if __name__ == "__main__": + demo() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000000000000000000000000000000000000..a2cfcc450686145a6468672223be23824bc358d3 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,90 @@ +[project] +name = "hyperview" +version = "0.1.0" +description = "Open-source dataset curation with hyperbolic embeddings visualization" +readme = "README.md" +license = { text = "MIT" } +requires-python = ">=3.10" +authors = [ + { name = "HyperView Team" } +] +keywords = ["embeddings", "visualization", "hyperbolic", "dataset", "curation", "machine-learning"] +classifiers = [ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Artificial Intelligence", + "Topic :: Scientific/Engineering :: Visualization", +] + +dependencies = [ + "fastapi>=0.128.0", + "uvicorn[standard]>=0.40.0", + "embed-anything>=0.7.0", + "hyper-models @ git+https://github.com/Hyper3Labs/hyper-models.git@7489595f4f665802671136872b2bf61794995e1b", + "numpy>=1.26.4,<2.4", + "umap-learn>=0.5.11", + "pillow>=12.1.0", + "pydantic>=2.12.5", + "aiofiles>=25.1.0", + "datasets>=4.5.0", + "lancedb>=0.26.1", + "pyarrow>=22.0.0", +] + +[project.optional-dependencies] +dev = [ + "pytest>=9.0.2", + "pytest-asyncio>=1.3.0", + "httpx>=0.28.1", + "ruff>=0.14.13", +] +ml = [ + "torch>=2.9.1", + "torchvision>=0.24.1", + "timm>=1.0.0", +] + +[project.scripts] +hyperview = "hyperview.cli:main" + +[project.urls] +Homepage = "https://github.com/Hyper3Labs/HyperView" +Documentation = "https://github.com/Hyper3Labs/HyperView#readme" +Repository = "https://github.com/Hyper3Labs/HyperView" + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.hatch.metadata] +allow-direct-references = true + +[tool.hatch.build.targets.wheel] +packages = ["src/hyperview"] +# Include frontend static assets (pre-built before packaging) +artifacts = ["src/hyperview/server/static/**"] + +[tool.hatch.build.targets.sdist] +include = [ + "/src", + "/README.md", + "/LICENSE", +] + +[tool.ruff] +line-length = 100 +target-version = "py310" + +[tool.ruff.lint] +select = ["E", "F", "I", "N", "W", "UP"] +ignore = ["E501"] + +[tool.pytest.ini_options] +asyncio_mode = "auto" +testpaths = ["tests"] diff --git a/scripts/demo.py b/scripts/demo.py new file mode 100644 index 0000000000000000000000000000000000000000..768064370b7d95efb563e6f2d919d997893dfe9b --- /dev/null +++ b/scripts/demo.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +"""Run HyperView demo with CIFAR-10 dataset.""" + +import argparse +import os +import sys +from pathlib import Path + +# Add src to path for development +sys.path.insert(0, str(Path(__file__).parent.parent / "src")) + + +def main(): + parser = argparse.ArgumentParser(description="Run HyperView demo") + parser.add_argument( + "--dataset", + type=str, + default="cifar10_demo", + help="Dataset name to use for persistence (default: cifar10_demo)", + ) + parser.add_argument( + "--samples", type=int, default=50000, help="Number of samples to load (default: 50000)" + ) + parser.add_argument( + "--port", type=int, default=6262, help="Port to run server on (default: 6262)" + ) + parser.add_argument( + "--no-browser", action="store_true", help="Don't open browser automatically" + ) + parser.add_argument( + "--no-persist", action="store_true", help="Don't persist to database (use in-memory)" + ) + parser.add_argument( + "--model", + type=str, + default="openai/clip-vit-base-patch32", + help=( + "Embedding model_id to use (default: openai/clip-vit-base-patch32). " + "This is passed to Dataset.compute_embeddings(model=...)." + ), + ) + parser.add_argument( + "--datasets-dir", + "--database-dir", + type=str, + default=None, + help="Override persistence directory (sets HYPERVIEW_DATASETS_DIR)", + ) + parser.add_argument( + "--no-server", + action="store_true", + help="Don't start the web server (useful for CI / DB checks)", + ) + args = parser.parse_args() + + if args.datasets_dir: + os.environ["HYPERVIEW_DATASETS_DIR"] = args.datasets_dir + + import hyperview as hv + + dataset = hv.Dataset(args.dataset, persist=not args.no_persist) + + dataset.add_from_huggingface( + "uoft-cs/cifar10", + split="train", + image_key="img", + label_key="label", + max_samples=args.samples, + ) + + dataset.compute_embeddings(model=args.model, show_progress=True) + + # Compute both euclidean and poincare layouts + dataset.compute_visualization(geometry="euclidean") + dataset.compute_visualization(geometry="poincare") + + if args.no_server: + return + + hv.launch(dataset, port=args.port, open_browser=not args.no_browser) + + +if __name__ == "__main__": + main() diff --git a/scripts/demo_hyperbolic_clip.py b/scripts/demo_hyperbolic_clip.py new file mode 100644 index 0000000000000000000000000000000000000000..513bd4ca3c4d8d3df82258c288d4a5ab36ddadc4 --- /dev/null +++ b/scripts/demo_hyperbolic_clip.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +"""Demo: CLIP (Euclidean) + HyCoCLIP (Poincaré) on CIFAR-100.""" + +import hyperview as hv +import hyperview.embeddings.providers.hycoclip # noqa: F401 +from hyperview.embeddings.providers import ModelSpec + +DATASET_NAME = "cifar100_clip_hycoclip" +HF_DATASET = "uoft-cs/cifar100" +HF_SPLIT = "test" +HF_IMAGE_KEY = "img" +HF_LABEL_KEY = "fine_label" +NUM_SAMPLES = 200 +CLIP_MODEL_ID = "openai/clip-vit-base-patch32" +HYCOCLIP_MODEL_ID = "hycoclip_vit_s" + + +def main() -> None: + print("Loading CIFAR-100 from Hugging Face...") + dataset = hv.Dataset(DATASET_NAME, persist=False) + dataset.add_from_huggingface( + HF_DATASET, + split=HF_SPLIT, + image_key=HF_IMAGE_KEY, + label_key=HF_LABEL_KEY, + max_samples=NUM_SAMPLES, + ) + print(f"Loaded {len(dataset)} samples") + + clip_space = dataset.compute_embeddings(CLIP_MODEL_ID) + dataset.compute_visualization(space_key=clip_space, geometry="euclidean") + hycoclip_spec = ModelSpec(provider="hycoclip", model_id=HYCOCLIP_MODEL_ID) + hycoclip_space = dataset.compute_embeddings(hycoclip_spec) + dataset.compute_visualization(space_key=hycoclip_space, geometry="poincare") + + print("Launching at http://127.0.0.1:6262") + + hv.launch(dataset, open_browser=True) + + +if __name__ == "__main__": + main() diff --git a/scripts/export_frontend.sh b/scripts/export_frontend.sh new file mode 100755 index 0000000000000000000000000000000000000000..dd1cc37db3612b1a7712146505efc59924fd58b3 --- /dev/null +++ b/scripts/export_frontend.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Export frontend to static files for Python package + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" +FRONTEND_DIR="$PROJECT_ROOT/frontend" +HYPER_SCATTER_DIR="$PROJECT_ROOT/hyper-scatter" +STATIC_DIR="$PROJECT_ROOT/src/hyperview/server/static" + +# Build hyper-scatter library if it's a local checkout +if [ -d "$HYPER_SCATTER_DIR" ] && [ -f "$HYPER_SCATTER_DIR/package.json" ]; then + echo "Building hyper-scatter library..." + cd "$HYPER_SCATTER_DIR" + if [ ! -d "node_modules" ]; then + npm install + fi + npm run build:lib +fi + +echo "Building frontend..." +cd "$FRONTEND_DIR" + +# Install dependencies if needed +if [ ! -d "node_modules" ]; then + echo "Installing frontend dependencies..." + npm install +fi + +# Build for static export +npm run build + +# Copy to Python package +echo "Copying build output into Python package..." +rm -rf "$STATIC_DIR" +mkdir -p "$STATIC_DIR" +cp -r out/* "$STATIC_DIR/" + +echo "" +echo "✅ Frontend exported to $STATIC_DIR" +echo "" +echo "To test, run:" +echo " cd $PROJECT_ROOT" +echo " uv run hyperview demo" diff --git a/scripts/precompute_hf_demo.py b/scripts/precompute_hf_demo.py new file mode 100644 index 0000000000000000000000000000000000000000..946a17e21d302e43a0c890e1cd2126cf2dd338ec --- /dev/null +++ b/scripts/precompute_hf_demo.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python +"""Pre-compute HuggingFace Spaces demo dataset. + +This script is run during Docker build to pre-compute embeddings and +visualizations, ensuring fast startup times on HuggingFace Spaces. + +Features: +- CIFAR-10 dataset (300 samples) +- CLIP embeddings (Euclidean) via embed-anything +- HyCoCLIP embeddings (Hyperbolic) via hyper-models ONNX +- Pre-computed UMAP visualizations for both geometries +""" + +import os +from pathlib import Path + +# Configuration +DATASET_NAME = "cifar10_hf_demo" +HF_DATASET = "uoft-cs/cifar10" +HF_SPLIT = "train" +HF_IMAGE_KEY = "img" +HF_LABEL_KEY = "label" +NUM_SAMPLES = int(os.environ.get("DEMO_SAMPLES", 300)) + +# Storage paths (LanceDB + media) +DEFAULT_DATASETS_DIR = Path( + os.environ.get("HYPERVIEW_DATASETS_DIR", "/home/user/app/demo_data/datasets") +) +DEFAULT_MEDIA_DIR = Path(os.environ.get("HYPERVIEW_MEDIA_DIR", "/home/user/app/demo_data/media")) + +# Model configurations +CLIP_MODEL_ID = "openai/clip-vit-base-patch32" + + +def create_demo_dataset(): + """Create and return the demo dataset with pre-computed embeddings.""" + import hyperview as hv + from hyperview.embeddings.providers import ModelSpec + + print("=" * 60) + print("HyperView HuggingFace Spaces Demo Dataset Builder") + print("=" * 60) + print(f"Dataset: {HF_DATASET} ({HF_SPLIT})") + print(f"Samples: {NUM_SAMPLES}") + print(f"Datasets dir: {DEFAULT_DATASETS_DIR}") + print(f"Media dir: {DEFAULT_MEDIA_DIR}") + print("=" * 60) + + # Create dataset (persistent LanceDB storage) + dataset = hv.Dataset(DATASET_NAME) + + # Load CIFAR-10 samples + print(f"\n[1/5] Loading {NUM_SAMPLES} samples from {HF_DATASET}...") + added, skipped = dataset.add_from_huggingface( + HF_DATASET, + split=HF_SPLIT, + image_key=HF_IMAGE_KEY, + label_key=HF_LABEL_KEY, + max_samples=NUM_SAMPLES, + ) + print(f" Loaded {added} samples ({skipped} skipped)") + + # Compute CLIP embeddings (Euclidean) + print(f"\n[2/5] Computing CLIP embeddings ({CLIP_MODEL_ID})...") + clip_space = dataset.compute_embeddings(CLIP_MODEL_ID, show_progress=True) + print(f" Embedding space: {clip_space}") + + # Compute Euclidean visualization + print("\n[3/5] Computing Euclidean (UMAP) visualization...") + dataset.compute_visualization(space_key=clip_space, geometry="euclidean") + print(" Euclidean layout ready") + + # Compute HyCoCLIP embeddings (Hyperbolic) - using ONNX provider + print("\n[4/5] Computing HyCoCLIP embeddings (hyperbolic)...") + try: + # First, download the ONNX model from HuggingFace Hub + from huggingface_hub import hf_hub_download + + repo_id = "mnm-matin/hyperbolic-clip" + onnx_path = hf_hub_download( + repo_id=repo_id, + filename="hycoclip-vit-s/model.onnx", + ) + data_path = hf_hub_download( + repo_id=repo_id, + filename="hycoclip-vit-s/model.onnx.data", + ) + print(f" Downloaded ONNX model to: {onnx_path}") + print(f" Downloaded ONNX weights to: {data_path}") + + # Create model spec with local path + hycoclip_spec = ModelSpec( + provider="hycoclip_onnx", + model_id="hycoclip-vit-s", + checkpoint=onnx_path, + ) + hyper_space = dataset.compute_embeddings(hycoclip_spec, show_progress=True) + print(f" Embedding space: {hyper_space}") + + # Compute Poincaré visualization + print("\n[5/5] Computing Poincaré disk visualization...") + dataset.compute_visualization(space_key=hyper_space, geometry="poincare") + print(" Poincaré layout ready") + + except Exception as e: + print(f" WARNING: HyCoCLIP failed: {e}") + print(" Falling back to CLIP-only with Poincaré projection") + # Fallback: use CLIP embeddings with Poincaré projection + print("\n[5/5] Computing Poincaré visualization from CLIP embeddings...") + dataset.compute_visualization(space_key=clip_space, geometry="poincare") + print(" Poincaré layout ready (from CLIP)") + + return dataset + + +def main() -> None: + """Main entry point for pre-computation.""" + dataset = create_demo_dataset() + + # Summary + print("\n" + "=" * 60) + print("Pre-computation complete!") + print("=" * 60) + print(f"Samples: {len(dataset)}") + print(f"Dataset: {DATASET_NAME}") + print("=" * 60) + + +if __name__ == "__main__": + main() diff --git a/src/hyperview/__init__.py b/src/hyperview/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..7def79fa43c27c5c151595d0569573f5a9d4c212 --- /dev/null +++ b/src/hyperview/__init__.py @@ -0,0 +1,6 @@ +"""HyperView - Open-source dataset curation with hyperbolic embeddings visualization.""" + +from hyperview.api import Dataset, launch + +__version__ = "0.1.0" +__all__ = ["Dataset", "launch", "__version__"] diff --git a/src/hyperview/api.py b/src/hyperview/api.py new file mode 100644 index 0000000000000000000000000000000000000000..904297051a74bd51784f27436a464884e7d6c03c --- /dev/null +++ b/src/hyperview/api.py @@ -0,0 +1,395 @@ +"""Public API for HyperView.""" + +import json +import os +import socket +import threading +import time +import webbrowser +from dataclasses import dataclass +from urllib.error import URLError +from urllib.request import Request, urlopen +from uuid import uuid4 + +import uvicorn + +from hyperview.core.dataset import Dataset +from hyperview.server.app import create_app, set_dataset + +__all__ = ["Dataset", "launch", "Session"] + + +@dataclass(frozen=True) +class _HealthResponse: + name: str | None + session_id: str | None + dataset: str | None + pid: int | None + + +def _can_connect(host: str, port: int, timeout_s: float) -> bool: + try: + with socket.create_connection((host, port), timeout=timeout_s): + return True + except OSError: + return False + + +def _try_read_health(url: str, timeout_s: float) -> _HealthResponse | None: + try: + return _read_health(url, timeout_s=timeout_s) + except (URLError, TimeoutError, OSError, ValueError, json.JSONDecodeError): + return None + + +def _read_health(url: str, timeout_s: float) -> _HealthResponse: + request = Request(url, headers={"Accept": "application/json"}) + with urlopen(request, timeout=timeout_s) as response: + data = json.loads(response.read().decode("utf-8")) + + return _HealthResponse( + name=data.get("name"), + session_id=data.get("session_id"), + dataset=data.get("dataset"), + pid=data.get("pid") if isinstance(data.get("pid"), int) else None, + ) + + +class Session: + """A session for the HyperView visualizer.""" + + def __init__(self, dataset: Dataset, host: str, port: int): + self.dataset = dataset + self.host = host + self.port = port + # Prefer a browser-connectable host for user-facing URLs. + # When binding to 0.0.0.0, users should connect via 127.0.0.1 locally. + self.url = f"http://{self._connect_host}:{port}" + self._server_thread: threading.Thread | None = None + self._server: uvicorn.Server | None = None + self._startup_error: BaseException | None = None + self.session_id = uuid4().hex + + @property + def _connect_host(self) -> str: + return "127.0.0.1" if self.host == "0.0.0.0" else self.host + + @property + def _health_url(self) -> str: + return f"http://{self._connect_host}:{self.port}/__hyperview__/health" + + def _run_server(self): + try: + set_dataset(self.dataset) + app = create_app(self.dataset, session_id=self.session_id) + config = uvicorn.Config(app, host=self.host, port=self.port, log_level="warning") + self._server = uvicorn.Server(config) + self._server.run() + except BaseException as exc: + self._startup_error = exc + + def start(self, background: bool = True): + """Start the visualizer server.""" + if not background: + self._run_server() + return + + # Fail fast if something is already listening on this port. + if _can_connect(self._connect_host, self.port, timeout_s=0.2): + health = _try_read_health(self._health_url, timeout_s=0.2) + if health is not None and health.name == "hyperview": + raise RuntimeError( + "HyperView failed to start because the port is already serving " + f"HyperView (port={self.port}, session_id={health.session_id}). " + "Choose a different port or stop the existing server." + ) + + raise RuntimeError( + "HyperView failed to start because the port is already in use " + f"by a non-HyperView service (port={self.port}). Choose a different " + "port or stop the process listening on that port." + ) + + self._startup_error = None + self._server_thread = threading.Thread(target=self._run_server, daemon=True) + self._server_thread.start() + + deadline = time.time() + 5.0 + last_health_error: Exception | None = None + + while time.time() < deadline: + if self._startup_error is not None: + raise RuntimeError( + f"HyperView server failed to start (port={self.port}): " + f"{type(self._startup_error).__name__}: {self._startup_error}" + ) + + if self._server_thread is not None and not self._server_thread.is_alive(): + raise RuntimeError( + "HyperView server thread exited during startup. " + f"The port may be in use (port={self.port})." + ) + + try: + health = _read_health(self._health_url, timeout_s=0.2) + except (URLError, TimeoutError, OSError, ValueError, json.JSONDecodeError) as exc: + last_health_error = exc + time.sleep(0.05) + continue + + if health.name == "hyperview" and health.session_id == self.session_id: + return + + if health.name == "hyperview": + raise RuntimeError( + "HyperView failed to start because the port is already serving " + f"a different HyperView session (port={self.port}, " + f"session_id={health.session_id})." + ) + + raise RuntimeError( + "HyperView failed to start because the port is already serving " + f"a non-HyperView app (port={self.port})." + ) + + raise TimeoutError( + "HyperView server did not become ready in time " + f"(port={self.port}). Last error: {last_health_error}" + ) + + def stop(self): + """Stop the visualizer server.""" + if self._server: + self._server.should_exit = True + + def show(self, height: int = 800): + """Display the visualizer in a notebook. + + In Google Colab, notebook kernels cannot be accessed via localhost. + Colab exposes kernel ports through a proxy URL (see + `google.colab.kernel.proxyPort`). This renders a link to the proxied URL + that opens in a new tab. + + In other notebook environments, it renders a clickable link to the local + URL and a best-effort JavaScript auto-open. + """ + if _is_colab(): + try: + from google.colab.output import eval_js # type: ignore[import-not-found] + from IPython.display import HTML, display + + proxy_url = eval_js(f"google.colab.kernel.proxyPort({self.port})") + app_url = str(proxy_url).rstrip("/") + "/" + + display( + HTML( + "

HyperView is running in Colab. " + f"" + "Open HyperView in a new tab.

" + ) + ) + display(HTML(f"

{app_url}

")) + return + except Exception: + # Fall through to the generic notebook behavior. + pass + + # Default: open in a new browser tab (works well for Jupyter). + try: + from IPython.display import HTML, Javascript, display + + display( + HTML( + "

HyperView is running. " + f"Open in a new tab." + "

" + ) + ) + + # Best-effort auto-open. Some browsers may block popups. + display(Javascript(f'window.open("{self.url}", "_blank");')) + except ImportError: + print(f"IPython not installed. Please visit {self.url} in your browser.") + + def open_browser(self): + """Open the visualizer in a browser window.""" + webbrowser.open(self.url) + + +def launch( + dataset: Dataset, + port: int = 6262, + host: str = "127.0.0.1", + open_browser: bool = True, + notebook: bool | None = None, + height: int = 800, + reuse_server: bool = False, +) -> Session: + """Launch the HyperView visualization server. + + Note: + HyperView's UI requires 2D layouts (Euclidean + Poincare). If they are + missing but high-dimensional embeddings exist, this function will compute + them automatically. + + Args: + dataset: The dataset to visualize. + port: Port to run the server on. + host: Host to bind to. + open_browser: Whether to open a browser window. + notebook: Whether to display in a notebook. If None, auto-detects. + height: Height of the iframe in the notebook. + reuse_server: If True, and the requested port is already serving HyperView, + attach to the existing server instead of starting a new one. For safety, + this will only attach when the existing server reports the same dataset + name (via `/__hyperview__/health`). + + Returns: + A Session object. + + Example: + >>> import hyperview as hv + >>> dataset = hv.Dataset("my_dataset") + >>> dataset.add_images_dir("/path/to/images", label_from_folder=True) + >>> dataset.compute_embeddings() + >>> dataset.compute_visualization() + >>> hv.launch(dataset) + """ + if notebook is None: + # Colab is always a notebook environment, even if _is_notebook() fails to detect it + notebook = _is_notebook() or _is_colab() + + if _is_colab() and host == "127.0.0.1": + # Colab port forwarding/proxying is most reliable when the server binds + # to all interfaces. + host = "0.0.0.0" + + # Preflight: avoid doing expensive work if the port is already in use. + # If it's already serving HyperView and reuse_server=True, we can safely attach. + connect_host = "127.0.0.1" if host == "0.0.0.0" else host + health_url = f"http://{connect_host}:{port}/__hyperview__/health" + + if _can_connect(connect_host, port, timeout_s=0.2): + health = _try_read_health(health_url, timeout_s=0.2) + if health is not None and health.name == "hyperview": + if not reuse_server: + raise RuntimeError( + "HyperView failed to start because the port is already serving " + f"HyperView (port={port}, dataset={health.dataset}, " + f"session_id={health.session_id}, pid={health.pid}). " + "Choose a different port, stop the existing server, or pass " + "reuse_server=True to attach." + ) + + if health.dataset is not None and health.dataset != dataset.name: + raise RuntimeError( + "HyperView refused to attach to the existing server because it is " + f"serving a different dataset (port={port}, dataset={health.dataset}). " + f"Requested dataset={dataset.name}. Stop the existing server or " + "choose a different port." + ) + + session = Session(dataset, host, port) + if health.session_id is not None: + session.session_id = health.session_id + + if notebook: + if _is_colab(): + print( + f"\nHyperView is already running (Colab, port={session.port}). " + "Use the link below to open it." + ) + else: + print( + f"\nHyperView is already running at {session.url} (port={session.port}). " + "Opening a new tab..." + ) + session.show(height=height) + else: + print(f"\nHyperView is already running at {session.url} (port={session.port}).") + if open_browser: + session.open_browser() + + return session + + raise RuntimeError( + "HyperView failed to start because the port is already in use " + f"by a non-HyperView service (port={port}). Choose a different " + "port or stop the process listening on that port." + ) + + # The frontend requires 2D coords from /api/embeddings. + # Ensure at least one layout exists; do not auto-generate optional geometries. + layouts = dataset.list_layouts() + spaces = dataset.list_spaces() + + if not spaces: + raise ValueError( + "HyperView launch requires 2D projections for the UI. " + "No projections or embedding spaces were found. " + "Call `dataset.compute_embeddings()` and `dataset.compute_visualization()` " + "before `hv.launch()`." + ) + + if not layouts: + default_space_key = spaces[0].space_key + print("No layouts found. Computing euclidean visualization...") + dataset.compute_visualization(space_key=default_space_key, geometry="euclidean") + + session = Session(dataset, host, port) + + if notebook: + session.start(background=True) + if _is_colab(): + print( + f"\nHyperView is running (Colab, port={session.port}). " + "Use the link below to open it." + ) + else: + print(f"\nHyperView is running at {session.url}. Opening a new tab...") + session.show(height=height) + else: + session.start(background=True) + print(" Press Ctrl+C to stop.\n") + print(f"\nHyperView is running at {session.url}") + + if open_browser: + session.open_browser() + + try: + while True: + # Keep the main thread alive so the daemon server thread can run. + time.sleep(0.25) + if session._server_thread is not None and not session._server_thread.is_alive(): + raise RuntimeError("HyperView server stopped unexpectedly.") + except KeyboardInterrupt: + pass + finally: + session.stop() + if session._server_thread is not None: + session._server_thread.join(timeout=2.0) + + return session + + +def _is_notebook() -> bool: + """Check if running in a notebook environment.""" + try: + from IPython import get_ipython + except ImportError: + return False + + shell = get_ipython() + return shell is not None and shell.__class__.__name__ == "ZMQInteractiveShell" + + +def _is_colab() -> bool: + """Check if running inside a Google Colab notebook runtime.""" + if os.environ.get("COLAB_RELEASE_TAG"): + return True + try: + import google.colab # type: ignore[import-not-found] + + return True + except ImportError: + return False diff --git a/src/hyperview/cli.py b/src/hyperview/cli.py new file mode 100644 index 0000000000000000000000000000000000000000..9e5486ca24bc7b22ad4850d45158f662f3e9715e --- /dev/null +++ b/src/hyperview/cli.py @@ -0,0 +1,159 @@ +"""Command-line interface for HyperView.""" + +import argparse +import sys + +from hyperview import Dataset, launch + + +def main(): + """Main CLI entry point.""" + parser = argparse.ArgumentParser( + prog="hyperview", + description="HyperView - Dataset visualization with hyperbolic embeddings", + ) + subparsers = parser.add_subparsers(dest="command", help="Available commands") + + # Demo command + demo_parser = subparsers.add_parser("demo", help="Run a demo with sample data") + demo_parser.add_argument( + "--samples", + type=int, + default=500, + help="Number of samples to load (default: 500)", + ) + demo_parser.add_argument( + "--port", + type=int, + default=6262, + help="Port to run the server on (default: 6262)", + ) + demo_parser.add_argument( + "--host", + type=str, + default="127.0.0.1", + help="Host to bind the server to (default: 127.0.0.1)", + ) + demo_parser.add_argument( + "--no-browser", + action="store_true", + help="Do not open a browser window automatically", + ) + demo_parser.add_argument( + "--reuse-server", + action="store_true", + help=( + "If the port is already serving HyperView, attach instead of failing. " + "For safety, this only attaches when the existing server reports the same dataset name." + ), + ) + + # Serve command + serve_parser = subparsers.add_parser("serve", help="Serve a saved dataset") + serve_parser.add_argument("dataset", help="Path to saved dataset JSON file") + serve_parser.add_argument( + "--port", + type=int, + default=6262, + help="Port to run the server on (default: 6262)", + ) + serve_parser.add_argument( + "--host", + type=str, + default="127.0.0.1", + help="Host to bind the server to (default: 127.0.0.1)", + ) + serve_parser.add_argument( + "--no-browser", + action="store_true", + help="Do not open a browser window automatically", + ) + serve_parser.add_argument( + "--reuse-server", + action="store_true", + help=( + "If the port is already serving HyperView, attach instead of failing. " + "For safety, this only attaches when the existing server reports the same dataset name." + ), + ) + + args = parser.parse_args() + + if args.command == "demo": + run_demo( + args.samples, + args.port, + host=args.host, + open_browser=not args.no_browser, + reuse_server=args.reuse_server, + ) + elif args.command == "serve": + serve_dataset( + args.dataset, + args.port, + host=args.host, + open_browser=not args.no_browser, + reuse_server=args.reuse_server, + ) + else: + parser.print_help() + sys.exit(1) + + +def run_demo( + num_samples: int = 500, + port: int = 6262, + *, + host: str = "127.0.0.1", + open_browser: bool = True, + reuse_server: bool = False, +): + """Run a demo with CIFAR-10 data.""" + print("Loading CIFAR-10 dataset...") + dataset = Dataset("cifar10_demo") + + added, skipped = dataset.add_from_huggingface( + "uoft-cs/cifar10", + split="train", + image_key="img", + label_key="label", + max_samples=num_samples, + ) + if skipped > 0: + print(f"Loaded {added} samples ({skipped} already present)") + else: + print(f"Loaded {added} samples") + + print("Computing embeddings...") + dataset.compute_embeddings(show_progress=True) + print("Embeddings computed") + + print("Computing visualizations...") + # Compute both euclidean and poincare layouts + dataset.compute_visualization(geometry="euclidean") + dataset.compute_visualization(geometry="poincare") + print("Visualizations ready") + + launch(dataset, port=port, host=host, open_browser=open_browser, reuse_server=reuse_server) + + +def serve_dataset( + filepath: str, + port: int = 6262, + *, + host: str = "127.0.0.1", + open_browser: bool = True, + reuse_server: bool = False, +): + """Serve a saved dataset.""" + from hyperview import Dataset, launch + + print(f"Loading dataset from {filepath}...") + dataset = Dataset.load(filepath) + print(f"Loaded {len(dataset)} samples") + + launch(dataset, port=port, host=host, open_browser=open_browser, reuse_server=reuse_server) + + +if __name__ == "__main__": + main() diff --git a/src/hyperview/core/__init__.py b/src/hyperview/core/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..2f09c78cc3b71fb293208678553e3774c9bf0032 --- /dev/null +++ b/src/hyperview/core/__init__.py @@ -0,0 +1,6 @@ +"""Core data structures for HyperView.""" + +from hyperview.core.dataset import Dataset +from hyperview.core.sample import Sample + +__all__ = ["Dataset", "Sample"] diff --git a/src/hyperview/core/dataset.py b/src/hyperview/core/dataset.py new file mode 100644 index 0000000000000000000000000000000000000000..a943e8a419d7c3a5ebe755ebf6b2d8931f939b1a --- /dev/null +++ b/src/hyperview/core/dataset.py @@ -0,0 +1,670 @@ +"""Dataset class for managing collections of samples.""" + +from __future__ import annotations + +import hashlib +import json +import uuid +from collections.abc import Callable, Iterator +from pathlib import Path +from typing import Any, cast + +import numpy as np +from datasets import DownloadConfig, load_dataset +from PIL import Image + +from hyperview.core.sample import Sample +from hyperview.storage.backend import StorageBackend +from hyperview.storage.schema import make_layout_key + + +class Dataset: + """A collection of samples with support for embeddings and visualization. + + Datasets are automatically persisted to LanceDB by default, providing: + - Automatic persistence (no need to call save()) + - Vector similarity search + - Efficient storage and retrieval + + Embeddings are stored separately from samples, keyed by model_id. + Layouts (2D projections) are stored per layout_key (space + method). + + Examples: + # Create a new dataset (auto-persisted) + dataset = hv.Dataset("my_dataset") + dataset.add_images_dir("/path/to/images") + + # Create an in-memory dataset (for testing) + dataset = hv.Dataset("temp", persist=False) + """ + + def __init__( + self, + name: str | None = None, + persist: bool = True, + storage: StorageBackend | None = None, + ): + """Initialize a new dataset. + + Args: + name: Optional name for the dataset. + persist: If True (default), use LanceDB for persistence. + If False, use in-memory storage. + storage: Optional custom storage backend. If provided, persist is ignored. + """ + self.name = name or f"dataset_{uuid.uuid4().hex[:8]}" + + # Initialize storage backend + if storage is not None: + self._storage = storage + elif persist: + from hyperview.storage import LanceDBBackend, StorageConfig + + config = StorageConfig.default() + self._storage = LanceDBBackend(self.name, config) + else: + from hyperview.storage import MemoryBackend + self._storage = MemoryBackend(self.name) + + # Color palette for deterministic label color assignment + _COLOR_PALETTE = [ + "#e6194b", "#3cb44b", "#ffe119", "#4363d8", "#f58231", + "#911eb4", "#46f0f0", "#f032e6", "#bcf60c", "#fabebe", + "#008080", "#e6beff", "#9a6324", "#fffac8", "#800000", + "#aaffc3", "#808000", "#ffd8b1", "#000075", "#808080", + ] + + def __len__(self) -> int: + return len(self._storage) + + def __iter__(self) -> Iterator[Sample]: + return iter(self._storage) + + def __getitem__(self, sample_id: str) -> Sample: + sample = self._storage.get_sample(sample_id) + if sample is None: + raise KeyError(sample_id) + return sample + + def add_sample(self, sample: Sample) -> None: + """Add a sample to the dataset (idempotent).""" + self._storage.add_sample(sample) + + def _ingest_samples( + self, + samples: list[Sample], + *, + skip_existing: bool = True, + ) -> tuple[int, int]: + """Shared ingestion helper for batch sample insertion. + + Handles deduplication uniformly. + + Args: + samples: List of samples to ingest. + skip_existing: If True, skip samples that already exist in storage. + + Returns: + Tuple of (num_added, num_skipped). + """ + if not samples: + return 0, 0 + + skipped = 0 + if skip_existing: + all_ids = [s.id for s in samples] + existing_ids = self._storage.get_existing_ids(all_ids) + if existing_ids: + samples = [s for s in samples if s.id not in existing_ids] + skipped = len(all_ids) - len(samples) + + if not samples: + return 0, skipped + + self._storage.add_samples_batch(samples) + + return len(samples), skipped + + def add_image( + self, + filepath: str, + label: str | None = None, + metadata: dict[str, Any] | None = None, + sample_id: str | None = None, + ) -> Sample: + """Add a single image to the dataset. + + Args: + filepath: Path to the image file. + label: Optional label for the image. + metadata: Optional metadata dictionary. + sample_id: Optional custom ID. If not provided, one will be generated. + + Returns: + The created Sample. + """ + if sample_id is None: + sample_id = hashlib.md5(filepath.encode()).hexdigest()[:12] + + sample = Sample( + id=sample_id, + filepath=filepath, + label=label, + metadata=metadata or {}, + ) + self.add_sample(sample) + return sample + + def add_images_dir( + self, + directory: str, + extensions: tuple[str, ...] = (".jpg", ".jpeg", ".png", ".webp"), + label_from_folder: bool = False, + recursive: bool = True, + skip_existing: bool = True, + ) -> tuple[int, int]: + """Add all images from a directory. + + Args: + directory: Path to the directory containing images. + extensions: Tuple of valid file extensions. + label_from_folder: If True, use parent folder name as label. + recursive: If True, search subdirectories. + skip_existing: If True (default), skip samples that already exist. + + Returns: + Tuple of (num_added, num_skipped). + """ + directory_path = Path(directory) + if not directory_path.exists(): + raise ValueError(f"Directory does not exist: {directory_path}") + + samples = [] + pattern = "**/*" if recursive else "*" + + for path in directory_path.glob(pattern): + if path.is_file() and path.suffix.lower() in extensions: + label = path.parent.name if label_from_folder else None + sample_id = hashlib.md5(str(path).encode()).hexdigest()[:12] + sample = Sample( + id=sample_id, + filepath=str(path), + label=label, + metadata={}, + ) + samples.append(sample) + + # Use shared ingestion helper + return self._ingest_samples(samples, skip_existing=skip_existing) + + def add_from_huggingface( + self, + dataset_name: str, + split: str = "train", + image_key: str = "img", + label_key: str | None = "fine_label", + label_names_key: str | None = None, + max_samples: int | None = None, + show_progress: bool = True, + skip_existing: bool = True, + image_format: str = "auto", + ) -> tuple[int, int]: + """Load samples from a HuggingFace dataset. + + Images are downloaded to disk at ~/.hyperview/media/huggingface/{dataset}/{split}/ + This ensures images persist across sessions and embeddings can be computed + at any time, similar to FiftyOne's approach. + + Args: + dataset_name: Name of the HuggingFace dataset. + split: Dataset split to use. + image_key: Key for the image column. + label_key: Key for the label column (can be None). + label_names_key: Key for label names in dataset info. + max_samples: Maximum number of samples to load. + show_progress: Whether to print progress. + skip_existing: If True (default), skip samples that already exist in storage. + image_format: Image format to save: "auto" (detect from source, fallback PNG), + "png" (lossless), or "jpeg" (smaller files). + + Returns: + Tuple of (num_added, num_skipped). + """ + from hyperview.storage import StorageConfig + + # HuggingFace `load_dataset()` can be surprisingly slow even when the dataset + # is already cached, due to Hub reachability checks in some environments. + # For a fast path, first try loading in "offline" mode (cache-only), and + # fall back to an online load if the dataset isn't cached yet. + try: + ds = cast( + Any, + load_dataset( + dataset_name, + split=split, + download_config=DownloadConfig(local_files_only=True), + ), + ) + except Exception: + ds = cast(Any, load_dataset(dataset_name, split=split)) + + # Get label names if available + label_names = None + if label_key and label_names_key: + if label_names_key in ds.features: + label_names = ds.features[label_names_key].names + elif label_key: + if hasattr(ds.features[label_key], "names"): + label_names = ds.features[label_key].names + + # Extract dataset metadata for robust sample IDs + config_name = getattr(ds.info, "config_name", None) or "default" + fingerprint = ds._fingerprint[:8] if hasattr(ds, "_fingerprint") and ds._fingerprint else "unknown" + version = str(ds.info.version) if ds.info.version else None + + # Get media directory for this dataset + config = StorageConfig.default() + media_dir = config.get_huggingface_media_dir(dataset_name, split) + + samples = [] + total = len(ds) if max_samples is None else min(len(ds), max_samples) + + if show_progress: + print(f"Loading {total} samples from {dataset_name}...") + + iterator = range(total) + + for i in iterator: + item = ds[i] + image = item[image_key] + + # Handle PIL Image or numpy array + if isinstance(image, Image.Image): + pil_image = image + else: + pil_image = Image.fromarray(np.asarray(image)) + + # Get label + label = None + if label_key and label_key in item: + label_idx = item[label_key] + if label_names and isinstance(label_idx, int): + label = label_names[label_idx] + else: + label = str(label_idx) + + # Generate robust sample ID with config and fingerprint + safe_name = dataset_name.replace("/", "_") + sample_id = f"{safe_name}_{config_name}_{fingerprint}_{split}_{i}" + + # Determine image format and extension + if image_format == "auto": + # Try to preserve original format, fallback to PNG + original_format = getattr(pil_image, "format", None) + if original_format in ("JPEG", "JPG"): + save_format = "JPEG" + ext = ".jpg" + else: + save_format = "PNG" + ext = ".png" + elif image_format == "jpeg": + save_format = "JPEG" + ext = ".jpg" + else: + save_format = "PNG" + ext = ".png" + + # Enhanced metadata with dataset info + metadata = { + "source": dataset_name, + "config": config_name, + "split": split, + "index": i, + "fingerprint": ds._fingerprint if hasattr(ds, "_fingerprint") else None, + "version": version, + } + + image_path = media_dir / f"{sample_id}{ext}" + if not image_path.exists(): + if save_format == "JPEG" or pil_image.mode in ("RGBA", "P", "L"): + pil_image = pil_image.convert("RGB") + pil_image.save(image_path, format=save_format) + + sample = Sample( + id=sample_id, + filepath=str(image_path), + label=label, + metadata=metadata, + ) + + samples.append(sample) + + # Use shared ingestion helper + num_added, skipped = self._ingest_samples(samples, skip_existing=skip_existing) + + if show_progress: + print(f"Images saved to: {media_dir}") + if skipped > 0: + print(f"Skipped {skipped} existing samples") + + return num_added, skipped + + def compute_embeddings( + self, + model: str | ModelSpec = "openai/clip-vit-base-patch32", + batch_size: int = 32, + show_progress: bool = True, + ) -> str: + """Compute embeddings for samples that don't have them yet. + + Embeddings are stored in a dedicated space keyed by model_id. + + Args: + model: EmbedAnything HuggingFace `model_id` to use. + batch_size: Batch size for processing. + show_progress: Whether to show progress bar. + + Returns: + space_key for the embedding space. + """ + from hyperview.embeddings.pipelines import compute_embeddings + from hyperview.embeddings.providers import ModelSpec + + if isinstance(model, ModelSpec): + model_spec = model + else: + model_spec = ModelSpec(provider="embed_anything", model_id=model) + space_key, _num_computed, _num_skipped = compute_embeddings( + storage=self._storage, + model_spec=model_spec, + batch_size=batch_size, + show_progress=show_progress, + ) + return space_key + + def compute_visualization( + self, + space_key: str | None = None, + method: str = "umap", + geometry: str = "euclidean", + n_neighbors: int = 15, + min_dist: float = 0.1, + metric: str = "cosine", + force: bool = False, + ) -> str: + """Compute 2D projections for visualization. + + Args: + space_key: Embedding space to project. If None, uses the first available. + method: Projection method ('umap' supported). + geometry: Output geometry type ('euclidean' or 'poincare'). + n_neighbors: Number of neighbors for UMAP. + min_dist: Minimum distance for UMAP. + metric: Distance metric for UMAP. + force: Force recomputation even if layout exists. + + Returns: + layout_key for the computed layout. + """ + from hyperview.embeddings.pipelines import compute_layout + + return compute_layout( + storage=self._storage, + space_key=space_key, + method=method, + geometry=geometry, + n_neighbors=n_neighbors, + min_dist=min_dist, + metric=metric, + force=force, + show_progress=True, + ) + + def list_spaces(self) -> list[Any]: + """List all embedding spaces in this dataset.""" + return self._storage.list_spaces() + + def list_layouts(self) -> list[Any]: + """List all layouts in this dataset (returns LayoutInfo objects).""" + return self._storage.list_layouts() + + def find_similar( + self, + sample_id: str, + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + """Find k most similar samples to a given sample. + + Args: + sample_id: ID of the query sample. + k: Number of neighbors to return. + space_key: Embedding space to search in. If None, uses first available. + + Returns: + List of (sample, distance) tuples, sorted by distance ascending. + """ + return self._storage.find_similar(sample_id, k, space_key) + + def find_similar_by_vector( + self, + vector: list[float], + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + """Find k most similar samples to a given vector. + + Args: + vector: Query vector. + k: Number of neighbors to return. + space_key: Embedding space to search in. If None, uses first available. + + Returns: + List of (sample, distance) tuples, sorted by distance ascending. + """ + return self._storage.find_similar_by_vector(vector, k, space_key) + + @staticmethod + def _compute_label_color(label: str, palette: list[str]) -> str: + """Compute a deterministic color for a label.""" + digest = hashlib.md5(label.encode("utf-8")).digest() + idx = int.from_bytes(digest[:4], "big") % len(palette) + return palette[idx] + + def get_label_colors(self) -> dict[str, str]: + """Get the color mapping for labels (computed deterministically).""" + labels = self._storage.get_unique_labels() + return {label: self._compute_label_color(label, self._COLOR_PALETTE) for label in labels} + + def set_coords( + self, + geometry: str, + ids: list[str], + coords: np.ndarray | list[list[float]], + ) -> str: + """Set precomputed 2D coordinates for visualization. + + Use this when you have precomputed 2D projections and want to skip + embedding computation. Useful for smoke tests or external projections. + + Args: + geometry: "euclidean" or "poincare". + ids: List of sample IDs. + coords: (N, 2) array of coordinates. + + Returns: + The layout_key for the stored coordinates. + + Example: + >>> dataset.set_coords("euclidean", ["s0", "s1"], [[0.1, 0.2], [0.3, 0.4]]) + >>> dataset.set_coords("poincare", ["s0", "s1"], [[0.1, 0.2], [0.3, 0.4]]) + >>> hv.launch(dataset) + """ + if geometry not in ("euclidean", "poincare"): + raise ValueError(f"geometry must be 'euclidean' or 'poincare', got '{geometry}'") + + coords_arr = np.asarray(coords, dtype=np.float32) + if coords_arr.ndim != 2 or coords_arr.shape[1] != 2: + raise ValueError(f"coords must be (N, 2), got shape {coords_arr.shape}") + + # Ensure a synthetic space exists (required by launch()) + space_key = "precomputed" + if not any(s.space_key == space_key for s in self._storage.list_spaces()): + precomputed_config = { + "provider": "precomputed", + "geometry": "unknown", # Precomputed coords don't have a source embedding geometry + } + self._storage.ensure_space(space_key, dim=2, config=precomputed_config) + + layout_key = make_layout_key(space_key, method="precomputed", geometry=geometry) + + # Ensure layout registry entry exists + self._storage.ensure_layout( + layout_key=layout_key, + space_key=space_key, + method="precomputed", + geometry=geometry, + params=None, + ) + + self._storage.add_layout_coords(layout_key, list(ids), coords_arr) + return layout_key + + @property + def samples(self) -> list[Sample]: + """Get all samples as a list.""" + return self._storage.get_all_samples() + + @property + def labels(self) -> list[str]: + """Get unique labels in the dataset.""" + return self._storage.get_unique_labels() + + def filter(self, predicate: Callable[[Sample], bool]) -> list[Sample]: + """Filter samples based on a predicate function.""" + return self._storage.filter(predicate) + + def get_samples_paginated( + self, + offset: int = 0, + limit: int = 100, + label: str | None = None, + ) -> tuple[list[Sample], int]: + """Get paginated samples. + + This avoids loading all samples into memory and is used by the server + API for efficient pagination. + """ + return self._storage.get_samples_paginated(offset=offset, limit=limit, label=label) + + def get_samples_by_ids(self, sample_ids: list[str]) -> list[Sample]: + """Retrieve multiple samples by ID. + + The returned list is aligned to the input order and skips missing IDs. + """ + return self._storage.get_samples_by_ids(sample_ids) + + def get_visualization_data( + self, + layout_key: str, + ) -> tuple[list[str], list[str | None], np.ndarray]: + """Get visualization data (ids, labels, coords) for a layout.""" + layout_ids, layout_coords = self._storage.get_layout_coords(layout_key) + if not layout_ids: + return [], [], np.empty((0, 2), dtype=np.float32) + + labels_by_id = self._storage.get_labels_by_ids(layout_ids) + + ids: list[str] = [] + labels: list[str | None] = [] + coords: list[np.ndarray] = [] + + for i, sample_id in enumerate(layout_ids): + if sample_id in labels_by_id: + ids.append(sample_id) + labels.append(labels_by_id[sample_id]) + coords.append(layout_coords[i]) + + if not coords: + return [], [], np.empty((0, 2), dtype=np.float32) + + return ids, labels, np.asarray(coords, dtype=np.float32) + + + def get_lasso_candidates_aabb( + self, + *, + layout_key: str, + x_min: float, + x_max: float, + y_min: float, + y_max: float, + ) -> tuple[list[str], np.ndarray]: + """Return candidate (id, xy) rows within an AABB for a layout.""" + return self._storage.get_lasso_candidates_aabb( + layout_key=layout_key, + x_min=x_min, + x_max=x_max, + y_min=y_min, + y_max=y_max, + ) + + def save(self, filepath: str, include_thumbnails: bool = True) -> None: + """Export dataset to a JSON file. + + Args: + filepath: Path to save the JSON file. + include_thumbnails: Whether to include cached thumbnails. + """ + samples = self._storage.get_all_samples() + if include_thumbnails: + for s in samples: + s.cache_thumbnail() + + data = { + "name": self.name, + "samples": [ + { + "id": s.id, + "filepath": s.filepath, + "label": s.label, + "metadata": s.metadata, + "thumbnail_base64": s.thumbnail_base64 if include_thumbnails else None, + } + for s in samples + ], + } + with open(filepath, "w") as f: + json.dump(data, f) + + @classmethod + def load(cls, filepath: str, persist: bool = False) -> "Dataset": + """Load dataset from a JSON file. + + Args: + filepath: Path to the JSON file. + persist: If True, persist the loaded data to LanceDB. + If False (default), keep in memory only. + + Returns: + Dataset instance. + """ + with open(filepath) as f: + data = json.load(f) + + dataset = cls(name=data["name"], persist=persist) + + # Add samples + samples = [] + for s_data in data["samples"]: + sample = Sample( + id=s_data["id"], + filepath=s_data["filepath"], + label=s_data.get("label"), + metadata=s_data.get("metadata", {}), + thumbnail_base64=s_data.get("thumbnail_base64"), + ) + samples.append(sample) + + dataset._storage.add_samples_batch(samples) + return dataset diff --git a/src/hyperview/core/sample.py b/src/hyperview/core/sample.py new file mode 100644 index 0000000000000000000000000000000000000000..d0e3f38afb2541915f830ad7278e5e225b1a141d --- /dev/null +++ b/src/hyperview/core/sample.py @@ -0,0 +1,95 @@ +"""Sample class representing a single data point in a dataset.""" + +import base64 +import io +from pathlib import Path +from typing import Any + +from PIL import Image +from pydantic import BaseModel, Field + + +class Sample(BaseModel): + """A single sample in a HyperView dataset. + + Samples are pure metadata containers. Embeddings and layouts are stored + separately in dedicated tables (per embedding space / per layout). + """ + + id: str = Field(..., description="Unique identifier for the sample") + filepath: str = Field(..., description="Path to the image file") + label: str | None = Field(default=None, description="Label for the sample") + metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata") + thumbnail_base64: str | None = Field(default=None, description="Cached thumbnail as base64") + width: int | None = Field(default=None, description="Image width in pixels") + height: int | None = Field(default=None, description="Image height in pixels") + + model_config = {"arbitrary_types_allowed": True} + + @property + def filename(self) -> str: + """Get the filename from the filepath.""" + return Path(self.filepath).name + + def load_image(self) -> Image.Image: + """Load the image from disk.""" + return Image.open(self.filepath) + + def get_thumbnail(self, size: tuple[int, int] = (128, 128)) -> Image.Image: + """Get a thumbnail of the image. Also captures original dimensions.""" + img = self.load_image() + # Capture original dimensions while we have the image loaded + if self.width is None or self.height is None: + self.width, self.height = img.size + img.thumbnail(size, Image.Resampling.LANCZOS) + return img + + def _encode_thumbnail(self, size: tuple[int, int] = (128, 128)) -> str: + """Encode thumbnail as base64 JPEG.""" + thumb = self.get_thumbnail(size) + if thumb.mode in ("RGBA", "P"): + thumb = thumb.convert("RGB") + buffer = io.BytesIO() + thumb.save(buffer, format="JPEG", quality=85) + return base64.b64encode(buffer.getvalue()).decode("utf-8") + + def get_thumbnail_base64(self, size: tuple[int, int] = (128, 128)) -> str: + """Get thumbnail as base64 encoded string.""" + return self.thumbnail_base64 or self._encode_thumbnail(size) + + def cache_thumbnail(self, size: tuple[int, int] = (128, 128)) -> None: + """Cache the thumbnail as base64 for persistence.""" + if self.thumbnail_base64 is None: + self.thumbnail_base64 = self._encode_thumbnail(size) + + def to_api_dict(self, include_thumbnail: bool = True) -> dict[str, Any]: + """Convert to dictionary for API response.""" + # Ensure dimensions are populated (loads image if needed but not cached) + if self.width is None or self.height is None: + self.ensure_dimensions() + + data = { + "id": self.id, + "filepath": self.filepath, + "filename": self.filename, + "label": self.label, + "metadata": self.metadata, + "width": self.width, + "height": self.height, + } + if include_thumbnail: + data["thumbnail"] = self.get_thumbnail_base64() + return data + + def ensure_dimensions(self) -> None: + """Load image dimensions if not already set.""" + if self.width is None or self.height is None: + try: + img = self.load_image() + self.width, self.height = img.size + except Exception: + # If image can't be loaded, leave as None + pass + + + diff --git a/src/hyperview/core/selection.py b/src/hyperview/core/selection.py new file mode 100644 index 0000000000000000000000000000000000000000..1dee065d6b8e177425439152def48cd132406aa5 --- /dev/null +++ b/src/hyperview/core/selection.py @@ -0,0 +1,53 @@ +"""Selection / geometry helpers. + +This module contains small, backend-agnostic utilities used by selection endpoints +(e.g. lasso selection over 2D embeddings). +""" + +from __future__ import annotations + +import numpy as np + + +def points_in_polygon(points_xy: np.ndarray, polygon_xy: np.ndarray) -> np.ndarray: + """Vectorized point-in-polygon (even-odd rule / ray casting). + + Args: + points_xy: Array of shape (m, 2) with point coordinates. + polygon_xy: Array of shape (n, 2) with polygon vertices. + + Returns: + Boolean mask of length m, True where point lies inside polygon. + + Notes: + Boundary points may be classified as outside depending on floating point + ties (common for lasso selection tools). + """ + if polygon_xy.shape[0] < 3: + return np.zeros((points_xy.shape[0],), dtype=bool) + + x = points_xy[:, 0] + y = points_xy[:, 1] + poly_x = polygon_xy[:, 0] + poly_y = polygon_xy[:, 1] + + inside = np.zeros((points_xy.shape[0],), dtype=bool) + j = polygon_xy.shape[0] - 1 + + for i in range(polygon_xy.shape[0]): + xi = poly_x[i] + yi = poly_y[i] + xj = poly_x[j] + yj = poly_y[j] + + # Half-open y-interval to avoid double-counting vertices. + intersects = (yi > y) != (yj > y) + + denom = yj - yi + # denom == 0 => intersects is always False; add tiny epsilon to avoid warnings. + x_intersect = (xj - xi) * (y - yi) / (denom + 1e-30) + xi + + inside ^= intersects & (x < x_intersect) + j = i + + return inside diff --git a/src/hyperview/embeddings/__init__.py b/src/hyperview/embeddings/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..14ff04dcdfcc580a95b4a6f9eb80014de80c1a96 --- /dev/null +++ b/src/hyperview/embeddings/__init__.py @@ -0,0 +1,37 @@ +"""Embedding computation, projection, and provider modules.""" + +from hyperview.embeddings.compute import EmbeddingComputer +from hyperview.embeddings.providers import ( + BaseEmbeddingProvider, + ModelSpec, + get_provider, + list_providers, + make_provider_aware_space_key, + register_provider, +) + + +def __getattr__(name: str): + """Lazy import for heavy dependencies (UMAP/numba).""" + if name == "ProjectionEngine": + from hyperview.embeddings.projection import ProjectionEngine + return ProjectionEngine + if name == "EmbedAnythingProvider": + from hyperview.embeddings.providers.embed_anything import EmbedAnythingProvider + return EmbedAnythingProvider + raise AttributeError(f"module {__name__!r} has no attribute {name!r}") + + +__all__ = [ + "EmbeddingComputer", + "ProjectionEngine", + # Provider types + "BaseEmbeddingProvider", + "EmbedAnythingProvider", + "ModelSpec", + # Provider utilities + "get_provider", + "list_providers", + "register_provider", + "make_provider_aware_space_key", +] diff --git a/src/hyperview/embeddings/compute.py b/src/hyperview/embeddings/compute.py new file mode 100644 index 0000000000000000000000000000000000000000..d2026b528bc3b37b74aafd84c35cee71fb8d8fc4 --- /dev/null +++ b/src/hyperview/embeddings/compute.py @@ -0,0 +1,89 @@ +"""Image embedding computation via EmbedAnything.""" + +import os +import tempfile +from pathlib import Path + +import numpy as np +from embed_anything import EmbeddingModel +from PIL import Image + +from hyperview.core.sample import Sample + + +class EmbeddingComputer: + """Compute embeddings for image samples using EmbedAnything.""" + + def __init__(self, model: str): + """Initialize the embedding computer. + + Args: + model: HuggingFace model ID to load via EmbedAnything. + """ + if not model or not model.strip(): + raise ValueError("model must be a non-empty HuggingFace model_id") + + self.model_id = model + self._model: EmbeddingModel | None = None + + def _get_model(self) -> EmbeddingModel: + """Lazily initialize the EmbedAnything model.""" + if self._model is None: + self._model = EmbeddingModel.from_pretrained_hf(model_id=self.model_id) + return self._model + + def _load_rgb_image(self, sample: Sample) -> Image.Image: + """Load an image and normalize it to RGB. + + For file-backed samples, returns an in-memory copy and closes the file + handle immediately to avoid leaking descriptors during batch processing. + """ + with sample.load_image() as img: + img.load() + if img.mode != "RGB": + return img.convert("RGB") + return img.copy() + + def _embed_file(self, file_path: str) -> np.ndarray: + model = self._get_model() + result = model.embed_file(file_path) + + if not result: + raise RuntimeError(f"EmbedAnything returned no embeddings for: {file_path}") + if len(result) != 1: + raise RuntimeError( + f"Expected 1 embedding for an image file, got {len(result)}: {file_path}" + ) + + return np.asarray(result[0].embedding, dtype=np.float32) + + def _embed_pil_image(self, image: Image.Image) -> np.ndarray: + temp_fd, temp_path = tempfile.mkstemp(suffix=".png") + os.close(temp_fd) + try: + image.save(temp_path, format="PNG") + return self._embed_file(temp_path) + finally: + Path(temp_path).unlink(missing_ok=True) + + def compute_single(self, sample: Sample) -> np.ndarray: + """Compute embedding for a single sample.""" + image = self._load_rgb_image(sample) + return self._embed_pil_image(image) + + def compute_batch( + self, + samples: list[Sample], + batch_size: int = 32, + show_progress: bool = True, + ) -> list[np.ndarray]: + """Compute embeddings for a list of samples.""" + if batch_size <= 0: + raise ValueError("batch_size must be > 0") + self._get_model() + + if show_progress: + print(f"Computing embeddings for {len(samples)} samples...") + + return [self.compute_single(sample) for sample in samples] + diff --git a/src/hyperview/embeddings/pipelines.py b/src/hyperview/embeddings/pipelines.py new file mode 100644 index 0000000000000000000000000000000000000000..578a9f363205a9ccd1efb186b33392c4b9337891 --- /dev/null +++ b/src/hyperview/embeddings/pipelines.py @@ -0,0 +1,191 @@ +"""Compute orchestration pipelines for HyperView. + +These functions coordinate embedding computation and 2D layout/projection +computation, persisting results into the configured storage backend. +""" + +from __future__ import annotations + +import numpy as np + +from hyperview.embeddings.providers import ModelSpec, get_provider, make_provider_aware_space_key +from hyperview.storage.backend import StorageBackend +from hyperview.storage.schema import make_layout_key + + +def compute_embeddings( + storage: StorageBackend, + model_spec: ModelSpec, + batch_size: int = 32, + show_progress: bool = True, +) -> tuple[str, int, int]: + """Compute embeddings for samples that don't have them yet. + + Args: + storage: Storage backend to read samples from and write embeddings to. + model_spec: Model specification (provider, model_id, geometry, etc.). + batch_size: Batch size for processing. + show_progress: Whether to show progress bar. + + Returns: + Tuple of (space_key, num_computed, num_skipped). + + Raises: + ValueError: If no samples in storage or provider not found. + """ + provider = get_provider(model_spec.provider) + + all_samples = storage.get_all_samples() + if not all_samples: + raise ValueError("No samples in storage") + + # Generate space key before computing (deterministic from spec) + space_key = make_provider_aware_space_key(model_spec) + + # Check which samples need embeddings + missing_ids = storage.get_missing_embedding_ids(space_key) + + # If space doesn't exist yet, all samples are missing + if not storage.get_space(space_key): + missing_ids = [s.id for s in all_samples] + + num_skipped = len(all_samples) - len(missing_ids) + + if not missing_ids: + if show_progress: + print(f"All {len(all_samples)} samples already have embeddings in space '{space_key}'") + return space_key, 0, num_skipped + + samples_to_embed = storage.get_samples_by_ids(missing_ids) + + if show_progress and num_skipped > 0: + print(f"Skipped {num_skipped} samples with existing embeddings") + + # Compute all embeddings in one pass (no separate probe) + embeddings = provider.compute_embeddings( + samples=samples_to_embed, + model_spec=model_spec, + batch_size=batch_size, + show_progress=show_progress, + ) + + dim = embeddings.shape[1] + + # Ensure space exists (create if needed) + config = provider.get_space_config(model_spec, dim) + storage.ensure_space( + model_id=model_spec.model_id, + dim=dim, + config=config, + space_key=space_key, + ) + + # Store embeddings + ids = [s.id for s in samples_to_embed] + storage.add_embeddings(space_key, ids, embeddings) + + return space_key, len(ids), num_skipped + + +def compute_layout( + storage: StorageBackend, + space_key: str | None = None, + method: str = "umap", + geometry: str = "euclidean", + n_neighbors: int = 15, + min_dist: float = 0.1, + metric: str = "cosine", + force: bool = False, + show_progress: bool = True, +) -> str: + """Compute 2D layout/projection for visualization. + + Args: + storage: Storage backend with embeddings. + space_key: Embedding space to project. If None, uses the first available. + method: Projection method ('umap' supported). + geometry: Output geometry type ('euclidean' or 'poincare'). + n_neighbors: Number of neighbors for UMAP. + min_dist: Minimum distance for UMAP. + metric: Distance metric for UMAP. + force: Force recomputation even if layout exists. + show_progress: Whether to print progress messages. + + Returns: + layout_key for the computed layout. + + Raises: + ValueError: If no embedding spaces, space not found, or insufficient samples. + """ + from hyperview.embeddings.projection import ProjectionEngine + + if method != "umap": + raise ValueError(f"Invalid method: {method}. Only 'umap' is supported.") + + if geometry not in ("euclidean", "poincare"): + raise ValueError(f"Invalid geometry: {geometry}. Must be 'euclidean' or 'poincare'.") + + if space_key is None: + spaces = storage.list_spaces() + if not spaces: + raise ValueError("No embedding spaces. Call compute_embeddings() first.") + space_key = spaces[0].space_key + + space = storage.get_space(space_key) + if space is None: + raise ValueError(f"Space not found: {space_key}") + + input_geometry = space.geometry + curvature = (space.config or {}).get("curvature") + + ids, vectors = storage.get_embeddings(space_key) + if len(ids) == 0: + raise ValueError(f"No embeddings in space '{space_key}'. Call compute_embeddings() first.") + + if len(ids) < 3: + raise ValueError(f"Need at least 3 samples for visualization, have {len(ids)}") + + layout_params = { + "n_neighbors": n_neighbors, + "min_dist": min_dist, + "metric": metric, + } + layout_key = make_layout_key(space_key, method, geometry, layout_params) + + if not force: + existing_layout = storage.get_layout(layout_key) + if existing_layout is not None: + existing_ids, _ = storage.get_layout_coords(layout_key) + if set(existing_ids) == set(ids): + if show_progress: + print(f"Layout '{layout_key}' already exists with {len(ids)} points") + return layout_key + if show_progress: + print("Layout exists but has different samples, recomputing...") + + if show_progress: + print(f"Computing {geometry} {method} layout for {len(ids)} samples...") + + storage.ensure_layout( + layout_key=layout_key, + space_key=space_key, + method=method, + geometry=geometry, + params=layout_params, + ) + + engine = ProjectionEngine() + coords = engine.project( + vectors, + input_geometry=input_geometry, + output_geometry=geometry, + curvature=curvature, + method=method, + n_neighbors=n_neighbors, + min_dist=min_dist, + metric=metric, + ) + + storage.add_layout_coords(layout_key, ids, coords) + + return layout_key diff --git a/src/hyperview/embeddings/projection.py b/src/hyperview/embeddings/projection.py new file mode 100644 index 0000000000000000000000000000000000000000..83dff50655cf11f5dd5984e0a1710afd852d3e43 --- /dev/null +++ b/src/hyperview/embeddings/projection.py @@ -0,0 +1,267 @@ +"""Projection methods for dimensionality reduction.""" + +import logging +import warnings + +import numpy as np +import umap + +logger = logging.getLogger(__name__) + + +class ProjectionEngine: + """Engine for projecting high-dimensional embeddings to 2D.""" + + def to_poincare_ball( + self, + hyperboloid_embeddings: np.ndarray, + curvature: float | None = None, + clamp_radius: float = 0.999999, + ) -> np.ndarray: + """Convert hyperboloid (Lorentz) coordinates to Poincaré ball coordinates. + + Input is expected to be shape (N, D+1) with first coordinate being time-like. + Points are assumed to satisfy: t^2 - ||x||^2 = 1/c (c > 0). + + Returns Poincaré ball coordinates of shape (N, D) in the unit ball. + + Notes: + - Many hyperbolic libraries parameterize curvature as a positive number c + where the manifold has sectional curvature -c. + - We map to the unit ball for downstream distance metrics (UMAP 'poincare'). + """ + if hyperboloid_embeddings.ndim != 2 or hyperboloid_embeddings.shape[1] < 2: + raise ValueError( + "hyperboloid_embeddings must have shape (N, D+1) with D>=1" + ) + + c = float(curvature) if curvature is not None else 1.0 + if c <= 0: + raise ValueError(f"curvature must be > 0, got {c}") + + # Radius R = 1/sqrt(c) for curvature -c + R = 1.0 / np.sqrt(c) + + t = hyperboloid_embeddings[:, :1] + x = hyperboloid_embeddings[:, 1:] + + # Map to ball radius R: u_R = x / (t + R) + denom = t + R + u_R = x / denom + + # Rescale to unit ball: u = u_R / R = sqrt(c) * u_R + u = u_R / R + + # Numerical guard: ensure inside the unit ball + radii = np.linalg.norm(u, axis=1) + mask = radii >= clamp_radius + if np.any(mask): + u[mask] = u[mask] / radii[mask][:, np.newaxis] * clamp_radius + + return u.astype(np.float32) + + def project( + self, + embeddings: np.ndarray, + *, + input_geometry: str = "euclidean", + output_geometry: str = "euclidean", + curvature: float | None = None, + method: str = "umap", + n_neighbors: int = 15, + min_dist: float = 0.1, + metric: str = "cosine", + random_state: int = 42, + ) -> np.ndarray: + """Project embeddings to 2D with geometry-aware preprocessing. + + This separates two concerns: + 1) Geometry/model transforms for the *input* embeddings (e.g. hyperboloid -> Poincaré) + 2) Dimensionality reduction / layout (currently UMAP) + + Args: + embeddings: Input embeddings (N x D) or hyperboloid (N x D+1). + input_geometry: Geometry/model of the input embeddings (euclidean, hyperboloid). + output_geometry: Geometry of the output coordinates (euclidean, poincare). + curvature: Curvature parameter for hyperbolic embeddings (positive c). + method: Layout method (currently only 'umap'). + n_neighbors: UMAP neighbors. + min_dist: UMAP min_dist. + metric: Input metric (used for euclidean inputs). + random_state: Random seed. + + Returns: + 2D coordinates (N x 2). + """ + if method != "umap": + raise ValueError(f"Invalid method: {method}. Only 'umap' is supported.") + + prepared = embeddings + prepared_metric: str = metric + + if input_geometry == "hyperboloid": + # Convert to unit Poincaré ball and use UMAP's built-in hyperbolic distance. + prepared = self.to_poincare_ball(embeddings, curvature=curvature) + prepared_metric = "poincare" + + if output_geometry == "poincare": + return self.project_to_poincare( + prepared, + n_neighbors=n_neighbors, + min_dist=min_dist, + metric=prepared_metric, + random_state=random_state, + ) + + if output_geometry == "euclidean": + return self.project_umap( + prepared, + n_neighbors=n_neighbors, + min_dist=min_dist, + metric=prepared_metric, + n_components=2, + random_state=random_state, + ) + + raise ValueError( + f"Invalid output_geometry: {output_geometry}. Must be 'euclidean' or 'poincare'." + ) + + def project_umap( + self, + embeddings: np.ndarray, + n_neighbors: int = 15, + min_dist: float = 0.1, + metric: str = "cosine", + n_components: int = 2, + random_state: int = 42, + ) -> np.ndarray: + """Project embeddings to Euclidean 2D using UMAP.""" + n_neighbors = min(n_neighbors, len(embeddings) - 1) + if n_neighbors < 2: + n_neighbors = 2 + + n_jobs = 1 if random_state is not None else -1 + + reducer = umap.UMAP( + n_neighbors=n_neighbors, + min_dist=min_dist, + n_components=n_components, + metric=metric, + random_state=random_state, + n_jobs=n_jobs, + ) + + coords = reducer.fit_transform(embeddings) + coords = self._normalize_coords(coords) + + return coords + + def project_to_poincare( + self, + embeddings: np.ndarray, + n_neighbors: int = 15, + min_dist: float = 0.1, + metric: str = "cosine", + random_state: int = 42, + ) -> np.ndarray: + """Project embeddings to the Poincaré disk using UMAP with hyperboloid output.""" + n_neighbors = min(n_neighbors, len(embeddings) - 1) + if n_neighbors < 2: + n_neighbors = 2 + + n_jobs = 1 if random_state is not None else -1 + + # Suppress warning about missing gradient for poincare metric (only affects inverse_transform) + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", message="gradient function is not yet implemented") + reducer = umap.UMAP( + n_neighbors=n_neighbors, + min_dist=min_dist, + n_components=2, + metric=metric, + output_metric="hyperboloid", + random_state=random_state, + n_jobs=n_jobs, + ) + spatial_coords = reducer.fit_transform(embeddings) + + squared_norm = np.sum(spatial_coords**2, axis=1) + t = np.sqrt(1 + squared_norm) + + # Project to Poincaré disk: u = x / (1 + t) + denom = 1 + t + poincare_coords = spatial_coords / denom[:, np.newaxis] + + # Clamp to unit disk for numerical stability + radii = np.linalg.norm(poincare_coords, axis=1) + max_radius = 0.999 + mask = radii > max_radius + if np.any(mask): + logger.warning(f"Clamping {np.sum(mask)} points to unit disk.") + poincare_coords[mask] = ( + poincare_coords[mask] / radii[mask][:, np.newaxis] * max_radius + ) + + poincare_coords = self._center_poincare(poincare_coords) + poincare_coords = self._scale_poincare(poincare_coords, factor=0.65) + + return poincare_coords + + def _scale_poincare(self, coords: np.ndarray, factor: float) -> np.ndarray: + """Scale points towards the origin in hyperbolic space. + + Scales hyperbolic distance from origin by `factor`. If factor < 1, points move closer to center. + """ + radii = np.linalg.norm(coords, axis=1) + mask = radii > 1e-6 + + r = radii[mask] + r = np.minimum(r, 0.9999999) + r_new = np.tanh(factor * np.arctanh(r)) + + scale_ratios = np.ones_like(radii) + scale_ratios[mask] = r_new / r + + return coords * scale_ratios[:, np.newaxis] + + def _center_poincare(self, coords: np.ndarray) -> np.ndarray: + """Center points in the Poincaré disk using a Möbius transformation.""" + if len(coords) == 0: + return coords + + z = coords[:, 0] + 1j * coords[:, 1] + centroid = np.mean(z) + + if np.abs(centroid) > 0.99 or np.abs(centroid) < 1e-6: + return coords + + # Möbius transformation: w = (z - a) / (1 - conj(a) * z) + a = centroid + w = (z - a) / (1 - np.conj(a) * z) + + return np.stack([w.real, w.imag], axis=1) + + def _normalize_coords(self, coords: np.ndarray) -> np.ndarray: + """Normalize coordinates to [-1, 1] range.""" + if len(coords) == 0: + return coords + + coords = coords - coords.mean(axis=0) + max_abs = np.abs(coords).max() + if max_abs > 0: + coords = coords / max_abs * 0.95 + + return coords + + def poincare_distance(self, u: np.ndarray, v: np.ndarray) -> float: + """Compute the Poincaré distance between two points.""" + u_norm_sq = np.sum(u**2) + v_norm_sq = np.sum(v**2) + diff_norm_sq = np.sum((u - v) ** 2) + + u_norm_sq = min(u_norm_sq, 0.99999) + v_norm_sq = min(v_norm_sq, 0.99999) + + delta = 2 * diff_norm_sq / ((1 - u_norm_sq) * (1 - v_norm_sq)) + return np.arccosh(1 + delta) diff --git a/src/hyperview/embeddings/providers/__init__.py b/src/hyperview/embeddings/providers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..55fca86a161d201117fad86dc9af27056c2b11f4 --- /dev/null +++ b/src/hyperview/embeddings/providers/__init__.py @@ -0,0 +1,200 @@ +"""Embedding provider abstraction for HyperView.""" + +from __future__ import annotations + +import hashlib +from importlib import import_module +import json +from abc import ABC, abstractmethod +from dataclasses import dataclass +from typing import Any + +import numpy as np + +from hyperview.core.sample import Sample + + +@dataclass +class ModelSpec: + """Structured specification for an embedding model. + + Attributes: + provider: Provider identifier (e.g., "embed_anything", "hycoclip") + model_id: Model identifier (HuggingFace model_id, checkpoint path, etc.) + checkpoint: Optional checkpoint path or URL for weight-only models + config_path: Optional config path for models that need it + output_geometry: Geometry of the embedding space ("euclidean", "hyperboloid") + curvature: Hyperbolic curvature (only relevant for hyperbolic geometries) + """ + + provider: str + model_id: str + checkpoint: str | None = None + config_path: str | None = None + output_geometry: str = "euclidean" + curvature: float | None = None + + def to_dict(self) -> dict[str, Any]: + """Convert to JSON-serializable dict.""" + d: dict[str, Any] = { + "provider": self.provider, + "model_id": self.model_id, + "geometry": self.output_geometry, + } + if self.checkpoint: + d["checkpoint"] = self.checkpoint + if self.config_path: + d["config_path"] = self.config_path + if self.curvature is not None: + d["curvature"] = self.curvature + return d + + @classmethod + def from_dict(cls, d: dict[str, Any]) -> ModelSpec: + """Create from dict (e.g., loaded from JSON).""" + return cls( + provider=d["provider"], + model_id=d["model_id"], + checkpoint=d.get("checkpoint"), + config_path=d.get("config_path"), + output_geometry=d.get("geometry", "euclidean"), + curvature=d.get("curvature"), + ) + + def content_hash(self) -> str: + """Generate a short hash of the spec for collision-resistant keys.""" + content = json.dumps(self.to_dict(), sort_keys=True) + return hashlib.sha256(content.encode()).hexdigest()[:12] + + +class BaseEmbeddingProvider(ABC): + """Base class for embedding providers.""" + + @property + @abstractmethod + def provider_id(self) -> str: + """Unique identifier for this provider.""" + ... + + @abstractmethod + def compute_embeddings( + self, + samples: list[Sample], + model_spec: ModelSpec, + batch_size: int = 32, + show_progress: bool = True, + ) -> np.ndarray: + """Compute embeddings for samples. + + Returns: + Array of shape (N, D) where N is len(samples) and D is embedding dim. + """ + ... + + def get_space_config(self, model_spec: ModelSpec, dim: int) -> dict[str, Any]: + """Get config dict for SpaceInfo.config_json. + + Args: + model_spec: Model specification. + dim: Embedding dimension. + + Returns: + Config dict with provider, geometry, model_id, dim, and any extras. + """ + return { + **model_spec.to_dict(), + "dim": dim, + } + + +_PROVIDER_CLASSES: dict[str, type[BaseEmbeddingProvider]] = {} +_PROVIDER_INSTANCES: dict[str, BaseEmbeddingProvider] = {} + + +_KNOWN_PROVIDER_MODULES: dict[str, str] = { + "embed_anything": "hyperview.embeddings.providers.embed_anything", + "hycoclip": "hyperview.embeddings.providers.hycoclip", + "hycoclip_onnx": "hyperview.embeddings.providers.hycoclip_onnx", +} + + +def register_provider(provider_id: str, provider_class: type[BaseEmbeddingProvider]) -> None: + """Register a new embedding provider class.""" + _PROVIDER_CLASSES[provider_id] = provider_class + # Clear cached instance if re-registering + _PROVIDER_INSTANCES.pop(provider_id, None) + + +def _try_auto_register(provider_id: str, *, silent: bool = True) -> None: + """Attempt to auto-register a provider by importing its module. + + Args: + provider_id: Provider identifier. + silent: If True, swallow ImportError (used when listing providers). + If False, let ImportError propagate (used when explicitly requesting + a provider via get_provider()). + """ + + module_name = _KNOWN_PROVIDER_MODULES.get(provider_id) + if not module_name: + return + + if silent: + try: + import_module(module_name) + except ImportError: + return + else: + import_module(module_name) + + +def get_provider(provider_id: str) -> BaseEmbeddingProvider: + """Get a provider singleton instance by ID. + + Providers are cached to preserve model state across calls. + """ + if provider_id not in _PROVIDER_CLASSES: + _try_auto_register(provider_id, silent=False) + + if provider_id not in _PROVIDER_CLASSES: + available = ", ".join(sorted(_PROVIDER_CLASSES.keys())) or "(none registered)" + raise ValueError( + f"Unknown embedding provider: '{provider_id}'. " + f"Available: {available}" + ) + + if provider_id not in _PROVIDER_INSTANCES: + _PROVIDER_INSTANCES[provider_id] = _PROVIDER_CLASSES[provider_id]() + + return _PROVIDER_INSTANCES[provider_id] + + +def list_providers() -> list[str]: + """List available provider IDs.""" + # Trigger auto-registration for known providers + for pid in _KNOWN_PROVIDER_MODULES: + _try_auto_register(pid, silent=True) + return list(_PROVIDER_CLASSES.keys()) + + +def make_provider_aware_space_key(model_spec: ModelSpec) -> str: + """Generate a collision-resistant space_key from a ModelSpec. + + Format: {provider}__{slugified_model_id}__{content_hash} + """ + from hyperview.storage.schema import slugify_model_id + + slug = slugify_model_id(model_spec.model_id) + content_hash = model_spec.content_hash() + + return f"{model_spec.provider}__{slug}__{content_hash}" + + +__all__ = [ + "BaseEmbeddingProvider", + "ModelSpec", + "get_provider", + "list_providers", + "make_provider_aware_space_key", + "register_provider", +] diff --git a/src/hyperview/embeddings/providers/embed_anything.py b/src/hyperview/embeddings/providers/embed_anything.py new file mode 100644 index 0000000000000000000000000000000000000000..60370df7649a916e610ef179b963c9b5c9f88503 --- /dev/null +++ b/src/hyperview/embeddings/providers/embed_anything.py @@ -0,0 +1,57 @@ +"""EmbedAnything embedding provider - default lightweight provider.""" + +from __future__ import annotations + +from typing import Any + +import numpy as np + +from hyperview.core.sample import Sample +from hyperview.embeddings.providers import ( + BaseEmbeddingProvider, + ModelSpec, + register_provider, +) + +__all__ = ["EmbedAnythingProvider"] + + +class EmbedAnythingProvider(BaseEmbeddingProvider): + """Default embedding provider using EmbedAnything. + + Supports HuggingFace vision models via EmbedAnything's inference engine. + Model is cached per model_id to avoid repeated initialization. + """ + + def __init__(self) -> None: + self._computers: dict[str, Any] = {} # model_id -> EmbeddingComputer + + @property + def provider_id(self) -> str: + return "embed_anything" + + def _get_computer(self, model_id: str) -> Any: + """Get or create an EmbeddingComputer for the given model_id.""" + if model_id not in self._computers: + from hyperview.embeddings.compute import EmbeddingComputer + + self._computers[model_id] = EmbeddingComputer(model=model_id) + return self._computers[model_id] + + def compute_embeddings( + self, + samples: list[Sample], + model_spec: ModelSpec, + batch_size: int = 32, + show_progress: bool = True, + ) -> np.ndarray: + """Compute embeddings using EmbedAnything.""" + computer = self._get_computer(model_spec.model_id) + embeddings = computer.compute_batch( + samples, batch_size=batch_size, show_progress=show_progress + ) + return np.array(embeddings, dtype=np.float32) + + +# Auto-register on import +register_provider("embed_anything", EmbedAnythingProvider) diff --git a/src/hyperview/embeddings/providers/hycoclip.py b/src/hyperview/embeddings/providers/hycoclip.py new file mode 100644 index 0000000000000000000000000000000000000000..3f8a81c9b276916a976ffa9f601bf8614f3320d3 --- /dev/null +++ b/src/hyperview/embeddings/providers/hycoclip.py @@ -0,0 +1,279 @@ +"""Clean HyCoCLIP embedding provider (PyTorch) - no external hycoclip package. + +This is a minimal reimplementation that loads HyCoCLIP weights directly. +Only depends on torch, timm, and numpy. + +Architecture: +- ViT backbone (timm) +- Linear projection to embedding space +- Exponential map to hyperboloid (Lorentz model) + +Checkpoints: https://huggingface.co/avik-pal/hycoclip + +Requirements: + uv sync --extra ml +""" + +from __future__ import annotations + +import math +from pathlib import Path +from typing import Any + +import numpy as np + +from hyperview.core.sample import Sample +from hyperview.embeddings.providers import ( + BaseEmbeddingProvider, + ModelSpec, + register_provider, +) + +__all__ = ["HyCoCLIPProvider"] + + +HYCOCLIP_CHECKPOINTS: dict[str, str] = { + "hycoclip_vit_s": "hf://avik-pal/hycoclip#hycoclip_vit_s.pth", + "hycoclip_vit_b": "hf://avik-pal/hycoclip#hycoclip_vit_b.pth", + "meru_vit_s": "hf://avik-pal/hycoclip#meru_vit_s.pth", + "meru_vit_b": "hf://avik-pal/hycoclip#meru_vit_b.pth", +} + + +def _exp_map_lorentz(x: "torch.Tensor", c: float) -> "torch.Tensor": + """Exponential map from tangent space at the hyperboloid vertex. + + Maps Euclidean tangent vectors at the origin onto the Lorentz (hyperboloid) + model of hyperbolic space with curvature -c. + + Output is ordered as (t, x1, ..., xD) and satisfies: + t^2 - ||x||^2 = 1/c + + This matches HyCoCLIP/MERU exp_map0 numerics by clamping the sinh input for + stability and inferring the time component from the hyperboloid constraint. + + Args: + x: Euclidean tangent vectors at the origin, shape (..., D). + c: Positive curvature parameter (hyperbolic curvature is -c). + + Returns: + Hyperboloid coordinates, shape (..., D + 1). + """ + import torch + + if c <= 0: + raise ValueError(f"curvature c must be > 0, got {c}") + + # Compute in float32 under AMP to avoid float16/bfloat16 overflow. + if x.dtype in (torch.float16, torch.bfloat16): + x = x.float() + + sqrt_c = math.sqrt(c) + rc_xnorm = sqrt_c * torch.norm(x, dim=-1, keepdim=True) + + eps = 1e-8 + sinh_input = torch.clamp(rc_xnorm, min=eps, max=math.asinh(2**15)) + spatial = torch.sinh(sinh_input) * x / torch.clamp(rc_xnorm, min=eps) + + t = torch.sqrt((1.0 / c) + torch.sum(spatial * spatial, dim=-1, keepdim=True)) + return torch.cat([t, spatial], dim=-1) + + +def _create_encoder( + embed_dim: int = 512, + curvature: float = 0.1, + vit_model: str = "vit_small_patch16_224", +) -> "nn.Module": + """Create HyCoCLIP image encoder using timm ViT backbone.""" + import timm + import torch.nn as nn + + class HyCoCLIPImageEncoder(nn.Module): + def __init__(self) -> None: + super().__init__() + self.backbone = timm.create_model(vit_model, pretrained=False, num_classes=0) + backbone_dim = int(getattr(self.backbone, "embed_dim")) + self.proj = nn.Linear(backbone_dim, embed_dim, bias=False) + self.curvature = curvature + self.embed_dim = embed_dim + + def forward(self, x: "torch.Tensor") -> "torch.Tensor": + features = self.backbone(x) + spatial = self.proj(features) + return _exp_map_lorentz(spatial, self.curvature) + + return HyCoCLIPImageEncoder() + + +def _load_encoder(checkpoint_path: str, device: str = "cpu") -> Any: + """Load HyCoCLIP image encoder from checkpoint.""" + import torch + + ckpt = torch.load(checkpoint_path, map_location="cpu", weights_only=False) + state = ckpt["model"] + + # Extract curvature (stored as log) + curvature = torch.exp(state["curv"]).item() + + # Determine model variant from checkpoint + proj_shape = state["visual_proj.weight"].shape + embed_dim = proj_shape[0] + backbone_dim = proj_shape[1] + + vit_models = { + 384: "vit_small_patch16_224", + 768: "vit_base_patch16_224", + 1024: "vit_large_patch16_224", + } + vit_model = vit_models.get(backbone_dim, "vit_small_patch16_224") + + model = _create_encoder(embed_dim=embed_dim, curvature=curvature, vit_model=vit_model) + + # Remap checkpoint keys + new_state = {} + for key, value in state.items(): + if key.startswith("visual."): + new_state["backbone." + key[7:]] = value + elif key == "visual_proj.weight": + new_state["proj.weight"] = value + + model.load_state_dict(new_state, strict=False) + return model.to(device).eval() + + +class HyCoCLIPProvider(BaseEmbeddingProvider): + """Clean HyCoCLIP provider (PyTorch) - no hycoclip package dependency. + + Requires: torch, torchvision, timm (install via `uv sync --extra ml`) + """ + + def __init__(self) -> None: + self._model: Any = None + self._model_spec: ModelSpec | None = None + self._device: Any = None + self._transform: Any = None + + @property + def provider_id(self) -> str: + return "hycoclip" + + def _get_device(self) -> Any: + import torch + + if self._device is None: + self._device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + return self._device + + def _get_transform(self) -> Any: + if self._transform is None: + from torchvision import transforms + + self._transform = transforms.Compose([ + transforms.Resize(224, transforms.InterpolationMode.BICUBIC), + transforms.CenterCrop(224), + transforms.ToTensor(), + transforms.Normalize( + mean=[0.48145466, 0.4578275, 0.40821073], + std=[0.26862954, 0.26130258, 0.27577711], + ), + ]) + return self._transform + + def _resolve_checkpoint(self, checkpoint: str) -> Path: + """Resolve checkpoint path, downloading from HuggingFace if needed.""" + # Handle HuggingFace Hub URLs: hf://repo_id#filename + if checkpoint.startswith("hf://"): + from huggingface_hub import hf_hub_download + + path = checkpoint[5:] + if "#" not in path: + raise ValueError(f"HF checkpoint must include filename: {checkpoint}") + repo_id, filename = path.split("#", 1) + return Path(hf_hub_download(repo_id=repo_id, filename=filename)).resolve() + + # Local path + path = Path(checkpoint).expanduser().resolve() + if not path.exists(): + raise FileNotFoundError(f"Checkpoint not found: {path}") + return path + + def _load_model(self, model_spec: ModelSpec) -> None: + if self._model is not None and self._model_spec == model_spec: + return + + # Auto-resolve checkpoint from model_id if not provided + checkpoint = model_spec.checkpoint + if not checkpoint: + checkpoint = HYCOCLIP_CHECKPOINTS.get(model_spec.model_id) + if not checkpoint: + available = ", ".join(sorted(HYCOCLIP_CHECKPOINTS.keys())) + raise ValueError( + f"Unknown HyCoCLIP model_id: '{model_spec.model_id}'. " + f"Known models: {available}. " + f"Or provide 'checkpoint' path explicitly." + ) + + checkpoint_path = self._resolve_checkpoint(checkpoint) + self._model = _load_encoder(str(checkpoint_path), str(self._get_device())) + self._model_spec = model_spec + + def compute_embeddings( + self, + samples: list["Sample"], + model_spec: ModelSpec, + batch_size: int = 32, + show_progress: bool = True, + ) -> np.ndarray: + """Compute hyperboloid embeddings for samples.""" + import torch + + self._load_model(model_spec) + assert self._model is not None + + device = self._get_device() + transform = self._get_transform() + + if show_progress: + print(f"Computing HyCoCLIP embeddings for {len(samples)} samples...") + + all_embeddings = [] + + for i in range(0, len(samples), batch_size): + batch_samples = samples[i : i + batch_size] + + images = [] + for sample in batch_samples: + img = sample.load_image() + if img.mode != "RGB": + img = img.convert("RGB") + images.append(transform(img)) + + batch_tensor = torch.stack(images).to(device) + + with torch.no_grad(), torch.amp.autocast( + device_type=device.type, enabled=device.type == "cuda" + ): + embeddings = self._model(batch_tensor) + + all_embeddings.append(embeddings.cpu().numpy()) + + return np.concatenate(all_embeddings, axis=0) + + def get_space_config(self, model_spec: ModelSpec, dim: int) -> dict[str, Any]: + """Return embedding space configuration with curvature.""" + self._load_model(model_spec) + assert self._model is not None + + return { + "provider": self.provider_id, + "model_id": model_spec.model_id, + "geometry": "hyperboloid", + "checkpoint": model_spec.checkpoint, + "dim": dim, + "curvature": self._model.curvature, + "spatial_dim": self._model.embed_dim, + } + + +# Auto-register on import +register_provider("hycoclip", HyCoCLIPProvider) diff --git a/src/hyperview/embeddings/providers/hycoclip_onnx.py b/src/hyperview/embeddings/providers/hycoclip_onnx.py new file mode 100644 index 0000000000000000000000000000000000000000..6d01dbef54c29ecfb03319342f08f6f4bfeae58f --- /dev/null +++ b/src/hyperview/embeddings/providers/hycoclip_onnx.py @@ -0,0 +1,210 @@ +"""HyCoCLIP ONNX embedding provider - torch-free runtime. + +This provider runs an ONNX-exported HyCoCLIP/MERU image encoder with +`onnxruntime` to compute *hyperboloid (Lorentz)* embeddings. + +Outputs: +- Embeddings are returned in hyperboloid format with shape (N, D+1), where the + first coordinate is the time component. + +Requirements: +- onnxruntime (already included via embed-anything) +- An exported ONNX model (and its external weights .data file) produced by + `hyperbolic_model_zoo/hycoclip_onnx/export_onnx.py`. + +Why this exists: +- Torch is required to *export* HyCoCLIP to ONNX. +- Torch is NOT required at runtime once you have the ONNX artifacts. +""" + +from __future__ import annotations + +from pathlib import Path +from typing import Any + +import numpy as np + +from hyperview.core.sample import Sample +from hyperview.embeddings.providers import ( + BaseEmbeddingProvider, + ModelSpec, + register_provider, +) + +__all__ = ["HyCoCLIPOnnxProvider"] + + +def _preprocess_rgb_image_to_chw_float01(img: Any, size: int = 224) -> np.ndarray: + """Resize shortest side to `size`, center crop, return (3,H,W) float32 in [0,1].""" + from PIL import Image + + if not isinstance(img, Image.Image): + raise TypeError(f"Expected PIL.Image.Image, got {type(img)}") + + w, h = img.size + if w <= 0 or h <= 0: + raise ValueError(f"Invalid image size: {w}x{h}") + + # Resize shortest side to `size`. + scale = float(size) / float(min(w, h)) + new_w = int(round(w * scale)) + new_h = int(round(h * scale)) + img = img.resize((new_w, new_h), resample=Image.Resampling.BICUBIC) + + # Center crop. + left = int(round((new_w - size) / 2.0)) + top = int(round((new_h - size) / 2.0)) + img = img.crop((left, top, left + size, top + size)) + + arr = np.asarray(img, dtype=np.float32) / 255.0 + arr = np.transpose(arr, (2, 0, 1)) + return arr + + +class HyCoCLIPOnnxProvider(BaseEmbeddingProvider): + """ONNX HyCoCLIP provider - torch-free runtime. + + Uses onnxruntime for inference. No PyTorch required at runtime. + """ + + def __init__(self) -> None: + self._session: Any = None + self._model_spec: ModelSpec | None = None + self._input_name: str | None = None + self._output_names: list[str] | None = None + self._curvature: float | None = None + + @property + def provider_id(self) -> str: + return "hycoclip_onnx" + + def _resolve_onnx_path(self, model_spec: ModelSpec) -> Path: + if not model_spec.checkpoint: + raise ValueError( + "HyCoCLIP ONNX provider requires 'checkpoint' to be a path/URL to a .onnx file." + ) + + checkpoint = model_spec.checkpoint + + # Handle HuggingFace Hub URLs (hf://repo_id/path/to/model.onnx) + if checkpoint.startswith("hf://"): + from huggingface_hub import hf_hub_download + + # Parse: hf://mnm-matin/hyperbolic-clip/hycoclip-vit-s/model.onnx + path_part = checkpoint[5:] # Remove "hf://" + parts = path_part.split("/", 2) + if len(parts) < 3: + raise ValueError( + f"Invalid hf:// URL format: {checkpoint}. " + "Expected: hf://owner/repo/path/to/file.onnx" + ) + repo_id = f"{parts[0]}/{parts[1]}" + filename = parts[2] + + downloaded_path = hf_hub_download(repo_id=repo_id, filename=filename) + return Path(downloaded_path) + + path = Path(checkpoint).expanduser() + if not path.exists(): + raise FileNotFoundError(f"ONNX model not found: {path}") + checkpoint_suffix = Path(checkpoint).suffix.lower() + if path.suffix.lower() != ".onnx" and checkpoint_suffix != ".onnx": + raise ValueError(f"Expected a .onnx file, got: {path}") + return path + + def _ensure_session(self, model_spec: ModelSpec) -> None: + if self._session is not None and self._model_spec == model_spec: + return + + import onnxruntime as ort + + onnx_path = self._resolve_onnx_path(model_spec) + + # Default to CPU for maximum compatibility. + available = ort.get_available_providers() + providers = ( + ["CPUExecutionProvider"] if "CPUExecutionProvider" in available else list(available) + ) + + self._session = ort.InferenceSession(str(onnx_path), providers=providers) + self._input_name = self._session.get_inputs()[0].name + self._output_names = [o.name for o in self._session.get_outputs()] + self._curvature = None + self._model_spec = model_spec + + def compute_embeddings( + self, + samples: list[Sample], + model_spec: ModelSpec, + batch_size: int = 32, + show_progress: bool = True, + ) -> np.ndarray: + """Compute hyperboloid embeddings (t, x) with shape (N, D+1).""" + self._ensure_session(model_spec) + + assert self._session is not None + assert self._input_name is not None + + output_names = self._output_names or [] + if not output_names: + raise RuntimeError("ONNX session has no outputs") + + # Prefer named outputs if present. + emb_name = ( + "embedding_hyperboloid" if "embedding_hyperboloid" in output_names else output_names[0] + ) + curv_name = "curvature" if "curvature" in output_names else None + + if batch_size != 1 and show_progress: + print("HyCoCLIP-ONNX export currently runs with batch_size=1; overriding") + batch_size = 1 + + all_embeddings: list[np.ndarray] = [] + + if show_progress: + print(f"Computing HyCoCLIP-ONNX embeddings for {len(samples)} samples...") + + for i in range(0, len(samples), batch_size): + batch_samples = samples[i : i + batch_size] + + images = [] + for sample in batch_samples: + with sample.load_image() as img: + img.load() + if img.mode != "RGB": + img = img.convert("RGB") + chw = _preprocess_rgb_image_to_chw_float01(img.copy(), size=224) + images.append(chw) + + batch_np = np.stack(images, axis=0).astype(np.float32) + + outputs = self._session.run( + [name for name in (emb_name, curv_name) if name is not None], + {self._input_name: batch_np}, + ) + + hyper = np.asarray(outputs[0], dtype=np.float32) + if hyper.ndim != 2: + raise RuntimeError(f"Expected (B,D) embeddings, got shape={hyper.shape}") + + # Capture curvature once. + if curv_name is not None and self._curvature is None and len(outputs) > 1: + curv_arr = np.asarray(outputs[1]).reshape(-1) + if curv_arr.size > 0: + self._curvature = float(curv_arr[0]) + + all_embeddings.append(hyper) + + return np.vstack(all_embeddings) + + def get_space_config(self, model_spec: ModelSpec, dim: int) -> dict[str, Any]: + config = super().get_space_config(model_spec, dim) + config["geometry"] = "hyperboloid" + if self._curvature is not None: + config["curvature"] = self._curvature + config["spatial_dim"] = dim - 1 + return config + + +# Auto-register on import +register_provider("hycoclip_onnx", HyCoCLIPOnnxProvider) diff --git a/src/hyperview/server/__init__.py b/src/hyperview/server/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..a2db27419e7f6b9e2bfc32b76bb0aab94b1380e0 --- /dev/null +++ b/src/hyperview/server/__init__.py @@ -0,0 +1,5 @@ +"""FastAPI server for HyperView.""" + +from hyperview.server.app import create_app + +__all__ = ["create_app"] diff --git a/src/hyperview/server/app.py b/src/hyperview/server/app.py new file mode 100644 index 0000000000000000000000000000000000000000..26e897a62082082a8ba4e78b173f67eb15d0ab7c --- /dev/null +++ b/src/hyperview/server/app.py @@ -0,0 +1,399 @@ +"""FastAPI application for HyperView.""" + +import os +from pathlib import Path +from typing import Any + +from fastapi import Depends, FastAPI, HTTPException, Query +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse +from fastapi.staticfiles import StaticFiles +from pydantic import BaseModel + +import numpy as np + +from hyperview.core.dataset import Dataset +from hyperview.core.selection import points_in_polygon + +# Global dataset reference (set by launch()) +_current_dataset: Dataset | None = None +_current_session_id: str | None = None + + +class SelectionRequest(BaseModel): + """Request model for selection sync.""" + + sample_ids: list[str] + + +class LassoSelectionRequest(BaseModel): + """Request model for lasso selection queries.""" + + layout_key: str # e.g., "openai_clip-vit-base-patch32__umap" + # Polygon vertices in data space, interleaved: [x0, y0, x1, y1, ...] + polygon: list[float] + offset: int = 0 + limit: int = 100 + include_thumbnails: bool = True + + +class SampleResponse(BaseModel): + """Response model for a sample.""" + + id: str + filepath: str + filename: str + label: str | None + thumbnail: str | None + metadata: dict + width: int | None = None + height: int | None = None + + +class LayoutInfoResponse(BaseModel): + """Response model for layout info.""" + + layout_key: str + space_key: str + method: str + geometry: str + count: int + params: dict[str, Any] | None + + +class SpaceInfoResponse(BaseModel): + """Response model for embedding space info.""" + + space_key: str + model_id: str + dim: int + count: int + provider: str + geometry: str + config: dict[str, Any] | None + + +class DatasetResponse(BaseModel): + """Response model for dataset info.""" + + name: str + num_samples: int + labels: list[str] + label_colors: dict[str, str] + spaces: list[SpaceInfoResponse] + layouts: list[LayoutInfoResponse] + + +class EmbeddingsResponse(BaseModel): + """Response model for embeddings data (for scatter plot).""" + + layout_key: str + geometry: str + ids: list[str] + labels: list[str | None] + coords: list[list[float]] + label_colors: dict[str, str] + + +class SimilarSampleResponse(BaseModel): + """Response model for a similar sample with distance.""" + + id: str + filepath: str + filename: str + label: str | None + thumbnail: str | None + distance: float + metadata: dict + + +class SimilaritySearchResponse(BaseModel): + """Response model for similarity search results.""" + + query_id: str + k: int + results: list[SimilarSampleResponse] + + +def create_app(dataset: Dataset | None = None, session_id: str | None = None) -> FastAPI: + """Create the FastAPI application. + + Args: + dataset: Optional dataset to serve. If None, uses global dataset. + + Returns: + FastAPI application instance. + """ + global _current_dataset, _current_session_id + if dataset is not None: + _current_dataset = dataset + if session_id is not None: + _current_session_id = session_id + + app = FastAPI( + title="HyperView", + description="Dataset visualization with hyperbolic embeddings", + version="0.1.0", + ) + + def get_dataset() -> Dataset: + """Dependency that returns the current dataset or raises 404.""" + if _current_dataset is None: + raise HTTPException(status_code=404, detail="No dataset loaded") + return _current_dataset + + # CORS middleware for development + app.add_middleware( + CORSMiddleware, + allow_origins=["*"], + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], + ) + + @app.get("/__hyperview__/health") + async def hyperview_health(): + return { + "name": "hyperview", + "version": app.version, + "session_id": _current_session_id, + "dataset": _current_dataset.name if _current_dataset is not None else None, + "pid": os.getpid(), + } + + @app.get("/api/dataset", response_model=DatasetResponse) + async def get_dataset_info(ds: Dataset = Depends(get_dataset)): + """Get dataset metadata.""" + spaces = ds.list_spaces() + space_dicts = [s.to_api_dict() for s in spaces] + + layouts = ds.list_layouts() + layout_dicts = [l.to_api_dict() for l in layouts] + + return DatasetResponse( + name=ds.name, + num_samples=len(ds), + labels=ds.labels, + label_colors=ds.get_label_colors(), + spaces=space_dicts, + layouts=layout_dicts, + ) + + @app.get("/api/samples") + async def get_samples( + ds: Dataset = Depends(get_dataset), + offset: int = Query(0, ge=0), + limit: int = Query(100, ge=1, le=1000), + label: str | None = None, + ): + """Get paginated samples with thumbnails.""" + samples, total = ds.get_samples_paginated( + offset=offset, limit=limit, label=label + ) + + return { + "total": total, + "offset": offset, + "limit": limit, + "samples": [s.to_api_dict(include_thumbnail=True) for s in samples], + } + + @app.get("/api/samples/{sample_id}", response_model=SampleResponse) + async def get_sample(sample_id: str, ds: Dataset = Depends(get_dataset)): + """Get a single sample by ID.""" + try: + sample = ds[sample_id] + return SampleResponse(**sample.to_api_dict()) + except KeyError: + raise HTTPException(status_code=404, detail=f"Sample not found: {sample_id}") + + @app.post("/api/samples/batch") + async def get_samples_batch(request: SelectionRequest, ds: Dataset = Depends(get_dataset)): + """Get multiple samples by their IDs.""" + samples = ds.get_samples_by_ids(request.sample_ids) + return {"samples": [s.to_api_dict(include_thumbnail=True) for s in samples]} + + @app.get("/api/embeddings", response_model=EmbeddingsResponse) + async def get_embeddings(ds: Dataset = Depends(get_dataset), layout_key: str | None = None): + """Get embedding coordinates for visualization.""" + layouts = ds.list_layouts() + if not layouts: + raise HTTPException( + status_code=400, detail="No layouts computed. Call compute_visualization() first." + ) + + # Find the requested layout + layout_info = None + if layout_key is None: + layout_info = layouts[0] + layout_key = layout_info.layout_key + else: + layout_info = next((l for l in layouts if l.layout_key == layout_key), None) + if layout_info is None: + raise HTTPException(status_code=404, detail=f"Layout not found: {layout_key}") + + ids, labels, coords = ds.get_visualization_data(layout_key) + + if not ids: + raise HTTPException(status_code=400, detail=f"No data in layout '{layout_key}'.") + + return EmbeddingsResponse( + layout_key=layout_key, + geometry=layout_info.geometry, + ids=ids, + labels=labels, + coords=coords.tolist(), + label_colors=ds.get_label_colors(), + ) + + @app.get("/api/spaces") + async def get_spaces(ds: Dataset = Depends(get_dataset)): + """Get all embedding spaces.""" + spaces = ds.list_spaces() + return {"spaces": [s.to_api_dict() for s in spaces]} + + @app.get("/api/layouts") + async def get_layouts(ds: Dataset = Depends(get_dataset)): + """Get all available layouts.""" + layouts = ds.list_layouts() + return {"layouts": [l.to_api_dict() for l in layouts]} + + @app.post("/api/selection") + async def sync_selection(request: SelectionRequest): + """Sync selection state (for future use).""" + return {"status": "ok", "selected": request.sample_ids} + + @app.post("/api/selection/lasso") + async def lasso_selection(request: LassoSelectionRequest, ds: Dataset = Depends(get_dataset)): + """Compute a lasso selection over the current embeddings. + + Returns a total selected count and a paginated page of selected samples. + + Notes: + - Selection is performed in *data space* (the same coordinates returned + by /api/embeddings). + - For now we use an in-memory scan with a tight AABB prefilter. + """ + if request.offset < 0: + raise HTTPException(status_code=400, detail="offset must be >= 0") + if request.limit < 1 or request.limit > 2000: + raise HTTPException(status_code=400, detail="limit must be between 1 and 2000") + + if len(request.polygon) < 6 or len(request.polygon) % 2 != 0: + raise HTTPException( + status_code=400, + detail="polygon must be an even-length list with at least 3 vertices", + ) + + poly = np.asarray(request.polygon, dtype=np.float32).reshape((-1, 2)) + if not np.all(np.isfinite(poly)): + raise HTTPException(status_code=400, detail="polygon must contain only finite numbers") + + # Tight AABB prefilter. + x_min = float(np.min(poly[:, 0])) + x_max = float(np.max(poly[:, 0])) + y_min = float(np.min(poly[:, 1])) + y_max = float(np.max(poly[:, 1])) + + candidate_ids, candidate_coords = ds.get_lasso_candidates_aabb( + layout_key=request.layout_key, + x_min=x_min, + x_max=x_max, + y_min=y_min, + y_max=y_max, + ) + + if candidate_coords.size == 0: + return {"total": 0, "offset": request.offset, "limit": request.limit, "sample_ids": [], "samples": []} + + inside_mask = points_in_polygon(candidate_coords, poly) + if not np.any(inside_mask): + return {"total": 0, "offset": request.offset, "limit": request.limit, "sample_ids": [], "samples": []} + + selected_ids = [candidate_ids[i] for i in np.flatnonzero(inside_mask)] + total = len(selected_ids) + + start = int(request.offset) + end = int(request.offset + request.limit) + sample_ids = selected_ids[start:end] + + samples = ds.get_samples_by_ids(sample_ids) + sample_dicts = [s.to_api_dict(include_thumbnail=request.include_thumbnails) for s in samples] + + return { + "total": total, + "offset": request.offset, + "limit": request.limit, + "sample_ids": sample_ids, + "samples": sample_dicts, + } + + @app.get("/api/search/similar/{sample_id}", response_model=SimilaritySearchResponse) + async def search_similar( + sample_id: str, + ds: Dataset = Depends(get_dataset), + k: int = Query(10, ge=1, le=100), + space_key: str | None = None, + ): + """Return k nearest neighbors for a given sample.""" + try: + similar = ds.find_similar( + sample_id, k=k, space_key=space_key + ) + except ValueError as e: + raise HTTPException(status_code=400, detail=str(e)) + except KeyError: + raise HTTPException(status_code=404, detail=f"Sample not found: {sample_id}") + + results = [] + for sample, distance in similar: + try: + thumbnail = sample.get_thumbnail_base64() + except Exception: + thumbnail = None + + results.append( + SimilarSampleResponse( + id=sample.id, + filepath=sample.filepath, + filename=sample.filename, + label=sample.label, + thumbnail=thumbnail, + distance=distance, + metadata=sample.metadata, + ) + ) + + return SimilaritySearchResponse( + query_id=sample_id, + k=k, + results=results, + ) + + @app.get("/api/thumbnail/{sample_id}") + async def get_thumbnail(sample_id: str, ds: Dataset = Depends(get_dataset)): + """Get thumbnail image for a sample.""" + try: + sample = ds[sample_id] + thumbnail_b64 = sample.get_thumbnail_base64() + return JSONResponse({"thumbnail": thumbnail_b64}) + except KeyError: + raise HTTPException(status_code=404, detail=f"Sample not found: {sample_id}") + + # Serve static frontend files + static_dir = Path(__file__).parent / "static" + if static_dir.exists(): + app.mount("/", StaticFiles(directory=str(static_dir), html=True), name="static") + else: + # Fallback: serve a simple HTML page + @app.get("/") + async def root(): + return {"message": "HyperView API", "docs": "/docs"} + + return app + + +def set_dataset(dataset: Dataset) -> None: + """Set the global dataset for the server.""" + global _current_dataset + _current_dataset = dataset diff --git a/src/hyperview/server/static/404.html b/src/hyperview/server/static/404.html new file mode 100644 index 0000000000000000000000000000000000000000..7d84c4644e74ddb20f4cbd03dfb1c8ba576a6fa8 --- /dev/null +++ b/src/hyperview/server/static/404.html @@ -0,0 +1 @@ +404: This page could not be found.HyperView

404

This page could not be found.

\ No newline at end of file diff --git a/src/hyperview/server/static/404/index.html b/src/hyperview/server/static/404/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7d84c4644e74ddb20f4cbd03dfb1c8ba576a6fa8 --- /dev/null +++ b/src/hyperview/server/static/404/index.html @@ -0,0 +1 @@ +404: This page could not be found.HyperView

404

This page could not be found.

\ No newline at end of file diff --git a/src/hyperview/server/static/__next.__PAGE__.txt b/src/hyperview/server/static/__next.__PAGE__.txt new file mode 100644 index 0000000000000000000000000000000000000000..e475e5795e20b2bb0c7c983fa8ddc2994affd98a --- /dev/null +++ b/src/hyperview/server/static/__next.__PAGE__.txt @@ -0,0 +1,9 @@ +1:"$Sreact.fragment" +2:I[73440,["/_next/static/chunks/48c5753aca325314.js"],"ClientPageRoot"] +3:I[50912,["/_next/static/chunks/b3cfdd883c96563c.js","/_next/static/chunks/a096ec8e6ed56d42.js"],"default"] +6:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +7:"$Sreact.suspense" +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/b3cfdd883c96563c.js","async":true}],["$","script","script-1",{"src":"/_next/static/chunks/a096ec8e6ed56d42.js","async":true}]],["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false} +4:{} +5:"$0:rsc:props:children:0:props:serverProvidedParams:params" +8:null diff --git a/src/hyperview/server/static/__next._full.txt b/src/hyperview/server/static/__next._full.txt new file mode 100644 index 0000000000000000000000000000000000000000..119a8ae23b7651880eba7af4b5a33a1c990f395a --- /dev/null +++ b/src/hyperview/server/static/__next._full.txt @@ -0,0 +1,17 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +4:I[73440,["/_next/static/chunks/48c5753aca325314.js"],"ClientPageRoot"] +5:I[50912,["/_next/static/chunks/b3cfdd883c96563c.js","/_next/static/chunks/a096ec8e6ed56d42.js"],"default"] +8:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +9:"$Sreact.suspense" +b:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +d:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +f:I[75115,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"P":null,"b":"8FqA-ERyePplcUaEYWohc","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/b3cfdd883c96563c.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/a096ec8e6ed56d42.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$@c"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$@e"}]}]}],null]}],false]],"m":"$undefined","G":["$f",[]],"S":true} +6:{} +7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params" +c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +e:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] +a:null diff --git a/src/hyperview/server/static/__next._head.txt b/src/hyperview/server/static/__next._head.txt new file mode 100644 index 0000000000000000000000000000000000000000..a58ca7079bce87534f116bae2319797a0223a5ea --- /dev/null +++ b/src/hyperview/server/static/__next._head.txt @@ -0,0 +1,7 @@ +1:"$Sreact.fragment" +2:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +4:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +5:"$Sreact.suspense" +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":"$@3"}],["$","div",null,{"hidden":true,"children":["$","$L4",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@6"}]}]}],null]}],"loading":null,"isPartial":false} +3:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +6:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] diff --git a/src/hyperview/server/static/__next._index.txt b/src/hyperview/server/static/__next._index.txt new file mode 100644 index 0000000000000000000000000000000000000000..2378d67a870d0c37e8e751acebf615de6693997b --- /dev/null +++ b/src/hyperview/server/static/__next._index.txt @@ -0,0 +1,5 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}],"loading":null,"isPartial":false} diff --git a/src/hyperview/server/static/__next._tree.txt b/src/hyperview/server/static/__next._tree.txt new file mode 100644 index 0000000000000000000000000000000000000000..3fa1db993ccd2a2e75acc96caa73a356b9c30de3 --- /dev/null +++ b/src/hyperview/server/static/__next._tree.txt @@ -0,0 +1,2 @@ +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"buildId":"8FqA-ERyePplcUaEYWohc","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300} diff --git a/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_buildManifest.js b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_buildManifest.js new file mode 100644 index 0000000000000000000000000000000000000000..1af6a5b0d2690f65f1f5976004fdc904268ef46c --- /dev/null +++ b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_buildManifest.js @@ -0,0 +1,15 @@ +self.__BUILD_MANIFEST = { + "__rewrites": { + "afterFiles": [ + { + "source": "/api/:path*" + } + ], + "beforeFiles": [], + "fallback": [] + }, + "sortedPages": [ + "/_app", + "/_error" + ] +};self.__BUILD_MANIFEST_CB && self.__BUILD_MANIFEST_CB() \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_clientMiddlewareManifest.json b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_clientMiddlewareManifest.json new file mode 100644 index 0000000000000000000000000000000000000000..0637a088a01e8ddab3bf3fa98dbe804cbde1a0dc --- /dev/null +++ b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_clientMiddlewareManifest.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_ssgManifest.js b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_ssgManifest.js new file mode 100644 index 0000000000000000000000000000000000000000..5b3ff592fd46c8736892a12864fdf3fed8775202 --- /dev/null +++ b/src/hyperview/server/static/_next/static/8FqA-ERyePplcUaEYWohc/_ssgManifest.js @@ -0,0 +1 @@ +self.__SSG_MANIFEST=new Set([]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB() \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/10c3a2ade180023c.js b/src/hyperview/server/static/_next/static/chunks/10c3a2ade180023c.js new file mode 100644 index 0000000000000000000000000000000000000000..90e79ab29478fe0431c7c72b7c3e2d3058d76cb9 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/10c3a2ade180023c.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,75115,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"default",{enumerable:!0,get:function(){return s}});let n=e.r(48277),o=e.r(86846),i={fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},u={fontSize:"14px",fontWeight:400,lineHeight:"28px",margin:"0 8px"},s=function({error:e}){let t=e?.digest;return(0,n.jsxs)("html",{id:"__next_error__",children:[(0,n.jsx)("head",{}),(0,n.jsxs)("body",{children:[(0,n.jsx)(o.HandleISRError,{error:e}),(0,n.jsx)("div",{style:i,children:(0,n.jsxs)("div",{children:[(0,n.jsxs)("h2",{style:u,children:["Application error: a ",t?"server":"client","-side exception has occurred while loading ",window.location.hostname," (see the"," ",t?"server logs":"browser console"," for more information)."]}),t?(0,n.jsx)("p",{style:u,children:`Digest: ${t}`}):null]})})]})]})};("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},90175,(e,t,r)=>{var n={229:function(e){var t,r,n,o=e.exports={};function i(){throw Error("setTimeout has not been defined")}function u(){throw Error("clearTimeout has not been defined")}try{t="function"==typeof setTimeout?setTimeout:i}catch(e){t=i}try{r="function"==typeof clearTimeout?clearTimeout:u}catch(e){r=u}function s(e){if(t===setTimeout)return setTimeout(e,0);if((t===i||!t)&&setTimeout)return t=setTimeout,setTimeout(e,0);try{return t(e,0)}catch(r){try{return t.call(null,e,0)}catch(r){return t.call(this,e,0)}}}var c=[],a=!1,l=-1;function f(){a&&n&&(a=!1,n.length?c=n.concat(c):l=-1,c.length&&p())}function p(){if(!a){var e=s(f);a=!0;for(var t=c.length;t;){for(n=c,c=[];++l1)for(var r=1;r{"use strict";var n,o;t.exports=(null==(n=e.g.process)?void 0:n.env)&&"object"==typeof(null==(o=e.g.process)?void 0:o.env)?e.g.process:e.r(90175)},14871,(e,t,r)=>{"use strict";var n=Symbol.for("react.transitional.element");function o(e,t,r){var o=null;if(void 0!==r&&(o=""+r),void 0!==t.key&&(o=""+t.key),"key"in t)for(var i in r={},t)"key"!==i&&(r[i]=t[i]);else r=t;return{$$typeof:n,type:e,key:o,ref:void 0!==(t=r.ref)?t:null,props:r}}r.Fragment=Symbol.for("react.fragment"),r.jsx=o,r.jsxs=o},48277,(e,t,r)=>{"use strict";t.exports=e.r(14871)},24171,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={bindSnapshot:function(){return a},createAsyncLocalStorage:function(){return c},createSnapshot:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let i=Object.defineProperty(Error("Invariant: AsyncLocalStorage accessed in runtime where it is not available"),"__NEXT_ERROR_CODE",{value:"E504",enumerable:!1,configurable:!0});class u{disable(){throw i}getStore(){}run(){throw i}exit(){throw i}enterWith(){throw i}static bind(e){return e}}let s="undefined"!=typeof globalThis&&globalThis.AsyncLocalStorage;function c(){return s?new s:new u}function a(e){return s?s.bind(e):u.bind(e)}function l(){return s?s.snapshot():function(e,...t){return e(...t)}}},98616,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"workAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(24171).createAsyncLocalStorage)()},26628,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"workAsyncStorage",{enumerable:!0,get:function(){return n.workAsyncStorageInstance}});let n=e.r(98616)},86846,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"HandleISRError",{enumerable:!0,get:function(){return o}});let n="undefined"==typeof window?e.r(26628).workAsyncStorage:void 0;function o({error:e}){if(n){let t=n.getStore();if(t?.isStaticGeneration)throw e&&console.error(e),e}return null}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},42124,(e,t,r)=>{"use strict";var n=e.i(39057),o=Symbol.for("react.transitional.element"),i=Symbol.for("react.portal"),u=Symbol.for("react.fragment"),s=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),a=Symbol.for("react.consumer"),l=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),p=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),y=Symbol.for("react.lazy"),h=Symbol.for("react.activity"),g=Symbol.for("react.view_transition"),v=Symbol.iterator,_={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},m=Object.assign,b={};function S(e,t,r){this.props=e,this.context=t,this.refs=b,this.updater=r||_}function O(){}function E(e,t,r){this.props=e,this.context=t,this.refs=b,this.updater=r||_}S.prototype.isReactComponent={},S.prototype.setState=function(e,t){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")},S.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},O.prototype=S.prototype;var T=E.prototype=new O;T.constructor=E,m(T,S.prototype),T.isPureReactComponent=!0;var w=Array.isArray;function j(){}var R={H:null,A:null,T:null,S:null},x=Object.prototype.hasOwnProperty;function A(e,t,r){var n=r.ref;return{$$typeof:o,type:e,key:t,ref:void 0!==n?n:null,props:r}}function P(e){return"object"==typeof e&&null!==e&&e.$$typeof===o}var C=/\/+/g;function H(e,t){var r,n;return"object"==typeof e&&null!==e&&null!=e.key?(r=""+e.key,n={"=":"=0",":":"=2"},"$"+r.replace(/[=:]/g,function(e){return n[e]})):t.toString(36)}function k(e,t,r){if(null==e)return e;var n=[],u=0;return!function e(t,r,n,u,s){var c,a,l,f=typeof t;("undefined"===f||"boolean"===f)&&(t=null);var p=!1;if(null===t)p=!0;else switch(f){case"bigint":case"string":case"number":p=!0;break;case"object":switch(t.$$typeof){case o:case i:p=!0;break;case y:return e((p=t._init)(t._payload),r,n,u,s)}}if(p)return s=s(t),p=""===u?"."+H(t,0):u,w(s)?(n="",null!=p&&(n=p.replace(C,"$&/")+"/"),e(s,r,n,"",function(e){return e})):null!=s&&(P(s)&&(c=s,a=n+(null==s.key||t&&t.key===s.key?"":(""+s.key).replace(C,"$&/")+"/")+p,s=A(c.type,a,c.props)),r.push(s)),1;p=0;var d=""===u?".":u+":";if(w(t))for(var h=0;h{"use strict";t.exports=e.r(42124)},15501,(e,t,r)=>{"use strict";var n=e.r(30668);function o(e){var t="https://react.dev/errors/"+e;if(1{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),t.exports=e.r(15501)}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/118bac1f0e1f8b45.js b/src/hyperview/server/static/_next/static/chunks/118bac1f0e1f8b45.js new file mode 100644 index 0000000000000000000000000000000000000000..48c41587fdd324fc1535b4c2058357672d32d2c0 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/118bac1f0e1f8b45.js @@ -0,0 +1,4 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,84524,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"InvariantError",{enumerable:!0,get:function(){return n}});class n extends Error{constructor(e,t){super(`Invariant: ${e.endsWith(".")?e:e+"."} This is a bug in Next.js.`,t),this.name="InvariantError"}}},35856,(e,t,r)=>{"use strict";r._=function(e){return e&&e.__esModule?e:{default:e}}},19551,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={BailoutToCSRError:function(){return a},isBailoutToCSRError:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="BAILOUT_TO_CLIENT_SIDE_RENDERING";class a extends Error{constructor(e){super(`Bail out to client-side rendering: ${e}`),this.reason=e,this.digest=u}}function i(e){return"object"==typeof e&&null!==e&&"digest"in e&&e.digest===u}},64918,(e,t,r)=>{"use strict";var n=e.r(69941),o={stream:!0},u=Object.prototype.hasOwnProperty;function a(t){var r=e.r(t);return"function"!=typeof r.then||"fulfilled"===r.status?null:(r.then(function(e){r.status="fulfilled",r.value=e},function(e){r.status="rejected",r.reason=e}),r)}var i=new WeakSet,l=new WeakSet;function s(){}function c(t){for(var r=t[1],n=[],o=0;of||35===f||114===f||120===f?(p=f,f=3,s++):(p=0,f=3);continue;case 2:44===(b=l[s++])?f=4:h=h<<4|(96l.length&&(b=-1)}var g=l.byteOffset+s;if(-1{"use strict";t.exports=e.r(64918)},30545,(e,t,r)=>{"use strict";t.exports=e.r(14992)},88112,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={HTTPAccessErrorStatus:function(){return u},HTTP_ERROR_FALLBACK_ERROR_CODE:function(){return i},getAccessFallbackErrorTypeByStatus:function(){return c},getAccessFallbackHTTPStatus:function(){return s},isHTTPAccessFallbackError:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u={NOT_FOUND:404,FORBIDDEN:403,UNAUTHORIZED:401},a=new Set(Object.values(u)),i="NEXT_HTTP_ERROR_FALLBACK";function l(e){if("object"!=typeof e||null===e||!("digest"in e)||"string"!=typeof e.digest)return!1;let[t,r]=e.digest.split(";");return t===i&&a.has(Number(r))}function s(e){return Number(e.digest.split(";")[1])}function c(e){switch(e){case 401:return"unauthorized";case 403:return"forbidden";case 404:return"not-found";default:return}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},91945,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"RedirectStatusCode",{enumerable:!0,get:function(){return o}});var n,o=((n={})[n.SeeOther=303]="SeeOther",n[n.TemporaryRedirect=307]="TemporaryRedirect",n[n.PermanentRedirect=308]="PermanentRedirect",n);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},84628,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n,o={REDIRECT_ERROR_CODE:function(){return i},RedirectType:function(){return l},isRedirectError:function(){return s}};for(var u in o)Object.defineProperty(r,u,{enumerable:!0,get:o[u]});let a=e.r(91945),i="NEXT_REDIRECT";var l=((n={}).push="push",n.replace="replace",n);function s(e){if("object"!=typeof e||null===e||!("digest"in e)||"string"!=typeof e.digest)return!1;let t=e.digest.split(";"),[r,n]=t,o=t.slice(2,-2).join(";"),u=Number(t.at(-2));return r===i&&("replace"===n||"push"===n)&&"string"==typeof o&&!isNaN(u)&&u in a.RedirectStatusCode}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},31028,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isNextRouterError",{enumerable:!0,get:function(){return u}});let n=e.r(88112),o=e.r(84628);function u(e){return(0,o.isRedirectError)(e)||(0,n.isHTTPAccessFallbackError)(e)}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},69370,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={NavigationPromisesContext:function(){return s},PathParamsContext:function(){return l},PathnameContext:function(){return i},SearchParamsContext:function(){return a},createDevToolsInstrumentedPromise:function(){return c}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(30668),a=(0,u.createContext)(null),i=(0,u.createContext)(null),l=(0,u.createContext)(null),s=(0,u.createContext)(null);function c(e,t){let r=Promise.resolve(t);return r.status="fulfilled",r.value=t,r.displayName=`${e} (SSR)`,r}},29037,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"workUnitAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(24171).createAsyncLocalStorage)()},2089,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={ACTION_HEADER:function(){return a},FLIGHT_HEADERS:function(){return h},NEXT_ACTION_NOT_FOUND_HEADER:function(){return E},NEXT_DID_POSTPONE_HEADER:function(){return b},NEXT_HMR_REFRESH_HASH_COOKIE:function(){return f},NEXT_HMR_REFRESH_HEADER:function(){return c},NEXT_HTML_REQUEST_ID_HEADER:function(){return O},NEXT_IS_PRERENDER_HEADER:function(){return m},NEXT_REQUEST_ID_HEADER:function(){return R},NEXT_REWRITTEN_PATH_HEADER:function(){return g},NEXT_REWRITTEN_QUERY_HEADER:function(){return v},NEXT_ROUTER_PREFETCH_HEADER:function(){return l},NEXT_ROUTER_SEGMENT_PREFETCH_HEADER:function(){return s},NEXT_ROUTER_STALE_TIME_HEADER:function(){return y},NEXT_ROUTER_STATE_TREE_HEADER:function(){return i},NEXT_RSC_UNION_QUERY:function(){return _},NEXT_URL:function(){return d},RSC_CONTENT_TYPE_HEADER:function(){return p},RSC_HEADER:function(){return u}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="rsc",a="next-action",i="next-router-state-tree",l="next-router-prefetch",s="next-router-segment-prefetch",c="next-hmr-refresh",f="__next_hmr_refresh_hash__",d="next-url",p="text/x-component",h=[u,i,l,c,s],_="_rsc",y="x-nextjs-stale-time",b="x-nextjs-postponed",g="x-nextjs-rewritten-path",v="x-nextjs-rewritten-query",m="x-nextjs-prerender",E="x-nextjs-action-not-found",R="x-nextjs-request-id",O="x-nextjs-html-request-id";("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},63416,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={getCacheSignal:function(){return y},getDraftModeProviderForCacheScope:function(){return _},getHmrRefreshHash:function(){return d},getPrerenderResumeDataCache:function(){return c},getRenderResumeDataCache:function(){return f},getRuntimeStagePromise:function(){return b},getServerComponentsHmrCache:function(){return h},isHmrRefresh:function(){return p},throwForMissingRequestStore:function(){return l},throwInvariantForMissingStore:function(){return s},workUnitAsyncStorage:function(){return u.workUnitAsyncStorageInstance}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(29037),a=e.r(2089),i=e.r(84524);function l(e){throw Object.defineProperty(Error(`\`${e}\` was called outside a request scope. Read more: https://nextjs.org/docs/messages/next-dynamic-api-wrong-context`),"__NEXT_ERROR_CODE",{value:"E251",enumerable:!1,configurable:!0})}function s(){throw Object.defineProperty(new i.InvariantError("Expected workUnitAsyncStorage to have a store."),"__NEXT_ERROR_CODE",{value:"E696",enumerable:!1,configurable:!0})}function c(e){switch(e.type){case"prerender":case"prerender-runtime":case"prerender-ppr":case"prerender-client":return e.prerenderResumeDataCache;case"request":if(e.prerenderResumeDataCache)return e.prerenderResumeDataCache;case"prerender-legacy":case"cache":case"private-cache":case"unstable-cache":return null;default:return e}}function f(e){switch(e.type){case"request":case"prerender":case"prerender-runtime":case"prerender-client":if(e.renderResumeDataCache)return e.renderResumeDataCache;case"prerender-ppr":return e.prerenderResumeDataCache??null;case"cache":case"private-cache":case"unstable-cache":case"prerender-legacy":return null;default:return e}}function d(e,t){if(e.dev)switch(t.type){case"cache":case"private-cache":case"prerender":case"prerender-runtime":return t.hmrRefreshHash;case"request":var r;return null==(r=t.cookies.get(a.NEXT_HMR_REFRESH_HASH_COOKIE))?void 0:r.value}}function p(e,t){if(e.dev)switch(t.type){case"cache":case"private-cache":case"request":return t.isHmrRefresh??!1}return!1}function h(e,t){if(e.dev)switch(t.type){case"cache":case"private-cache":case"request":return t.serverComponentsHmrCache}}function _(e,t){if(e.isDraftMode)switch(t.type){case"cache":case"private-cache":case"unstable-cache":case"prerender-runtime":case"request":return t.draftMode}}function y(e){switch(e.type){case"prerender":case"prerender-client":case"prerender-runtime":return e.cacheSignal;case"request":if(e.cacheSignal)return e.cacheSignal;case"prerender-ppr":case"prerender-legacy":case"cache":case"private-cache":case"unstable-cache":return null;default:return e}}function b(e){switch(e.type){case"prerender-runtime":case"private-cache":return e.runtimeStagePromise;case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":case"request":case"cache":case"unstable-cache":return null;default:return e}}},83441,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"useUntrackedPathname",{enumerable:!0,get:function(){return u}});let n=e.r(30668),o=e.r(69370);function u(){return!function(){if("undefined"==typeof window){let{workUnitAsyncStorage:t}=e.r(63416),r=t.getStore();if(!r)return!1;switch(r.type){case"prerender":case"prerender-client":case"prerender-ppr":let n=r.fallbackRouteParams;return!!n&&n.size>0}}return!1}()?(0,n.useContext)(o.PathnameContext):null}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},80118,(e,t,r)=>{"use strict";function n(e,t=!0){return e.pathname+e.search+(t?e.hash:"")}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createHrefFromUrl",{enumerable:!0,get:function(){return n}}),("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},61524,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={handleHardNavError:function(){return a},useNavFailureHandler:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});e.r(30668);let u=e.r(80118);function a(e){return!!e&&"undefined"!=typeof window&&!!window.next.__pendingUrl&&(0,u.createHrefFromUrl)(new URL(window.location.href))!==(0,u.createHrefFromUrl)(window.next.__pendingUrl)&&(console.error("Error occurred during navigation, falling back to hard navigation",e),window.location.href=window.next.__pendingUrl.toString(),!0)}function i(){}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},26470,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"HTML_LIMITED_BOT_UA_RE",{enumerable:!0,get:function(){return n}});let n=/[\w-]+-Google|Google-[\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight/i},62112,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={HTML_LIMITED_BOT_UA_RE:function(){return u.HTML_LIMITED_BOT_UA_RE},HTML_LIMITED_BOT_UA_RE_STRING:function(){return i},getBotType:function(){return c},isBot:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(26470),a=/Googlebot(?!-)|Googlebot$/i,i=u.HTML_LIMITED_BOT_UA_RE.source;function l(e){return u.HTML_LIMITED_BOT_UA_RE.test(e)}function s(e){return a.test(e)||l(e)}function c(e){return a.test(e)?"dom":l(e)?"html":void 0}},71202,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={ErrorBoundary:function(){return h},ErrorBoundaryHandler:function(){return p}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(35856),a=e.r(48277),i=u._(e.r(30668)),l=e.r(83441),s=e.r(31028);e.r(61524);let c=e.r(86846),f=e.r(62112),d="undefined"!=typeof window&&(0,f.isBot)(window.navigator.userAgent);class p extends i.default.Component{constructor(e){super(e),this.reset=()=>{this.setState({error:null})},this.state={error:null,previousPathname:this.props.pathname}}static getDerivedStateFromError(e){if((0,s.isNextRouterError)(e))throw e;return{error:e}}static getDerivedStateFromProps(e,t){let{error:r}=t;return e.pathname!==t.previousPathname&&t.error?{error:null,previousPathname:e.pathname}:{error:t.error,previousPathname:e.pathname}}render(){return this.state.error&&!d?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(c.HandleISRError,{error:this.state.error}),this.props.errorStyles,this.props.errorScripts,(0,a.jsx)(this.props.errorComponent,{error:this.state.error,reset:this.reset})]}):this.props.children}}function h({errorComponent:e,errorStyles:t,errorScripts:r,children:n}){let o=(0,l.useUntrackedPathname)();return e?(0,a.jsx)(p,{pathname:o,errorComponent:e,errorStyles:t,errorScripts:r,children:n}):(0,a.jsx)(a.Fragment,{children:n})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},98165,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n,o={ACTION_HMR_REFRESH:function(){return c},ACTION_NAVIGATE:function(){return i},ACTION_REFRESH:function(){return a},ACTION_RESTORE:function(){return l},ACTION_SERVER_ACTION:function(){return f},ACTION_SERVER_PATCH:function(){return s},PrefetchKind:function(){return d}};for(var u in o)Object.defineProperty(r,u,{enumerable:!0,get:o[u]});let a="refresh",i="navigate",l="restore",s="server-patch",c="hmr-refresh",f="server-action";var d=((n={}).AUTO="auto",n.FULL="full",n.TEMPORARY="temporary",n);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},61909,(e,t,r)=>{"use strict";function n(e){if("function"!=typeof WeakMap)return null;var t=new WeakMap,r=new WeakMap;return(n=function(e){return e?r:t})(e)}r._=function(e,t){if(!t&&e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var r=n(t);if(r&&r.has(e))return r.get(e);var o={__proto__:null},u=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var a in e)if("default"!==a&&Object.prototype.hasOwnProperty.call(e,a)){var i=u?Object.getOwnPropertyDescriptor(e,a):null;i&&(i.get||i.set)?Object.defineProperty(o,a,i):o[a]=e[a]}return o.default=e,r&&r.set(e,o),o}},65035,(e,t,r)=>{"use strict";function n(e){return null!==e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isThenable",{enumerable:!0,get:function(){return n}})},53128,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={dispatchAppRouterAction:function(){return l},useActionQueue:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(61909)._(e.r(30668)),a=e.r(65035),i=null;function l(e){if(null===i)throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0});i(e)}function s(e){let[t,r]=u.default.useState(e.state);i=t=>e.dispatch(t,r);let n=(0,u.useMemo)(()=>t,[t]);return(0,a.isThenable)(n)?(0,u.use)(n):n}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},59295,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"callServer",{enumerable:!0,get:function(){return a}});let n=e.r(30668),o=e.r(98165),u=e.r(53128);async function a(e,t){return new Promise((r,a)=>{(0,n.startTransition)(()=>{(0,u.dispatchAppRouterAction)({type:o.ACTION_SERVER_ACTION,actionId:e,actionArgs:t,resolve:r,reject:a})})})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},85045,(e,t,r)=>{"use strict";let n;Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"findSourceMapURL",{enumerable:!0,get:function(){return n}});("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},96670,(e,t,r)=>{"use strict";function n(e){return e.startsWith("/")?e:`/${e}`}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ensureLeadingSlash",{enumerable:!0,get:function(){return n}})},91395,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={DEFAULT_SEGMENT_KEY:function(){return f},PAGE_SEGMENT_KEY:function(){return c},addSearchParamsIfPageSegment:function(){return l},computeSelectedLayoutSegment:function(){return s},getSegmentValue:function(){return u},getSelectedLayoutSegmentPath:function(){return function e(t,r,n=!0,o=[]){let a;if(n)a=t[1][r];else{let e=t[1];a=e.children??Object.values(e)[0]}if(!a)return o;let i=u(a[0]);return!i||i.startsWith(c)?o:(o.push(i),e(a,r,!1,o))}},isGroupSegment:function(){return a},isParallelRouteSegment:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function u(e){return Array.isArray(e)?e[1]:e}function a(e){return"("===e[0]&&e.endsWith(")")}function i(e){return e.startsWith("@")&&"@children"!==e}function l(e,t){if(e.includes(c)){let e=JSON.stringify(t);return"{}"!==e?c+"?"+e:c}return e}function s(e,t){if(!e||0===e.length)return null;let r="children"===t?e[0]:e[e.length-1];return r===f?null:r}let c="__PAGE__",f="__DEFAULT__"},86511,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={normalizeAppPath:function(){return i},normalizeRscURL:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(96670),a=e.r(91395);function i(e){return(0,u.ensureLeadingSlash)(e.split("/").reduce((e,t,r,n)=>!t||(0,a.isGroupSegment)(t)||"@"===t[0]||("page"===t||"route"===t)&&r===n.length-1?e:`${e}/${t}`,""))}function l(e){return e.replace(/\.rsc($|\?)/,"$1")}},50864,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={INTERCEPTION_ROUTE_MARKERS:function(){return a},extractInterceptionRouteInformation:function(){return l},isInterceptionRouteAppPath:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(86511),a=["(..)(..)","(.)","(..)","(...)"];function i(e){return void 0!==e.split("/").find(e=>a.find(t=>e.startsWith(t)))}function l(e){let t,r,n;for(let o of e.split("/"))if(r=a.find(e=>o.startsWith(e))){[t,n]=e.split(r,2);break}if(!t||!r||!n)throw Object.defineProperty(Error(`Invalid interception route: ${e}. Must be in the format //(..|...|..)(..)/`),"__NEXT_ERROR_CODE",{value:"E269",enumerable:!1,configurable:!0});switch(t=(0,u.normalizeAppPath)(t),r){case"(.)":n="/"===t?`/${n}`:t+"/"+n;break;case"(..)":if("/"===t)throw Object.defineProperty(Error(`Invalid interception route: ${e}. Cannot use (..) marker at the root level, use (.) instead.`),"__NEXT_ERROR_CODE",{value:"E207",enumerable:!1,configurable:!0});n=t.split("/").slice(0,-1).concat(n).join("/");break;case"(...)":n="/"+n;break;case"(..)(..)":let o=t.split("/");if(o.length<=2)throw Object.defineProperty(Error(`Invalid interception route: ${e}. Cannot use (..)(..) marker at the root level or one level up.`),"__NEXT_ERROR_CODE",{value:"E486",enumerable:!1,configurable:!0});n=o.slice(0,-2).concat(n).join("/");break;default:throw Object.defineProperty(Error("Invariant: unexpected marker"),"__NEXT_ERROR_CODE",{value:"E112",enumerable:!1,configurable:!0})}return{interceptingRoute:t,interceptedRoute:n}}},22039,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"matchSegment",{enumerable:!0,get:function(){return n}});let n=(e,t)=>"string"==typeof e?"string"==typeof t&&e===t:"string"!=typeof t&&e[0]===t[0]&&e[1]===t[1];("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},69434,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={HEAD_REQUEST_KEY:function(){return i},ROOT_SEGMENT_REQUEST_KEY:function(){return a},appendSegmentRequestKeyPart:function(){return s},convertSegmentPathToStaticExportFilename:function(){return d},createSegmentRequestKeyPart:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(91395),a="",i="/_head";function l(e){if("string"==typeof e)return e.startsWith(u.PAGE_SEGMENT_KEY)?u.PAGE_SEGMENT_KEY:"/_not-found"===e?"_not-found":f(e);let t=e[0];return"$"+e[2]+"$"+f(t)}function s(e,t,r){return e+"/"+("children"===t?r:`@${f(t)}/${r}`)}let c=/^[a-zA-Z0-9\-_@]+$/;function f(e){return c.test(e)?e:"!"+btoa(e).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}function d(e){return`__next${e.replace(/\//g,".")}.txt`}},88617,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={doesStaticSegmentAppearInURL:function(){return f},getCacheKeyForDynamicParam:function(){return d},getParamValueFromCacheKey:function(){return h},getRenderedPathname:function(){return s},getRenderedSearch:function(){return l},parseDynamicParamFromURLPart:function(){return c},urlSearchParamsToParsedUrlQuery:function(){return _},urlToUrlWithoutFlightMarker:function(){return p}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(91395),a=e.r(69434),i=e.r(2089);function l(e){let t=e.headers.get(i.NEXT_REWRITTEN_QUERY_HEADER);return null!==t?""===t?"":"?"+t:p(new URL(e.url)).search}function s(e){return e.headers.get(i.NEXT_REWRITTEN_PATH_HEADER)??p(new URL(e.url)).pathname}function c(e,t,r){switch(e){case"c":return rencodeURIComponent(e)):[];case"ci(..)(..)":case"ci(.)":case"ci(..)":case"ci(...)":{let n=e.length-2;return r0===t?encodeURIComponent(e.slice(n)):encodeURIComponent(e)):[]}case"oc":return rencodeURIComponent(e)):null;case"d":if(r>=t.length)return"";return encodeURIComponent(t[r]);case"di(..)(..)":case"di(.)":case"di(..)":case"di(...)":{let n=e.length-2;if(r>=t.length)return"";return encodeURIComponent(t[r].slice(n))}default:return""}}function f(e){return!(e===a.ROOT_SEGMENT_REQUEST_KEY||e.startsWith(u.PAGE_SEGMENT_KEY)||"("===e[0]&&e.endsWith(")"))&&e!==u.DEFAULT_SEGMENT_KEY&&"/_not-found"!==e}function d(e,t){return"string"==typeof e?(0,u.addSearchParamsIfPageSegment)(e,Object.fromEntries(new URLSearchParams(t))):null===e?"":e.join("/")}function p(e){let t=new URL(e);if(t.searchParams.delete(i.NEXT_RSC_UNION_QUERY),t.pathname.endsWith(".txt")){let{pathname:e}=t,r=e.endsWith("/index.txt")?10:4;t.pathname=e.slice(0,-r)}return t}function h(e,t){return"c"===t||"oc"===t?e.split("/"):e}function _(e){let t={};for(let[r,n]of e.entries())void 0===t[r]?t[r]=n:Array.isArray(t[r])?t[r].push(n):t[r]=[t[r],n];return t}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},94955,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={createInitialRSCPayloadFromFallbackPrerender:function(){return s},getFlightDataPartsFromPath:function(){return l},getNextFlightSegmentPath:function(){return c},normalizeFlightData:function(){return f},prepareFlightRouterStateForRequest:function(){return d}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(91395),a=e.r(88617),i=e.r(80118);function l(e){let[t,r,n,o]=e.slice(-4),u=e.slice(0,-4);return{pathToSegment:u.slice(0,-1),segmentPath:u,segment:u[u.length-1]??"",tree:t,seedData:r,head:n,isHeadPartial:o,isRootRender:4===e.length}}function s(e,t){let r=(0,a.getRenderedPathname)(e),n=(0,a.getRenderedSearch)(e),o=(0,i.createHrefFromUrl)(new URL(location.href)),u=t.f[0],l=u[0];return{b:t.b,c:o.split("/"),q:n,i:t.i,f:[[function e(t,r,n,o){let u,i,l=t[0];if("string"==typeof l)u=l,i=(0,a.doesStaticSegmentAppearInURL)(l);else{let e=l[0],t=l[2],s=(0,a.parseDynamicParamFromURLPart)(t,n,o);u=[e,(0,a.getCacheKeyForDynamicParam)(s,r),t],i=!0}let s=i?o+1:o,c=t[1],f={};for(let t in c){let o=c[t];f[t]=e(o,r,n,s)}return[u,f,null,t[3],t[4]]}(l,n,r.split("/").filter(e=>""!==e),0),u[1],u[2],u[2]]],m:t.m,G:t.G,S:t.S}}function c(e){return e.slice(2)}function f(e){return"string"==typeof e?e:e.map(e=>l(e))}function d(e,t){return t?encodeURIComponent(JSON.stringify(e)):encodeURIComponent(JSON.stringify(function e(t){var r,n;let[o,a,i,l,s,c]=t,f="string"==typeof(r=o)&&r.startsWith(u.PAGE_SEGMENT_KEY+"?")?u.PAGE_SEGMENT_KEY:r,d={};for(let[t,r]of Object.entries(a))d[t]=e(r);let p=[f,d,null,(n=l)&&"refresh"!==n?l:null];return void 0!==s&&(p[4]=s),void 0!==c&&(p[5]=c),p}(e)))}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},70410,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={getAppBuildId:function(){return i},setAppBuildId:function(){return a}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="";function a(e){u=e}function i(){return u}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},83767,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={djb2Hash:function(){return u},hexHash:function(){return a}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function u(e){let t=5381;for(let r=0;r>>0}function a(e){return u(e).toString(36).slice(0,5)}},62858,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"computeCacheBustingSearchParam",{enumerable:!0,get:function(){return o}});let n=e.r(83767);function o(e,t,r,o){return(void 0===e||"0"===e)&&void 0===t&&void 0===r&&void 0===o?"":(0,n.hexHash)([e||"0",t||"0",r||"0",o||"0"].join(","))}},57283,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={setCacheBustingSearchParam:function(){return i},setCacheBustingSearchParamWithHash:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(62858),a=e.r(2089),i=(e,t)=>{l(e,(0,u.computeCacheBustingSearchParam)(t[a.NEXT_ROUTER_PREFETCH_HEADER],t[a.NEXT_ROUTER_SEGMENT_PREFETCH_HEADER],t[a.NEXT_ROUTER_STATE_TREE_HEADER],t[a.NEXT_URL]))},l=(e,t)=>{let r=e.search,n=(r.startsWith("?")?r.slice(1):r).split("&").filter(e=>e&&!e.startsWith(`${a.NEXT_RSC_UNION_QUERY}=`));t.length>0?n.push(`${a.NEXT_RSC_UNION_QUERY}=${t}`):n.push(`${a.NEXT_RSC_UNION_QUERY}`),e.search=n.length?`?${n.join("&")}`:""};("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},20320,(e,t,r)=>{"use strict";let n;Object.defineProperty(r,"__esModule",{value:!0});var o={createFetch:function(){return m},createFromNextReadableStream:function(){return E},fetchServerResponse:function(){return v}};for(var u in o)Object.defineProperty(r,u,{enumerable:!0,get:o[u]});let a=e.r(30545),i=e.r(2089),l=e.r(59295),s=e.r(85045),c=e.r(98165),f=e.r(94955),d=e.r(70410),p=e.r(57283),h=e.r(88617),_=a.createFromReadableStream,y=a.createFromFetch;function b(e){return(0,h.urlToUrlWithoutFlightMarker)(new URL(e,location.origin)).toString()}let g=!1;async function v(e,t){let{flightRouterState:r,nextUrl:n,prefetchKind:o}=t,u={[i.RSC_HEADER]:"1",[i.NEXT_ROUTER_STATE_TREE_HEADER]:(0,f.prepareFlightRouterStateForRequest)(r,t.isHmrRefresh)};o===c.PrefetchKind.AUTO&&(u[i.NEXT_ROUTER_PREFETCH_HEADER]="1"),n&&(u[i.NEXT_URL]=n);let a=e;try{let t=o?o===c.PrefetchKind.TEMPORARY?"high":"low":"auto";(e=new URL(e)).pathname.endsWith("/")?e.pathname+="index.txt":e.pathname+=".txt";let r=await m(e,u,t,!0),n=(0,h.urlToUrlWithoutFlightMarker)(new URL(r.url)),l=r.redirected?n:a,s=r.headers.get("content-type")||"",p=!!r.headers.get("vary")?.includes(i.NEXT_URL),_=!!r.headers.get(i.NEXT_DID_POSTPONE_HEADER),y=r.headers.get(i.NEXT_ROUTER_STALE_TIME_HEADER),g=null!==y?1e3*parseInt(y,10):-1,v=s.startsWith(i.RSC_CONTENT_TYPE_HEADER);if(v||(v=s.startsWith("text/plain")),!v||!r.ok||!r.body)return e.hash&&(n.hash=e.hash),b(n.toString());let R=r.flightResponse;if(null===R){let e,t=_?(e=r.body.getReader(),new ReadableStream({async pull(t){for(;;){let{done:r,value:n}=await e.read();if(!r){t.enqueue(n);continue}return}}})):r.body;R=E(t,u)}let O=await R;if((0,d.getAppBuildId)()!==O.b)return b(r.url);let S=(0,f.normalizeFlightData)(O.f);if("string"==typeof S)return b(S);return{flightData:S,canonicalUrl:l,renderedSearch:(0,h.getRenderedSearch)(r),couldBeIntercepted:p,prerendered:O.S,postponed:_,staleTime:g,debugInfo:R._debugInfo??null}}catch(e){return g||console.error(`Failed to fetch RSC payload for ${a}. Falling back to browser navigation.`,e),a.toString()}}async function m(e,t,r,o,u){var a,c;let f=new URL(e);(0,p.setCacheBustingSearchParam)(f,t);let d=fetch(f,{credentials:"same-origin",headers:t,priority:r||void 0,signal:u}),h=o?(a=d,c=t,y(a,{callServer:l.callServer,findSourceMapURL:s.findSourceMapURL,debugChannel:n&&n(c)})):null,_=await d,b=_.redirected,g=new URL(_.url,f);return g.searchParams.delete(i.NEXT_RSC_UNION_QUERY),{url:g.href,redirected:b,ok:_.ok,headers:_.headers,body:_.body,status:_.status,flightResponse:h}}function E(e,t){return _(e,{callServer:l.callServer,findSourceMapURL:s.findSourceMapURL,debugChannel:n&&n(t)})}"undefined"!=typeof window&&(window.addEventListener("pagehide",()=>{g=!0}),window.addEventListener("pageshow",()=>{g=!1})),("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},43317,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createRouterCacheKey",{enumerable:!0,get:function(){return o}});let n=e.r(91395);function o(e,t=!1){return Array.isArray(e)?`${e[0]}|${e[1]}|${e[2]}`:t&&e.startsWith(n.PAGE_SEGMENT_KEY)?n.PAGE_SEGMENT_KEY:e}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},59162,(e,t,r)=>{"use strict";function n(){let e,t,r=new Promise((r,n)=>{e=r,t=n});return{resolve:e,reject:t,promise:r}}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"createPromiseWithResolvers",{enumerable:!0,get:function(){return n}})},45243,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={AppRouterContext:function(){return a},GlobalLayoutRouterContext:function(){return l},LayoutRouterContext:function(){return i},MissingSlotContext:function(){return c},TemplateContext:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(35856)._(e.r(30668)),a=u.default.createContext(null),i=u.default.createContext(null),l=u.default.createContext(null),s=u.default.createContext(null),c=u.default.createContext(new Set)},13058,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"ReadonlyURLSearchParams",{enumerable:!0,get:function(){return o}});class n extends Error{constructor(){super("Method unavailable on `ReadonlyURLSearchParams`. Read more: https://nextjs.org/docs/app/api-reference/functions/use-search-params#updating-searchparams")}}class o extends URLSearchParams{append(){throw new n}delete(){throw new n}set(){throw new n}sort(){throw new n}}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},98680,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={ServerInsertedHTMLContext:function(){return a},useServerInsertedHTML:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(61909)._(e.r(30668)),a=u.default.createContext(null);function i(e){let t=(0,u.useContext)(a);t&&t(e)}},40288,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={UnrecognizedActionError:function(){return u},unstable_isUnrecognizedActionError:function(){return a}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});class u extends Error{constructor(...e){super(...e),this.name="UnrecognizedActionError"}}function a(e){return!!(e&&"object"==typeof e&&e instanceof u)}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},39069,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"actionAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(24171).createAsyncLocalStorage)()},93988,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"actionAsyncStorage",{enumerable:!0,get:function(){return n.actionAsyncStorageInstance}});let n=e.r(39069)},44216,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={getRedirectError:function(){return l},getRedirectStatusCodeFromError:function(){return p},getRedirectTypeFromError:function(){return d},getURLFromRedirectError:function(){return f},permanentRedirect:function(){return c},redirect:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(91945),a=e.r(84628),i="undefined"==typeof window?e.r(93988).actionAsyncStorage:void 0;function l(e,t,r=u.RedirectStatusCode.TemporaryRedirect){let n=Object.defineProperty(Error(a.REDIRECT_ERROR_CODE),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return n.digest=`${a.REDIRECT_ERROR_CODE};${t};${e};${r};`,n}function s(e,t){throw l(e,t??=i?.getStore()?.isAction?a.RedirectType.push:a.RedirectType.replace,u.RedirectStatusCode.TemporaryRedirect)}function c(e,t=a.RedirectType.replace){throw l(e,t,u.RedirectStatusCode.PermanentRedirect)}function f(e){return(0,a.isRedirectError)(e)?e.digest.split(";").slice(2,-2).join(";"):null}function d(e){if(!(0,a.isRedirectError)(e))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return e.digest.split(";",2)[1]}function p(e){if(!(0,a.isRedirectError)(e))throw Object.defineProperty(Error("Not a redirect error"),"__NEXT_ERROR_CODE",{value:"E260",enumerable:!1,configurable:!0});return Number(e.digest.split(";").at(-2))}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},48918,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"notFound",{enumerable:!0,get:function(){return u}});let n=e.r(88112),o=`${n.HTTP_ERROR_FALLBACK_ERROR_CODE};404`;function u(){let e=Object.defineProperty(Error(o),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});throw e.digest=o,e}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},92881,(e,t,r)=>{"use strict";function n(){throw Object.defineProperty(Error("`forbidden()` is experimental and only allowed to be enabled when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E488",enumerable:!1,configurable:!0})}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"forbidden",{enumerable:!0,get:function(){return n}}),e.r(88112).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},24673,(e,t,r)=>{"use strict";function n(){throw Object.defineProperty(Error("`unauthorized()` is experimental and only allowed to be used when `experimental.authInterrupts` is enabled."),"__NEXT_ERROR_CODE",{value:"E411",enumerable:!1,configurable:!0})}Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"unauthorized",{enumerable:!0,get:function(){return n}}),e.r(88112).HTTP_ERROR_FALLBACK_ERROR_CODE,("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},33517,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"unstable_rethrow",{enumerable:!0,get:function(){return function e(t){if((0,o.isNextRouterError)(t)||(0,n.isBailoutToCSRError)(t))throw t;t instanceof Error&&"cause"in t&&e(t.cause)}}});let n=e.r(19551),o=e.r(31028);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},64265,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={isHangingPromiseRejectionError:function(){return u},makeDevtoolsIOAwarePromise:function(){return f},makeHangingPromise:function(){return s}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});function u(e){return"object"==typeof e&&null!==e&&"digest"in e&&e.digest===a}let a="HANGING_PROMISE_REJECTION";class i extends Error{constructor(e,t){super(`During prerendering, ${t} rejects when the prerender is complete. Typically these errors are handled by React but if you move ${t} to a different context by using \`setTimeout\`, \`after\`, or similar functions you may observe this error and you should handle it in that context. This occurred at route "${e}".`),this.route=e,this.expression=t,this.digest=a}}let l=new WeakMap;function s(e,t,r){if(e.aborted)return Promise.reject(new i(t,r));{let n=new Promise((n,o)=>{let u=o.bind(null,new i(t,r)),a=l.get(e);if(a)a.push(u);else{let t=[u];l.set(e,t),e.addEventListener("abort",()=>{for(let e=0;e{setTimeout(()=>{t(e)},0)})}},67867,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"isPostpone",{enumerable:!0,get:function(){return o}});let n=Symbol.for("react.postpone");function o(e){return"object"==typeof e&&null!==e&&e.$$typeof===n}},61541,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={DynamicServerError:function(){return a},isDynamicServerError:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="DYNAMIC_SERVER_USAGE";class a extends Error{constructor(e){super(`Dynamic server usage: ${e}`),this.description=e,this.digest=u}}function i(e){return"object"==typeof e&&null!==e&&"digest"in e&&"string"==typeof e.digest&&e.digest===u}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},16819,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={StaticGenBailoutError:function(){return a},isStaticGenBailoutError:function(){return i}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="NEXT_STATIC_GEN_BAILOUT";class a extends Error{constructor(...e){super(...e),this.code=u}}function i(e){return"object"==typeof e&&null!==e&&"code"in e&&e.code===u}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},66251,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={METADATA_BOUNDARY_NAME:function(){return u},OUTLET_BOUNDARY_NAME:function(){return i},ROOT_LAYOUT_BOUNDARY_NAME:function(){return l},VIEWPORT_BOUNDARY_NAME:function(){return a}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u="__next_metadata_boundary__",a="__next_viewport_boundary__",i="__next_outlet_boundary__",l="__next_root_layout_boundary__"},25992,(e,t,r)=>{"use strict";var n=e.i(39057);Object.defineProperty(r,"__esModule",{value:!0});var o={atLeastOneTask:function(){return l},scheduleImmediate:function(){return i},scheduleOnNextTick:function(){return a},waitAtLeastOneReactRenderTask:function(){return s}};for(var u in o)Object.defineProperty(r,u,{enumerable:!0,get:o[u]});let a=e=>{Promise.resolve().then(()=>{n.default.nextTick(e)})},i=e=>{setImmediate(e)};function l(){return new Promise(e=>i(e))}function s(){return new Promise(e=>setImmediate(e))}},93501,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n,o={RenderStage:function(){return l},StagedRenderingController:function(){return s}};for(var u in o)Object.defineProperty(r,u,{enumerable:!0,get:o[u]});let a=e.r(84524),i=e.r(59162);var l=((n={})[n.Static=1]="Static",n[n.Runtime=2]="Runtime",n[n.Dynamic=3]="Dynamic",n);class s{constructor(e=null){this.abortSignal=e,this.currentStage=1,this.runtimeStagePromise=(0,i.createPromiseWithResolvers)(),this.dynamicStagePromise=(0,i.createPromiseWithResolvers)(),e&&e.addEventListener("abort",()=>{let{reason:t}=e;this.currentStage<2&&(this.runtimeStagePromise.promise.catch(c),this.runtimeStagePromise.reject(t)),this.currentStage<3&&(this.dynamicStagePromise.promise.catch(c),this.dynamicStagePromise.reject(t))},{once:!0})}advanceStage(e){!(this.currentStage>=e)&&(this.currentStage=e,e>=2&&this.runtimeStagePromise.resolve(),e>=3&&this.dynamicStagePromise.resolve())}getStagePromise(e){switch(e){case 2:return this.runtimeStagePromise.promise;case 3:return this.dynamicStagePromise.promise;default:throw Object.defineProperty(new a.InvariantError(`Invalid render stage: ${e}`),"__NEXT_ERROR_CODE",{value:"E881",enumerable:!1,configurable:!0})}}waitForStage(e){return this.getStagePromise(e)}delayUntilStage(e,t,r){var n,o,u;let a,i=(n=this.getStagePromise(e),o=t,u=r,a=new Promise((e,t)=>{n.then(e.bind(null,u),t)}),void 0!==o&&(a.displayName=o),a);return this.abortSignal&&i.catch(c),i}}function c(){}},93869,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n,o,u={Postpone:function(){return A},PreludeState:function(){return J},abortAndThrowOnSynchronousRequestDataAccess:function(){return T},abortOnSynchronousPlatformIOAccess:function(){return j},accessedDynamicData:function(){return I},annotateDynamicAccess:function(){return B},consumeDynamicAccess:function(){return L},createDynamicTrackingState:function(){return v},createDynamicValidationState:function(){return m},createHangingInputAbortSignal:function(){return H},createRenderInBrowserAbortSignal:function(){return F},delayUntilRuntimeStage:function(){return ee},formatDynamicAPIAccesses:function(){return $},getFirstDynamicReason:function(){return E},isDynamicPostpone:function(){return N},isPrerenderInterruptedError:function(){return U},logDisallowedDynamicError:function(){return Q},markCurrentScopeAsDynamic:function(){return R},postponeWithTracking:function(){return M},throwIfDisallowedDynamic:function(){return Z},throwToInterruptStaticGeneration:function(){return O},trackAllowedDynamicAccess:function(){return V},trackDynamicDataInDynamicRender:function(){return S},trackSynchronousPlatformIOAccessInDev:function(){return w},useDynamicRouteParams:function(){return X},useDynamicSearchParams:function(){return W}};for(var a in u)Object.defineProperty(r,a,{enumerable:!0,get:u[a]});let i=(n=e.r(30668))&&n.__esModule?n:{default:n},l=e.r(61541),s=e.r(16819),c=e.r(63416),f=e.r(26628),d=e.r(64265),p=e.r(66251),h=e.r(25992),_=e.r(19551),y=e.r(84524),b=e.r(93501),g="function"==typeof i.default.unstable_postpone;function v(e){return{isDebugDynamicAccesses:e,dynamicAccesses:[],syncDynamicErrorWithStack:null}}function m(){return{hasSuspenseAboveBody:!1,hasDynamicMetadata:!1,hasDynamicViewport:!1,hasAllowedDynamic:!1,dynamicErrors:[]}}function E(e){var t;return null==(t=e.dynamicAccesses[0])?void 0:t.expression}function R(e,t,r){if(t)switch(t.type){case"cache":case"unstable-cache":case"private-cache":return}if(!e.forceDynamic&&!e.forceStatic){if(e.dynamicShouldError)throw Object.defineProperty(new s.StaticGenBailoutError(`Route ${e.route} with \`dynamic = "error"\` couldn't be rendered statically because it used \`${r}\`. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`),"__NEXT_ERROR_CODE",{value:"E553",enumerable:!1,configurable:!0});if(t)switch(t.type){case"prerender-ppr":return M(e.route,r,t.dynamicTracking);case"prerender-legacy":t.revalidate=0;let n=Object.defineProperty(new l.DynamicServerError(`Route ${e.route} couldn't be rendered statically because it used ${r}. See more info here: https://nextjs.org/docs/messages/dynamic-server-error`),"__NEXT_ERROR_CODE",{value:"E550",enumerable:!1,configurable:!0});throw e.dynamicUsageDescription=r,e.dynamicUsageStack=n.stack,n}}}function O(e,t,r){let n=Object.defineProperty(new l.DynamicServerError(`Route ${t.route} couldn't be rendered statically because it used \`${e}\`. See more info here: https://nextjs.org/docs/messages/dynamic-server-error`),"__NEXT_ERROR_CODE",{value:"E558",enumerable:!1,configurable:!0});throw r.revalidate=0,t.dynamicUsageDescription=e,t.dynamicUsageStack=n.stack,n}function S(e){switch(e.type){case"cache":case"unstable-cache":case"private-cache":return}}function P(e,t,r){let n=k(`Route ${e} needs to bail out of prerendering at this point because it used ${t}.`);r.controller.abort(n);let o=r.dynamicTracking;o&&o.dynamicAccesses.push({stack:o.isDebugDynamicAccesses?Error().stack:void 0,expression:t})}function j(e,t,r,n){let o=n.dynamicTracking;P(e,t,n),o&&null===o.syncDynamicErrorWithStack&&(o.syncDynamicErrorWithStack=r)}function w(e){e.stagedRendering&&e.stagedRendering.advanceStage(b.RenderStage.Dynamic)}function T(e,t,r,n){if(!1===n.controller.signal.aborted){P(e,t,n);let o=n.dynamicTracking;o&&null===o.syncDynamicErrorWithStack&&(o.syncDynamicErrorWithStack=r)}throw k(`Route ${e} needs to bail out of prerendering at this point because it used ${t}.`)}function A({reason:e,route:t}){let r=c.workUnitAsyncStorage.getStore();M(t,e,r&&"prerender-ppr"===r.type?r.dynamicTracking:null)}function M(e,t,r){(function(){if(!g)throw Object.defineProperty(Error("Invariant: React.unstable_postpone is not defined. This suggests the wrong version of React was loaded. This is a bug in Next.js"),"__NEXT_ERROR_CODE",{value:"E224",enumerable:!1,configurable:!0})})(),r&&r.dynamicAccesses.push({stack:r.isDebugDynamicAccesses?Error().stack:void 0,expression:t}),i.default.unstable_postpone(D(e,t))}function D(e,t){return`Route ${e} needs to bail out of prerendering at this point because it used ${t}. React throws this special object to indicate where. It should not be caught by your own try/catch. Learn more: https://nextjs.org/docs/messages/ppr-caught-error`}function N(e){return"object"==typeof e&&null!==e&&"string"==typeof e.message&&x(e.message)}function x(e){return e.includes("needs to bail out of prerendering at this point because it used")&&e.includes("Learn more: https://nextjs.org/docs/messages/ppr-caught-error")}if(!1===x(D("%%%","^^^")))throw Object.defineProperty(Error("Invariant: isDynamicPostpone misidentified a postpone reason. This is a bug in Next.js"),"__NEXT_ERROR_CODE",{value:"E296",enumerable:!1,configurable:!0});let C="NEXT_PRERENDER_INTERRUPTED";function k(e){let t=Object.defineProperty(Error(e),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});return t.digest=C,t}function U(e){return"object"==typeof e&&null!==e&&e.digest===C&&"name"in e&&"message"in e&&e instanceof Error}function I(e){return e.length>0}function L(e,t){return e.dynamicAccesses.push(...t.dynamicAccesses),e.dynamicAccesses}function $(e){return e.filter(e=>"string"==typeof e.stack&&e.stack.length>0).map(({expression:e,stack:t})=>(t=t.split("\n").slice(4).filter(e=>!(e.includes("node_modules/next/")||e.includes(" ()")||e.includes(" (node:"))).join("\n"),`Dynamic API Usage Debug - ${e}: +${t}`))}function F(){let e=new AbortController;return e.abort(Object.defineProperty(new _.BailoutToCSRError("Render in Browser"),"__NEXT_ERROR_CODE",{value:"E721",enumerable:!1,configurable:!0})),e.signal}function H(e){switch(e.type){case"prerender":case"prerender-runtime":let t=new AbortController;if(e.cacheSignal)e.cacheSignal.inputReady().then(()=>{t.abort()});else{let r=(0,c.getRuntimeStagePromise)(e);r?r.then(()=>(0,h.scheduleOnNextTick)(()=>t.abort())):(0,h.scheduleOnNextTick)(()=>t.abort())}return t.signal;case"prerender-client":case"prerender-ppr":case"prerender-legacy":case"request":case"cache":case"private-cache":case"unstable-cache":return}}function B(e,t){let r=t.dynamicTracking;r&&r.dynamicAccesses.push({stack:r.isDebugDynamicAccesses?Error().stack:void 0,expression:e})}function X(e){let t=f.workAsyncStorage.getStore(),r=c.workUnitAsyncStorage.getStore();if(t&&r)switch(r.type){case"prerender-client":case"prerender":{let n=r.fallbackRouteParams;n&&n.size>0&&i.default.use((0,d.makeHangingPromise)(r.renderSignal,t.route,e));break}case"prerender-ppr":{let n=r.fallbackRouteParams;if(n&&n.size>0)return M(t.route,e,r.dynamicTracking);break}case"prerender-runtime":throw Object.defineProperty(new y.InvariantError(`\`${e}\` was called during a runtime prerender. Next.js should be preventing ${e} from being included in server components statically, but did not in this case.`),"__NEXT_ERROR_CODE",{value:"E771",enumerable:!1,configurable:!0});case"cache":case"private-cache":throw Object.defineProperty(new y.InvariantError(`\`${e}\` was called inside a cache scope. Next.js should be preventing ${e} from being included in server components statically, but did not in this case.`),"__NEXT_ERROR_CODE",{value:"E745",enumerable:!1,configurable:!0})}}function W(e){let t=f.workAsyncStorage.getStore(),r=c.workUnitAsyncStorage.getStore();if(t)switch(!r&&(0,c.throwForMissingRequestStore)(e),r.type){case"prerender-client":i.default.use((0,d.makeHangingPromise)(r.renderSignal,t.route,e));break;case"prerender-legacy":case"prerender-ppr":if(t.forceStatic)return;throw Object.defineProperty(new _.BailoutToCSRError(e),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});case"prerender":case"prerender-runtime":throw Object.defineProperty(new y.InvariantError(`\`${e}\` was called from a Server Component. Next.js should be preventing ${e} from being included in server components statically, but did not in this case.`),"__NEXT_ERROR_CODE",{value:"E795",enumerable:!1,configurable:!0});case"cache":case"unstable-cache":case"private-cache":throw Object.defineProperty(new y.InvariantError(`\`${e}\` was called inside a cache scope. Next.js should be preventing ${e} from being included in server components statically, but did not in this case.`),"__NEXT_ERROR_CODE",{value:"E745",enumerable:!1,configurable:!0});case"request":return}}let G=/\n\s+at Suspense \(\)/,Y=RegExp(`\\n\\s+at Suspense \\(\\)(?:(?!\\n\\s+at (?:body|div|main|section|article|aside|header|footer|nav|form|p|span|h1|h2|h3|h4|h5|h6) \\(\\))[\\s\\S])*?\\n\\s+at ${p.ROOT_LAYOUT_BOUNDARY_NAME} \\([^\\n]*\\)`),q=RegExp(`\\n\\s+at ${p.METADATA_BOUNDARY_NAME}[\\n\\s]`),K=RegExp(`\\n\\s+at ${p.VIEWPORT_BOUNDARY_NAME}[\\n\\s]`),z=RegExp(`\\n\\s+at ${p.OUTLET_BOUNDARY_NAME}[\\n\\s]`);function V(e,t,r,n){if(!z.test(t)){if(q.test(t)){r.hasDynamicMetadata=!0;return}if(K.test(t)){r.hasDynamicViewport=!0;return}if(Y.test(t)){r.hasAllowedDynamic=!0,r.hasSuspenseAboveBody=!0;return}else if(G.test(t)){r.hasAllowedDynamic=!0;return}else{var o,u;let a;if(n.syncDynamicErrorWithStack)return void r.dynamicErrors.push(n.syncDynamicErrorWithStack);let i=(o=`Route "${e.route}": Uncached data was accessed outside of . This delays the entire page from rendering, resulting in a slow user experience. Learn more: https://nextjs.org/docs/messages/blocking-route`,u=t,(a=Object.defineProperty(Error(o),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0})).stack=a.name+": "+o+u,a);return void r.dynamicErrors.push(i)}}}var J=((o={})[o.Full=0]="Full",o[o.Empty=1]="Empty",o[o.Errored=2]="Errored",o);function Q(e,t){console.error(t),e.dev||(e.hasReadableErrorStacks?console.error(`To get a more detailed stack trace and pinpoint the issue, start the app in development mode by running \`next dev\`, then open "${e.route}" in your browser to investigate the error.`):console.error(`To get a more detailed stack trace and pinpoint the issue, try one of the following: + - Start the app in development mode by running \`next dev\`, then open "${e.route}" in your browser to investigate the error. + - Rerun the production build with \`next build --debug-prerender\` to generate better stack traces.`))}function Z(e,t,r,n){if(n.syncDynamicErrorWithStack)throw Q(e,n.syncDynamicErrorWithStack),new s.StaticGenBailoutError;if(0!==t){if(r.hasSuspenseAboveBody)return;let n=r.dynamicErrors;if(n.length>0){for(let t=0;tt):t}},57617,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"unstable_rethrow",{enumerable:!0,get:function(){return function e(t){if((0,a.isNextRouterError)(t)||(0,u.isBailoutToCSRError)(t)||(0,l.isDynamicServerError)(t)||(0,i.isDynamicPostpone)(t)||(0,o.isPostpone)(t)||(0,n.isHangingPromiseRejectionError)(t)||(0,i.isPrerenderInterruptedError)(t))throw t;t instanceof Error&&"cause"in t&&e(t.cause)}}});let n=e.r(64265),o=e.r(67867),u=e.r(19551),a=e.r(31028),i=e.r(93869),l=e.r(61541);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},60516,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"unstable_rethrow",{enumerable:!0,get:function(){return n}});let n="undefined"==typeof window?e.r(57617).unstable_rethrow:e.r(33517).unstable_rethrow;("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},8e3,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={ReadonlyURLSearchParams:function(){return u.ReadonlyURLSearchParams},RedirectType:function(){return i.RedirectType},forbidden:function(){return s.forbidden},notFound:function(){return l.notFound},permanentRedirect:function(){return a.permanentRedirect},redirect:function(){return a.redirect},unauthorized:function(){return c.unauthorized},unstable_isUnrecognizedActionError:function(){return d},unstable_rethrow:function(){return f.unstable_rethrow}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(13058),a=e.r(44216),i=e.r(84628),l=e.r(48918),s=e.r(92881),c=e.r(24673),f=e.r(60516);function d(){throw Object.defineProperty(Error("`unstable_isUnrecognizedActionError` can only be used on the client."),"__NEXT_ERROR_CODE",{value:"E776",enumerable:!1,configurable:!0})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},9187,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={ReadonlyURLSearchParams:function(){return d.ReadonlyURLSearchParams},RedirectType:function(){return d.RedirectType},ServerInsertedHTMLContext:function(){return c.ServerInsertedHTMLContext},forbidden:function(){return d.forbidden},notFound:function(){return d.notFound},permanentRedirect:function(){return d.permanentRedirect},redirect:function(){return d.redirect},unauthorized:function(){return d.unauthorized},unstable_isUnrecognizedActionError:function(){return f.unstable_isUnrecognizedActionError},unstable_rethrow:function(){return d.unstable_rethrow},useParams:function(){return g},usePathname:function(){return y},useRouter:function(){return b},useSearchParams:function(){return _},useSelectedLayoutSegment:function(){return m},useSelectedLayoutSegments:function(){return v},useServerInsertedHTML:function(){return c.useServerInsertedHTML}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(61909)._(e.r(30668)),a=e.r(45243),i=e.r(69370),l=e.r(91395),s=e.r(13058),c=e.r(98680),f=e.r(40288),d=e.r(8e3),p="undefined"==typeof window?e.r(93869).useDynamicRouteParams:void 0,h="undefined"==typeof window?e.r(93869).useDynamicSearchParams:void 0;function _(){h?.("useSearchParams()");let e=(0,u.useContext)(i.SearchParamsContext);return(0,u.useMemo)(()=>e?new s.ReadonlyURLSearchParams(e):null,[e])}function y(){return p?.("usePathname()"),(0,u.useContext)(i.PathnameContext)}function b(){let e=(0,u.useContext)(a.AppRouterContext);if(null===e)throw Object.defineProperty(Error("invariant expected app router to be mounted"),"__NEXT_ERROR_CODE",{value:"E238",enumerable:!1,configurable:!0});return e}function g(){return p?.("useParams()"),(0,u.useContext)(i.PathParamsContext)}function v(e="children"){p?.("useSelectedLayoutSegments()");let t=(0,u.useContext)(a.LayoutRouterContext);return t?(0,l.getSelectedLayoutSegmentPath)(t.parentTree,e):null}function m(e="children"){p?.("useSelectedLayoutSegment()"),(0,u.useContext)(i.NavigationPromisesContext);let t=v(e);return(0,l.computeSelectedLayoutSegment)(t,e)}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},2188,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={RedirectBoundary:function(){return p},RedirectErrorBoundary:function(){return d}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(61909),a=e.r(48277),i=u._(e.r(30668)),l=e.r(9187),s=e.r(44216),c=e.r(84628);function f({redirect:e,reset:t,redirectType:r}){let n=(0,l.useRouter)();return(0,i.useEffect)(()=>{i.default.startTransition(()=>{r===c.RedirectType.push?n.push(e,{}):n.replace(e,{}),t()})},[e,r,t,n]),null}class d extends i.default.Component{constructor(e){super(e),this.state={redirect:null,redirectType:null}}static getDerivedStateFromError(e){if((0,c.isRedirectError)(e)){let t=(0,s.getURLFromRedirectError)(e),r=(0,s.getRedirectTypeFromError)(e);return"handled"in e?{redirect:null,redirectType:null}:{redirect:t,redirectType:r}}throw e}render(){let{redirect:e,redirectType:t}=this.state;return null!==e&&null!==t?(0,a.jsx)(f,{redirect:e,redirectType:t,reset:()=>this.setState({redirect:null})}):this.props.children}}function p({children:e}){let t=(0,l.useRouter)();return(0,a.jsx)(d,{router:t,children:e})}("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},83648,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"unresolvedThenable",{enumerable:!0,get:function(){return n}});let n={then:()=>{}};("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)},64381,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0});var n={MetadataBoundary:function(){return i},OutletBoundary:function(){return s},RootLayoutBoundary:function(){return c},ViewportBoundary:function(){return l}};for(var o in n)Object.defineProperty(r,o,{enumerable:!0,get:n[o]});let u=e.r(66251),a={[u.METADATA_BOUNDARY_NAME]:function({children:e}){return e},[u.VIEWPORT_BOUNDARY_NAME]:function({children:e}){return e},[u.OUTLET_BOUNDARY_NAME]:function({children:e}){return e},[u.ROOT_LAYOUT_BOUNDARY_NAME]:function({children:e}){return e}},i=a[u.METADATA_BOUNDARY_NAME.slice(0)],l=a[u.VIEWPORT_BOUNDARY_NAME.slice(0)],s=a[u.OUTLET_BOUNDARY_NAME.slice(0)],c=a[u.ROOT_LAYOUT_BOUNDARY_NAME.slice(0)]},20017,(e,t,r)=>{"use strict";Object.defineProperty(r,"__esModule",{value:!0}),Object.defineProperty(r,"hasInterceptionRouteInCurrentTree",{enumerable:!0,get:function(){return function e([t,r]){if(Array.isArray(t)&&("di(..)(..)"===t[2]||"ci(..)(..)"===t[2]||"di(.)"===t[2]||"ci(.)"===t[2]||"di(..)"===t[2]||"ci(..)"===t[2]||"di(...)"===t[2]||"ci(...)"===t[2])||"string"==typeof t&&(0,n.isInterceptionRouteAppPath)(t))return!0;if(r){for(let t in r)if(e(r[t]))return!0}return!1}}});let n=e.r(50864);("function"==typeof r.default||"object"==typeof r.default&&null!==r.default)&&void 0===r.default.__esModule&&(Object.defineProperty(r.default,"__esModule",{value:!0}),Object.assign(r.default,r),t.exports=r.default)}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/3686d57edf1023fb.js b/src/hyperview/server/static/_next/static/chunks/3686d57edf1023fb.js new file mode 100644 index 0000000000000000000000000000000000000000..8044046a308726938272226eccbd2f4e84b35734 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/3686d57edf1023fb.js @@ -0,0 +1,301 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,54214,e=>{"use strict";function t(e,t,i){if(t.length%2!=0)throw Error(`positions length must be even (got ${t.length})`);let r=t.length/2,o=i??new Uint16Array(r);if(o.length!==r)throw Error(`labels length must equal number of points (${r}), got ${o.length}`);return{n:r,positions:t,labels:o,geometry:e}}function i(e){let t=new Float32Array(2*e.length);for(let i=0;i65535)throw Error(`label index out of range at ${i}: ${r}`);t[i]=r}return t}e.s(["createDataset",()=>t,"packPositions",()=>i,"packPositionsXY",()=>r,"packUint16Labels",()=>o],15454),e.i(15454);let s=["#4e79a7","#f28e2c","#e15759","#76b7b2","#59a14f","#edc949","#af7aa1","#ff9da7","#9c755f","#bab0ab"],a="#ff0000",n="#ffffff";function l(e,t){return{kind:"indices",indices:e,computeTimeMs:t,has:t=>e.has(t)}}function h(e,t,i,r){return{kind:"geometry",geometry:e,computeTimeMs:i,has:i=>r(t[2*i],t[2*i+1],e.coords)}}function u(e,t,i,r,o){let s=.4*Math.min(r,o)*i.zoom;return{x:r/2+(e-i.centerX)*s,y:o/2-(t-i.centerY)*s}}function d(e,t,i,r,o){let s=.4*Math.min(r,o)*i.zoom;return{x:i.centerX+(e-r/2)/s,y:i.centerY-(t-o/2)/s}}function f(){return{type:"poincare",ax:0,ay:0,displayZoom:1}}function c(e,t,i,r){let o=e-i,s=t-r,a=1-(i*e+r*t),n=-(i*t-r*e),l=a*a+n*n;if(l<1e-12){let e=Math.sqrt(o*o+s*s);return e<1e-12?{x:0,y:0}:{x:o/e*.999,y:s/e*.999}}let h=(o*a+s*n)/l,u=(s*a-o*n)/l,d=h*h+u*u;if(d>=1){let e=Math.sqrt(d);return{x:h/e*.999,y:u/e*.999}}return{x:h,y:u}}function p(e,t,i,r){let o=e+i,s=t+r,a=1+(i*e+r*t),n=i*t-r*e,l=a*a+n*n;if(l<1e-12){let e=Math.sqrt(o*o+s*s);return e<1e-12?{x:0,y:0}:{x:o/e*.999,y:s/e*.999}}let h=(o*a+s*n)/l,u=(s*a-o*n)/l,d=h*h+u*u;if(d>=1){let e=Math.sqrt(d);return{x:h/e*.999,y:u/e*.999}}return{x:h,y:u}}function m(e,t,i,r,o){let s=.45*Math.min(r,o)*i.displayZoom,a=(e-r/2)/s,n=-(t-o/2)/s,l=a*a+n*n;if(l>=1){let e=Math.sqrt(l);return p(a/e*.999,n/e*.999,i.ax,i.ay)}return p(a,n,i.ax,i.ay)}function x(e,t,i,r,o,s,a){let n=.45*Math.min(s,a)*e.displayZoom,l=(e,t,i=.95)=>{let r=e*e+t*t;if(r>i*i){let o=Math.sqrt(r);return{x:e/o*i,y:t/o*i}}return{x:e,y:t}},h=l((t-s/2)/n,-(i-a/2)/n),u=l((r-s/2)/n,-(o-a/2)/n),d=p(h.x,h.y,e.ax,e.ay),f=function(e,t,i,r){let o=i*e-r*t,s=i*t+r*e,a=o*o+s*s-1;if(1e-10>Math.abs(a))return{x:-i,y:-r};let n=e-i,l=r-t,h=(-(1+o)*n+s*l)/a,u=((1-o)*l-s*n)/a,d=h*h+u*u;if(d>=1){let e=Math.sqrt(d);return{x:h/e*.99,y:u/e*.99}}return{x:h,y:u}}(d.x,d.y,u.x,u.y);return{...e,ax:f.x,ay:f.y}}function g(e,t,i){let r=i.length/2;if(r<3)return!1;let o=!1;for(let s=0,a=r-1;sl||tu)return!1;let d=o-i,f=s-r,c=d*d+f*f;if(c<1e-9*1e-9)return 1e-9>=Math.sqrt((e-i)*(e-i)+(t-r)*(t-r));let p=Math.max(0,Math.min(1,((e-i)*d+(t-r)*f)/c)),m=i+p*d,x=r+p*f;return 1e-9>=Math.sqrt((e-m)*(e-m)+(t-x)*(t-x))}(e,t,r,n,l,h,1e-9))return!0;n>t!=h>t&&e<(l-r)*(t-n)/(h-n)+r&&(o=!o)}return o}function b(e){let t=1/0,i=1/0,r=-1/0,o=-1/0;for(let s=0;sr&&(r=a),no&&(o=n)}return Number.isFinite(t)&&Number.isFinite(i)&&Number.isFinite(r)&&Number.isFinite(o)?{xMin:t,yMin:i,xMax:r,yMax:o}:{xMin:0,yMin:0,xMax:0,yMax:0}}function E(e,t,i){return ei?i:0|e}class R{n;bounds;cellsX;cellsY;cellSizeX;cellSizeY;offsets;ids;constructor(e,t,i=64){this.n=e.length/2|0,this.bounds=t??function(e){let t=1/0,i=1/0,r=-1/0,o=-1/0;for(let s=0;sr&&(r=a),no&&(o=n)}return Number.isFinite(t)&&Number.isFinite(i)?(1e-9>Math.abs(r-t)&&(r=t+1),1e-9>Math.abs(o-i)&&(o=i+1),{minX:t,minY:i,maxX:r,maxY:o}):{minX:0,minY:0,maxX:0,maxY:0}}(e);const r=this.bounds.maxX-this.bounds.minX,o=this.bounds.maxY-this.bounds.minY,s=Math.max(64,Math.min(1e6,Math.ceil(this.n/Math.max(1,i))));let a=Math.round(Math.sqrt(r/o*s)),n=Math.round(s/(a=E(a,8,2048)));n=E(n,8,2048),this.cellsX=a,this.cellsY=n,this.cellSizeX=r/a,this.cellSizeY=o/n;const l=a*n,h=new Uint32Array(l);for(let t=0;tr.push(e))}}function T(e){let t=e.trim();if(!t.startsWith("#"))return[1,1,1,1];let i=t.slice(1);return 3===i.length?[parseInt(i[0]+i[0],16)/255,parseInt(i[1]+i[1],16)/255,parseInt(i[2]+i[2],16)/255,1]:6===i.length||8===i.length?[parseInt(i.slice(0,2),16)/255,parseInt(i.slice(2,4),16)/255,parseInt(i.slice(4,6),16)/255,8===i.length?parseInt(i.slice(6,8),16)/255:1]:[1,1,1,1]}function y(e,t,i){let r=e.createShader(t);if(!r)throw Error("Failed to create shader");if(e.shaderSource(r,i),e.compileShader(r),!e.getShaderParameter(r,e.COMPILE_STATUS)){let t=e.getShaderInfoLog(r)??"unknown";throw e.deleteShader(r),Error(`Shader compile failed: ${t}`)}return r}function _(e,t,i){let r=y(e,e.VERTEX_SHADER,t),o=y(e,e.FRAGMENT_SHADER,i),s=e.createProgram();if(!s)throw Error("Failed to create program");if(e.attachShader(s,r),e.attachShader(s,o),e.linkProgram(s),e.deleteShader(r),e.deleteShader(o),!e.getProgramParameter(s,e.LINK_STATUS)){let t=e.getProgramInfoLog(s)??"unknown";throw e.deleteProgram(s),Error(`Program link failed: ${t}`)}return s}function v(e,t,i,r){e.width=Math.max(1,Math.floor(t*r)),e.height=Math.max(1,Math.floor(i*r)),e.style.width=`${t}px`,e.style.height=`${i}px`}let A=`#version 300 es +precision highp float; +precision highp int; + +flat in uint v_label; + +// Present in the vertex stage too; redeclare here so we can compute AA width. +uniform float u_dpr; +uniform float u_pointRadiusCss; + +uniform sampler2D u_paletteTex; +uniform int u_paletteSize; +uniform int u_paletteWidth; + +out vec4 outColor; + +void main() { + vec2 p = gl_PointCoord * 2.0 - 1.0; + // Anti-aliased circle: avoid harsh discard edges that can look like + // "weird polygons" at small sizes or without MSAA. + float r = length(p); + // Ensure at least ~1px transition (in point-local coordinates) so small + // points remain visually circular. + float radiusPx = max(u_pointRadiusCss * u_dpr, 1.0); + // Slightly wider than 1px helps circles stay round-looking when zoomed out + // (where points are perceptually tiny and aliasing is more obvious). + float aa = max(fwidth(r), 1.5 / radiusPx); + float alpha = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r); + if (alpha <= 0.0) discard; + + int size = max(u_paletteSize, 1); + int w = max(u_paletteWidth, 1); + int idx = int(v_label) % size; + int x = idx % w; + int y = idx / w; + vec4 c = texelFetch(u_paletteTex, ivec2(x, y), 0); + outColor = vec4(c.rgb, c.a * alpha); +} +`,S=`#version 300 es +precision highp float; +precision highp int; + +flat in uint v_label; + +uniform sampler2D u_paletteTex; +uniform int u_paletteSize; +uniform int u_paletteWidth; + +out vec4 outColor; + +void main() { + int size = max(u_paletteSize, 1); + int w = max(u_paletteWidth, 1); + int idx = int(v_label) % size; + int x = idx % w; + int y = idx / w; + outColor = texelFetch(u_paletteTex, ivec2(x, y), 0); +} +`,P=`#version 300 es +precision highp float; +precision highp int; + +uniform float u_dpr; +uniform float u_pointRadiusCss; + +uniform vec4 u_color; +uniform float u_pointSizePx; +uniform float u_ringThicknessPx; +uniform int u_ringMode; // 0 = solid, 1 = ring + +out vec4 outColor; + +void main() { + vec2 p = gl_PointCoord * 2.0 - 1.0; + float r = length(p); + float radiusPx = max(u_pointRadiusCss * u_dpr, 1.0); + float aa = max(fwidth(r), 1.5 / radiusPx); + float outer = 1.0 - smoothstep(1.0 - aa, 1.0 + aa, r); + if (outer <= 0.0) discard; + + float alpha = outer; + + if (u_ringMode == 1) { + float radiusPx = u_pointSizePx * 0.5; + float t = clamp(u_ringThicknessPx / max(radiusPx, 1e-6), 0.0, 1.0); + float inner = 1.0 - t; + // Keep only the outer ring with an anti-aliased inner boundary. + float innerMask = smoothstep(inner - aa, inner + aa, r); + alpha *= innerMask; + if (alpha <= 0.0) discard; + } + + outColor = vec4(u_color.rgb, u_color.a * alpha); +} +`,M=`#version 300 es +precision highp float; + +out vec2 v_uv; + +void main() { + // Fullscreen triangle + // (-1,-1), (3,-1), (-1,3) + if (gl_VertexID == 0) { + gl_Position = vec4(-1.0, -1.0, 0.0, 1.0); + v_uv = vec2(0.0, 0.0); + } else if (gl_VertexID == 1) { + gl_Position = vec4(3.0, -1.0, 0.0, 1.0); + v_uv = vec2(2.0, 0.0); + } else { + gl_Position = vec4(-1.0, 3.0, 0.0, 1.0); + v_uv = vec2(0.0, 2.0); + } +} +`,F=`#version 300 es +precision highp float; + +in vec2 v_uv; + +uniform sampler2D u_tex; + +out vec4 outColor; + +void main() { + vec2 uv = clamp(v_uv, 0.0, 1.0); + outColor = texture(u_tex, uv); +} +`,B=`#version 300 es +precision highp float; +precision highp int; + +uniform vec2 u_cssSize; +uniform float u_dpr; +uniform float u_displayZoom; + +uniform vec4 u_diskFillColor; +uniform vec4 u_diskBorderColor; +uniform vec4 u_gridColor; +uniform float u_diskBorderWidthPx; +uniform float u_gridWidthPx; + +out vec4 outColor; + +void main() { + // Convert framebuffer pixels to CSS pixels + vec2 fragCss = gl_FragCoord.xy / max(u_dpr, 1.0); + vec2 center = u_cssSize * 0.5; + + float diskRadius = min(u_cssSize.x, u_cssSize.y) * 0.45 * u_displayZoom; + vec2 p = fragCss - center; + float dist = length(p); + + // Reference-like styling + vec3 diskFill = u_diskFillColor.rgb; + vec3 diskBorder = u_diskBorderColor.rgb; + + float borderWidth = max(u_diskBorderWidthPx, 0.0); + float halfW = 0.5 * borderWidth; + + // Anti-aliasing width (CSS px). Keep at least 1px for crisp edges. + float aa = max(1.0, fwidth(dist)); + + // Discard outside disk+border region so the clear color remains intact. + if (dist > diskRadius + halfW + aa) discard; + + // Outer fade for anti-aliased boundary + float outerAlpha = 1.0 - smoothstep(diskRadius + halfW - aa, diskRadius + halfW + aa, dist); + + // Border mask + float borderInner = smoothstep(diskRadius - halfW - aa, diskRadius - halfW + aa, dist); + float borderOuter = 1.0 - smoothstep(diskRadius + halfW - aa, diskRadius + halfW + aa, dist); + float borderMask = clamp(borderInner * borderOuter, 0.0, 1.0); + + vec3 col = mix(diskFill, diskBorder, borderMask); + + // ------------------------------------------------------------------------ + // Reference-like hyperbolic grid overlay + // ------------------------------------------------------------------------ + // Matches HyperbolicReference.drawHyperbolicGrid(): + // - 8 radial lines (geodesics through origin) + // - 5 concentric circles + vec3 gridCol = u_gridColor.rgb; + float gridWidth = max(u_gridWidthPx, 0.0); + float halfGrid = 0.5 * gridWidth; + + // AA width for thin lines in CSS pixel space. + float aaLine = max(1.0, fwidth(dist)); + + float gridMask = 0.0; + + // Concentric circles (5) + for (int i = 1; i <= 5; i++) { + float r = (float(i) / 6.0) * diskRadius; + float d = abs(dist - r); + float m = 1.0 - smoothstep(halfGrid - aaLine, halfGrid + aaLine, d); + gridMask = max(gridMask, m); + } + + // Radial lines (8), angle = (i/8)*pi + // Distance to line through origin with direction (cos a, sin a): |cross(p, dir)| + for (int i = 0; i < 8; i++) { + float a = (float(i) / 8.0) * 3.141592653589793; + vec2 dir = vec2(cos(a), sin(a)); + float d = abs(p.x * dir.y - p.y * dir.x); + float m = 1.0 - smoothstep(halfGrid - aaLine, halfGrid + aaLine, d); + gridMask = max(gridMask, m); + } + + // Apply grid on top of disk fill/border. Use u_gridColor alpha as intensity. + col = mix(col, gridCol, clamp(gridMask, 0.0, 1.0) * clamp(u_gridColor.a, 0.0, 1.0)); + outColor = vec4(col, outerAlpha); +} +`,D=`#version 300 es +precision highp float; +precision highp int; + +layout(location = 0) in vec2 a_pos; +layout(location = 1) in uint a_label; + +uniform vec2 u_center; +uniform vec2 u_cssSize; +uniform float u_zoom; +uniform float u_dpr; +uniform float u_pointRadiusCss; + +flat out uint v_label; + +void main() { + float baseScale = min(u_cssSize.x, u_cssSize.y) * 0.4 * u_zoom; + float sx = u_cssSize.x * 0.5 + (a_pos.x - u_center.x) * baseScale; + float sy = u_cssSize.y * 0.5 - (a_pos.y - u_center.y) * baseScale; + + vec2 dbufSize = u_cssSize * u_dpr; + vec2 dbuf = vec2(sx, sy) * u_dpr; + + float cx = (dbuf.x / dbufSize.x) * 2.0 - 1.0; + float cy = 1.0 - (dbuf.y / dbufSize.y) * 2.0; + + gl_Position = vec4(cx, cy, 0.0, 1.0); + gl_PointSize = (u_pointRadiusCss * 2.0) * u_dpr; + v_label = a_label; +} +`,C=`#version 300 es +precision highp float; +precision highp int; + +layout(location = 0) in vec2 a_pos; +layout(location = 1) in uint a_label; + +uniform vec2 u_cssSize; +uniform float u_dpr; +uniform float u_pointRadiusCss; + +uniform vec2 u_a; // camera translation (ax, ay) +uniform float u_displayZoom; // visual zoom + +flat out uint v_label; + +vec2 mobiusTransform(vec2 z, vec2 a) { + // (z - a) / (1 - conj(a) * z) + vec2 num = z - a; + + // denom = 1 - (ax*zx + ay*zy) + i * (-(ax*zy - ay*zx)) + float denomX = 1.0 - (a.x * z.x + a.y * z.y); + float denomY = -(a.x * z.y - a.y * z.x); + float denomNormSq = denomX * denomX + denomY * denomY; + if (denomNormSq < 1e-12) { + // Push outside clip + return vec2(2.0, 2.0); + } + + // complex division + float rx = (num.x * denomX + num.y * denomY) / denomNormSq; + float ry = (num.y * denomX - num.x * denomY) / denomNormSq; + return vec2(rx, ry); +} + +void main() { + vec2 w = mobiusTransform(a_pos, u_a); + float r2 = dot(w, w); + if (r2 >= 1.0) { + gl_Position = vec4(2.0, 2.0, 0.0, 1.0); + gl_PointSize = 0.0; + v_label = a_label; + return; + } + + float diskRadius = min(u_cssSize.x, u_cssSize.y) * 0.45 * u_displayZoom; + float sx = u_cssSize.x * 0.5 + w.x * diskRadius; + float sy = u_cssSize.y * 0.5 - w.y * diskRadius; + + vec2 dbufSize = u_cssSize * u_dpr; + vec2 dbuf = vec2(sx, sy) * u_dpr; + + float cx = (dbuf.x / dbufSize.x) * 2.0 - 1.0; + float cy = 1.0 - (dbuf.y / dbufSize.y) * 2.0; + + gl_Position = vec4(cx, cy, 0.0, 1.0); + gl_PointSize = (u_pointRadiusCss * 2.0) * u_dpr; + v_label = a_label; +} +`;class U{canvas=null;width=0;height=0;deviceDpr=1;canvasDpr=1;dpr=1;dataset=null;selection=new Set;hoveredIndex=-1;pointRadiusCss=3;colors=s;backgroundColor="#0a0a0a";poincareDiskFillColor="#141414";poincareDiskBorderColor="#666666";poincareGridColor="#66666633";poincareDiskBorderWidthPx=2;poincareGridWidthPx=.5;paletteSize=0;paletteDirty=!0;paletteTex=null;paletteTexW=0;paletteTexH=0;paletteBytes=new Uint8Array(0);paletteTexUnit=1;scratchIds=[];hoverPosScratch=new Float32Array(2);hoverLabScratch=new Uint16Array(1);hoverIndexScratch=new Uint32Array(1);lastViewChangeTs=0;markViewChanged(){this.lastViewChangeTs=performance.now()}endInteraction(){this.lastViewChangeTs=0}markBackdropDirty(){this.backdropDirty=!0}uploadPoincareDiskStyleUniforms(){let e=this.gl,t=this.poincareDisk;if(!e||!t)return;let i=T(this.poincareDiskFillColor),r=T(this.poincareDiskBorderColor),o=T(this.poincareGridColor);t.uDiskFillColor&&e.uniform4f(t.uDiskFillColor,i[0],i[1],i[2],i[3]),t.uDiskBorderColor&&e.uniform4f(t.uDiskBorderColor,r[0],r[1],r[2],r[3]),t.uGridColor&&e.uniform4f(t.uGridColor,o[0],o[1],o[2],o[3]),t.uDiskBorderWidthPx&&e.uniform1f(t.uDiskBorderWidthPx,this.poincareDiskBorderWidthPx),t.uGridWidthPx&&e.uniform1f(t.uGridWidthPx,this.poincareGridWidthPx)}getBackdropZoom(){return 1}dataIndex=null;gl=null;vao=null;posBuffer=null;labelBuffer=null;hoverVao=null;hoverPosBuffer=null;hoverLabelBuffer=null;selectionVao=null;selectionPosBuffer=null;selectionLabelBuffer=null;selectionOverlayCount=0;selectionEbo=null;hoverEbo=null;interactionEbo=null;interactionCount=0;maxBaseDrawPoints=4e6;maxGpuUploadPoints=1e7;gpuUsesFullDataset=!0;gpuPointCount=0;policy={fragmentBudget:1e8,circleBudget:6e7,squareOnRatio:1,squareOffRatio:.75,minPointsDpr:.35};renderAsSquares=!1;__debugPolicy=null;backdropTex=null;backdropFbo=null;backdropW=0;backdropH=0;backdropDpr=1;backdropZoom=NaN;backdropDirty=!0;pointsTex=null;pointsFbo=null;pointsW=0;pointsH=0;programComposite=null;uCompositeTex=null;poincareDisk=null;pointsCircle=null;pointsSquare=null;programSolid=null;uSolidColor=null;uSolidPointSizePx=null;uSolidRingThicknessPx=null;uSolidRingMode=null;uCssSizeSolid=null;uDprSolid=null;uPointRadiusSolid=null;selectionDirty=!0;hoverDirty=!0;init(e,t){this.canvas=e,this.width=t.width,this.height=t.height,this.deviceDpr=t.devicePixelRatio??window.devicePixelRatio??1,this.canvasDpr=this.deviceDpr,this.dpr=this.deviceDpr;let i="string"==typeof t.poincareDiskFillColor;t.backgroundColor&&(this.backgroundColor=t.backgroundColor),t.pointRadius&&(this.pointRadiusCss=t.pointRadius),t.colors&&(this.colors=t.colors),this.poincareDiskFillColor=i?t.poincareDiskFillColor:this.poincareDiskFillColor,t.poincareDiskBorderColor&&(this.poincareDiskBorderColor=t.poincareDiskBorderColor),t.poincareGridColor&&(this.poincareGridColor=t.poincareGridColor),"number"==typeof t.poincareDiskBorderWidthPx&&Number.isFinite(t.poincareDiskBorderWidthPx)&&(this.poincareDiskBorderWidthPx=Math.max(0,t.poincareDiskBorderWidthPx)),"number"==typeof t.poincareGridWidthPx&&Number.isFinite(t.poincareGridWidthPx)&&(this.poincareGridWidthPx=Math.max(0,t.poincareGridWidthPx)),this.paletteDirty=!0}chooseRenderDpr(e){let t=this.deviceDpr,i=Math.max(1,this.width)*Math.max(1,this.height),r=e>this.maxBaseDrawPoints?this.estimateSubsampleCount(e):e,o=Math.sqrt((e>=1e6?i>1e6?2e5:5e5:e>=5e5?14e5:e>=25e4?21e5:8e6)/i),s=Math.max(.5,this.pointRadiusCss),a=Math.max(1,r)*Math.PI*s*s,n=Math.sqrt(this.policy.fragmentBudget/a),l=e>=1e6?1:e>=5e5?1.25:1.5;return Math.max(e>=1e6?this.policy.minPointsDpr:e>=5e5?.75:1,Math.min(t,l,o,n))}estimateSubsampleCount(e){if(e<5e5)return e;let t=Math.min(e,Math.max(25e4,Math.min(this.maxBaseDrawPoints,Math.floor(.25*e)))),i=Math.max(1,Math.floor(e/t));return Math.min(t,Math.ceil(e/i))}estimatePointFragments(e,t){let i=Math.max(.5,this.pointRadiusCss),r=Math.max(0,t);return Math.max(0,e)*Math.PI*i*i*r*r}updateSquarePointPolicy(e){let t=this.policy.circleBudget*this.policy.squareOnRatio,i=this.policy.circleBudget*this.policy.squareOffRatio;if(this.dpr<=.75){this.renderAsSquares=!0;return}this.renderAsSquares?e<=i&&(this.renderAsSquares=!1):e>=t&&(this.renderAsSquares=!0)}setDataset(e){this.dataset=e,this.selection=new Set,this.hoveredIndex=-1,this.selectionDirty=!0,this.hoverDirty=!0;let t=this.chooseRenderDpr(e.n);t!==this.dpr&&(this.dpr=t),this.dataIndex=new R(e.positions,void 0,64),this.gl&&this.uploadDatasetToGPU(),this.markBackdropDirty()}resize(e,t){this.width=e,this.height=t,this.gl&&this.canvas&&(v(this.canvas,e,t,this.canvasDpr),this.gl.viewport(0,0,this.canvas.width,this.canvas.height),this.markBackdropDirty())}setSelection(e){let t=e.size;this.selection=t<=2e5?new Set(e):e,this.selectionDirty=!0,this.gl&&this.uploadSelectionToGPU()}getSelection(){return this.selection.size<=2e5?new Set(this.selection):this.selection}setHovered(e){this.hoveredIndex=e,this.hoverDirty=!0,this.gl&&this.uploadHoverToGPU()}destroy(){let e=this.gl;e&&(this.pointsCircle&&e.deleteProgram(this.pointsCircle.program),this.pointsSquare&&e.deleteProgram(this.pointsSquare.program),this.programSolid&&e.deleteProgram(this.programSolid),this.poincareDisk&&e.deleteProgram(this.poincareDisk.program),this.vao&&e.deleteVertexArray(this.vao),this.hoverVao&&e.deleteVertexArray(this.hoverVao),this.selectionVao&&e.deleteVertexArray(this.selectionVao),this.posBuffer&&e.deleteBuffer(this.posBuffer),this.labelBuffer&&e.deleteBuffer(this.labelBuffer),this.hoverPosBuffer&&e.deleteBuffer(this.hoverPosBuffer),this.hoverLabelBuffer&&e.deleteBuffer(this.hoverLabelBuffer),this.selectionPosBuffer&&e.deleteBuffer(this.selectionPosBuffer),this.selectionLabelBuffer&&e.deleteBuffer(this.selectionLabelBuffer),this.selectionEbo&&e.deleteBuffer(this.selectionEbo),this.hoverEbo&&e.deleteBuffer(this.hoverEbo),this.interactionEbo&&e.deleteBuffer(this.interactionEbo),this.backdropFbo&&e.deleteFramebuffer(this.backdropFbo),this.backdropTex&&e.deleteTexture(this.backdropTex),this.pointsFbo&&e.deleteFramebuffer(this.pointsFbo),this.pointsTex&&e.deleteTexture(this.pointsTex),this.paletteTex&&e.deleteTexture(this.paletteTex),this.programComposite&&e.deleteProgram(this.programComposite)),this.gl=null,this.vao=null,this.hoverVao=null,this.selectionVao=null,this.posBuffer=null,this.labelBuffer=null,this.hoverPosBuffer=null,this.hoverLabelBuffer=null,this.selectionPosBuffer=null,this.selectionLabelBuffer=null,this.selectionOverlayCount=0,this.selectionEbo=null,this.hoverEbo=null,this.interactionEbo=null,this.interactionCount=0,this.gpuUsesFullDataset=!0,this.gpuPointCount=0,this.backdropFbo=null,this.backdropTex=null,this.backdropW=0,this.backdropH=0,this.backdropDpr=1,this.backdropZoom=NaN,this.backdropDirty=!0,this.pointsFbo=null,this.pointsTex=null,this.pointsW=0,this.pointsH=0,this.programComposite=null,this.uCompositeTex=null,this.pointsCircle=null,this.pointsSquare=null,this.programSolid=null,this.poincareDisk=null,this.paletteTex=null,this.paletteTexW=0,this.paletteTexH=0,this.paletteSize=0,this.paletteDirty=!0}uploadPaletteUniforms(){let e=this.gl;if(!e)return;let t=this.colors.length,i=Math.max(1,Math.min(t,65536)),r=e.getParameter(e.MAX_TEXTURE_SIZE),o=Math.min(r,i),s=Math.ceil(i/o);if(s>r)throw Error(`Palette too large for WebGL texture: size=${i}, maxTex=${r}`);let a=o*s;if(this.paletteBytes.length!==4*a?this.paletteBytes=new Uint8Array(4*a):this.paletteBytes.fill(0),0===t)this.paletteBytes[0]=255,this.paletteBytes[1]=255,this.paletteBytes[2]=255,this.paletteBytes[3]=255;else for(let e=0;e{t&&(e.useProgram(t.program),t.uPaletteTex&&e.uniform1i(t.uPaletteTex,this.paletteTexUnit),t.uPaletteSize&&e.uniform1i(t.uPaletteSize,this.paletteSize),t.uPaletteWidth&&e.uniform1i(t.uPaletteWidth,this.paletteTexW))};n(this.pointsCircle),n(this.pointsSquare),this.paletteDirty=!1}bindPaletteTexture(){let e=this.gl;e&&this.paletteTex&&(e.activeTexture(e.TEXTURE0+this.paletteTexUnit),e.bindTexture(e.TEXTURE_2D,this.paletteTex),e.activeTexture(e.TEXTURE0))}async countSelection(e,t={}){let i=this.dataset,r=this.dataIndex;if(!i||!r)return 0;if(e.indices)return e.indices.size;if("geometry"!==e.kind||!e.geometry)return 0;let o=e.geometry.coords;if(o.length/2<3)return 0;let s=e.geometry.bounds;if(!s){let e=1/0,t=1/0,i=-1/0,r=-1/0;for(let s=0;si&&(i=a),nr&&(r=n)}s={xMin:e,yMin:t,xMax:i,yMax:r}}let a=t.shouldCancel,n=t.onProgress,l="number"==typeof t.yieldEveryMs&&Number.isFinite(t.yieldEveryMs)?Math.max(0,t.yieldEveryMs):8,h=s.xMin-1e-12,u=s.yMin-1e-12,d=s.xMax+1e-12,f=s.yMax+1e-12,c=(e,t,i)=>ei?i:0|e,p=c(Math.floor((h-r.bounds.minX)/r.cellSizeX),0,r.cellsX-1),m=c(Math.floor((u-r.bounds.minY)/r.cellSizeY),0,r.cellsY-1),x=c(Math.floor((d-r.bounds.minX)/r.cellSizeX),0,r.cellsX-1),b=c(Math.floor((f-r.bounds.minY)/r.cellSizeY),0,r.cellsY-1),E=i.positions,R=r.ids,T=r.offsets,y=0,_=0,v=16384,A=l>0?performance.now():0;for(let e=m;e<=b;e++){let t=e*r.cellsX;for(let e=p;e<=x;e++){let i=t+e,r=T[i],h=T[i+1];for(let e=r;es.xMax)&&!(rs.yMax)&&(g(i,r,o)&&y++,_++,l>0&&_>=v)){if(v=_+16384,a?.())return y;performance.now()-A>=l&&(n?.(y,_),await new Promise(e=>requestAnimationFrame(()=>e())),A=performance.now())}}}}return n?.(y,_),y}ensureGL(){if(this.gl)return;if(!this.canvas)throw Error("Renderer not initialized");v(this.canvas,this.width,this.height,this.canvasDpr);let e=this.canvas.getContext("webgl2",{antialias:!1,alpha:!1,depth:!1,stencil:!1,preserveDrawingBuffer:!1,premultipliedAlpha:!1,desynchronized:!0});if(!e)throw Error("Failed to get WebGL2 context (is the canvas already using 2D context?)");this.gl=e,e.disable(e.DEPTH_TEST),e.disable(e.CULL_FACE),e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA);let[t,i,r,o]=T(this.backgroundColor);e.clearColor(t,i,r,o),e.viewport(0,0,this.canvas.width,this.canvas.height),this.createProgramsAndBuffers(),this.uploadPaletteUniforms(),this.dataset&&this.uploadDatasetToGPU(),this.uploadSelectionToGPU(),this.uploadHoverToGPU(),this.markBackdropDirty()}ensurePointsResources(){if(!this.gl||!this.canvas)return;let e=this.gl,t=Math.max(1,Math.floor(this.width*this.dpr)),i=Math.max(1,Math.floor(this.height*this.dpr)),r=e.getParameter(e.MAX_TEXTURE_SIZE);if(t>r||i>r){let e=Math.min(1,r/t,r/i);t=Math.max(1,Math.floor(t*e)),i=Math.max(1,Math.floor(i*e))}if(!this.pointsTex){if(this.pointsTex=e.createTexture(),!this.pointsTex)throw Error("Failed to create points texture");e.bindTexture(e.TEXTURE_2D,this.pointsTex),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.LINEAR),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}if(!this.pointsFbo&&(this.pointsFbo=e.createFramebuffer(),!this.pointsFbo))throw Error("Failed to create points framebuffer");if(t!==this.pointsW||i!==this.pointsH){this.pointsW=t,this.pointsH=i,e.bindTexture(e.TEXTURE_2D,this.pointsTex),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,t,i,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindTexture(e.TEXTURE_2D,null),e.bindFramebuffer(e.FRAMEBUFFER,this.pointsFbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.pointsTex,0);let r=e.checkFramebufferStatus(e.FRAMEBUFFER);if(e.bindFramebuffer(e.FRAMEBUFFER,null),r!==e.FRAMEBUFFER_COMPLETE)throw Error(`Points framebuffer incomplete: ${r}`)}}ensureBackdropResources(){if(!this.gl||!this.canvas||"poincare"!==this.geometryKind()||!this.poincareDisk||!this.vao)return;let e=this.gl,t=Math.max(1,this.canvasDpr),i=Math.max(1,Math.floor(this.width*t)),r=Math.max(1,Math.floor(this.height*t)),o=e.getParameter(e.MAX_TEXTURE_SIZE);if(i>o||r>o){let e=Math.min(1,o/i,o/r);i=Math.max(1,Math.floor(i*e)),r=Math.max(1,Math.floor(r*e)),this.backdropDpr=t*e}else this.backdropDpr=t;if(!this.backdropTex){if(this.backdropTex=e.createTexture(),!this.backdropTex)throw Error("Failed to create backdrop texture");e.bindTexture(e.TEXTURE_2D,this.backdropTex),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MIN_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_MAG_FILTER,e.NEAREST),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_S,e.CLAMP_TO_EDGE),e.texParameteri(e.TEXTURE_2D,e.TEXTURE_WRAP_T,e.CLAMP_TO_EDGE),e.bindTexture(e.TEXTURE_2D,null)}if(!this.backdropFbo&&(this.backdropFbo=e.createFramebuffer(),!this.backdropFbo))throw Error("Failed to create backdrop framebuffer");if(i!==this.backdropW||r!==this.backdropH){this.backdropW=i,this.backdropH=r,e.bindTexture(e.TEXTURE_2D,this.backdropTex),e.texImage2D(e.TEXTURE_2D,0,e.RGBA,i,r,0,e.RGBA,e.UNSIGNED_BYTE,null),e.bindTexture(e.TEXTURE_2D,null),e.bindFramebuffer(e.FRAMEBUFFER,this.backdropFbo),e.framebufferTexture2D(e.FRAMEBUFFER,e.COLOR_ATTACHMENT0,e.TEXTURE_2D,this.backdropTex,0);let t=e.checkFramebufferStatus(e.FRAMEBUFFER);if(e.bindFramebuffer(e.FRAMEBUFFER,null),t!==e.FRAMEBUFFER_COMPLETE)throw Error(`Backdrop framebuffer incomplete: ${t}`);this.markBackdropDirty()}}renderBackdropIfNeeded(){if(!this.gl||!this.canvas||"poincare"!==this.geometryKind()||!this.poincareDisk||!this.vao||(this.ensureBackdropResources(),!this.backdropFbo))return;let e=this.getBackdropZoom(),t=Number.isFinite(this.backdropZoom)&&1e-12>=Math.abs(this.backdropZoom-e);if(!this.backdropDirty&&t)return;let i=this.gl;i.bindFramebuffer(i.FRAMEBUFFER,this.backdropFbo),i.viewport(0,0,this.backdropW,this.backdropH);let[r,o,s,a]=T(this.backgroundColor);i.clearColor(r,o,s,a),i.clear(i.COLOR_BUFFER_BIT),i.useProgram(this.poincareDisk.program),this.bindViewUniformsForProgram(this.poincareDisk.program),this.uploadPoincareDiskStyleUniforms(),this.poincareDisk.uCssSize&&i.uniform2f(this.poincareDisk.uCssSize,this.width,this.height),this.poincareDisk.uDpr&&i.uniform1f(this.poincareDisk.uDpr,this.backdropDpr),i.bindVertexArray(this.vao),i.drawArrays(i.TRIANGLES,0,3),i.bindFramebuffer(i.FRAMEBUFFER,null),i.viewport(0,0,this.canvas.width,this.canvas.height),this.backdropZoom=e,this.backdropDirty=!1}createProgramsAndBuffers(){let e=this.gl,t="euclidean"===this.geometryKind()?D:C,i=_(e,t,A),r=_(e,t,S);if(this.programSolid=_(e,t,P),this.programComposite=_(e,M,F),e.useProgram(this.programComposite),this.uCompositeTex=e.getUniformLocation(this.programComposite,"u_tex"),"poincare"===this.geometryKind()){let t=_(e,M,B);this.poincareDisk={program:t,uCssSize:e.getUniformLocation(t,"u_cssSize"),uDpr:e.getUniformLocation(t,"u_dpr"),uDiskFillColor:e.getUniformLocation(t,"u_diskFillColor"),uDiskBorderColor:e.getUniformLocation(t,"u_diskBorderColor"),uGridColor:e.getUniformLocation(t,"u_gridColor"),uDiskBorderWidthPx:e.getUniformLocation(t,"u_diskBorderWidthPx"),uGridWidthPx:e.getUniformLocation(t,"u_gridWidthPx")},e.useProgram(t),this.uploadPoincareDiskStyleUniforms()}if(e.useProgram(i),this.pointsCircle={program:i,uPaletteTex:e.getUniformLocation(i,"u_paletteTex"),uPaletteSize:e.getUniformLocation(i,"u_paletteSize"),uPaletteWidth:e.getUniformLocation(i,"u_paletteWidth"),uCssSize:e.getUniformLocation(i,"u_cssSize"),uDpr:e.getUniformLocation(i,"u_dpr"),uPointRadius:e.getUniformLocation(i,"u_pointRadiusCss")},e.useProgram(r),this.pointsSquare={program:r,uPaletteTex:e.getUniformLocation(r,"u_paletteTex"),uPaletteSize:e.getUniformLocation(r,"u_paletteSize"),uPaletteWidth:e.getUniformLocation(r,"u_paletteWidth"),uCssSize:e.getUniformLocation(r,"u_cssSize"),uDpr:e.getUniformLocation(r,"u_dpr"),uPointRadius:e.getUniformLocation(r,"u_pointRadiusCss")},e.useProgram(this.programSolid),this.uSolidColor=e.getUniformLocation(this.programSolid,"u_color"),this.uSolidPointSizePx=e.getUniformLocation(this.programSolid,"u_pointSizePx"),this.uSolidRingThicknessPx=e.getUniformLocation(this.programSolid,"u_ringThicknessPx"),this.uSolidRingMode=e.getUniformLocation(this.programSolid,"u_ringMode"),this.uCssSizeSolid=e.getUniformLocation(this.programSolid,"u_cssSize"),this.uDprSolid=e.getUniformLocation(this.programSolid,"u_dpr"),this.uPointRadiusSolid=e.getUniformLocation(this.programSolid,"u_pointRadiusCss"),this.vao=e.createVertexArray(),this.posBuffer=e.createBuffer(),this.labelBuffer=e.createBuffer(),this.hoverVao=e.createVertexArray(),this.hoverPosBuffer=e.createBuffer(),this.hoverLabelBuffer=e.createBuffer(),this.selectionVao=e.createVertexArray(),this.selectionPosBuffer=e.createBuffer(),this.selectionLabelBuffer=e.createBuffer(),this.selectionEbo=e.createBuffer(),this.hoverEbo=e.createBuffer(),this.interactionEbo=e.createBuffer(),!this.vao||!this.posBuffer||!this.labelBuffer||!this.hoverVao||!this.hoverPosBuffer||!this.hoverLabelBuffer||!this.selectionVao||!this.selectionPosBuffer||!this.selectionLabelBuffer||!this.selectionEbo||!this.hoverEbo||!this.interactionEbo)throw Error("Failed to allocate WebGL resources");e.bindVertexArray(this.vao),e.bindBuffer(e.ARRAY_BUFFER,this.posBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.labelBuffer),e.enableVertexAttribArray(1),e.vertexAttribIPointer(1,1,e.UNSIGNED_SHORT,0,0),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),e.bindVertexArray(this.hoverVao),e.bindBuffer(e.ARRAY_BUFFER,this.hoverPosBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.hoverLabelBuffer),e.enableVertexAttribArray(1),e.vertexAttribIPointer(1,1,e.UNSIGNED_SHORT,0,0),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),e.bindVertexArray(this.selectionVao),e.bindBuffer(e.ARRAY_BUFFER,this.selectionPosBuffer),e.enableVertexAttribArray(0),e.vertexAttribPointer(0,2,e.FLOAT,!1,0,0),e.bindBuffer(e.ARRAY_BUFFER,this.selectionLabelBuffer),e.enableVertexAttribArray(1),e.vertexAttribIPointer(1,1,e.UNSIGNED_SHORT,0,0),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null)}uploadDatasetToGPU(){let e=this.gl,t=this.dataset;if(!t)return;e.bindVertexArray(this.vao);let i=t.n<=this.maxGpuUploadPoints;if(this.gpuUsesFullDataset=i,i)e.bindBuffer(e.ARRAY_BUFFER,this.posBuffer),e.bufferData(e.ARRAY_BUFFER,t.positions,e.STATIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.labelBuffer),e.bufferData(e.ARRAY_BUFFER,t.labels,e.STATIC_DRAW),this.gpuPointCount=t.n;else{let i=t.n,r=Math.min(i,Math.max(25e4,Math.min(this.maxBaseDrawPoints,Math.floor(.25*i)))),o=Math.max(1,Math.floor(i/r)),s=Math.min(r,Math.ceil(i/o)),a=new Float32Array(2*s),n=new Uint16Array(s),l=0;for(let e=0;e=5e5){let t=Math.min(i,Math.max(25e4,Math.min(this.maxBaseDrawPoints,Math.floor(.25*i)))),r=Math.max(1,Math.floor(i/t)),o=Math.min(t,Math.ceil(i/r)),s=new Uint32Array(o),a=0;for(let e=0;e=r)break;this.selectionOverlayCount=a,e.bindVertexArray(this.selectionVao),e.bindBuffer(e.ARRAY_BUFFER,this.selectionPosBuffer),e.bufferData(e.ARRAY_BUFFER,o,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.selectionLabelBuffer),e.bufferData(e.ARRAY_BUFFER,s,e.DYNAMIC_DRAW),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),this.selectionDirty=!1;return}let t=Math.min(this.selection.size,25e4);if(this.selectionOverlayCount=t,0===t){this.selectionDirty=!1;return}let i=new Uint32Array(t),r=0;for(let e of this.selection)if(i[r++]=e,r>=t)break;this.selectionOverlayCount=r,e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.selectionEbo),e.bufferData(e.ELEMENT_ARRAY_BUFFER,i,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null),this.selectionDirty=!1}uploadHoverToGPU(){if(!this.gl||!this.hoverEbo)return;let e=this.gl;if(!this.gpuUsesFullDataset){let t=this.dataset;if(!t||!this.hoverVao||!this.hoverPosBuffer||!this.hoverLabelBuffer)return;let i=this.hoveredIndex>=0&&this.hoveredIndex=0?(r[0]=t.positions[2*i],r[1]=t.positions[2*i+1],o[0]=t.labels[i]):(r[0]=2,r[1]=2,o[0]=0),e.bindVertexArray(this.hoverVao),e.bindBuffer(e.ARRAY_BUFFER,this.hoverPosBuffer),e.bufferData(e.ARRAY_BUFFER,r,e.DYNAMIC_DRAW),e.bindBuffer(e.ARRAY_BUFFER,this.hoverLabelBuffer),e.bufferData(e.ARRAY_BUFFER,o,e.DYNAMIC_DRAW),e.bindVertexArray(null),e.bindBuffer(e.ARRAY_BUFFER,null),this.hoverDirty=!1;return}let t=this.hoveredIndex>=0?this.hoveredIndex:0,i=this.hoverIndexScratch;i[0]=t,e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.hoverEbo),e.bufferData(e.ELEMENT_ARRAY_BUFFER,i,e.DYNAMIC_DRAW),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null),this.hoverDirty=!1}render(){this.ensureGL();let e=this.gl,t=this.dataset;if(!t)return;let i=performance.now()-this.lastViewChangeTs<80,r=!!this.interactionEbo&&this.interactionCount>0,o=i&&"poincare"===this.geometryKind()&&t.n>=2e6&&r,s=t.n>this.maxBaseDrawPoints&&r,l=this.gpuUsesFullDataset&&(o||s),h=this.gpuUsesFullDataset?l?this.interactionCount:t.n:this.gpuPointCount,u=this.estimatePointFragments(h,this.dpr);if(this.updateSquarePointPolicy(u),this.selectionDirty&&this.uploadSelectionToGPU(),this.hoverDirty&&this.uploadHoverToGPU(),e.bindFramebuffer(e.FRAMEBUFFER,null),e.viewport(0,0,this.canvas.width,this.canvas.height),e.disable(e.BLEND),"poincare"===this.geometryKind())if(this.renderBackdropIfNeeded(),this.backdropTex&&this.programComposite)e.useProgram(this.programComposite),e.activeTexture(e.TEXTURE0),e.bindTexture(e.TEXTURE_2D,this.backdropTex),this.uCompositeTex&&e.uniform1i(this.uCompositeTex,0),e.bindVertexArray(this.vao),e.drawArrays(e.TRIANGLES,0,3),e.bindTexture(e.TEXTURE_2D,null);else{let[t,i,r,o]=T(this.backgroundColor);e.clearColor(t,i,r,o),e.clear(e.COLOR_BUFFER_BIT)}else{let[t,i,r,o]=T(this.backgroundColor);e.clearColor(t,i,r,o),e.clear(e.COLOR_BUFFER_BIT)}if(this.ensurePointsResources(),!this.pointsFbo||!this.pointsTex||!this.programComposite)return;e.bindFramebuffer(e.FRAMEBUFFER,this.pointsFbo),e.viewport(0,0,this.pointsW,this.pointsH),e.clearColor(0,0,0,0),e.clear(e.COLOR_BUFFER_BIT);let d=this.renderAsSquares?this.pointsSquare:this.pointsCircle;if(d){if(e.useProgram(d.program),this.bindViewUniformsForProgram(d.program),this.paletteDirty&&this.uploadPaletteUniforms(),this.bindPaletteTexture(),d.uCssSize&&e.uniform2f(d.uCssSize,this.width,this.height),d.uDpr&&e.uniform1f(d.uDpr,this.dpr),d.uPointRadius&&e.uniform1f(d.uPointRadius,this.pointRadiusCss),this.renderAsSquares?e.disable(e.BLEND):(e.enable(e.BLEND),e.blendFunc(e.SRC_ALPHA,e.ONE_MINUS_SRC_ALPHA)),e.bindVertexArray(this.vao),l)e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.interactionEbo),e.drawElements(e.POINTS,this.interactionCount,e.UNSIGNED_INT,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null);else{let i=this.gpuUsesFullDataset?t.n:this.gpuPointCount;e.drawArrays(e.POINTS,0,i)}if(this.__debugPolicy={pointsDpr:this.dpr,deviceDpr:this.deviceDpr,canvasDpr:this.canvasDpr,renderAsSquares:this.renderAsSquares,useLod:l,baseDrawCount:h,interactionCount:this.interactionCount,gpuUsesFullDataset:this.gpuUsesFullDataset,gpuPointCount:this.gpuPointCount,estimatedPointFragments:u,fragmentBudget:this.policy.fragmentBudget,isInteracting:i},!i&&this.selection.size>0){if(e.useProgram(this.programSolid),this.bindViewUniformsForProgram(this.programSolid),this.uCssSizeSolid&&e.uniform2f(this.uCssSizeSolid,this.width,this.height),this.uDprSolid&&e.uniform1f(this.uDprSolid,this.dpr),this.uPointRadiusSolid&&e.uniform1f(this.uPointRadiusSolid,this.pointRadiusCss+1),this.uSolidColor){let[t,i,r,o]=T(a);e.uniform4f(this.uSolidColor,t,i,r,o)}this.uSolidRingMode&&e.uniform1i(this.uSolidRingMode,0),this.uSolidRingThicknessPx&&e.uniform1f(this.uSolidRingThicknessPx,0),this.uSolidPointSizePx&&e.uniform1f(this.uSolidPointSizePx,(this.pointRadiusCss+1)*2*this.dpr),this.gpuUsesFullDataset?(e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,this.selectionEbo),e.drawElements(e.POINTS,this.selectionOverlayCount,e.UNSIGNED_INT,0),e.bindBuffer(e.ELEMENT_ARRAY_BUFFER,null)):this.selectionVao&&this.selectionOverlayCount>0&&(e.bindVertexArray(this.selectionVao),e.drawArrays(e.POINTS,0,this.selectionOverlayCount),e.bindVertexArray(this.vao))}if(!i&&this.hoveredIndex>=0&&this.hoveredIndex0))return null;let n=o/a*(1+1e-12),l=n*n,h=d(e,t,this.view,this.width,this.height),f=.5*this.width,c=.5*this.height,p=this.view.centerX,m=this.view.centerY,x=-1,g=1/0;if(r.forEachInAABB(h.x-n,h.y-n,h.x+n,h.y+n,r=>{let o=i.positions[2*r],n=i.positions[2*r+1],u=o-h.x,d=n-h.y;if(u*u+d*d>l)return;let b=f+(o-p)*a-e,E=c-(n-m)*a-t,R=b*b+E*E;R<=s&&(Rn&&(n=t),iu&&(u=i)}let f={xMin:s,yMin:a,xMax:n,yMax:u},c=performance.now()-r;return h({type:"polygon",coords:o,bounds:f},t.positions,c,(e,t,i)=>!(ef.xMax)&&!(tf.yMax)&&g(e,t,i))}projectToScreen(e,t){return u(e,t,this.view,this.width,this.height)}unprojectFromScreen(e,t){return d(e,t,this.view,this.width,this.height)}}class k extends U{view=f();uniformCache=new Map;lastPanScreenX=0;lastPanScreenY=0;hasPanAnchor=!1;geometryKind(){return"poincare"}getBackdropZoom(){return this.view.displayZoom}setDataset(e){if("poincare"!==e.geometry)throw Error("HyperbolicWebGLCandidate only supports poincare geometry");super.setDataset(e),this.view=f(),this.hasPanAnchor=!1}setView(e){if("poincare"!==e.type)throw Error("HyperbolicWebGLCandidate only supports poincare view state");this.view=e,this.markBackdropDirty()}getView(){return{...this.view}}bindViewUniformsForProgram(e){if(!this.gl)return;let t=this.gl,i=this.uniformCache.get(e);i||(i={uA:t.getUniformLocation(e,"u_a"),uDisplayZoom:t.getUniformLocation(e,"u_displayZoom")},this.uniformCache.set(e,i)),i.uA&&t.uniform2f(i.uA,this.view.ax,this.view.ay),i.uDisplayZoom&&t.uniform1f(i.uDisplayZoom,this.view.displayZoom)}startPan(e,t){this.lastPanScreenX=e,this.lastPanScreenY=t,this.hasPanAnchor=!0}pan(e,t,i){this.hasPanAnchor||(this.lastPanScreenX=this.width/2,this.lastPanScreenY=this.height/2,this.hasPanAnchor=!0);let r=this.lastPanScreenX,o=this.lastPanScreenY,s=r+e,a=o+t;this.view=x(this.view,r,o,s,a,this.width,this.height),this.markViewChanged(),this.lastPanScreenX=s,this.lastPanScreenY=a}zoom(e,t,i,r){var o,s,a;let n,l,h,u,d,f,p,g;this.view=(o=this.view,s=this.width,a=this.height,n=Math.pow(1.1,i),l=Math.max(.5,Math.min(10,o.displayZoom*n)),h=m(e,t,o,s,a),u=.45*Math.min(s,a)*l,f=s/2+(d=c(h.x,h.y,o.ax,o.ay)).x*u,g=(p=a/2-d.y*u)-t,Math.abs(f-e)>.5||Math.abs(g)>.5?x({...o,displayZoom:l},f,p,e,t,s,a):{...o,displayZoom:l}),this.markViewChanged(),this.markBackdropDirty()}mobiusDerivativeScaleAt(e,t){let i=this.view.ax,r=this.view.ay,o=1-(i*e+r*t),s=-(i*t-r*e),a=o*o+s*s;return a<1e-12?0:Math.max(0,1-(i*i+r*r))/a}conservativeDataRadiusForScreenRadius(e,t,i,r){let o=this.view.ax,s=this.view.ay,a=o*o+s*s,n=Math.sqrt(a),l=Math.max(1e-12,1-a);if(!(r>1e-9)||!(i>0))return 0;let h=1-(o*e+s*t),u=-(o*t-s*e),d=Math.sqrt(h*h+u*u);if(!Number.isFinite(d)||d<1e-12)return 2;let f=i/(r*l),c=f*d*d;for(let e=0;e<5;e++){let e=d+n*c;c=f*e*e}return Number.isFinite(c)?Math.min(1.999,Math.max(0,c*=1.001)):2}hitTest(e,t){let i=this.dataset,r=this.dataIndex;if(!i||!r)return null;let{width:o,height:s,view:a}=this,n=o/2,l=s/2,h=.45*Math.min(o,s)*a.displayZoom,u=h*h,d=this.pointRadiusCss+5,f=d*d,c=e-n,p=t-l,x=h+d;if(c*c+p*p>x*x)return null;let g=m(e,t,a,o,s),b=this.conservativeDataRadiusForScreenRadius(g.x,g.y,d,h),E=-1,R=1/0,T=a.ax,y=a.ay;if(r.forEachInAABB(g.x-b,g.y-b,g.x+b,g.y+b,r=>{let o=i.positions[2*r],s=i.positions[2*r+1],a=o-T,d=s-y,c=1-(T*o+y*s),p=-(T*s-y*o),m=c*c+p*p,x=0,g=0;if(m<1e-12){let e=Math.sqrt(a*a+d*d);e<1e-12?(x=0,g=0):(x=a/e*.999,g=d/e*.999)}else{let e=(x=(a*c+d*p)/m)*x+(g=(d*c-a*p)/m)*g;if(e>=1){let t=Math.sqrt(e);x=x/t*.999,g=g/t*.999}}let b=n+x*h,_=l-g*h,v=b-n,A=_-l;if(v*v+A*A>u)return;let S=b-e,P=_-t,M=S*S+P*P;M<=f&&(M=1){let t=Math.sqrt(e);B=B/t*.999,D=D/t*.999}}return{index:E,screenX:n+B*h,screenY:l-D*h,distance:Math.sqrt(R)}}lassoSelect(e){let t=this.dataset,i=this.dataIndex;if(!t||!i)return l(new Set,0);let r=performance.now(),o=new Float32Array(e.length);for(let t=0;tn&&(n=t),iu&&(u=i)}let d={xMin:s,yMin:a,xMax:n,yMax:u},f=performance.now()-r;return h({type:"polygon",coords:o,bounds:d},t.positions,f,(e,t,i)=>!(ed.xMax)&&!(td.yMax)&&g(e,t,i))}projectToScreen(e,t){var i,r,o;let s,a;return i=this.view,r=this.width,o=this.height,s=c(e,t,i.ax,i.ay),a=.45*Math.min(r,o)*i.displayZoom,{x:r/2+s.x*a,y:o/2-s.y*a}}unprojectFromScreen(e,t){return m(e,t,this.view,this.width,this.height)}}function L(e,t){let i=Math.floor(e.length/2);if(i<=t)return new Float32Array(e);let r=e;if(i>2048){let t=new Float32Array(4096);for(let r=0;r<2048;r++){let o=Math.floor(r*i/2048);t[2*r]=e[2*o],t[2*r+1]=e[2*o+1]}r=t}let o=function(e,t){let i=Array.from(e),r=Math.floor(i.length/2);if(r<3)return i;for(let e=0;e<5&&!((r=Math.floor(i.length/2))<3);e++){let e=Array(4*r),t=0;for(let o=0;or&&(r=a),no&&(o=n)}return Number.isFinite(t)&&Number.isFinite(i)?{xMin:t,yMin:i,xMax:r,yMax:o}:{xMin:0,yMin:0,xMax:0,yMax:0}}(o),a=Math.max(s.xMax-s.xMin,s.yMax-s.yMin),n=(e,t,i,r,o,s)=>{let a=o-i,n=s-r,l=a*a+n*n,h=0;l>1e-12&&((h=((e-i)*a+(t-r)*n)/l)<0?h=0:h>1&&(h=1));let u=e-(i+h*a),d=t-(r+h*n);return u*u+d*d},l=e=>{let t=Math.floor(o.length/2);if(t<=2)return o.slice();let i=e*e,r=new Uint8Array(t);r[0]=1,r[t-1]=1;let s=[0,t-1];for(;s.length>0;){let e=s.pop(),t=s.pop(),a=o[2*t],l=o[2*t+1],h=o[2*e],u=o[2*e+1],d=-1,f=-1;for(let i=t+1;id&&(d=e,f=i)}d>i&&f>=0&&(r[f]=1,s.push(t,f),s.push(f,e))}let a=[];for(let e=0;et&&d<20;)h*=1.1,u=l(h),d++;let f=Math.floor(u.length/2);if(f>t){let e=new Float32Array(2*t);for(let i=0;ie.shiftKey&&(e.metaKey||e.ctrlKey)),s=Number.isFinite(i.lassoMinSampleDistPx)?i.lassoMinSampleDistPx:2,a=Number.isFinite(i.lassoMaxVertsInteraction)?i.lassoMaxVertsInteraction:24,n=Number.isFinite(i.lassoMaxVertsFinal)?i.lassoMaxVertsFinal:48,l=i.observeResize??!0,h=0,u=0,d=0,f=!0,c="idle",p=null,m=0,x=0,g=0,b=0,E={shift:!1,ctrl:!1,alt:!1,meta:!1},R=0,T=0,y=0,_={shift:!1,ctrl:!1,alt:!1,meta:!1},v=!1,A=!1,S=0,P=0,M=-2,F=[],B=null,D=0,C=0,U=!1,w=(t,i)=>{let r=e.getBoundingClientRect();return{x:t-r.left,y:i-r.top}},k=e=>{let i=new Float32Array(e.length);for(let r=0;r{h||(h=requestAnimationFrame(()=>{h=0;let r=!1;if(f){let i,o,s;f=!1,o=I((i=e.getBoundingClientRect()).width),s=I(i.height),r=(o!==u||s!==d)&&(u=o,d=s,t.resize(o,s),!0)||r}if((0!==g||0!==b)&&(t.pan(g,b,E),g=0,b=0,r=!0),v&&0!==R&&(t.zoom(T,y,R,_),R=0,v=!1,r=!0),"idle"===c&&A){A=!1;let e=t.hitTest(S,P),o=e?e.index:-1;o!==M&&(M=o,t.setHovered(o),r=!0),i.onHover?.(e)}if("lasso"===c&&U&&i.onLassoUpdate&&F.length>=6){U=!1;let e=L(F,a);B=e;let t=k(e);i.onLassoUpdate(e,t)}r&&t.render()}))},Y=i=>{if(0!==i.button)return;let{x:r,y:s}=w(i.clientX,i.clientY);if(p=i.pointerId,m=r,x=s,-1!==M&&(M=-1,t.setHovered(-1)),o(i)){c="lasso",F=[],B=null,D=r,C=s;let e=t.unprojectFromScreen(r,s);F.push(e.x,e.y),U=!0,X()}else c="pan",g=0,b=0,E=z(i),"startPan"in t&&t.startPan(r,s),X();e.setPointerCapture(i.pointerId)},V=e=>{if(p!==e.pointerId){if("idle"===c){let{x:t,y:i}=w(e.clientX,e.clientY);S=t,P=i,A=!0,X()}return}let{x:i,y:r}=w(e.clientX,e.clientY);if("pan"===c){g+=i-m,b+=r-x,E=z(e),m=i,x=r,X();return}if("lasso"===c){let e=i-D,o=r-C;if(e*e+o*o>=s*s){let e=t.unprojectFromScreen(i,r);F.push(e.x,e.y),U=!0,D=i,C=r,X()}return}S=i,P=r,A=!0,X()},W=r=>{if(p===r.pointerId){if("pan"===c&&(0!==g||0!==b)&&(t.pan(g,b,E),g=0,b=0,t.render()),"lasso"===c&&F.length>=6){let e=B??L(F,n),r=k(e),o=t.lassoSelect(r);i.onLassoComplete?.(o,e,r)}"endInteraction"in t&&t.endInteraction(),c="idle",p=null,F=[],B=null,U=!1,A=!1;try{e.releasePointerCapture(r.pointerId)}catch{}}},G=e=>{e.preventDefault();let{x:t,y:i}=w(e.clientX,e.clientY),o=-e.deltaY*r;R+=o,T=t,y=i,_=z(e),v=!0,X()};e.addEventListener("pointerdown",Y),e.addEventListener("pointermove",V),e.addEventListener("pointerup",W),e.addEventListener("pointercancel",W),e.addEventListener("wheel",G,{passive:!1});let O=null;return l&&"undefined"!=typeof ResizeObserver&&(O=new ResizeObserver(()=>{f=!0,X()})).observe(e),f=!0,X(),{destroy(){h&&(cancelAnimationFrame(h),h=0),e.removeEventListener("pointerdown",Y),e.removeEventListener("pointermove",V),e.removeEventListener("pointerup",W),e.removeEventListener("pointercancel",W),e.removeEventListener("wheel",G),O?.disconnect(),O=null},requestResize(){f=!0,X()}}}e.s(["DEFAULT_COLORS",0,s,"EuclideanWebGLCandidate",()=>w,"HOVER_COLOR",0,n,"HyperbolicWebGLCandidate",()=>k,"SELECTION_COLOR",0,a,"boundsOfPolygon",()=>b,"createDataset",()=>t,"createInteractionController",()=>N,"packPositions",()=>i,"packPositionsXY",()=>r,"packUint16Labels",()=>o,"pointInPolygon",()=>g],54214)}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/48c5753aca325314.js b/src/hyperview/server/static/_next/static/chunks/48c5753aca325314.js new file mode 100644 index 0000000000000000000000000000000000000000..b10dff8009337a593c9b0c6b1bec4eef37e7fba2 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/48c5753aca325314.js @@ -0,0 +1 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,86051,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"warnOnce",{enumerable:!0,get:function(){return n}});let n=e=>{}},39400,(e,r,t)=>{"use strict";function n(e,r={}){if(r.onlyHashChange)return void e();let t=document.documentElement;if("smooth"!==t.dataset.scrollBehavior)return void e();let a=t.style.scrollBehavior;t.style.scrollBehavior="auto",r.dontForceLayout||t.getClientRects(),e(),t.style.scrollBehavior=a}Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"disableSmoothScrollDuringRouteTransition",{enumerable:!0,get:function(){return n}}),e.r(86051)},15128,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"HTTPAccessFallbackBoundary",{enumerable:!0,get:function(){return i}});let n=e.r(61909),a=e.r(48277),o=n._(e.r(30668)),c=e.r(83441),u=e.r(88112);e.r(86051);let l=e.r(45243);class s extends o.default.Component{constructor(e){super(e),this.state={triggeredStatus:void 0,previousPathname:e.pathname}}componentDidCatch(){}static getDerivedStateFromError(e){if((0,u.isHTTPAccessFallbackError)(e))return{triggeredStatus:(0,u.getAccessFallbackHTTPStatus)(e)};throw e}static getDerivedStateFromProps(e,r){return e.pathname!==r.previousPathname&&r.triggeredStatus?{triggeredStatus:void 0,previousPathname:e.pathname}:{triggeredStatus:r.triggeredStatus,previousPathname:e.pathname}}render(){let{notFound:e,forbidden:r,unauthorized:t,children:n}=this.props,{triggeredStatus:o}=this.state,c={[u.HTTPAccessErrorStatus.NOT_FOUND]:e,[u.HTTPAccessErrorStatus.FORBIDDEN]:r,[u.HTTPAccessErrorStatus.UNAUTHORIZED]:t};if(o){let l=o===u.HTTPAccessErrorStatus.NOT_FOUND&&e,s=o===u.HTTPAccessErrorStatus.FORBIDDEN&&r,i=o===u.HTTPAccessErrorStatus.UNAUTHORIZED&&t;return l||s||i?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)("meta",{name:"robots",content:"noindex"}),!1,c[o]]}):n}return n}}function i({notFound:e,forbidden:r,unauthorized:t,children:n}){let u=(0,c.useUntrackedPathname)(),i=(0,o.useContext)(l.MissingSlotContext);return e||r||t?(0,a.jsx)(s,{pathname:u,notFound:e,forbidden:r,unauthorized:t,missingSlots:i,children:n}):(0,a.jsx)(a.Fragment,{children:n})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},79227,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"useRouterBFCache",{enumerable:!0,get:function(){return a}});let n=e.r(30668);function a(e,r){let[t,a]=(0,n.useState)(()=>({tree:e,stateKey:r,next:null}));if(t.tree===e)return t;let o={tree:e,stateKey:r,next:null},c=1,u=t,l=o;for(;null!==u&&c<1;){if(u.stateKey===r){l.next=u.next;break}{c++;let e={tree:u.tree,stateKey:u.stateKey,next:null};l.next=e,l=e}u=u.next}return a(o),o}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},32035,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return T}});let n=e.r(35856),a=e.r(61909),o=e.r(48277),c=e.r(98165),u=a._(e.r(30668)),l=n._(e.r(69941)),s=e.r(45243),i=e.r(20320),d=e.r(83648),f=e.r(71202),p=e.r(22039),h=e.r(39400),m=e.r(2188),g=e.r(15128),y=e.r(43317),b=e.r(20017),P=e.r(53128),_=e.r(79227);e.r(86511);let v=e.r(69370),O=e.r(88617),S=l.default.__DOM_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE,E=["bottom","height","left","right","top","width","x","y"];function R(e,r){let t=e.getBoundingClientRect();return t.top>=0&&t.top<=r}class j extends u.default.Component{componentDidMount(){this.handlePotentialScroll()}componentDidUpdate(){this.props.focusAndScrollRef.apply&&this.handlePotentialScroll()}render(){return this.props.children}constructor(...e){super(...e),this.handlePotentialScroll=()=>{let{focusAndScrollRef:e,segmentPath:r}=this.props;if(e.apply){if(0!==e.segmentPaths.length&&!e.segmentPaths.some(e=>r.every((r,t)=>(0,p.matchSegment)(r,e[t]))))return;let t=null,n=e.hashFragment;if(n&&(t="top"===n?document.body:document.getElementById(n)??document.getElementsByName(n)[0]),t||(t="undefined"==typeof window?null:(0,S.findDOMNode)(this)),!(t instanceof Element))return;for(;!(t instanceof HTMLElement)||function(e){if(["sticky","fixed"].includes(getComputedStyle(e).position))return!0;let r=e.getBoundingClientRect();return E.every(e=>0===r[e])}(t);){if(null===t.nextElementSibling)return;t=t.nextElementSibling}e.apply=!1,e.hashFragment=null,e.segmentPaths=[],(0,h.disableSmoothScrollDuringRouteTransition)(()=>{if(n)return void t.scrollIntoView();let e=document.documentElement,r=e.clientHeight;!R(t,r)&&(e.scrollTop=0,R(t,r)||t.scrollIntoView())},{dontForceLayout:!0,onlyHashChange:e.onlyHashChange}),e.onlyHashChange=!1,t.focus()}}}}function w({segmentPath:e,children:r}){let t=(0,u.useContext)(s.GlobalLayoutRouterContext);if(!t)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});return(0,o.jsx)(j,{segmentPath:e,focusAndScrollRef:t.focusAndScrollRef,children:r})}function C({tree:e,segmentPath:r,debugNameContext:t,cacheNode:n,params:a,url:l,isActive:f}){let h=(0,u.useContext)(s.GlobalLayoutRouterContext);if((0,u.useContext)(v.NavigationPromisesContext),!h)throw Object.defineProperty(Error("invariant global layout router not mounted"),"__NEXT_ERROR_CODE",{value:"E473",enumerable:!1,configurable:!0});let{tree:m}=h,g=null!==n.prefetchRsc?n.prefetchRsc:n.rsc,y=(0,u.useDeferredValue)(n.rsc,g),_="object"==typeof y&&null!==y&&"function"==typeof y.then?(0,u.use)(y):y;if(!_){if(f){let e=n.lazyData;if(null===e){let t=function e(r,t){if(r){let[n,a]=r,o=2===r.length;if((0,p.matchSegment)(t[0],n)&&t[1].hasOwnProperty(a)){if(o){let r=e(void 0,t[1][a]);return[t[0],{...t[1],[a]:[r[0],r[1],r[2],"refetch"]}]}return[t[0],{...t[1],[a]:e(r.slice(2),t[1][a])}]}}return t}(["",...r],m),a=(0,b.hasInterceptionRouteInCurrentTree)(m),o=Date.now();n.lazyData=e=(0,i.fetchServerResponse)(new URL(l,location.origin),{flightRouterState:t,nextUrl:a?h.previousNextUrl||h.nextUrl:null}).then(e=>((0,u.startTransition)(()=>{(0,P.dispatchAppRouterAction)({type:c.ACTION_SERVER_PATCH,previousTree:m,serverResponse:e,navigatedAt:o})}),e)),(0,u.use)(e)}}(0,u.use)(d.unresolvedThenable)}return(0,o.jsx)(s.LayoutRouterContext.Provider,{value:{parentTree:e,parentCacheNode:n,parentSegmentPath:r,parentParams:a,debugNameContext:t,url:l,isActive:f},children:_})}function x({name:e,loading:r,children:t}){let n;if(n="object"==typeof r&&null!==r&&"function"==typeof r.then?(0,u.use)(r):r){let r=n[0],a=n[1],c=n[2];return(0,o.jsx)(u.Suspense,{name:e,fallback:(0,o.jsxs)(o.Fragment,{children:[a,c,r]}),children:t})}return(0,o.jsx)(o.Fragment,{children:t})}function T({parallelRouterKey:e,error:r,errorStyles:t,errorScripts:n,templateStyles:a,templateScripts:c,template:l,notFound:i,forbidden:d,unauthorized:p,segmentViewBoundaries:h}){let b=(0,u.useContext)(s.LayoutRouterContext);if(!b)throw Object.defineProperty(Error("invariant expected layout router to be mounted"),"__NEXT_ERROR_CODE",{value:"E56",enumerable:!1,configurable:!0});let{parentTree:P,parentCacheNode:v,parentSegmentPath:S,parentParams:E,url:R,isActive:j,debugNameContext:T}=b,A=v.parallelRoutes,M=A.get(e);M||(M=new Map,A.set(e,M));let F=P[0],D=null===S?[e]:S.concat([F,e]),k=P[1][e],N=k[0],I=(0,y.createRouterCacheKey)(N,!0),U=(0,_.useRouterBFCache)(k,I),H=[];do{let e=U.tree,u=U.stateKey,h=e[0],b=(0,y.createRouterCacheKey)(h),P=M.get(b);if(void 0===P){let e={lazyData:null,rsc:null,prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:new Map,loading:null,navigatedAt:-1};P=e,M.set(b,e)}let _=E;if(Array.isArray(h)){let e=h[0],r=h[1],t=h[2],n=(0,O.getParamValueFromCacheKey)(r,t);null!==n&&(_={...E,[e]:n})}let S=function(e){if("/"===e)return"/";if("string"==typeof e)if("(slot)"===e)return;else return e+"/";return e[1]+"/"}(h),A=S??T,F=void 0===S?void 0:T,k=v.loading,N=(0,o.jsxs)(s.TemplateContext.Provider,{value:(0,o.jsxs)(w,{segmentPath:D,children:[(0,o.jsx)(f.ErrorBoundary,{errorComponent:r,errorStyles:t,errorScripts:n,children:(0,o.jsx)(x,{name:F,loading:k,children:(0,o.jsx)(g.HTTPAccessFallbackBoundary,{notFound:i,forbidden:d,unauthorized:p,children:(0,o.jsxs)(m.RedirectBoundary,{children:[(0,o.jsx)(C,{url:R,tree:e,params:_,cacheNode:P,segmentPath:D,debugNameContext:A,isActive:j&&u===I}),null]})})})}),null]}),children:[a,c,l]},u);H.push(N),U=U.next}while(null!==U)return H}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},91168,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return u}});let n=e.r(61909),a=e.r(48277),o=n._(e.r(30668)),c=e.r(45243);function u(){let e=(0,o.useContext)(c.TemplateContext);return(0,a.jsx)(a.Fragment,{children:e})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},66387,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return a}});let n=new WeakMap;function a(e){let r=n.get(e);if(r)return r;let t=Promise.resolve(e);return n.set(e,t),t}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},12318,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createRenderSearchParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(66387).createRenderSearchParamsFromClient;("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},13972,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createRenderParamsFromClient",{enumerable:!0,get:function(){return a}});let n=new WeakMap;function a(e){let r=n.get(e);if(r)return r;let t=Promise.resolve(e);return n.set(e,t),t}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},4986,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createRenderParamsFromClient",{enumerable:!0,get:function(){return n}});let n=e.r(13972).createRenderParamsFromClient;("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},27731,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ReflectAdapter",{enumerable:!0,get:function(){return n}});class n{static get(e,r,t){let n=Reflect.get(e,r,t);return"function"==typeof n?n.bind(e):n}static set(e,r,t,n){return Reflect.set(e,r,t,n)}static has(e,r){return Reflect.has(e,r)}static deleteProperty(e,r){return Reflect.deleteProperty(e,r)}}},36380,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"createDedupedByCallsiteServerErrorLoggerDev",{enumerable:!0,get:function(){return l}});let n=function(e,r){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=a(void 0);if(t&&t.has(e))return t.get(e);var n={__proto__:null},o=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var c in e)if("default"!==c&&Object.prototype.hasOwnProperty.call(e,c)){var u=o?Object.getOwnPropertyDescriptor(e,c):null;u&&(u.get||u.set)?Object.defineProperty(n,c,u):n[c]=e[c]}return n.default=e,t&&t.set(e,n),n}(e.r(30668));function a(e){if("function"!=typeof WeakMap)return null;var r=new WeakMap,t=new WeakMap;return(a=function(e){return e?t:r})(e)}let o={current:null},c="function"==typeof n.cache?n.cache:e=>e,u=console.warn;function l(e){return function(...r){u(e(...r))}}c(e=>{try{u(o.current)}finally{o.current=null}})},20697,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={describeHasCheckingStringProperty:function(){return u},describeStringPropertyAccess:function(){return c},wellKnownProperties:function(){return l}};for(var a in n)Object.defineProperty(t,a,{enumerable:!0,get:n[a]});let o=/^[A-Za-z_$][A-Za-z0-9_$]*$/;function c(e,r){return o.test(r)?`\`${e}.${r}\``:`\`${e}[${JSON.stringify(r)}]\``}function u(e,r){let t=JSON.stringify(r);return`\`Reflect.has(${e}, ${t})\`, \`${t} in ${e}\`, or similar`}let l=new Set(["hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toString","valueOf","toLocaleString","then","catch","finally","status","displayName","_debugInfo","toJSON","$$typeof","__esModule"])},84642,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"afterTaskAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(24171).createAsyncLocalStorage)()},55436,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"afterTaskAsyncStorage",{enumerable:!0,get:function(){return n.afterTaskAsyncStorageInstance}});let n=e.r(84642)},83602,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={isRequestAPICallableInsideAfter:function(){return s},throwForSearchParamsAccessInUseCache:function(){return l},throwWithStaticGenerationBailoutErrorWithDynamicError:function(){return u}};for(var a in n)Object.defineProperty(t,a,{enumerable:!0,get:n[a]});let o=e.r(16819),c=e.r(55436);function u(e,r){throw Object.defineProperty(new o.StaticGenBailoutError(`Route ${e} with \`dynamic = "error"\` couldn't be rendered statically because it used ${r}. See more info here: https://nextjs.org/docs/app/building-your-application/rendering/static-and-dynamic#dynamic-rendering`),"__NEXT_ERROR_CODE",{value:"E543",enumerable:!1,configurable:!0})}function l(e,r){let t=Object.defineProperty(Error(`Route ${e.route} used \`searchParams\` inside "use cache". Accessing dynamic request data inside a cache scope is not supported. If you need some search params inside a cached function await \`searchParams\` outside of the cached function and pass only the required search params as arguments to the cached function. See more info here: https://nextjs.org/docs/messages/next-request-in-use-cache`),"__NEXT_ERROR_CODE",{value:"E842",enumerable:!1,configurable:!0});throw Error.captureStackTrace(t,r),e.invalidDynamicUsageError??=t,t}function s(){let e=c.afterTaskAsyncStorage.getStore();return(null==e?void 0:e.rootTaskSpawnPhase)==="action"}},9115,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={createPrerenderSearchParamsForClientPage:function(){return g},createSearchParamsFromClient:function(){return p},createServerSearchParamsForMetadata:function(){return h},createServerSearchParamsForServerPage:function(){return m},makeErroringSearchParamsForUseCache:function(){return v}};for(var a in n)Object.defineProperty(t,a,{enumerable:!0,get:n[a]});let o=e.r(27731),c=e.r(93869),u=e.r(63416),l=e.r(84524),s=e.r(64265),i=e.r(36380),d=e.r(20697),f=e.r(83602);function p(e,r){let t=u.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return y(r,t);case"prerender-runtime":throw Object.defineProperty(new l.InvariantError("createSearchParamsFromClient should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E769",enumerable:!1,configurable:!0});case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new l.InvariantError("createSearchParamsFromClient should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E739",enumerable:!1,configurable:!0});case"request":return b(e,r,t)}(0,u.throwInvariantForMissingStore)()}e.r(93501);let h=m;function m(e,r){let t=u.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return y(r,t);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new l.InvariantError("createServerSearchParamsForServerPage should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E747",enumerable:!1,configurable:!0});case"prerender-runtime":var n,a;return n=e,a=t,(0,c.delayUntilRuntimeStage)(a,O(n));case"request":return b(e,r,t)}(0,u.throwInvariantForMissingStore)()}function g(e){if(e.forceStatic)return Promise.resolve({});let r=u.workUnitAsyncStorage.getStore();if(r)switch(r.type){case"prerender":case"prerender-client":return(0,s.makeHangingPromise)(r.renderSignal,e.route,"`searchParams`");case"prerender-runtime":throw Object.defineProperty(new l.InvariantError("createPrerenderSearchParamsForClientPage should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E768",enumerable:!1,configurable:!0});case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new l.InvariantError("createPrerenderSearchParamsForClientPage should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E746",enumerable:!1,configurable:!0});case"prerender-ppr":case"prerender-legacy":case"request":return Promise.resolve({})}(0,u.throwInvariantForMissingStore)()}function y(e,r){if(e.forceStatic)return Promise.resolve({});switch(r.type){case"prerender":case"prerender-client":var t=e,n=r;let a=P.get(n);if(a)return a;let u=(0,s.makeHangingPromise)(n.renderSignal,t.route,"`searchParams`"),l=new Proxy(u,{get(e,r,t){if(Object.hasOwn(u,r))return o.ReflectAdapter.get(e,r,t);switch(r){case"then":return(0,c.annotateDynamicAccess)("`await searchParams`, `searchParams.then`, or similar",n),o.ReflectAdapter.get(e,r,t);case"status":return(0,c.annotateDynamicAccess)("`use(searchParams)`, `searchParams.status`, or similar",n),o.ReflectAdapter.get(e,r,t);default:return o.ReflectAdapter.get(e,r,t)}}});return P.set(n,l),l;case"prerender-ppr":case"prerender-legacy":var i=e,d=r;let p=P.get(i);if(p)return p;let h=Promise.resolve({}),m=new Proxy(h,{get(e,r,t){if(Object.hasOwn(h,r))return o.ReflectAdapter.get(e,r,t);if("string"==typeof r&&"then"===r){let e="`await searchParams`, `searchParams.then`, or similar";i.dynamicShouldError?(0,f.throwWithStaticGenerationBailoutErrorWithDynamicError)(i.route,e):"prerender-ppr"===d.type?(0,c.postponeWithTracking)(i.route,e,d.dynamicTracking):(0,c.throwToInterruptStaticGeneration)(e,i,d)}return o.ReflectAdapter.get(e,r,t)}});return P.set(i,m),m;default:return r}}function b(e,r,t){return r.forceStatic?Promise.resolve({}):O(e)}let P=new WeakMap,_=new WeakMap;function v(e){let r=_.get(e);if(r)return r;let t=Promise.resolve({}),n=new Proxy(t,{get:function r(n,a,c){return Object.hasOwn(t,a)||"string"!=typeof a||"then"!==a&&d.wellKnownProperties.has(a)||(0,f.throwForSearchParamsAccessInUseCache)(e,r),o.ReflectAdapter.get(n,a,c)}});return _.set(e,n),n}function O(e){let r=P.get(e);if(r)return r;let t=Promise.resolve(e);return P.set(e,t),t}(0,i.createDedupedByCallsiteServerErrorLoggerDev)(function(e,r){let t=e?`Route "${e}" `:"This route ";return Object.defineProperty(Error(`${t}used ${r}. \`searchParams\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`),"__NEXT_ERROR_CODE",{value:"E848",enumerable:!1,configurable:!0})})},6782,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"dynamicAccessAsyncStorageInstance",{enumerable:!0,get:function(){return n}});let n=(0,e.r(24171).createAsyncLocalStorage)()},14190,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"dynamicAccessAsyncStorage",{enumerable:!0,get:function(){return n.dynamicAccessAsyncStorageInstance}});let n=e.r(6782)},69318,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n={createParamsFromClient:function(){return h},createPrerenderParamsForClientSegment:function(){return b},createServerParamsForMetadata:function(){return m},createServerParamsForRoute:function(){return g},createServerParamsForServerSegment:function(){return y}};for(var a in n)Object.defineProperty(t,a,{enumerable:!0,get:n[a]});let o=e.r(26628),c=e.r(27731),u=e.r(93869),l=e.r(63416),s=e.r(84524),i=e.r(20697),d=e.r(64265),f=e.r(36380),p=e.r(14190);function h(e,r){let t=l.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,r,t);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new s.InvariantError("createParamsFromClient should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E736",enumerable:!1,configurable:!0});case"prerender-runtime":throw Object.defineProperty(new s.InvariantError("createParamsFromClient should not be called in a runtime prerender."),"__NEXT_ERROR_CODE",{value:"E770",enumerable:!1,configurable:!0});case"request":return S(e)}(0,l.throwInvariantForMissingStore)()}e.r(93501);let m=y;function g(e,r){let t=l.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,r,t);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new s.InvariantError("createServerParamsForRoute should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E738",enumerable:!1,configurable:!0});case"prerender-runtime":return _(e,t);case"request":return S(e)}(0,l.throwInvariantForMissingStore)()}function y(e,r){let t=l.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":case"prerender-ppr":case"prerender-legacy":return P(e,r,t);case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new s.InvariantError("createServerParamsForServerSegment should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E743",enumerable:!1,configurable:!0});case"prerender-runtime":return _(e,t);case"request":return S(e)}(0,l.throwInvariantForMissingStore)()}function b(e){let r=o.workAsyncStorage.getStore();if(!r)throw Object.defineProperty(new s.InvariantError("Missing workStore in createPrerenderParamsForClientSegment"),"__NEXT_ERROR_CODE",{value:"E773",enumerable:!1,configurable:!0});let t=l.workUnitAsyncStorage.getStore();if(t)switch(t.type){case"prerender":case"prerender-client":let n=t.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return(0,d.makeHangingPromise)(t.renderSignal,r.route,"`params`")}break;case"cache":case"private-cache":case"unstable-cache":throw Object.defineProperty(new s.InvariantError("createPrerenderParamsForClientSegment should not be called in cache contexts."),"__NEXT_ERROR_CODE",{value:"E734",enumerable:!1,configurable:!0})}return Promise.resolve(e)}function P(e,r,t){switch(t.type){case"prerender":case"prerender-client":{let n=t.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return function(e,r,t){let n=v.get(e);if(n)return n;let a=new Proxy((0,d.makeHangingPromise)(t.renderSignal,r.route,"`params`"),O);return v.set(e,a),a}(e,r,t)}break}case"prerender-ppr":{let n=t.fallbackRouteParams;if(n){for(let a in e)if(n.has(a))return function(e,r,t,n){let a=v.get(e);if(a)return a;let o={...e},c=Promise.resolve(o);return v.set(e,c),Object.keys(e).forEach(e=>{i.wellKnownProperties.has(e)||r.has(e)&&Object.defineProperty(o,e,{get(){let r=(0,i.describeStringPropertyAccess)("params",e);"prerender-ppr"===n.type?(0,u.postponeWithTracking)(t.route,r,n.dynamicTracking):(0,u.throwToInterruptStaticGeneration)(r,t,n)},enumerable:!0})}),c}(e,n,r,t)}}}return S(e)}function _(e,r){return(0,u.delayUntilRuntimeStage)(r,S(e))}let v=new WeakMap,O={get:function(e,r,t){if("then"===r||"catch"===r||"finally"===r){let n=c.ReflectAdapter.get(e,r,t);return({[r]:(...r)=>{let t=p.dynamicAccessAsyncStorage.getStore();return t&&t.abortController.abort(Object.defineProperty(Error("Accessed fallback `params` during prerendering."),"__NEXT_ERROR_CODE",{value:"E691",enumerable:!1,configurable:!0})),new Proxy(n.apply(e,r),O)}})[r]}return c.ReflectAdapter.get(e,r,t)}};function S(e){let r=v.get(e);if(r)return r;let t=Promise.resolve(e);return v.set(e,t),t}(0,f.createDedupedByCallsiteServerErrorLoggerDev)(function(e,r){let t=e?`Route "${e}" `:"This route ";return Object.defineProperty(Error(`${t}used ${r}. \`params\` is a Promise and must be unwrapped with \`await\` or \`React.use()\` before accessing its properties. Learn more: https://nextjs.org/docs/messages/sync-dynamic-apis`),"__NEXT_ERROR_CODE",{value:"E834",enumerable:!1,configurable:!0})})},73440,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ClientPageRoot",{enumerable:!0,get:function(){return s}});let n=e.r(48277),a=e.r(84524),o=e.r(45243),c=e.r(30668),u=e.r(88617),l=e.r(69370);function s({Component:r,serverProvidedParams:t}){let s,i;if(null!==t)s=t.searchParams,i=t.params;else{let e=(0,c.use)(o.LayoutRouterContext);i=null!==e?e.parentParams:{},s=(0,u.urlSearchParamsToParsedUrlQuery)((0,c.use)(l.SearchParamsContext))}if("undefined"==typeof window){let t,o,{workAsyncStorage:c}=e.r(26628),u=c.getStore();if(!u)throw Object.defineProperty(new a.InvariantError("Expected workStore to exist when handling searchParams in a client Page."),"__NEXT_ERROR_CODE",{value:"E564",enumerable:!1,configurable:!0});let{createSearchParamsFromClient:l}=e.r(9115);t=l(s,u);let{createParamsFromClient:d}=e.r(69318);return o=d(i,u),(0,n.jsx)(r,{params:o,searchParams:t})}{let{createRenderSearchParamsFromClient:t}=e.r(12318),a=t(s),{createRenderParamsFromClient:o}=e.r(4986),c=o(i);return(0,n.jsx)(r,{params:c,searchParams:a})}}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},34636,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"ClientSegmentRoot",{enumerable:!0,get:function(){return u}});let n=e.r(48277),a=e.r(84524),o=e.r(45243),c=e.r(30668);function u({Component:r,slots:t,serverProvidedParams:u}){let l;if(null!==u)l=u.params;else{let e=(0,c.use)(o.LayoutRouterContext);l=null!==e?e.parentParams:{}}if("undefined"==typeof window){let o,{workAsyncStorage:c}=e.r(26628),u=c.getStore();if(!u)throw Object.defineProperty(new a.InvariantError("Expected workStore to exist when handling params in a client segment such as a Layout or Template."),"__NEXT_ERROR_CODE",{value:"E600",enumerable:!1,configurable:!0});let{createParamsFromClient:s}=e.r(69318);return o=s(l,u),(0,n.jsx)(r,{...t,params:o})}{let{createRenderParamsFromClient:a}=e.r(4986),o=a(l);return(0,n.jsx)(r,{...t,params:o})}}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),r.exports=t.default)},12843,(e,r,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"IconMark",{enumerable:!0,get:function(){return a}});let n=e.r(48277),a=()=>"undefined"!=typeof window?null:(0,n.jsx)("meta",{name:"«nxt-icon»"})}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/5a5ec5690ca4254a.js b/src/hyperview/server/static/_next/static/chunks/5a5ec5690ca4254a.js new file mode 100644 index 0000000000000000000000000000000000000000..4111781d00ac6356f2a033440d600bf31d28a3e9 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/5a5ec5690ca4254a.js @@ -0,0 +1,2 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,50407,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"getAssetPrefix",{enumerable:!0,get:function(){return l}});let r=e.r(84524);function l(){let e=document.currentScript;if(!(e instanceof HTMLScriptElement))throw Object.defineProperty(new r.InvariantError(`Expected document.currentScript to be a ",a=a.removeChild(a.firstChild);break;case"select":a="string"==typeof r.is?u.createElement("select",{is:r.is}):u.createElement("select"),r.multiple?a.multiple=!0:r.size&&(a.size=r.size);break;default:a="string"==typeof r.is?u.createElement(l,{is:r.is}):u.createElement(l)}}a[eW]=t,a[eK]=r;e:for(u=t.child;null!==u;){if(5===u.tag||6===u.tag)a.appendChild(u.stateNode);else if(4!==u.tag&&27!==u.tag&&null!==u.child){u.child.return=u,u=u.child;continue}if(u===t)break;for(;null===u.sibling;){if(null===u.return||u.return===t)break e;u=u.return}u.sibling.return=u.return,u=u.sibling}switch(t.stateNode=a,cl(a,l,r),l){case"button":case"input":case"select":case"textarea":r=!!r.autoFocus;break;case"img":r=!0;break;default:r=!1}r&&ou(t)}}return of(t),t.subtreeFlags&=-0x2000001,oo(t,t.type,null===e?null:e.memoizedProps,t.pendingProps,n),null;case 6:if(e&&null!=t.stateNode)e.memoizedProps!==r&&ou(t);else{if("string"!=typeof r&&null===t.stateNode)throw Error(i(166));if(e=en.current,rY(t)){if(e=t.stateNode,n=t.memoizedProps,r=null,null!==(l=rB))switch(l.tag){case 27:case 5:r=l.memoizedProps}e[eW]=t,(e=!!(e.nodeValue===n||null!==r&&!0===r.suppressHydrationWarning||ct(e.nodeValue,n)))||rQ(t,!0)}else(e=ci(e).createTextNode(r))[eW]=t,t.stateNode=e}return of(t),null;case 31:if(n=t.memoizedState,null===e||null!==e.memoizedState){if(r=rY(t),null!==n){if(null===e){if(!r)throw Error(i(318));if(!(e=null!==(e=t.memoizedState)?e.dehydrated:null))throw Error(i(557));e[eW]=t}else rJ(),0==(128&t.flags)&&(t.memoizedState=null),t.flags|=4;of(t),e=!1}else n=rZ(),null!==e&&null!==e.memoizedState&&(e.memoizedState.hydrationErrors=n),e=!0;if(!e){if(256&t.flags)return l7(t),t;return l7(t),null}if(0!=(128&t.flags))throw Error(i(558))}return of(t),null;case 13:if(r=t.memoizedState,null===e||null!==e.memoizedState&&null!==e.memoizedState.dehydrated){if(l=rY(t),null!==r&&null!==r.dehydrated){if(null===e){if(!l)throw Error(i(318));if(!(l=null!==(l=t.memoizedState)?l.dehydrated:null))throw Error(i(317));l[eW]=t}else rJ(),0==(128&t.flags)&&(t.memoizedState=null),t.flags|=4;of(t),l=!1}else l=rZ(),null!==e&&null!==e.memoizedState&&(e.memoizedState.hydrationErrors=l),l=!0;if(!l){if(256&t.flags)return l7(t),t;return l7(t),null}}if(l7(t),0!=(128&t.flags))return t.lanes=n,t;return n=null!==r,e=null!==e&&null!==e.memoizedState,n&&(r=t.child,l=null,null!==r.alternate&&null!==r.alternate.memoizedState&&null!==r.alternate.memoizedState.cachePool&&(l=r.alternate.memoizedState.cachePool.pool),a=null,null!==r.memoizedState&&null!==r.memoizedState.cachePool&&(a=r.memoizedState.cachePool.pool),a!==l&&(r.flags|=2048)),n!==e&&n&&(t.child.flags|=8192),os(t,t.updateQueue),of(t),null;case 4:return ea(),null===e&&s1(t.stateNode.containerInfo),t.flags|=0x4000000,of(t),null;case 10:return r8(t.type),of(t),null;case 19:if(an(t),null===(r=t.memoizedState))return of(t),null;if(l=0!=(128&t.flags),null===(a=r.rendering))if(l)oc(r,!1);else{if(0!==iM||null!==e&&0!=(128&e.flags))for(e=t.child;null!==e;){if(null!==(a=ar(e))){for(t.flags|=128,oc(r,!1),t.updateQueue=e=a.updateQueue,os(t,e),t.subtreeFlags=0,e=n,n=t.child;null!==n;)rS(n,e),n=n.sibling;return at(t,1&ae.current|2),rq&&rA(t,r.treeForkCount),t.child}e=e.sibling}null!==r.tail&&ey()>iV&&(t.flags|=128,l=!0,oc(r,!1),t.lanes=4194304)}else{if(!l)if(null!==(e=ar(a))){if(t.flags|=128,l=!0,t.updateQueue=e=e.updateQueue,os(t,e),oc(r,!0),null===r.tail&&"collapsed"!==r.tailMode&&"visible"!==r.tailMode&&!a.alternate&&!rq)return of(t),null}else 2*ey()-r.renderingStartTime>iV&&0x20000000!==n&&(t.flags|=128,l=!0,oc(r,!1),t.lanes=4194304);r.isBackwards?(a.sibling=t.child,t.child=a):(null!==(e=r.last)?e.sibling=a:t.child=a,r.last=a)}if(null!==r.tail){e=r.tail;e:{for(n=e;null!==n;){if(null!==n.alternate){n=!1;break e}n=n.sibling}n=!0}return r.rendering=e,r.tail=e.sibling,r.renderingStartTime=ey(),e.sibling=null,a=ae.current,a=l?1&a|2:1&a,"visible"===r.tailMode||"collapsed"===r.tailMode||!n||rq?at(t,a):(n=a,Z(l3,t),Z(ae,n),null===l4&&(l4=t)),rq&&rA(t,r.treeForkCount),e}return of(t),null;case 22:case 23:return l7(t),l2(),r=null!==t.memoizedState,null!==e?null!==e.memoizedState!==r&&(t.flags|=8192):r&&(t.flags|=8192),r?0!=(0x20000000&n)&&0==(128&t.flags)&&(of(t),6&t.subtreeFlags&&(t.flags|=8192)):of(t),null!==(n=t.updateQueue)&&os(t,n.retryQueue),n=null,null!==e&&null!==e.memoizedState&&null!==e.memoizedState.cachePool&&(n=e.memoizedState.cachePool.pool),r=null,null!==t.memoizedState&&null!==t.memoizedState.cachePool&&(r=t.memoizedState.cachePool.pool),r!==n&&(t.flags|=2048),null!==e&&J(lv),null;case 24:return n=null,null!==e&&(n=e.memoizedState.cache),t.memoizedState.cache!==n&&(t.flags|=2048),r8(lo),of(t),null;case 25:return null;case 30:return t.flags|=0x2000000,of(t),null}throw Error(i(156,t.tag))}(t.alternate,t,iN);if(null!==n){iP=n;return}if(null!==(t=t.sibling)){iP=t;return}iP=t=e}while(null!==t)0===iM&&(iM=5)}function sh(e,t){do{var n=function(e,t){switch(rU(t),t.tag){case 1:return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 3:return r8(lo),ea(),0!=(65536&(e=t.flags))&&0==(128&e)?(t.flags=-65537&e|128,t):null;case 26:case 27:case 5:return eo(t),null;case 31:if(null!==t.memoizedState){if(l7(t),null===t.alternate)throw Error(i(340));rJ()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 13:if(l7(t),null!==(e=t.memoizedState)&&null!==e.dehydrated){if(null===t.alternate)throw Error(i(340));rJ()}return 65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 19:return an(t),65536&(e=t.flags)?(t.flags=-65537&e|128,null!==(e=t.memoizedState)&&(e.rendering=null,e.tail=null),t.flags|=4,t):null;case 4:return ea(),null;case 10:return r8(t.type),null;case 22:case 23:return l7(t),l2(),null!==e&&J(lv),65536&(e=t.flags)?(t.flags=-65537&e|128,t):null;case 24:return r8(lo),null;default:return null}}(e.alternate,e);if(null!==n){n.flags&=32767,iP=n;return}if(null!==(n=e.return)&&(n.flags|=32768,n.subtreeFlags=0,n.deletions=null),!t&&null!==(e=e.sibling)){iP=e;return}iP=e=n}while(null!==e)iM=6,iP=null}function sm(e,t,n,r,l,a,u,o,s,c,f){e.cancelPendingCommit=null;do sE();while(0!==iW)if(0!=(6&iE))throw Error(i(327));if(null!==t){var d;if(t===e.current)throw Error(i(177));if(!function(e,t,n,r,l,a){var u=e.pendingLanes;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.warmLanes=0,e.expiredLanes&=n,e.entangledLanes&=n,e.errorRecoveryDisabledLanes&=n,e.shellSuspendCounter=0;var o=e.entanglements,i=e.expirationTimes,s=e.hiddenUpdates;for(n=u&~n;0fc){o.length=u;break}d=new Promise(cR.bind(d)),o.push(d)}}}return 0g&&(u=g,g=m,m=u);var y=nH(o,m),v=nH(o,g);if(y&&v&&(1!==p.rangeCount||p.anchorNode!==y.node||p.anchorOffset!==y.offset||p.focusNode!==v.node||p.focusOffset!==v.offset)){var b=f.createRange();b.setStart(y.node,y.offset),p.removeAllRanges(),m>g?(p.addRange(b),p.extend(v.node,v.offset)):(b.setEnd(v.node,v.offset),p.addRange(b))}}}}for(f=[],p=o;p=p.parentNode;)1===p.nodeType&&f.push({element:p,left:p.scrollLeft,top:p.scrollTop});for("function"==typeof o.focus&&o.focus(),o=0;on?32:n,W.T=null,n=iY,iY=null;var a=iK,u=iG;if(iW=0,iQ=iK=null,iG=0,0!=(6&iE))throw Error(i(331));var o=iE;if(iE|=4,iv(a.current),ic(a,a.current,u,n),iE=o,sI(0,!1),ek&&"function"==typeof ek.onPostCommitFiberRoot)try{ek.onPostCommitFiberRoot(eP,a)}catch(e){}return!0}finally{K.p=l,W.T=r,sw(e,t)}}function sP(e,t,n){t=rT(n,t),t=uF(e.stateNode,t,2),null!==(e=lq(e,t,2))&&(eA(e,2),sA(e))}function sk(e,t,n){if(3===e.tag)sP(e,e,n);else for(;null!==t;){if(3===t.tag){sP(t,e,n);break}if(1===t.tag){var r=t.stateNode;if("function"==typeof t.type.getDerivedStateFromError||"function"==typeof r.componentDidCatch&&(null===i$||!i$.has(r))){e=rT(n,e),null!==(r=lq(t,n=uA(2),2))&&(uI(n,r,t,e),eA(r,2),sA(r));break}}t=t.return}}function sR(e,t,n){var r=e.pingCache;if(null===r){r=e.pingCache=new iw;var l=new Set;r.set(t,l)}else void 0===(l=r.get(t))&&(l=new Set,r.set(t,l));l.has(n)||(iC=!0,l.add(n),e=sT.bind(null,e,t,n),t.then(e,e))}function sT(e,t,n){var r=e.pingCache;null!==r&&r.delete(t),e.pingedLanes|=e.suspendedLanes&n,e.warmLanes&=~n,i_===e&&(ik&n)===n&&(4===iM||3===iM&&(0x3c00000&ik)===ik&&300>ey()-iH?0==(2&iE)&&sr(e,0):ij|=n,iA===ik&&(iA=0)),sA(e)}function sx(e,t){0===t&&(t=ej()),null!==(e=rd(e,t))&&(eA(e,t),sA(e))}function sO(e){var t=e.memoizedState,n=0;null!==t&&(n=t.retryLane),sx(e,n)}function sC(e,t){var n=0;switch(e.tag){case 31:case 13:var r=e.stateNode,l=e.memoizedState;null!==l&&(n=l.retryLane);break;case 19:r=e.stateNode;break;case 22:r=e.stateNode._retryCache;break;default:throw Error(i(314))}null!==r&&r.delete(t),sx(e,n)}var sN=null,sM=null,sL=!1,sz=!1,sj=!1,sF=0;function sA(e){e!==sM&&null===e.next&&(null===sM?sN=sM=e:sM=sM.next=e),sz=!0,sL||(sL=!0,cg(function(){0!=(6&iE)?ep(eb,sD):sU()}))}function sI(e,t){if(!sj&&sz){sj=!0;do for(var n=!1,r=sN;null!==r;){if(!t)if(0!==e){var l=r.pendingLanes;if(0===l)var a=0;else{var u=r.suspendedLanes,o=r.pingedLanes;a=0xc000095&(a=(1<<31-eR(42|e)+1)-1&(l&~(u&~o)))?0xc000095&a|1:a?2|a:0}0!==a&&(n=!0,sV(r,a))}else a=ik,0==(3&(a=eL(r,r===i_?a:0,null!==r.cancelPendingCommit||-1!==r.timeoutHandle)))||ez(r,a)||(n=!0,sV(r,a));r=r.next}while(n)sj=!1}}function sD(){sU()}function sU(){sz=sL=!1;var e,t=0;0===sF||((e=window.event)&&"popstate"===e.type?e===cd||(cd=e,0):(cd=null,1))||(t=sF);for(var n=ey(),r=null,l=sN;null!==l;){var a=l.next,u=sH(l,n);0===u?(l.next=null,null===r?sN=a:r.next=a,null===a&&(sM=r)):(r=l,(0!==t||0!=(3&u))&&(sz=!0)),l=a}0!==iW&&5!==iW||sI(t,!1),0!==sF&&(sF=0)}function sH(e,t){for(var n=e.suspendedLanes,r=e.pingedLanes,l=e.expirationTimes,a=-0x3c00001&e.pendingLanes;0 title"):null)}function fu(e,t){return"img"===e&&null!=t.src&&""!==t.src&&null==t.onLoad&&"lazy"!==t.loading}function fo(e){return"stylesheet"!==e.type||0!=(3&e.state.loading)}function fi(e){return(e.width||100)*(e.height||100)*("number"==typeof devicePixelRatio?devicePixelRatio:1)*.25}function fs(e,t){"function"==typeof t.decode&&(e.imgCount++,t.complete||(e.imgBytes+=fi(t),e.suspenseyImages.push(t)),e=fp.bind(e),t.decode().then(e,e))}var fc=0;function ff(e){if(0===e.count&&(0===e.imgCount||!e.waitingForImages)){if(e.stylesheets)fm(e,e.stylesheets);else if(e.unsuspend){var t=e.unsuspend;e.unsuspend=null,t()}}}function fd(){this.count--,ff(this)}function fp(){this.imgCount--,ff(this)}var fh=null;function fm(e,t){e.stylesheets=null,null!==e.unsuspend&&(e.count++,fh=new Map,t.forEach(fg,e),fh=null,fd.call(e))}function fg(e,t){if(!(4&t.state.loading)){var n=fh.get(e);if(n)var r=n.get(null);else{n=new Map,fh.set(e,n);for(var l=e.querySelectorAll("link[data-precedence],style[data-precedence]"),a=0;a{"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE)try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}(),t.exports=e.r(94454)},98084,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"HeadManagerContext",{enumerable:!0,get:function(){return r}});let r=e.r(35856)._(e.r(30668)).default.createContext({})},26717,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={onCaughtError:function(){return d},onUncaughtError:function(){return p}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(35856),u=e.r(31028),o=e.r(19551),i=e.r(96887),s=e.r(71202),c=a._(e.r(75115)),f={decorateDevError:e=>e,handleClientError:()=>{},originConsoleError:console.error.bind(console)};function d(e,t){let n,r=t.errorBoundary?.constructor;if(n=n||r===s.ErrorBoundaryHandler&&t.errorBoundary.props.errorComponent===c.default)return p(e);(0,o.isBailoutToCSRError)(e)||(0,u.isNextRouterError)(e)||f.originConsoleError(e)}function p(e){(0,o.isBailoutToCSRError)(e)||(0,u.isNextRouterError)(e)||(0,i.reportGlobalError)(e)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},5725,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={computeChangedPath:function(){return f},extractPathFromFlightRouterState:function(){return c},getSelectedParams:function(){return function e(t,n={}){for(let r of Object.values(t[1])){let t=r[0],l=Array.isArray(t),a=l?t[1]:t;!a||a.startsWith(u.PAGE_SEGMENT_KEY)||(l&&("c"===t[2]||"oc"===t[2])?n[t[0]]=t[1].split("/"):l&&(n[t[0]]=t[1]),n=e(r,n))}return n}}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(50864),u=e.r(91395),o=e.r(22039),i=e=>"string"==typeof e?"children"===e?"":e:e[1];function s(e){return e.reduce((e,t)=>{let n;return""===(t="/"===(n=t)[0]?n.slice(1):n)||(0,u.isGroupSegment)(t)?e:`${e}/${t}`},"")||"/"}function c(e){let t=Array.isArray(e[0])?e[0][1]:e[0];if(t===u.DEFAULT_SEGMENT_KEY||a.INTERCEPTION_ROUTE_MARKERS.some(e=>t.startsWith(e)))return;if(t.startsWith(u.PAGE_SEGMENT_KEY))return"";let n=[i(t)],r=e[1]??{},l=r.children?c(r.children):void 0;if(void 0!==l)n.push(l);else for(let[e,t]of Object.entries(r)){if("children"===e)continue;let r=c(t);void 0!==r&&n.push(r)}return s(n)}function f(e,t){let n=function e(t,n){let[r,l]=t,[u,s]=n,f=i(r),d=i(u);if(a.INTERCEPTION_ROUTE_MARKERS.some(e=>f.startsWith(e)||d.startsWith(e)))return"";if(!(0,o.matchSegment)(r,u))return c(n)??"";for(let t in l)if(s[t]){let n=e(l[t],s[t]);if(null!==n)return`${i(u)}/${n}`}return null}(e,t);return null==n||"/"===n?n:s(n.split("/"))}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},40494,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"handleMutable",{enumerable:!0,get:function(){return a}});let r=e.r(5725);function l(e){return void 0!==e}function a(e,t){let n=t.shouldScroll??!0,a=e.previousNextUrl,u=e.nextUrl;if(l(t.patchedTree)){let n=(0,r.computeChangedPath)(e.tree,t.patchedTree);n?(a=u,u=n):u||(u=e.canonicalUrl)}return{canonicalUrl:t.canonicalUrl??e.canonicalUrl,renderedSearch:t.renderedSearch??e.renderedSearch,pushRef:{pendingPush:l(t.pendingPush)?t.pendingPush:e.pushRef.pendingPush,mpaNavigation:l(t.mpaNavigation)?t.mpaNavigation:e.pushRef.mpaNavigation,preserveCustomHistoryState:l(t.preserveCustomHistoryState)?t.preserveCustomHistoryState:e.pushRef.preserveCustomHistoryState},focusAndScrollRef:{apply:!!n&&(!!l(t?.scrollableSegments)||e.focusAndScrollRef.apply),onlyHashChange:t.onlyHashChange||!1,hashFragment:n?t.hashFragment&&""!==t.hashFragment?decodeURIComponent(t.hashFragment.slice(1)):e.focusAndScrollRef.hashFragment:null,segmentPaths:n?t?.scrollableSegments??e.focusAndScrollRef.segmentPaths:[]},cache:t.cache?t.cache:e.cache,tree:l(t.patchedTree)?t.patchedTree:e.tree,nextUrl:u,previousNextUrl:a,debugInfo:t.collectedDebugInfo??null}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},84697,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"isNavigatingToNewRootLayout",{enumerable:!0,get:function(){return function e(t,n){let r=t[0],l=n[0];if(Array.isArray(r)&&Array.isArray(l)){if(r[0]!==l[0]||r[2]!==l[2])return!0}else if(r!==l)return!0;if(t[4])return!n[4];if(n[4])return!0;let a=Object.values(t[1])[0],u=Object.values(n[1])[0];return!a||!u||e(a,u)}}}),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},1989,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={abortTask:function(){return y},listenForDynamicRequest:function(){return g},startPPRNavigation:function(){return d},updateCacheNodeOnPopstateRestoration:function(){return function e(t,n){let r=n[1],l=t.parallelRoutes,a=new Map(l);for(let t in r){let n=r[t],u=n[0],o=(0,i.createRouterCacheKey)(u),s=l.get(t);if(void 0!==s){let r=s.get(o);if(void 0!==r){let l=e(r,n),u=new Map(s);u.set(o,l),a.set(t,u)}}}let u=t.rsc,o=S(u)&&"pending"===u.status;return{lazyData:null,rsc:u,head:t.head,prefetchHead:o?t.prefetchHead:[null,null],prefetchRsc:o?t.prefetchRsc:null,loading:t.loading,parallelRoutes:a,navigatedAt:t.navigatedAt}}}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(91395),u=e.r(22039),o=e.r(80118),i=e.r(43317),s=e.r(84697),c=e.r(28806),f={route:null,node:null,dynamicRequestTree:null,children:null};function d(e,t,n,r,l,s,c,d,m,g){return function e(t,n,r,l,s,c,d,m,g,y,v,b){let S=l[1],w=s[1],E=null!==d?d[1]:null;c||!0===s[4]&&(c=!0);let _=r.parallelRoutes,P=new Map(_),k={},R=null,T=!1,x={};for(let r in w){let l,s=w[r],d=S[r],O=_.get(r),C=null!==E?E[r]:null,N=s[0],M=v.concat([r,N]),L=(0,i.createRouterCacheKey)(N),z=void 0!==d?d[0]:void 0,j=void 0!==O?O.get(L):void 0;if(null!==(l=N===a.DEFAULT_SEGMENT_KEY?void 0!==d?function(e,t){let n;return"refresh"===t[3]?n=t:((n=h(t,t[1]))[2]=(0,o.createHrefFromUrl)(e),n[3]="refresh"),{route:n,node:null,dynamicRequestTree:null,children:null}}(n,d):p(t,d,s,j,c,void 0!==C?C:null,m,g,M,b):y&&0===Object.keys(s[1]).length?p(t,d,s,j,c,void 0!==C?C:null,m,g,M,b):void 0!==d&&void 0!==z&&(0,u.matchSegment)(N,z)&&void 0!==j&&void 0!==d?e(t,n,j,d,s,c,C,m,g,y,M,b):p(t,d,s,j,c,void 0!==C?C:null,m,g,M,b))){if(null===l.route)return f;null===R&&(R=new Map),R.set(r,l);let e=l.node;if(null!==e){let t=new Map(O);t.set(L,e),P.set(r,t)}let t=l.route;k[r]=t;let n=l.dynamicRequestTree;null!==n?(T=!0,x[r]=n):x[r]=t}else k[r]=s,x[r]=s}if(null===R)return null;let O={lazyData:null,rsc:r.rsc,prefetchRsc:r.prefetchRsc,head:r.head,prefetchHead:r.prefetchHead,loading:r.loading,parallelRoutes:P,navigatedAt:t};return{route:h(s,k),node:O,dynamicRequestTree:T?h(s,x):null,children:R}}(e,t,n,r,l,!1,s,c,d,m,[],g)}function p(e,t,n,r,l,a,u,o,d,p){return!l&&(void 0===t||(0,s.isNavigatingToNewRootLayout)(t,n))?f:function e(t,n,r,l,a,u,o,s){let f,d,p,g,y=n[1],v=0===Object.keys(y).length;if(void 0!==r&&r.navigatedAt+c.DYNAMIC_STALETIME_MS>t)f=r.rsc,d=r.loading,p=r.head,g=r.navigatedAt;else if(null===l)return m(t,n,null,a,u,o,s);else if(f=l[0],d=l[2],p=v?a:null,g=t,l[3]||u&&v)return m(t,n,l,a,u,o,s);let b=null!==l?l[1]:null,S=new Map,w=void 0!==r?r.parallelRoutes:null,E=new Map(w),_={},P=!1;if(v)s.push(o);else for(let n in y){let r=y[n],l=null!==b?b[n]:null,c=null!==w?w.get(n):void 0,f=r[0],d=o.concat([n,f]),p=(0,i.createRouterCacheKey)(f),h=e(t,r,void 0!==c?c.get(p):void 0,l,a,u,d,s);S.set(n,h);let m=h.dynamicRequestTree;null!==m?(P=!0,_[n]=m):_[n]=r;let g=h.node;if(null!==g){let e=new Map;e.set(p,g),E.set(n,e)}}return{route:n,node:{lazyData:null,rsc:f,prefetchRsc:null,head:p,prefetchHead:null,loading:d,parallelRoutes:E,navigatedAt:g},dynamicRequestTree:P?h(n,_):null,children:S}}(e,n,r,a,u,o,d,p)}function h(e,t){let n=[e[0],t];return 2 in e&&(n[2]=e[2]),3 in e&&(n[3]=e[3]),4 in e&&(n[4]=e[4]),n}function m(e,t,n,r,l,a,u){let o=h(t,t[1]);return o[3]="refetch",{route:t,node:function e(t,n,r,l,a,u,o){let s=n[1],c=null!==r?r[1]:null,f=new Map;for(let n in s){let r=s[n],d=null!==c?c[n]:null,p=r[0],h=u.concat([n,p]),m=(0,i.createRouterCacheKey)(p),g=e(t,r,void 0===d?null:d,l,a,h,o),y=new Map;y.set(m,g),f.set(n,y)}let d=0===f.size;d&&o.push(u);let p=null!==r?r[0]:null;return{lazyData:null,parallelRoutes:f,prefetchRsc:void 0!==p?p:null,prefetchHead:d?l:[null,null],rsc:w(),head:d?w():null,loading:null!==r?r[2]??null:w(),navigatedAt:t}}(e,t,n,r,l,a,u),dynamicRequestTree:o,children:null}}function g(e,t){t.then(t=>{if("string"==typeof t)return;let{flightData:n,debugInfo:r}=t;for(let t of n){let{segmentPath:n,tree:l,seedData:a,head:o}=t;a&&function(e,t,n,r,l,a){let o=e;for(let e=0;e{y(e,t,null)})}function y(e,t,n){let r=e.node;if(null===r)return;let l=e.children;if(null===l)v(e.route,r,t,n);else for(let e of l.values())y(e,t,n);e.dynamicRequestTree=null}function v(e,t,n,r){let l=e[1],a=t.parallelRoutes;for(let e in l){let t=l[e],u=a.get(e);if(void 0===u)continue;let o=t[0],s=(0,i.createRouterCacheKey)(o),c=u.get(s);void 0!==c&&v(t,c,n,r)}let u=t.rsc;S(u)&&(null===n?u.resolve(null,r):u.reject(n,r));let o=t.loading;S(o)&&o.resolve(null,r);let s=t.head;S(s)&&s.resolve(null,r)}let b=Symbol();function S(e){return e&&"object"==typeof e&&e.tag===b}function w(){let e,t,n=[],r=new Promise((n,r)=>{e=n,t=r});return r.status="pending",r.resolve=(t,l)=>{"pending"===r.status&&(r.status="fulfilled",r.value=t,null!==l&&n.push.apply(n,l),e(t))},r.reject=(e,l)=>{"pending"===r.status&&(r.status="rejected",r.reason=e,null!==l&&n.push.apply(n,l),t(e))},r.tag=b,r._debugInfo=n,r}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},18563,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"HasLoadingBoundary",{enumerable:!0,get:function(){return l}});var r,l=((r={})[r.SegmentHasLoadingBoundary=1]="SegmentHasLoadingBoundary",r[r.SubtreeHasLoadingBoundary=2]="SubtreeHasLoadingBoundary",r[r.SubtreeHasNoLoadingBoundary=3]="SubtreeHasNoLoadingBoundary",r)},24994,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r,l,a,u={FetchStrategy:function(){return c},NavigationResultTag:function(){return i},PrefetchPriority:function(){return s}};for(var o in u)Object.defineProperty(n,o,{enumerable:!0,get:u[o]});var i=((r={})[r.MPA=0]="MPA",r[r.Success=1]="Success",r[r.NoOp=2]="NoOp",r[r.Async=3]="Async",r),s=((l={})[l.Intent=2]="Intent",l[l.Default=1]="Default",l[l.Background=0]="Background",l),c=((a={})[a.LoadingBoundary=0]="LoadingBoundary",a[a.PPR=1]="PPR",a[a.PPRRuntime=2]="PPRRuntime",a[a.Full=3]="Full",a);("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},68323,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={deleteFromLru:function(){return f},lruPut:function(){return s},updateLruSize:function(){return c}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(47661),u=null,o=!1,i=0;function s(e){if(u===e)return;let t=e.prev,n=e.next;if(null===n||null===t?(i+=e.size,d()):(t.next=n,n.prev=t),null===u)e.prev=e,e.next=e;else{let t=u.prev;e.prev=t,null!==t&&(t.next=e),e.next=u,u.prev=e}u=e}function c(e,t){let n=e.size;e.size=t,null!==e.next&&(i=i-n+t,d())}function f(e){let t=e.next,n=e.prev;null!==t&&null!==n&&(i-=e.size,e.next=null,e.prev=null,u===e?u=t===u?null:t:(n.next=t,t.prev=n))}function d(){o||i<=0x3200000||(o=!0,h(p))}function p(){o=!1;for(;i>0x2d00000&&null!==u;){let e=u.prev;null!==e&&(0,a.deleteFromCacheMap)(e.value)}}let h="function"==typeof requestIdleCallback?requestIdleCallback:e=>setTimeout(e,0);("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},47661,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={Fallback:function(){return u},createCacheMap:function(){return i},deleteFromCacheMap:function(){return h},getFromCacheMap:function(){return s},isValueExpired:function(){return c},setInCacheMap:function(){return f},setSizeInCacheMap:function(){return g}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(68323),u={},o={};function i(){return{parent:null,key:null,value:null,map:null,prev:null,next:null,size:0}}function s(e,t,n,r,l){let i=function e(t,n,r,l,a,i){let s,f;if(null!==l)s=l.value,f=l.parent;else if(a&&i!==o)s=o,f=null;else return null===r.value?r:c(t,n,r.value)?(m(r),null):r;let d=r.map;if(null!==d){let r=d.get(s);if(void 0!==r){let l=e(t,n,r,f,a,s);if(null!==l)return l}let l=d.get(u);if(void 0!==l)return e(t,n,l,f,a,s)}return null}(e,t,n,r,l,0);return null===i||null===i.value?null:((0,a.lruPut)(i),i.value)}function c(e,t,n){return n.staleAt<=e||n.version{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={appendLayoutVaryPath:function(){return c},clonePageVaryPathWithNewSearchParams:function(){return m},finalizeLayoutVaryPath:function(){return f},finalizeMetadataVaryPath:function(){return p},finalizePageVaryPath:function(){return d},getFulfilledRouteVaryPath:function(){return s},getRouteVaryPath:function(){return i},getSegmentVaryPathForRequest:function(){return h}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(24994),u=e.r(47661),o=e.r(69434);function i(e,t,n){return{value:e,parent:{value:t,parent:{value:n,parent:null}}}}function s(e,t,n,r){return{value:e,parent:{value:t,parent:{value:r?n:u.Fallback,parent:null}}}}function c(e,t){return{value:t,parent:e}}function f(e,t){return{value:e,parent:t}}function d(e,t,n){return{value:e,parent:{value:t,parent:n}}}function p(e,t,n){return{value:e+o.HEAD_REQUEST_KEY,parent:{value:t,parent:n}}}function h(e,t){let n=t.varyPath;if(t.isPage&&e!==a.FetchStrategy.Full&&e!==a.FetchStrategy.PPRRuntime){let e=n.parent.parent;return{value:n.value,parent:{value:u.Fallback,parent:e}}}return n}function m(e,t){let n=e.parent;return{value:e.value,parent:{value:t,parent:n.parent}}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},63280,(e,t,n)=>{"use strict";function r(e,t){let n=new URL(e);return{pathname:n.pathname,search:n.search,nextUrl:t}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"createCacheKey",{enumerable:!0,get:function(){return r}}),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},40285,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={cancelPrefetchTask:function(){return w},isPrefetchTaskDirty:function(){return _},pingPrefetchTask:function(){return O},reschedulePrefetchTask:function(){return E},schedulePrefetchTask:function(){return S},startRevalidationCooldown:function(){return b}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(18563),u=e.r(22039),o=e.r(91666),i=e.r(91900),s=e.r(63280),c=e.r(24994),f=e.r(91395),d="function"==typeof queueMicrotask?queueMicrotask:e=>Promise.resolve().then(e).catch(e=>setTimeout(()=>{throw e})),p=[],h=0,m=0,g=!1,y=null,v=null;function b(){null!==v&&clearTimeout(v),v=setTimeout(()=>{v=null,k()},300)}function S(e,t,n,r,l){let a={key:e,treeAtTimeOfPrefetch:t,cacheVersion:(0,o.getCurrentCacheVersion)(),priority:r,phase:1,hasBackgroundWork:!1,spawnedRuntimePrefetches:null,fetchStrategy:n,sortId:m++,isCanceled:!1,onInvalidate:l,_heapIndex:-1};return P(a),H(p,a),k(),a}function w(e){e.isCanceled=!0,function(e,t){let n=t._heapIndex;if(-1!==n&&(t._heapIndex=-1,0!==e.length)){let r=e.pop();r!==t&&(e[n]=r,r._heapIndex=n,W(e,r,n))}}(p,e)}function E(e,t,n,r){e.isCanceled=!1,e.phase=1,e.sortId=m++,e.priority=e===y?c.PrefetchPriority.Intent:r,e.treeAtTimeOfPrefetch=t,e.fetchStrategy=n,P(e),-1!==e._heapIndex?q(p,e):H(p,e),k()}function _(e,t,n){let r=(0,o.getCurrentCacheVersion)();return e.cacheVersion!==r||e.treeAtTimeOfPrefetch!==n||e.key.nextUrl!==t}function P(e){e.priority===c.PrefetchPriority.Intent&&e!==y&&(null!==y&&y.priority!==c.PrefetchPriority.Background&&(y.priority=c.PrefetchPriority.Default,q(p,y)),y=e)}function k(){g||(g=!0,d(C))}function R(e){return null===v&&(e.priority===c.PrefetchPriority.Intent?h<12:h<4)}function T(e){return h++,e.then(e=>null===e?(x(),null):(e.closed.then(x),e.value))}function x(){h--,k()}function O(e){e.isCanceled||-1!==e._heapIndex||(H(p,e),k())}function C(){g=!1;let e=Date.now(),t=B(p);for(;null!==t&&R(t);){t.cacheVersion=(0,o.getCurrentCacheVersion)();let n=function(e,t){let n=t.key,r=(0,o.readOrCreateRouteCacheEntry)(e,t,n),l=function(e,t,n){switch(n.status){case o.EntryStatus.Empty:T((0,o.fetchRouteOnCacheMiss)(n,t,t.key)),n.staleAt=e+6e4,n.status=o.EntryStatus.Pending;case o.EntryStatus.Pending:{let e=n.blockedTasks;return null===e?n.blockedTasks=new Set([t]):e.add(t),1}case o.EntryStatus.Rejected:break;case o.EntryStatus.Fulfilled:{if(0!==t.phase)return 2;if(!R(t))return 0;let i=n.tree,s=t.fetchStrategy===c.FetchStrategy.PPR?n.isPPREnabled?c.FetchStrategy.PPR:c.FetchStrategy.LoadingBoundary:t.fetchStrategy;switch(s){case c.FetchStrategy.PPR:{var r,l,u;if(z(r=e,l=t,u=n,(0,o.readOrCreateSegmentCacheEntry)(r,c.FetchStrategy.PPR,u,u.metadata),l.key,u.metadata),0===function e(t,n,r,l,a){let u=(0,o.readOrCreateSegmentCacheEntry)(t,n.fetchStrategy,r,a);z(t,n,r,u,n.key,a);let i=l[1],s=a.slots;if(null!==s)for(let l in s){if(!R(n))return 0;let a=s[l],u=a.segment,c=i[l],f=c?.[0];if(0===(void 0!==f&&D(r,u,f)?e(t,n,r,c,a):function e(t,n,r,l){if(l.hasRuntimePrefetch)return null===n.spawnedRuntimePrefetches?n.spawnedRuntimePrefetches=new Set([l.requestKey]):n.spawnedRuntimePrefetches.add(l.requestKey),2;let a=(0,o.readOrCreateSegmentCacheEntry)(t,n.fetchStrategy,r,l);if(z(t,n,r,a,n.key,l),null!==l.slots){if(!R(n))return 0;for(let a in l.slots)if(0===e(t,n,r,l.slots[a]))return 0}return 2}(t,n,r,a)))return 0}return 2}(e,t,n,t.treeAtTimeOfPrefetch,i))return 0;let a=t.spawnedRuntimePrefetches;if(null!==a){let r=new Map;M(e,t,n,r,c.FetchStrategy.PPRRuntime);let l=function e(t,n,r,l,a,u){if(a.has(l.requestKey))return L(t,n,r,l,!1,u,c.FetchStrategy.PPRRuntime);let o={},i=l.slots;if(null!==i)for(let l in i){let s=i[l];o[l]=e(t,n,r,s,a,u)}return[l.segment,o,null,null]}(e,t,n,i,a,r);r.size>0&&T((0,o.fetchSegmentPrefetchesUsingDynamicRequest)(t,n,c.FetchStrategy.PPRRuntime,l,r))}return 2}case c.FetchStrategy.Full:case c.FetchStrategy.PPRRuntime:case c.FetchStrategy.LoadingBoundary:{let r=new Map;M(e,t,n,r,s);let l=function e(t,n,r,l,u,i,s){let f=l[1],d=u.slots,p={};if(null!==d)for(let l in d){let u=d[l],h=u.segment,m=f[l],g=m?.[0];if(void 0!==g&&D(r,h,g)){let a=e(t,n,r,m,u,i,s);p[l]=a}else switch(s){case c.FetchStrategy.LoadingBoundary:{let e=u.hasLoadingBoundary!==a.HasLoadingBoundary.SubtreeHasNoLoadingBoundary?function e(t,n,r,l,u,i){let s=null===u?"inside-shared-layout":null,f=(0,o.readOrCreateSegmentCacheEntry)(t,n.fetchStrategy,r,l);switch(f.status){case o.EntryStatus.Empty:i.set(l.requestKey,(0,o.upgradeToPendingSegment)(f,c.FetchStrategy.LoadingBoundary)),"refetch"!==u&&(s=u="refetch");break;case o.EntryStatus.Fulfilled:if(l.hasLoadingBoundary===a.HasLoadingBoundary.SegmentHasLoadingBoundary)return(0,o.convertRouteTreeToFlightRouterState)(l);case o.EntryStatus.Pending:case o.EntryStatus.Rejected:}let d={};if(null!==l.slots)for(let a in l.slots){let o=l.slots[a];d[a]=e(t,n,r,o,u,i)}return[l.segment,d,null,s,l.isRootLayout]}(t,n,r,u,null,i):(0,o.convertRouteTreeToFlightRouterState)(u);p[l]=e;break}case c.FetchStrategy.PPRRuntime:{let e=L(t,n,r,u,!1,i,s);p[l]=e;break}case c.FetchStrategy.Full:{let e=L(t,n,r,u,!1,i,s);p[l]=e}}}return[u.segment,p,null,null,u.isRootLayout]}(e,t,n,t.treeAtTimeOfPrefetch,i,r,s);return r.size>0&&T((0,o.fetchSegmentPrefetchesUsingDynamicRequest)(t,n,s,l,r)),2}}}}return 2}(e,t,r);if(0!==l&&""!==n.search){let r=new URL(n.pathname,location.origin),l=(0,s.createCacheKey)(r.href,n.nextUrl),a=(0,o.readOrCreateRouteCacheEntry)(e,t,l);switch(a.status){case o.EntryStatus.Empty:N(t)&&(a.status=o.EntryStatus.Pending,T((0,o.fetchRouteOnCacheMiss)(a,t,l)));case o.EntryStatus.Pending:case o.EntryStatus.Fulfilled:case o.EntryStatus.Rejected:}}return l}(e,t),r=t.hasBackgroundWork;switch(t.hasBackgroundWork=!1,t.spawnedRuntimePrefetches=null,n){case 0:return;case 1:V(p),t=B(p);continue;case 2:1===t.phase?(t.phase=0,q(p,t)):r?(t.priority=c.PrefetchPriority.Background,q(p,t)):V(p),t=B(p);continue}}}function N(e){return e.priority===c.PrefetchPriority.Background||(e.hasBackgroundWork=!0,!1)}function M(e,t,n,r,l){L(e,t,n,n.metadata,!1,r,l===c.FetchStrategy.LoadingBoundary?c.FetchStrategy.Full:l)}function L(e,t,n,r,l,a,u){let i=(0,o.readOrCreateSegmentCacheEntry)(e,u,n,r),s=null;switch(i.status){case o.EntryStatus.Empty:s=(0,o.upgradeToPendingSegment)(i,u);break;case o.EntryStatus.Fulfilled:i.isPartial&&(0,o.canNewFetchStrategyProvideMoreContent)(i.fetchStrategy,u)&&(s=F(e,n,r,u));break;case o.EntryStatus.Pending:case o.EntryStatus.Rejected:(0,o.canNewFetchStrategyProvideMoreContent)(i.fetchStrategy,u)&&(s=F(e,n,r,u))}let c={};if(null!==r.slots)for(let o in r.slots){let i=r.slots[o];c[o]=L(e,t,n,i,l||null!==s,a,u)}null!==s&&a.set(r.requestKey,s);let f=l||null===s?null:"refetch";return[r.segment,c,null,f,r.isRootLayout]}function z(e,t,n,r,l,a){switch(r.status){case o.EntryStatus.Empty:T((0,o.fetchSegmentOnCacheMiss)(n,(0,o.upgradeToPendingSegment)(r,c.FetchStrategy.PPR),l,a));break;case o.EntryStatus.Pending:switch(r.fetchStrategy){case c.FetchStrategy.PPR:case c.FetchStrategy.PPRRuntime:case c.FetchStrategy.Full:break;case c.FetchStrategy.LoadingBoundary:N(t)&&j(e,n,l,a);break;default:r.fetchStrategy}break;case o.EntryStatus.Rejected:switch(r.fetchStrategy){case c.FetchStrategy.PPR:case c.FetchStrategy.PPRRuntime:case c.FetchStrategy.Full:break;case c.FetchStrategy.LoadingBoundary:j(e,n,l,a);break;default:r.fetchStrategy}case o.EntryStatus.Fulfilled:}}function j(e,t,n,r){let l=(0,o.readOrCreateRevalidatingSegmentEntry)(e,c.FetchStrategy.PPR,t,r);switch(l.status){case o.EntryStatus.Empty:I(T((0,o.fetchSegmentOnCacheMiss)(t,(0,o.upgradeToPendingSegment)(l,c.FetchStrategy.PPR),n,r)),(0,i.getSegmentVaryPathForRequest)(c.FetchStrategy.PPR,r));case o.EntryStatus.Pending:case o.EntryStatus.Fulfilled:case o.EntryStatus.Rejected:}}function F(e,t,n,r){let l=(0,o.readOrCreateRevalidatingSegmentEntry)(e,r,t,n);if(l.status===o.EntryStatus.Empty){let e=(0,o.upgradeToPendingSegment)(l,r);return I((0,o.waitForSegmentCacheEntry)(e),(0,i.getSegmentVaryPathForRequest)(r,n)),e}if((0,o.canNewFetchStrategyProvideMoreContent)(l.fetchStrategy,r)){let e=(0,o.overwriteRevalidatingSegmentCacheEntry)(r,t,n),l=(0,o.upgradeToPendingSegment)(e,r);return I((0,o.waitForSegmentCacheEntry)(l),(0,i.getSegmentVaryPathForRequest)(r,n)),l}switch(l.status){case o.EntryStatus.Pending:case o.EntryStatus.Fulfilled:case o.EntryStatus.Rejected:default:return null}}let A=()=>{};function I(e,t){e.then(e=>{null!==e&&(0,o.upsertSegmentEntry)(Date.now(),t,e)},A)}function D(e,t,n){return n===f.PAGE_SEGMENT_KEY?t===(0,f.addSearchParamsIfPageSegment)(f.PAGE_SEGMENT_KEY,Object.fromEntries(new URLSearchParams(e.renderedSearch))):(0,u.matchSegment)(n,t)}function U(e,t){let n=t.priority-e.priority;if(0!==n)return n;let r=t.phase-e.phase;return 0!==r?r:t.sortId-e.sortId}function H(e,t){let n=e.length;e.push(t),t._heapIndex=n,$(e,t,n)}function B(e){return 0===e.length?null:e[0]}function V(e){if(0===e.length)return null;let t=e[0];t._heapIndex=-1;let n=e.pop();return n!==t&&(e[0]=n,n._heapIndex=0,W(e,n,0)),t}function q(e,t){let n=t._heapIndex;-1!==n&&(0===n?W(e,t,0):U(e[n-1>>>1],t)>0?$(e,t,n):W(e,t,n))}function $(e,t,n){let r=n;for(;r>0;){let n=r-1>>>1,l=e[n];if(!(U(l,t)>0))return;e[n]=t,t._heapIndex=n,e[r]=l,l._heapIndex=r,r=n}}function W(e,t,n){let r=n,l=e.length,a=l>>>1;for(;rU(a,t))uU(o,a)?(e[r]=o,o._heapIndex=r,e[u]=t,t._heapIndex=u,r=u):(e[r]=a,a._heapIndex=r,e[n]=t,t._heapIndex=n,r=n);else{if(!(uU(o,t)))return;e[r]=o,o._heapIndex=r,e[u]=t,t._heapIndex=u,r=u}}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},28732,(e,t,n)=>{"use strict";function r(e){let t=e.indexOf("#"),n=e.indexOf("?"),r=n>-1&&(t<0||n-1?{pathname:e.substring(0,r?n:t),query:r?e.substring(n,t>-1?t:void 0):"",hash:t>-1?e.slice(t):""}:{pathname:e,query:"",hash:""}}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"parsePath",{enumerable:!0,get:function(){return r}})},26935,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"addPathPrefix",{enumerable:!0,get:function(){return l}});let r=e.r(28732);function l(e,t){if(!e.startsWith("/")||!t)return e;let{pathname:n,query:l,hash:a}=(0,r.parsePath)(e);return`${t}${n}${l}${a}`}},20206,(e,t,n)=>{"use strict";function r(e){return e.replace(/\/$/,"")||"/"}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"removeTrailingSlash",{enumerable:!0,get:function(){return r}})},67268,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"normalizePathTrailingSlash",{enumerable:!0,get:function(){return a}});let r=e.r(20206),l=e.r(28732),a=e=>{if(!e.startsWith("/"))return e;let{pathname:t,query:n,hash:a}=(0,l.parsePath)(e);return/\.[^/]+\/?$/.test(t)?`${(0,r.removeTrailingSlash)(t)}${n}${a}`:t.endsWith("/")?`${t}${n}${a}`:`${t}/${n}${a}`};("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},39940,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"addBasePath",{enumerable:!0,get:function(){return a}});let r=e.r(26935),l=e.r(67268);function a(e,t){return(0,l.normalizePathTrailingSlash)((0,r.addPathPrefix)(e,""))}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},93259,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={createPrefetchURL:function(){return i},isExternalURL:function(){return o}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(62112),u=e.r(39940);function o(e){return e.origin!==window.location.origin}function i(e){let t;if((0,a.isBot)(window.navigator.userAgent))return null;try{t=new URL((0,u.addBasePath)(e),window.location.href)}catch(t){throw Object.defineProperty(Error(`Cannot prefetch '${e}' because it cannot be converted to a URL.`),"__NEXT_ERROR_CODE",{value:"E234",enumerable:!1,configurable:!0})}return o(t)?null:t}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},79111,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={IDLE_LINK_STATUS:function(){return f},PENDING_LINK_STATUS:function(){return c},mountFormInstance:function(){return S},mountLinkInstance:function(){return b},onLinkVisibilityChanged:function(){return E},onNavigationIntent:function(){return _},pingVisibleLinks:function(){return k},setLinkForCurrentNavigation:function(){return d},unmountLinkForCurrentNavigation:function(){return p},unmountPrefetchableInstance:function(){return w}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(24994),u=e.r(63280),o=e.r(40285),i=e.r(30668),s=null,c={pending:!0},f={pending:!1};function d(e){(0,i.startTransition)(()=>{s?.setOptimisticLinkStatus(f),e?.setOptimisticLinkStatus(c),s=e})}function p(e){s===e&&(s=null)}let h="function"==typeof WeakMap?new WeakMap:new Map,m=new Set,g="function"==typeof IntersectionObserver?new IntersectionObserver(function(e){for(let t of e){let e=t.intersectionRatio>0;E(t.target,e)}},{rootMargin:"200px"}):null;function y(e,t){void 0!==h.get(e)&&w(e),h.set(e,t),null!==g&&g.observe(e)}function v(t){if("undefined"==typeof window)return null;{let{createPrefetchURL:n}=e.r(93259);try{return n(t)}catch{return("function"==typeof reportError?reportError:console.error)(`Cannot prefetch '${t}' because it cannot be converted to a URL.`),null}}}function b(e,t,n,r,l,a){if(l){let l=v(t);if(null!==l){let t={router:n,fetchStrategy:r,isVisible:!1,prefetchTask:null,prefetchHref:l.href,setOptimisticLinkStatus:a};return y(e,t),t}}return{router:n,fetchStrategy:r,isVisible:!1,prefetchTask:null,prefetchHref:null,setOptimisticLinkStatus:a}}function S(e,t,n,r){let l=v(t);null===l||y(e,{router:n,fetchStrategy:r,isVisible:!1,prefetchTask:null,prefetchHref:l.href,setOptimisticLinkStatus:null})}function w(e){let t=h.get(e);if(void 0!==t){h.delete(e),m.delete(t);let n=t.prefetchTask;null!==n&&(0,o.cancelPrefetchTask)(n)}null!==g&&g.unobserve(e)}function E(e,t){let n=h.get(e);void 0!==n&&(n.isVisible=t,t?m.add(n):m.delete(n),P(n,a.PrefetchPriority.Default))}function _(e,t){let n=h.get(e);void 0!==n&&void 0!==n&&P(n,a.PrefetchPriority.Intent)}function P(t,n){if("undefined"!=typeof window){let r=t.prefetchTask;if(!t.isVisible){null!==r&&(0,o.cancelPrefetchTask)(r);return}let{getCurrentAppRouterState:l}=e.r(19998),a=l();if(null!==a){let e=a.tree;if(null===r){let r=a.nextUrl,l=(0,u.createCacheKey)(t.prefetchHref,r);t.prefetchTask=(0,o.schedulePrefetchTask)(l,e,t.fetchStrategy,n,null)}else(0,o.reschedulePrefetchTask)(r,e,t.fetchStrategy,n)}}}function k(e,t){for(let n of m){let r=n.prefetchTask;if(null!==r&&!(0,o.isPrefetchTaskDirty)(r,e,t))continue;null!==r&&(0,o.cancelPrefetchTask)(r);let l=(0,u.createCacheKey)(n.prefetchHref,e);n.prefetchTask=(0,o.schedulePrefetchTask)(l,t,n.fetchStrategy,a.PrefetchPriority.Default,null)}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},76534,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={DOC_PREFETCH_RANGE_HEADER_VALUE:function(){return u},doesExportedHtmlMatchBuildId:function(){return s},insertBuildIdComment:function(){return i}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a="",u="bytes=0-63";function o(e){return e.slice(0,24).replace(/-/g,"_")}function i(e,t){return t.includes("-->")||!e.startsWith(a)?e:e.replace(a,a+"")}function s(e,t){return e.startsWith(a+"")}},91666,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r,l={EntryStatus:function(){return k},canNewFetchStrategyProvideMoreContent:function(){return el},convertRouteTreeToFlightRouterState:function(){return function e(t){let n={};if(null!==t.slots)for(let r in t.slots)n[r]=e(t.slots[r]);return[t.segment,n,null,null,t.isRootLayout]}},createDetachedSegmentCacheEntry:function(){return q},fetchRouteOnCacheMiss:function(){return X},fetchSegmentOnCacheMiss:function(){return Y},fetchSegmentPrefetchesUsingDynamicRequest:function(){return J},getCurrentCacheVersion:function(){return N},getStaleTimeMs:function(){return P},overwriteRevalidatingSegmentCacheEntry:function(){return B},pingInvalidationListeners:function(){return L},readOrCreateRevalidatingSegmentEntry:function(){return H},readOrCreateRouteCacheEntry:function(){return A},readOrCreateSegmentCacheEntry:function(){return U},readRouteCacheEntry:function(){return z},readSegmentCacheEntry:function(){return j},requestOptimisticRouteCacheEntry:function(){return I},revalidateEntireCache:function(){return M},upgradeToPendingSegment:function(){return $},upsertSegmentEntry:function(){return V},waitForSegmentCacheEntry:function(){return F}};for(var a in l)Object.defineProperty(n,a,{enumerable:!0,get:l[a]});let u=e.r(18563),o=e.r(2089),i=e.r(20320),s=e.r(40285),c=e.r(91900),f=e.r(70410),d=e.r(80118),p=e.r(63280),h=e.r(88617),m=e.r(47661),g=e.r(69434),y=e.r(94955),v=e.r(28806),b=e.r(79111),S=e.r(91395),w=e.r(76534),E=e.r(24994),_=e.r(59162);function P(e){return 1e3*Math.max(e,30)}var k=((r={})[r.Empty=0]="Empty",r[r.Pending=1]="Pending",r[r.Fulfilled=2]="Fulfilled",r[r.Rejected=3]="Rejected",r);let R=["",{},null,"metadata-only"],T=(0,m.createCacheMap)(),x=(0,m.createCacheMap)(),O=null,C=0;function N(){return C}function M(e,t){C++,(0,s.startRevalidationCooldown)(),(0,b.pingVisibleLinks)(e,t),L(e,t)}function L(e,t){if(null!==O){let n=O;for(let r of(O=null,n))(0,s.isPrefetchTaskDirty)(r,e,t)&&function(e){let t=e.onInvalidate;if(null!==t){e.onInvalidate=null;try{t()}catch(e){"function"==typeof reportError?reportError(e):console.error(e)}}}(r)}}function z(e,t){let n=(0,c.getRouteVaryPath)(t.pathname,t.search,t.nextUrl);return(0,m.getFromCacheMap)(e,C,T,n,!1)}function j(e,t){return(0,m.getFromCacheMap)(e,C,x,t,!1)}function F(e){let t=e.promise;return null===t&&(t=e.promise=(0,_.createPromiseWithResolvers)()),t.promise}function A(e,t,n){null!==t.onInvalidate&&(null===O?O=new Set([t]):O.add(t));let r=z(e,n);if(null!==r)return r;let l={canonicalUrl:null,status:0,blockedTasks:null,tree:null,metadata:null,couldBeIntercepted:!0,isPPREnabled:!1,renderedSearch:null,ref:null,size:0,staleAt:1/0,version:C},a=(0,c.getRouteVaryPath)(n.pathname,n.search,n.nextUrl);return(0,m.setInCacheMap)(T,a,l,!1),l}function I(e,t,n){let r=t.search;if(""===r)return null;let l=new URL(t);l.search="";let a=z(e,(0,p.createCacheKey)(l.href,n));if(null===a||2!==a.status)return null;let u=new URL(a.canonicalUrl,t.origin),o=""!==u.search?u.search:r,i=""!==a.renderedSearch?a.renderedSearch:r,s=new URL(a.canonicalUrl,location.origin);return s.search=o,{canonicalUrl:(0,d.createHrefFromUrl)(s),status:2,blockedTasks:null,tree:D(a.tree,i),metadata:D(a.metadata,i),couldBeIntercepted:a.couldBeIntercepted,isPPREnabled:a.isPPREnabled,renderedSearch:i,ref:null,size:0,staleAt:a.staleAt,version:a.version}}function D(e,t){let n=null,r=e.slots;if(null!==r)for(let e in n={},r){let l=r[e];n[e]=D(l,t)}return e.isPage?{requestKey:e.requestKey,segment:e.segment,varyPath:(0,c.clonePageVaryPathWithNewSearchParams)(e.varyPath,t),isPage:!0,slots:n,isRootLayout:e.isRootLayout,hasLoadingBoundary:e.hasLoadingBoundary,hasRuntimePrefetch:e.hasRuntimePrefetch}:{requestKey:e.requestKey,segment:e.segment,varyPath:e.varyPath,isPage:!1,slots:n,isRootLayout:e.isRootLayout,hasLoadingBoundary:e.hasLoadingBoundary,hasRuntimePrefetch:e.hasRuntimePrefetch}}function U(e,t,n,r){let l=j(e,r.varyPath);if(null!==l)return l;let a=(0,c.getSegmentVaryPathForRequest)(t,r),u=q(n.staleAt);return(0,m.setInCacheMap)(x,a,u,!1),u}function H(e,t,n,r){var l;let a=(l=r.varyPath,(0,m.getFromCacheMap)(e,C,x,l,!0));if(null!==a)return a;let u=(0,c.getSegmentVaryPathForRequest)(t,r),o=q(n.staleAt);return(0,m.setInCacheMap)(x,u,o,!0),o}function B(e,t,n){let r=(0,c.getSegmentVaryPathForRequest)(e,n),l=q(t.staleAt);return(0,m.setInCacheMap)(x,r,l,!0),l}function V(e,t,n){if((0,m.isValueExpired)(e,C,n))return null;let r=j(e,t);if(null!==r){var l;if(n.fetchStrategy!==r.fetchStrategy&&(l=r.fetchStrategy,!(l""!==e),r=g.ROOT_SEGMENT_REQUEST_KEY,function e(t,n,r,l,a,o,i,s){let f,d,p=null,m=t.slots;if(null!==m)for(let t in f=!1,d=(0,c.finalizeLayoutVaryPath)(l,r),p={},m){let n,u,f,d=m[t],y=d.name,v=d.paramType,b=d.paramKey;if(null!==v){let e=(0,h.parseDynamicParamFromURLPart)(v,a,o),t=null!==b?b:(0,h.getCacheKeyForDynamicParam)(e,"");f=(0,c.appendLayoutVaryPath)(r,t),u=[y,t,v],n=!0}else f=r,u=y,n=(0,h.doesStaticSegmentAppearInURL)(y);let S=n?o+1:o,w=(0,g.createSegmentRequestKeyPart)(u),E=(0,g.appendSegmentRequestKeyPart)(l,t,w);p[t]=e(d,u,f,E,a,S,i,s)}else l.endsWith(S.PAGE_SEGMENT_KEY)?(f=!0,d=(0,c.finalizePageVaryPath)(l,i,r),null===s.metadataVaryPath&&(s.metadataVaryPath=(0,c.finalizeMetadataVaryPath)(l,i,r))):(f=!1,d=(0,c.finalizeLayoutVaryPath)(l,r));return{requestKey:l,segment:n,varyPath:d,isPage:f,slots:p,isRootLayout:t.isRootLayout,hasLoadingBoundary:u.HasLoadingBoundary.SegmentHasLoadingBoundary,hasRuntimePrefetch:t.hasRuntimePrefetch}}(o.tree,r,null,g.ROOT_SEGMENT_REQUEST_KEY,n,0,d,v)),E=v.metadataVaryPath;if(null===E)return Q(e,Date.now()+1e4),null;let _=P(o.staleTime);y=Date.now()+_,l={requestKey:g.HEAD_REQUEST_KEY,segment:g.HEAD_REQUEST_KEY,varyPath:E,isPage:!0,slots:null,isRootLayout:!1,hasLoadingBoundary:u.HasLoadingBoundary.SubtreeHasNoLoadingBoundary,hasRuntimePrefetch:!1},e.status=2,e.tree=w,e.metadata=l,e.staleAt=y,e.couldBeIntercepted=k,e.canonicalUrl=b,e.renderedSearch=d,e.isPPREnabled=x,W(e)}if(!k){let t=(0,c.getFulfilledRouteVaryPath)(r,l,a,k);(0,m.setInCacheMap)(T,t,e,!1)}return{value:null,closed:R.promise}}catch(t){return Q(e,Date.now()+1e4),null}}async function Y(e,t,n,r){let l=new URL(e.canonicalUrl,location.origin),a=n.nextUrl,u=r.requestKey,s=u===g.ROOT_SEGMENT_REQUEST_KEY?"/_index":u,c={[o.RSC_HEADER]:"1",[o.NEXT_ROUTER_PREFETCH_HEADER]:"1",[o.NEXT_ROUTER_SEGMENT_PREFETCH_HEADER]:s};null!==a&&(c[o.NEXT_URL]=a);let d=er(l,s);try{let n=await et(d,c);if(!n||!n.ok||204===n.status||"2"!==n.headers.get(o.NEXT_DID_POSTPONE_HEADER)&&0||!n.body)return G(t,Date.now()+1e4),null;let r=(0,_.createPromiseWithResolvers)(),l=en(n.body,r.resolve,function(e){(0,m.setSizeInCacheMap)(t,e)}),a=await (0,i.createFromNextReadableStream)(l,c);if(a.buildId!==(0,f.getAppBuildId)())return G(t,Date.now()+1e4),null;return{value:K(t,a.rsc,a.loading,e.staleAt,a.isPartial),closed:r.promise}}catch(e){return G(t,Date.now()+1e4),null}}async function J(e,t,n,r,l){let a=e.key,u=new URL(t.canonicalUrl,location.origin),s=a.nextUrl;1===l.size&&l.has(t.metadata.requestKey)&&(r=R);let c={[o.RSC_HEADER]:"1",[o.NEXT_ROUTER_STATE_TREE_HEADER]:(0,y.prepareFlightRouterStateForRequest)(r)};switch(null!==s&&(c[o.NEXT_URL]=s),n){case E.FetchStrategy.Full:break;case E.FetchStrategy.PPRRuntime:c[o.NEXT_ROUTER_PREFETCH_HEADER]="2";break;case E.FetchStrategy.LoadingBoundary:c[o.NEXT_ROUTER_PREFETCH_HEADER]="1"}try{let r=await et(u,c);if(!r||!r.ok||!r.body||(0,h.getRenderedSearch)(r)!==t.renderedSearch)return Z(l,Date.now()+1e4),null;let a=(0,_.createPromiseWithResolvers)(),s=null,d=en(r.body,a.resolve,function(e){if(null===s)return;let t=e/s.length;for(let e of s)(0,m.setSizeInCacheMap)(e,t)}),p=await (0,i.createFromNextReadableStream)(d,c),g=n===E.FetchStrategy.PPRRuntime&&p.rp?.[0]===!0;return s=function(e,t,n,r,l,a,u,i){if(l.b!==(0,f.getAppBuildId)())return null!==i&&Z(i,e+1e4),null;let s=(0,y.normalizeFlightData)(l.f);if("string"==typeof s)return null;let c="number"==typeof l.rp?.[1]?l.rp[1]:parseInt(r.headers.get(o.NEXT_ROUTER_STALE_TIME_HEADER)??"",10),d=e+(isNaN(c)?v.STATIC_STALETIME_MS:P(c));for(let r of s){let l=r.seedData;if(null!==l){let o=r.segmentPath,s=u.tree;for(let t=0;t{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"navigate",{enumerable:!0,get:function(){return c}});let r=e.r(20320),l=e.r(1989),a=e.r(80118),u=e.r(91666),o=e.r(63280),i=e.r(91395),s=e.r(24994);function c(e,t,n,r,l,a,i){let c=Date.now(),d=e.href,g=d===window.location.href,y=(0,o.createCacheKey)(d,l),v=(0,u.readRouteCacheEntry)(c,y);if(null!==v&&v.status===u.EntryStatus.Fulfilled){let u=p(c,v,v.tree),o=u.flightRouterState,i=u.seedData,s=h(c,v),d=s.rsc,m=s.isPartial,y=v.canonicalUrl+e.hash;return f(c,e,t,l,g,n,r,o,i,d,m,y,v.renderedSearch,a,e.hash)}if(null===v||v.status!==u.EntryStatus.Rejected){let o=(0,u.requestOptimisticRouteCacheEntry)(c,e,l);if(null!==o){let u=p(c,o,o.tree),i=u.flightRouterState,s=u.seedData,d=h(c,o),m=d.rsc,y=d.isPartial,v=o.canonicalUrl+e.hash;return f(c,e,t,l,g,n,r,i,s,m,y,v,o.renderedSearch,a,e.hash)}}let b=i.collectedDebugInfo??[];return void 0===i.collectedDebugInfo&&(b=i.collectedDebugInfo=[]),{tag:s.NavigationResultTag.Async,data:m(c,e,t,l,g,n,r,a,e.hash,b)}}function f(e,t,n,a,u,o,i,c,f,p,h,m,g,y,v){let b=[],S=(0,l.startPPRNavigation)(e,n,o,i,c,f,p,h,u,b);if(null!==S){let e=S.dynamicRequestTree;if(null!==e){let n=(0,r.fetchServerResponse)(new URL(m,t.origin),{flightRouterState:e,nextUrl:a});(0,l.listenForDynamicRequest)(S,n)}return d(S,o,m,g,b,y,v)}return{tag:s.NavigationResultTag.NoOp,data:{canonicalUrl:m,shouldScroll:y}}}function d(e,t,n,r,l,a,u){let o=e.route;if(null===o)return{tag:s.NavigationResultTag.MPA,data:n};let i=e.node;return{tag:s.NavigationResultTag.Success,data:{flightRouterState:o,cacheNode:null!==i?i:t,canonicalUrl:n,renderedSearch:r,scrollableSegments:l,shouldScroll:a,hash:u}}}function p(e,t,n){let r={},l={},a=n.slots;if(null!==a)for(let n in a){let u=p(e,t,a[n]);r[n]=u.flightRouterState,l[n]=u.seedData}let o=null,s=null,c=!0,f=(0,u.readSegmentCacheEntry)(e,n.varyPath);if(null!==f)switch(f.status){case u.EntryStatus.Fulfilled:o=f.rsc,s=f.loading,c=f.isPartial;break;case u.EntryStatus.Pending:{let e=(0,u.waitForSegmentCacheEntry)(f);o=e.then(e=>null!==e?e.rsc:null),s=e.then(e=>null!==e?e.loading:null),c=!0}case u.EntryStatus.Empty:case u.EntryStatus.Rejected:}return{flightRouterState:[(0,i.addSearchParamsIfPageSegment)(n.segment,Object.fromEntries(new URLSearchParams(t.renderedSearch))),r,null,null,n.isRootLayout],seedData:[o,l,s,c,!1]}}function h(e,t){let n=null,r=!0,l=(0,u.readSegmentCacheEntry)(e,t.metadata.varyPath);if(null!==l)switch(l.status){case u.EntryStatus.Fulfilled:n=l.rsc,r=l.isPartial;break;case u.EntryStatus.Pending:n=(0,u.waitForSegmentCacheEntry)(l).then(e=>null!==e?e.rsc:null),r=!0;case u.EntryStatus.Empty:case u.EntryStatus.Rejected:}return{rsc:n,isPartial:r}}async function m(e,t,n,u,o,i,c,f,p,h){let m=(0,r.fetchServerResponse)(t,{flightRouterState:c,nextUrl:u}),g=await m;if("string"==typeof g)return{tag:s.NavigationResultTag.MPA,data:g};let{flightData:y,canonicalUrl:v,renderedSearch:b,debugInfo:S}=g;null!==S&&h.push(...S);let w=function(e,t){let n=e;for(let{segmentPath:r,tree:l}of t){let t=n!==e;n=function e(t,n,r,l,a){if(a===r.length)return n;let u=r[a],o=t[1],i={};for(let t in o)if(t===u){let u=o[t];i[t]=e(u,n,r,l,a+2)}else i[t]=o[t];if(l)return t[1]=i,t;let s=[t[0],i];return 2 in t&&(s[2]=t[2]),3 in t&&(s[3]=t[3]),4 in t&&(s[4]=t[4]),s}(n,l,r,t,0)}return n}(c,y),E=[],_=(0,l.startPPRNavigation)(e,n,i,c,w,null,null,!0,o,E);return null!==_?(null!==_.dynamicRequestTree&&(0,l.listenForDynamicRequest)(_,m),d(_,i,(0,a.createHrefFromUrl)(v),b,E,f,p)):{tag:s.NavigationResultTag.NoOp,data:{canonicalUrl:(0,a.createHrefFromUrl)(v),shouldScroll:f}}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},28806,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={DYNAMIC_STALETIME_MS:function(){return c},STATIC_STALETIME_MS:function(){return f},generateSegmentsFromPatch:function(){return function e(t){let n=[],[r,l]=t;if(0===Object.keys(l).length)return[[r]];for(let[t,a]of Object.entries(l))for(let l of e(a))""===r?n.push([t,...l]):n.push([r,t,...l]);return n}},handleExternalUrl:function(){return d},navigateReducer:function(){return p}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(80118),u=e.r(40494),o=e.r(94345),i=e.r(24994),s=e.r(91666),c=1e3*Number("0"),f=(0,s.getStaleTimeMs)(Number("300"));function d(e,t,n,r){return t.mpaNavigation=!0,t.canonicalUrl=n,t.pendingPush=r,t.scrollableSegments=void 0,(0,u.handleMutable)(e,t)}function p(e,t){let{url:n,isExternalUrl:r,navigateType:l,shouldScroll:s}=t,c={},f=(0,a.createHrefFromUrl)(n),p="push"===l;if(c.preserveCustomHistoryState=!1,c.pendingPush=p,r)return d(e,c,n.toString(),p);if(document.getElementById("__next-page-redirect"))return d(e,c,f,p);let h=new URL(e.canonicalUrl,location.origin),m=(0,o.navigate)(n,h,e.cache,e.tree,e.nextUrl,s,c);return function e(t,n,r,l,a){switch(a.tag){case i.NavigationResultTag.MPA:return d(n,r,a.data,l);case i.NavigationResultTag.NoOp:{r.canonicalUrl=a.data.canonicalUrl;let e=new URL(n.canonicalUrl,t);return t.pathname===e.pathname&&t.search===e.search&&t.hash!==e.hash&&(r.onlyHashChange=!0,r.shouldScroll=a.data.shouldScroll,r.hashFragment=t.hash,r.scrollableSegments=[]),(0,u.handleMutable)(n,r)}case i.NavigationResultTag.Success:return r.cache=a.data.cacheNode,r.patchedTree=a.data.flightRouterState,r.renderedSearch=a.data.renderedSearch,r.canonicalUrl=a.data.canonicalUrl,r.scrollableSegments=a.data.scrollableSegments,r.shouldScroll=a.data.shouldScroll,r.hashFragment=a.data.hash,(0,u.handleMutable)(n,r);case i.NavigationResultTag.Async:return a.data.then(a=>e(t,n,r,l,a),()=>n);default:return n}}(n,e,c,p,m)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},61447,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"fillLazyItemsTillLeafWithHead",{enumerable:!0,get:function(){return function e(t,n,l,a,u,o){if(0===Object.keys(a[1]).length){n.head=o;return}for(let i in a[1]){let s,c=a[1][i],f=c[0],d=(0,r.createRouterCacheKey)(f),p=null!==u&&void 0!==u[1][i]?u[1][i]:null;if(l){let r=l.parallelRoutes.get(i);if(r){let l,a=new Map(r),u=a.get(d);l=null!==p?{lazyData:null,rsc:p[0],prefetchRsc:null,head:null,prefetchHead:null,loading:p[2],parallelRoutes:new Map(u?.parallelRoutes),navigatedAt:t}:{lazyData:null,rsc:null,prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:new Map(u?.parallelRoutes),loading:null,navigatedAt:t},a.set(d,l),e(t,l,u,c,p||null,o),n.parallelRoutes.set(i,a);continue}}if(null!==p){let e=p[0],n=p[2];s={lazyData:null,rsc:e,prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:new Map,loading:n,navigatedAt:t}}else s={lazyData:null,rsc:null,prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:new Map,loading:null,navigatedAt:t};let h=n.parallelRoutes.get(i);h?h.set(d,s):n.parallelRoutes.set(i,new Map([[d,s]])),e(t,s,void 0,c,p,o)}}}});let r=e.r(43317);("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},59941,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"invalidateCacheByRouterState",{enumerable:!0,get:function(){return l}});let r=e.r(43317);function l(e,t,n){for(let l in n[1]){let a=n[1][l][0],u=(0,r.createRouterCacheKey)(a),o=t.parallelRoutes.get(l);if(o){let t=new Map(o);t.delete(u),e.parallelRoutes.set(l,t)}}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},96397,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={fillCacheWithNewSubTreeData:function(){return c},fillCacheWithNewSubTreeDataButOnlyLoading:function(){return f}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(59941),u=e.r(61447),o=e.r(43317),i=e.r(91395);function s(e,t,n,r,l){let{segmentPath:s,seedData:c,tree:f,head:d}=r,p=t,h=n;for(let t=0;t{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"applyFlightData",{enumerable:!0,get:function(){return a}});let r=e.r(61447),l=e.r(96397);function a(e,t,n,a){let{tree:u,seedData:o,head:i,isRootRender:s}=a;if(null===o)return!1;if(s){let l=o[0];n.loading=o[2],n.rsc=l,n.prefetchRsc=null,(0,r.fillLazyItemsTillLeafWithHead)(e,n,t,u,o,i)}else n.rsc=t.rsc,n.prefetchRsc=t.prefetchRsc,n.parallelRoutes=new Map(t.parallelRoutes),n.loading=t.loading,(0,l.fillCacheWithNewSubTreeData)(e,n,t,a);return!0}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},51441,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={addRefreshMarkerToActiveParallelSegments:function(){return function e(t,n){let[r,l,,a]=t;for(let u in r.includes(o.PAGE_SEGMENT_KEY)&&"refresh"!==a&&(t[2]=n,t[3]="refresh"),l)e(l[u],n)}},refreshInactiveParallelSegments:function(){return i}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(1465),u=e.r(20320),o=e.r(91395);async function i(e){let t=new Set;await s({...e,rootTree:e.updatedTree,fetchedSegments:t})}async function s({navigatedAt:e,state:t,updatedTree:n,updatedCache:r,includeNextUrl:l,fetchedSegments:o,rootTree:i=n,canonicalUrl:c}){let[,f,d,p]=n,h=[];if(d&&d!==c&&"refresh"===p&&!o.has(d)){o.add(d);let n=(0,u.fetchServerResponse)(new URL(d,location.origin),{flightRouterState:[i[0],i[1],i[2],"refetch"],nextUrl:l?t.nextUrl:null}).then(t=>{if("string"!=typeof t){let{flightData:n}=t;for(let t of n)(0,a.applyFlightData)(e,r,r,t)}});h.push(n)}for(let n in f){let a=s({navigatedAt:e,state:t,updatedTree:f[n],updatedCache:r,includeNextUrl:l,fetchedSegments:o,rootTree:i,canonicalUrl:c});h.push(a)}await Promise.all(h)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},84938,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"applyRouterStatePatchToTree",{enumerable:!0,get:function(){return function e(t,n,r,i){let s,[c,f,d,p,h]=n;if(1===t.length){let e=o(n,r);return(0,u.addRefreshMarkerToActiveParallelSegments)(e,i),e}let[m,g]=t;if(!(0,a.matchSegment)(m,c))return null;if(2===t.length)s=o(f[g],r);else if(null===(s=e((0,l.getNextFlightSegmentPath)(t),f[g],r,i)))return null;let y=[t[0],{...f,[g]:s},d,p];return h&&(y[4]=!0),(0,u.addRefreshMarkerToActiveParallelSegments)(y,i),y}}});let r=e.r(91395),l=e.r(94955),a=e.r(22039),u=e.r(51441);function o(e,t){let[n,l]=e,[u,i]=t;if(u===r.DEFAULT_SEGMENT_KEY&&n!==r.DEFAULT_SEGMENT_KEY)return e;if((0,a.matchSegment)(n,u)){let t={};for(let e in l)void 0!==i[e]?t[e]=o(l[e],i[e]):t[e]=l[e];for(let e in i)t[e]||(t[e]=i[e]);let r=[n,t];return e[2]&&(r[2]=e[2]),e[3]&&(r[3]=e[3]),e[4]&&(r[4]=e[4]),r}return t}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},42887,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"AppRouterAnnouncer",{enumerable:!0,get:function(){return u}});let r=e.r(30668),l=e.r(69941),a="next-route-announcer";function u({tree:e}){let[t,n]=(0,r.useState)(null);(0,r.useEffect)(()=>(n(function(){let e=document.getElementsByName(a)[0];if(e?.shadowRoot?.childNodes[0])return e.shadowRoot.childNodes[0];{let e=document.createElement(a);e.style.cssText="position:absolute";let t=document.createElement("div");return t.ariaLive="assertive",t.id="__next-route-announcer__",t.role="alert",t.style.cssText="position:absolute;border:0;height:1px;margin:-1px;padding:0;width:1px;clip:rect(0 0 0 0);overflow:hidden;white-space:nowrap;word-wrap:normal",e.attachShadow({mode:"open"}).appendChild(t),document.body.appendChild(e),t}}()),()=>{let e=document.getElementsByTagName(a)[0];e?.isConnected&&document.body.removeChild(e)}),[]);let[u,o]=(0,r.useState)(""),i=(0,r.useRef)(void 0);return(0,r.useEffect)(()=>{let e="";if(document.title)e=document.title;else{let t=document.querySelector("h1");t&&(e=t.innerText||t.textContent||"")}void 0!==i.current&&i.current!==e&&o(e),i.current=e},[e]),t?(0,l.createPortal)(u,t):null}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},43941,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"findHeadInCache",{enumerable:!0,get:function(){return a}});let r=e.r(91395),l=e.r(43317);function a(e,t){return function e(t,n,a,u){if(0===Object.keys(n).length)return[t,a,u];let o=Object.keys(n).filter(e=>"children"!==e);for(let u of("children"in n&&o.unshift("children"),o)){let[o,i]=n[u];if(o===r.DEFAULT_SEGMENT_KEY)continue;let s=t.parallelRoutes.get(u);if(!s)continue;let c=(0,l.createRouterCacheKey)(o),f=(0,l.createRouterCacheKey)(o,!0),d=s.get(c);if(!d)continue;let p=e(d,i,a+"/"+c,a+"/"+f);if(p)return p}return null}(e,t,"","")}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},36254,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"pathHasPrefix",{enumerable:!0,get:function(){return l}});let r=e.r(28732);function l(e,t){if("string"!=typeof e)return!1;let{pathname:n}=(0,r.parsePath)(e);return n===t||n.startsWith(t+"/")}},37023,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"hasBasePath",{enumerable:!0,get:function(){return l}});let r=e.r(36254);function l(e){return(0,r.pathHasPrefix)(e,"")}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},44351,(e,t,n)=>{"use strict";function r(e){return e}Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"removeBasePath",{enumerable:!0,get:function(){return r}}),e.r(37023),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},9984,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={GracefulDegradeBoundary:function(){return o},default:function(){return i}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(48277),u=e.r(30668);class o extends u.Component{constructor(e){super(e),this.state={hasError:!1},this.rootHtml="",this.htmlAttributes={},this.htmlRef=(0,u.createRef)()}static getDerivedStateFromError(e){return{hasError:!0}}componentDidMount(){let e=this.htmlRef.current;this.state.hasError&&e&&Object.entries(this.htmlAttributes).forEach(([t,n])=>{e.setAttribute(t,n)})}render(){let{hasError:e}=this.state;return("undefined"==typeof window||this.rootHtml||(this.rootHtml=document.documentElement.innerHTML,this.htmlAttributes=function(e){let t={};for(let n=0;n{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"default",{enumerable:!0,get:function(){return s}});let r=e.r(35856),l=e.r(48277);e.r(30668);let a=r._(e.r(9984)),u=e.r(71202),o=e.r(62112),i="undefined"!=typeof window&&(0,o.isBot)(window.navigator.userAgent);function s({children:e,errorComponent:t,errorStyles:n,errorScripts:r}){return i?(0,l.jsx)(a.default,{children:e}):(0,l.jsx)(u.ErrorBoundary,{errorComponent:t,errorStyles:n,errorScripts:r,children:e})}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},87670,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={createEmptyCacheNode:function(){return N},default:function(){return j}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(35856),u=e.r(61909),o=e.r(48277),i=u._(e.r(30668)),s=e.r(45243),c=e.r(98165),f=e.r(80118),d=e.r(69370),p=e.r(53128),h=e.r(42887),m=e.r(2188),g=e.r(43941),y=e.r(83648),v=e.r(44351),b=e.r(37023),S=e.r(5725),w=e.r(61524),E=e.r(19998),_=e.r(44216),P=e.r(84628),k=e.r(79111),R=a._(e.r(81133)),T=a._(e.r(75115)),x=e.r(64381),O={};function C({appRouterState:e}){return(0,i.useInsertionEffect)(()=>{let{tree:t,pushRef:n,canonicalUrl:r,renderedSearch:l}=e,a={...n.preserveCustomHistoryState?window.history.state:{},__NA:!0,__PRIVATE_NEXTJS_INTERNALS_TREE:{tree:t,renderedSearch:l}};n.pendingPush&&(0,f.createHrefFromUrl)(new URL(window.location.href))!==r?(n.pendingPush=!1,window.history.pushState(a,"",r)):window.history.replaceState(a,"",r)},[e]),(0,i.useEffect)(()=>{(0,k.pingVisibleLinks)(e.nextUrl,e.tree)},[e.nextUrl,e.tree]),null}function N(){return{lazyData:null,rsc:null,prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:new Map,loading:null,navigatedAt:-1}}function M(e){null==e&&(e={});let t=window.history.state,n=t?.__NA;n&&(e.__NA=n);let r=t?.__PRIVATE_NEXTJS_INTERNALS_TREE;return r&&(e.__PRIVATE_NEXTJS_INTERNALS_TREE=r),e}function L({headCacheNode:e}){let t=null!==e?e.head:null,n=null!==e?e.prefetchHead:null,r=null!==n?n:t;return(0,i.useDeferredValue)(t,r)}function z({actionQueue:e,globalError:t,webSocket:n,staticIndicatorState:r}){let l,a=(0,p.useActionQueue)(e),{canonicalUrl:u}=a,{searchParams:f,pathname:w}=(0,i.useMemo)(()=>{let e=new URL(u,"undefined"==typeof window?"http://n":window.location.href);return{searchParams:e.searchParams,pathname:(0,b.hasBasePath)(e.pathname)?(0,v.removeBasePath)(e.pathname):e.pathname}},[u]);(0,i.useEffect)(()=>{function e(e){e.persisted&&window.history.state?.__PRIVATE_NEXTJS_INTERNALS_TREE&&(O.pendingMpaPath=void 0,(0,p.dispatchAppRouterAction)({type:c.ACTION_RESTORE,url:new URL(window.location.href),historyState:window.history.state.__PRIVATE_NEXTJS_INTERNALS_TREE}))}return window.addEventListener("pageshow",e),()=>{window.removeEventListener("pageshow",e)}},[]),(0,i.useEffect)(()=>{function e(e){let t="reason"in e?e.reason:e.error;if((0,P.isRedirectError)(t)){e.preventDefault();let n=(0,_.getURLFromRedirectError)(t);(0,_.getRedirectTypeFromError)(t)===P.RedirectType.push?E.publicAppRouterInstance.push(n,{}):E.publicAppRouterInstance.replace(n,{})}}return window.addEventListener("error",e),window.addEventListener("unhandledrejection",e),()=>{window.removeEventListener("error",e),window.removeEventListener("unhandledrejection",e)}},[]);let{pushRef:k}=a;if(k.mpaNavigation){if(O.pendingMpaPath!==u){let e=window.location;k.pendingPush?e.assign(u):e.replace(u),O.pendingMpaPath=u}throw y.unresolvedThenable}(0,i.useEffect)(()=>{let e=window.history.pushState.bind(window.history),t=window.history.replaceState.bind(window.history),n=e=>{let t=window.location.href,n=window.history.state?.__PRIVATE_NEXTJS_INTERNALS_TREE;(0,i.startTransition)(()=>{(0,p.dispatchAppRouterAction)({type:c.ACTION_RESTORE,url:new URL(e??t,t),historyState:n})})};window.history.pushState=function(t,r,l){return t?.__NA||t?._N||(t=M(t),l&&n(l)),e(t,r,l)},window.history.replaceState=function(e,r,l){return e?.__NA||e?._N||(e=M(e),l&&n(l)),t(e,r,l)};let r=e=>{if(e.state){if(!e.state.__NA)return void window.location.reload();(0,i.startTransition)(()=>{(0,E.dispatchTraverseAction)(window.location.href,e.state.__PRIVATE_NEXTJS_INTERNALS_TREE)})}};return window.addEventListener("popstate",r),()=>{window.history.pushState=e,window.history.replaceState=t,window.removeEventListener("popstate",r)}},[]);let{cache:T,tree:N,nextUrl:z,focusAndScrollRef:j,previousNextUrl:F}=a,A=(0,i.useMemo)(()=>(0,g.findHeadInCache)(T,N[1]),[T,N]),D=(0,i.useMemo)(()=>(0,S.getSelectedParams)(N),[N]),U=(0,i.useMemo)(()=>({parentTree:N,parentCacheNode:T,parentSegmentPath:null,parentParams:{},debugNameContext:"/",url:u,isActive:!0}),[N,T,u]),H=(0,i.useMemo)(()=>({tree:N,focusAndScrollRef:j,nextUrl:z,previousNextUrl:F}),[N,j,z,F]);if(null!==A){let[e,t,n]=A;l=(0,o.jsx)(L,{headCacheNode:e},"undefined"==typeof window?n:t)}else l=null;let B=(0,o.jsxs)(m.RedirectBoundary,{children:[l,(0,o.jsx)(x.RootLayoutBoundary,{children:T.rsc}),(0,o.jsx)(h.AppRouterAnnouncer,{tree:N})]});return B=(0,o.jsx)(R.default,{errorComponent:t[0],errorStyles:t[1],children:B}),(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(C,{appRouterState:a}),(0,o.jsx)(I,{}),(0,o.jsx)(d.NavigationPromisesContext.Provider,{value:null,children:(0,o.jsx)(d.PathParamsContext.Provider,{value:D,children:(0,o.jsx)(d.PathnameContext.Provider,{value:w,children:(0,o.jsx)(d.SearchParamsContext.Provider,{value:f,children:(0,o.jsx)(s.GlobalLayoutRouterContext.Provider,{value:H,children:(0,o.jsx)(s.AppRouterContext.Provider,{value:E.publicAppRouterInstance,children:(0,o.jsx)(s.LayoutRouterContext.Provider,{value:U,children:B})})})})})})})]})}function j({actionQueue:e,globalErrorState:t,webSocket:n,staticIndicatorState:r}){(0,w.useNavFailureHandler)();let l=(0,o.jsx)(z,{actionQueue:e,globalError:t,webSocket:n,staticIndicatorState:r});return(0,o.jsx)(R.default,{errorComponent:T.default,children:l})}let F=new Set,A=new Set;function I(){let[,e]=i.default.useState(0),t=F.size;return(0,i.useEffect)(()=>{let n=()=>e(e=>e+1);return A.add(n),t!==F.size&&n(),()=>{A.delete(n)}},[t,e]),[...F].map((e,t)=>(0,o.jsx)("link",{rel:"stylesheet",href:`${e}`,precedence:"next"},t))}globalThis._N_E_STYLE_LOAD=function(e){let t=F.size;return F.add(e),F.size!==t&&A.forEach(e=>e()),Promise.resolve()},("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},76702,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"serverPatchReducer",{enumerable:!0,get:function(){return c}});let r=e.r(80118),l=e.r(84938),a=e.r(84697),u=e.r(28806),o=e.r(1465),i=e.r(40494),s=e.r(87670);function c(e,t){let{serverResponse:n,navigatedAt:c}=t,f={};if(f.preserveCustomHistoryState=!1,"string"==typeof n)return(0,u.handleExternalUrl)(e,f,n,e.pushRef.pendingPush);let{flightData:d,canonicalUrl:p,renderedSearch:h}=n,m=e.tree,g=e.cache;for(let t of d){let{segmentPath:n,tree:i}=t,d=(0,l.applyRouterStatePatchToTree)(["",...n],m,i,e.canonicalUrl);if(null===d)return e;if((0,a.isNavigatingToNewRootLayout)(m,d))return(0,u.handleExternalUrl)(e,f,e.canonicalUrl,e.pushRef.pendingPush);f.canonicalUrl=(0,r.createHrefFromUrl)(p);let y=(0,s.createEmptyCacheNode)();(0,o.applyFlightData)(c,g,y,t),f.patchedTree=d,f.renderedSearch=h,f.cache=y,g=y,m=d}return(0,i.handleMutable)(e,f)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},43746,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"restoreReducer",{enumerable:!0,get:function(){return a}});let r=e.r(80118),l=e.r(5725);function a(e,t){let n,a,{url:u,historyState:o}=t,i=(0,r.createHrefFromUrl)(u);o?(n=o.tree,a=o.renderedSearch):(n=e.tree,a=e.renderedSearch);let s=e.cache;return{canonicalUrl:i,renderedSearch:a,pushRef:{pendingPush:!1,mpaNavigation:!1,preserveCustomHistoryState:!0},focusAndScrollRef:e.focusAndScrollRef,cache:s,tree:n,nextUrl:(0,l.extractPathFromFlightRouterState)(n)??u.pathname,previousNextUrl:null,debugInfo:null}}e.r(1989),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},45733,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"handleSegmentMismatch",{enumerable:!0,get:function(){return l}});let r=e.r(28806);function l(e,t,n){return(0,r.handleExternalUrl)(e,{},e.canonicalUrl,!0)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},64324,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"refreshReducer",{enumerable:!0,get:function(){return m}});let r=e.r(20320),l=e.r(80118),a=e.r(84938),u=e.r(84697),o=e.r(28806),i=e.r(40494),s=e.r(61447),c=e.r(87670),f=e.r(45733),d=e.r(20017),p=e.r(51441),h=e.r(91666);function m(e,t){let{origin:n}=t,m={},g=e.canonicalUrl,y=e.tree;m.preserveCustomHistoryState=!1;let v=(0,c.createEmptyCacheNode)(),b=(0,d.hasInterceptionRouteInCurrentTree)(e.tree);v.lazyData=(0,r.fetchServerResponse)(new URL(g,n),{flightRouterState:[y[0],y[1],y[2],"refetch"],nextUrl:b?e.nextUrl:null});let S=Date.now();return v.lazyData.then(async n=>{if("string"==typeof n)return(0,o.handleExternalUrl)(e,m,n,e.pushRef.pendingPush);let{flightData:r,canonicalUrl:c,renderedSearch:d}=n;for(let n of(v.lazyData=null,r)){let{tree:r,seedData:i,head:w,isRootRender:E}=n;if(!E)return console.log("REFRESH FAILED"),e;let _=(0,a.applyRouterStatePatchToTree)([""],y,r,e.canonicalUrl);if(null===_)return(0,f.handleSegmentMismatch)(e,t,r);if((0,u.isNavigatingToNewRootLayout)(y,_))return(0,o.handleExternalUrl)(e,m,g,e.pushRef.pendingPush);if(m.canonicalUrl=(0,l.createHrefFromUrl)(c),null!==i){let t=i[0],n=i[2];v.rsc=t,v.prefetchRsc=null,v.loading=n,(0,s.fillLazyItemsTillLeafWithHead)(S,v,void 0,r,i,w),(0,h.revalidateEntireCache)(e.nextUrl,_)}await (0,p.refreshInactiveParallelSegments)({navigatedAt:S,state:e,updatedTree:_,updatedCache:v,includeNextUrl:b,canonicalUrl:m.canonicalUrl||e.canonicalUrl}),m.cache=v,m.patchedTree=_,m.renderedSearch=d,y=_}return(0,i.handleMutable)(e,m)},()=>e)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},1470,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"hmrRefreshReducer",{enumerable:!0,get:function(){return r}}),e.r(20320),e.r(80118),e.r(84938),e.r(84697),e.r(28806),e.r(40494),e.r(1465),e.r(87670),e.r(45733),e.r(20017);let r=function(e,t){return e};("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},98454,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"assignLocation",{enumerable:!0,get:function(){return l}});let r=e.r(39940);function l(e,t){if(e.startsWith(".")){let n=t.origin+t.pathname;return new URL((n.endsWith("/")?n:n+"/")+e)}return new URL((0,r.addBasePath)(e),t.href)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},17213,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={extractInfoFromServerReferenceId:function(){return a},omitUnusedArgs:function(){return u}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});function a(e){let t=parseInt(e.slice(0,2),16),n=t>>1&63,r=Array(6);for(let e=0;e<6;e++){let t=n>>5-e&1;r[e]=1===t}return{type:1==(t>>7&1)?"use-cache":"server-action",usedArgs:r,hasRestArgs:1==(1&t)}}function u(e,t){let n=Array(e.length);for(let r=0;r=6&&t.hasRestArgs)&&(n[r]=e[r]);return n}},92114,(e,t,n)=>{"use strict";let r;Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"serverActionReducer",{enumerable:!0,get:function(){return C}});let l=e.r(59295),a=e.r(85045),u=e.r(2089),o=e.r(40288),i=e.r(30545),s=e.r(98454),c=e.r(80118),f=e.r(28806),d=e.r(84938),p=e.r(84697),h=e.r(40494),m=e.r(61447),g=e.r(87670),y=e.r(20017),v=e.r(45733),b=e.r(51441),S=e.r(94955),w=e.r(44216),E=e.r(84628),_=e.r(44351),P=e.r(37023),k=e.r(17213),R=e.r(91666),T=i.createFromFetch;async function x(e,t,{actionId:n,actionArgs:c}){let f,d,p,h,m=(0,i.createTemporaryReferenceSet)(),g=(0,k.extractInfoFromServerReferenceId)(n),y="use-cache"===g.type?(0,k.omitUnusedArgs)(c,g):c,v=await (0,i.encodeReply)(y,{temporaryReferences:m}),b={Accept:u.RSC_CONTENT_TYPE_HEADER,[u.ACTION_HEADER]:n,[u.NEXT_ROUTER_STATE_TREE_HEADER]:(0,S.prepareFlightRouterStateForRequest)(e.tree)};t&&(b[u.NEXT_URL]=t);let w=await fetch(e.canonicalUrl,{method:"POST",headers:b,body:v});if("1"===w.headers.get(u.NEXT_ACTION_NOT_FOUND_HEADER))throw Object.defineProperty(new o.UnrecognizedActionError(`Server Action "${n}" was not found on the server. +Read more: https://nextjs.org/docs/messages/failed-to-find-server-action`),"__NEXT_ERROR_CODE",{value:"E715",enumerable:!1,configurable:!0});let _=w.headers.get("x-action-redirect"),[P,R]=_?.split(";")||[];switch(R){case"push":f=E.RedirectType.push;break;case"replace":f=E.RedirectType.replace;break;default:f=void 0}let x=!!w.headers.get(u.NEXT_IS_PRERENDER_HEADER);try{let e=JSON.parse(w.headers.get("x-action-revalidated")||"[[],0,0]");d={paths:e[0]||[],tag:!!e[1],cookie:e[2]}}catch(e){d=O}let C=P?(0,s.assignLocation)(P,new URL(e.canonicalUrl,window.location.href)):void 0,N=w.headers.get("content-type"),M=!!(N&&N.startsWith(u.RSC_CONTENT_TYPE_HEADER));if(!M&&!C)throw Object.defineProperty(Error(w.status>=400&&"text/plain"===N?await w.text():"An unexpected response was received from the server."),"__NEXT_ERROR_CODE",{value:"E394",enumerable:!1,configurable:!0});if(M){let e=await T(Promise.resolve(w),{callServer:l.callServer,findSourceMapURL:a.findSourceMapURL,temporaryReferences:m,debugChannel:r&&r(b)});p=C?void 0:e.a,h=(0,S.normalizeFlightData)(e.f)}else p=void 0,h=void 0;return{actionResult:p,actionFlightData:h,redirectLocation:C,redirectType:f,revalidatedParts:d,isPrerender:x}}let O={paths:[],tag:!1,cookie:!1};function C(e,t){let{resolve:n,reject:r}=t,l={},a=e.tree;l.preserveCustomHistoryState=!1;let u=(e.previousNextUrl||e.nextUrl)&&(0,y.hasInterceptionRouteInCurrentTree)(e.tree)?e.previousNextUrl||e.nextUrl:null,o=Date.now();return x(e,u,t).then(async({actionResult:i,actionFlightData:s,redirectLocation:y,redirectType:S,revalidatedParts:k})=>{let T;if(y&&(S===E.RedirectType.replace?(e.pushRef.pendingPush=!1,l.pendingPush=!1):(e.pushRef.pendingPush=!0,l.pendingPush=!0),l.canonicalUrl=T=(0,c.createHrefFromUrl)(y,!1)),!s)return(n(i),y)?(0,f.handleExternalUrl)(e,l,y.href,e.pushRef.pendingPush):e;if("string"==typeof s)return n(i),(0,f.handleExternalUrl)(e,l,s,e.pushRef.pendingPush);let x=k.paths.length>0||k.tag||k.cookie;for(let r of(x&&(t.didRevalidate=!0),s)){let{tree:s,seedData:c,head:h,isRootRender:y}=r;if(!y)return console.log("SERVER ACTION APPLY FAILED"),n(i),e;let S=(0,d.applyRouterStatePatchToTree)([""],a,s,T||e.canonicalUrl);if(null===S)return n(i),(0,v.handleSegmentMismatch)(e,t,s);if((0,p.isNavigatingToNewRootLayout)(a,S))return n(i),(0,f.handleExternalUrl)(e,l,T||e.canonicalUrl,e.pushRef.pendingPush);if(null!==c){let t=c[0],n=(0,g.createEmptyCacheNode)();n.rsc=t,n.prefetchRsc=null,n.loading=c[2],(0,m.fillLazyItemsTillLeafWithHead)(o,n,void 0,s,c,h),l.cache=n,(0,R.revalidateEntireCache)(e.nextUrl,S),x&&await (0,b.refreshInactiveParallelSegments)({navigatedAt:o,state:e,updatedTree:S,updatedCache:n,includeNextUrl:!!u,canonicalUrl:l.canonicalUrl||e.canonicalUrl})}l.patchedTree=S,a=S}if(y&&T){let e=(0,w.getRedirectError)((0,P.hasBasePath)(T)?(0,_.removeBasePath)(T):T,S||E.RedirectType.push);e.handled=!0,r(e)}else n(i);return(0,h.handleMutable)(e,l)},t=>(r(t),e))}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},42939,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"reducer",{enumerable:!0,get:function(){return c}});let r=e.r(98165),l=e.r(28806),a=e.r(76702),u=e.r(43746),o=e.r(64324),i=e.r(1470),s=e.r(92114),c="undefined"==typeof window?function(e,t){return e}:function(e,t){switch(t.type){case r.ACTION_NAVIGATE:return(0,l.navigateReducer)(e,t);case r.ACTION_SERVER_PATCH:return(0,a.serverPatchReducer)(e,t);case r.ACTION_RESTORE:return(0,u.restoreReducer)(e,t);case r.ACTION_REFRESH:return(0,o.refreshReducer)(e,t);case r.ACTION_HMR_REFRESH:return(0,i.hmrRefreshReducer)(e,t);case r.ACTION_SERVER_ACTION:return(0,s.serverActionReducer)(e,t);default:throw Object.defineProperty(Error("Unknown action"),"__NEXT_ERROR_CODE",{value:"E295",enumerable:!1,configurable:!0})}};("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},19939,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"prefetch",{enumerable:!0,get:function(){return o}});let r=e.r(93259),l=e.r(63280),a=e.r(40285),u=e.r(24994);function o(e,t,n,o,i){let s=(0,r.createPrefetchURL)(e);if(null===s)return;let c=(0,l.createCacheKey)(s.href,t);(0,a.schedulePrefetchTask)(c,n,o,u.PrefetchPriority.Default,i)}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},19998,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});var r={createMutableActionQueue:function(){return v},dispatchNavigateAction:function(){return w},dispatchTraverseAction:function(){return E},getCurrentAppRouterState:function(){return b},publicAppRouterInstance:function(){return _}};for(var l in r)Object.defineProperty(n,l,{enumerable:!0,get:r[l]});let a=e.r(98165),u=e.r(42939),o=e.r(30668),i=e.r(65035),s=e.r(24994),c=e.r(19939),f=e.r(53128),d=e.r(39940),p=e.r(93259),h=e.r(79111);function m(e,t){null!==e.pending?(e.pending=e.pending.next,null!==e.pending&&g({actionQueue:e,action:e.pending,setState:t})):e.needsRefresh&&(e.needsRefresh=!1,e.dispatch({type:a.ACTION_REFRESH,origin:window.location.origin},t))}async function g({actionQueue:e,action:t,setState:n}){let r=e.state;e.pending=t;let l=t.payload,u=e.action(r,l);function o(r){if(t.discarded){t.payload.type===a.ACTION_SERVER_ACTION&&t.payload.didRevalidate&&(e.needsRefresh=!0),m(e,n);return}e.state=r,m(e,n),t.resolve(r)}(0,i.isThenable)(u)?u.then(o,r=>{m(e,n),t.reject(r)}):o(u)}let y=null;function v(e,t){let n={state:e,dispatch:(e,t)=>(function(e,t,n){let r={resolve:n,reject:()=>{}};if(t.type!==a.ACTION_RESTORE){let e=new Promise((e,t)=>{r={resolve:e,reject:t}});(0,o.startTransition)(()=>{n(e)})}let l={payload:t,next:null,resolve:r.resolve,reject:r.reject};null===e.pending?(e.last=l,g({actionQueue:e,action:l,setState:n})):t.type===a.ACTION_NAVIGATE||t.type===a.ACTION_RESTORE?(e.pending.discarded=!0,l.next=e.pending.next,g({actionQueue:e,action:l,setState:n})):(null!==e.last&&(e.last.next=l),e.last=l)})(n,e,t),action:async(e,t)=>(0,u.reducer)(e,t),pending:null,last:null,onRouterTransitionStart:null!==t&&"function"==typeof t.onRouterTransitionStart?t.onRouterTransitionStart:null};if("undefined"!=typeof window){if(null!==y)throw Object.defineProperty(Error("Internal Next.js Error: createMutableActionQueue was called more than once"),"__NEXT_ERROR_CODE",{value:"E624",enumerable:!1,configurable:!0});y=n}return n}function b(){return null!==y?y.state:null}function S(){return null!==y?y.onRouterTransitionStart:null}function w(e,t,n,r){let l=new URL((0,d.addBasePath)(e),location.href);(0,h.setLinkForCurrentNavigation)(r);let u=S();null!==u&&u(e,t),(0,f.dispatchAppRouterAction)({type:a.ACTION_NAVIGATE,url:l,isExternalUrl:(0,p.isExternalURL)(l),locationSearch:location.search,shouldScroll:n,navigateType:t})}function E(e,t){let n=S();null!==n&&n(e,"traverse"),(0,f.dispatchAppRouterAction)({type:a.ACTION_RESTORE,url:new URL(e),historyState:t})}let _={back:()=>window.history.back(),forward:()=>window.history.forward(),prefetch:(e,t)=>{let n,r=function(){if(null===y)throw Object.defineProperty(Error("Internal Next.js error: Router action dispatched before initialization."),"__NEXT_ERROR_CODE",{value:"E668",enumerable:!1,configurable:!0});return y}();switch(t?.kind??a.PrefetchKind.AUTO){case a.PrefetchKind.AUTO:n=s.FetchStrategy.PPR;break;case a.PrefetchKind.FULL:n=s.FetchStrategy.Full;break;case a.PrefetchKind.TEMPORARY:return;default:n=s.FetchStrategy.PPR}(0,c.prefetch)(e,r.state.nextUrl,r.state.tree,n,t?.onInvalidate??null)},replace:(e,t)=>{(0,o.startTransition)(()=>{w(e,"replace",t?.scroll??!0,null)})},push:(e,t)=>{(0,o.startTransition)(()=>{w(e,"push",t?.scroll??!0,null)})},refresh:()=>{(0,o.startTransition)(()=>{(0,f.dispatchAppRouterAction)({type:a.ACTION_REFRESH,origin:window.location.origin})})},hmrRefresh:()=>{throw Object.defineProperty(Error("hmrRefresh can only be used in development mode. Please use refresh instead."),"__NEXT_ERROR_CODE",{value:"E485",enumerable:!1,configurable:!0})}};"undefined"!=typeof window&&window.next&&(window.next.router=_),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},79216,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"createInitialRouterState",{enumerable:!0,get:function(){return i}});let r=e.r(80118),l=e.r(61447),a=e.r(5725),u=e.r(51441),o=e.r(94955);function i({navigatedAt:e,initialFlightData:t,initialCanonicalUrlParts:n,initialRenderedSearch:i,initialParallelRoutes:s,location:c}){let f=n.join("/"),{tree:d,seedData:p,head:h}=(0,o.getFlightDataPartsFromPath)(t[0]),m={lazyData:null,rsc:p?.[0],prefetchRsc:null,head:null,prefetchHead:null,parallelRoutes:s,loading:p?.[2]??null,navigatedAt:e},g=c?(0,r.createHrefFromUrl)(c):f;return(0,u.addRefreshMarkerToActiveParallelSegments)(d,g),(null===s||0===s.size)&&(0,l.fillLazyItemsTillLeafWithHead)(e,m,void 0,d,p,h),{tree:d,cache:m,pushRef:{pendingPush:!1,mpaNavigation:!1,preserveCustomHistoryState:!0},focusAndScrollRef:{apply:!1,onlyHashChange:!1,hashFragment:null,segmentPaths:[]},canonicalUrl:g,renderedSearch:i,nextUrl:((0,a.extractPathFromFlightRouterState)(d)||c?.pathname)??null,previousNextUrl:null,debugInfo:null}}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},51971,(e,t,n)=>{"use strict";let r,l,a,u;Object.defineProperty(n,"__esModule",{value:!0}),Object.defineProperty(n,"hydrate",{enumerable:!0,get:function(){return I}});let o=e.r(35856),i=e.r(48277);e.r(86096);let s=o._(e.r(69460)),c=o._(e.r(30668)),f=e.r(30545),d=e.r(98084),p=e.r(29554),h=e.r(26717),m=e.r(59295),g=e.r(85045),y=e.r(19998),v=o._(e.r(87670)),b=e.r(79216);e.r(45243);let S=e.r(70410),w=e.r(94955),E=f.createFromReadableStream,_=f.createFromFetch,P=document,k=new TextEncoder,R=!1,T=!1,x=null;function O(e){if(0===e[0])a=[];else if(1===e[0]){if(!a)throw Object.defineProperty(Error("Unexpected server data: missing bootstrap script."),"__NEXT_ERROR_CODE",{value:"E18",enumerable:!1,configurable:!0});u?u.enqueue(k.encode(e[1])):a.push(e[1])}else if(2===e[0])x=e[1];else if(3===e[0]){if(!a)throw Object.defineProperty(Error("Unexpected server data: missing bootstrap script."),"__NEXT_ERROR_CODE",{value:"E18",enumerable:!1,configurable:!0});let n=atob(e[1]),r=new Uint8Array(n.length);for(var t=0;t{e.enqueue("string"==typeof t?k.encode(t):t)}),R&&!T)&&(null===e.desiredSize||e.desiredSize<0?e.error(Object.defineProperty(Error("The connection to the page was unexpectedly closed, possibly due to the stop button being clicked, loss of Wi-Fi, or an unstable internet connection."),"__NEXT_ERROR_CODE",{value:"E117",enumerable:!1,configurable:!0})):e.close(),T=!0,a=void 0),u=e}}),L=window.__NEXT_CLIENT_RESUME;function z({initialRSCPayload:e,actionQueue:t,webSocket:n,staticIndicatorState:r}){return(0,i.jsx)(v.default,{actionQueue:t,globalErrorState:e.G,webSocket:n,staticIndicatorState:r})}l=L?Promise.resolve(_(L,{callServer:m.callServer,findSourceMapURL:g.findSourceMapURL,debugChannel:r})).then(async e=>(0,w.createInitialRSCPayloadFromFallbackPrerender)(await L,e)):E(M,{callServer:m.callServer,findSourceMapURL:g.findSourceMapURL,debugChannel:r,startTime:0});let j=c.default.StrictMode;function F({children:e}){return e}let A={onDefaultTransitionIndicator:function(){return()=>{}},onRecoverableError:p.onRecoverableError,onCaughtError:h.onCaughtError,onUncaughtError:h.onUncaughtError};async function I(e,t){let n,r,a=await l;(0,S.setAppBuildId)(a.b);let u=Date.now(),o=(0,y.createMutableActionQueue)((0,b.createInitialRouterState)({navigatedAt:u,initialFlightData:a.f,initialCanonicalUrlParts:a.c,initialRenderedSearch:a.q,initialParallelRoutes:new Map,location:window.location}),e),f=(0,i.jsx)(j,{children:(0,i.jsx)(d.HeadManagerContext.Provider,{value:{appDir:!0},children:(0,i.jsx)(F,{children:(0,i.jsx)(z,{initialRSCPayload:a,actionQueue:o,webSocket:r,staticIndicatorState:n})})})});"__next_error__"===document.documentElement.id?s.default.createRoot(P,A).render(f):c.default.startTransition(()=>{s.default.hydrateRoot(P,f,{...A,formState:x})})}("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)},24153,(e,t,n)=>{"use strict";Object.defineProperty(n,"__esModule",{value:!0});let r=e.r(68402);e.r(29554),window.next.turbopack=!0,self.__webpack_hash__="";let l=e.r(22487);(0,r.appBootstrap)(t=>{let{hydrate:n}=e.r(51971);n(l,t)}),("function"==typeof n.default||"object"==typeof n.default&&null!==n.default)&&void 0===n.default.__esModule&&(Object.defineProperty(n.default,"__esModule",{value:!0}),Object.assign(n.default,n),t.exports=n.default)}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/a096ec8e6ed56d42.js b/src/hyperview/server/static/_next/static/chunks/a096ec8e6ed56d42.js new file mode 100644 index 0000000000000000000000000000000000000000..411bf1bb4daeed77de7c0e0f4b28de1a4370f54b --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/a096ec8e6ed56d42.js @@ -0,0 +1,9 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,50912,e=>{"use strict";let t,r,n,o,l,s;var i,a,d=e.i(48277),u=e.i(30668);let c=e=>{let t=e.replace(/^([A-Z])|[\s-_]+(\w)/g,(e,t,r)=>r?r.toUpperCase():t.toLowerCase());return t.charAt(0).toUpperCase()+t.slice(1)},f=(...e)=>e.filter((e,t,r)=>!!e&&""!==e.trim()&&r.indexOf(e)===t).join(" ").trim();var p={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};let h=(0,u.forwardRef)(({color:e="currentColor",size:t=24,strokeWidth:r=2,absoluteStrokeWidth:n,className:o="",children:l,iconNode:s,...i},a)=>(0,u.createElement)("svg",{ref:a,...p,width:t,height:t,stroke:e,strokeWidth:n?24*Number(r)/Number(t):r,className:f("lucide",o),...!l&&!(e=>{for(let t in e)if(t.startsWith("aria-")||"role"===t||"title"===t)return!0})(i)&&{"aria-hidden":"true"},...i},[...s.map(([e,t])=>(0,u.createElement)(e,t)),...Array.isArray(l)?l:[l]])),m=(i="grip-vertical",a=[["circle",{cx:"9",cy:"12",r:"1",key:"1vctgf"}],["circle",{cx:"9",cy:"5",r:"1",key:"hp0tcf"}],["circle",{cx:"9",cy:"19",r:"1",key:"fkjjf6"}],["circle",{cx:"15",cy:"12",r:"1",key:"1tmaij"}],["circle",{cx:"15",cy:"5",r:"1",key:"19l28e"}],["circle",{cx:"15",cy:"19",r:"1",key:"f4zoj3"}]],(r=(0,u.forwardRef)(({className:e,...t},r)=>(0,u.createElement)(h,{ref:r,iconNode:a,className:f(`lucide-${c(i).replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase()}`,`lucide-${i}`,e),...t}))).displayName=c(i),r);function g(e,t="Assertion error"){if(!e)throw Error(t)}function y({group:e}){let{orientation:t,panels:r}=e;return r.reduce((e,r)=>e+="horizontal"===t?r.element.offsetWidth:r.element.offsetHeight,0)}function b(e,t){return t.sort("horizontal"===e?x:v)}function x(e,t){let r=e.element.offsetLeft-t.element.offsetLeft;return 0!==r?r:e.element.offsetWidth-t.element.offsetWidth}function v(e,t){let r=e.element.offsetTop-t.element.offsetTop;return 0!==r?r:e.element.offsetHeight-t.element.offsetHeight}function w(e){return null!==e&&"object"==typeof e&&"nodeType"in e&&e.nodeType===Node.ELEMENT_NODE}function k(e,t){return{x:e.x>=t.left&&e.x<=t.right?0:Math.min(Math.abs(e.x-t.left),Math.abs(e.x-t.right)),y:e.y>=t.top&&e.y<=t.bottom?0:Math.min(Math.abs(e.y-t.top),Math.abs(e.y-t.bottom))}}function S(e){let{element:t,orientation:r,panels:n,separators:o}=e,l=b(r,Array.from(t.children).filter(w).map(e=>({element:e}))).map(({element:e})=>e),s=[],i=!1,a,d=[];for(let t of l)if(t.hasAttribute("data-panel")){let o=n.find(e=>e.element===t);if(o){if(a){let n,l=a.element.getBoundingClientRect(),u=t.getBoundingClientRect();if(i){let e="horizontal"===r?new DOMRect(l.right,l.top,0,l.height):new DOMRect(l.left,l.bottom,l.width,0),t="horizontal"===r?new DOMRect(u.left,u.top,0,u.height):new DOMRect(u.left,u.top,u.width,0);switch(d.length){case 0:n=[e,t];break;case 1:{let o=d[0],s=function({orientation:e,rects:t,targetRect:r}){let n={x:r.x+r.width/2,y:r.y+r.height/2},o,l=Number.MAX_VALUE;for(let r of t){let{x:t,y:s}=k(n,r),i="horizontal"===e?t:s;ie.element===t);e?d.push(e):(a=void 0,d=[])}else i=!0;return s}function z({groupSize:e,panelElement:t,styleProp:r}){let n,[o,l]=function(e){switch(typeof e){case"number":return[e,"px"];case"string":{let t=parseFloat(e);return e.endsWith("%")?[t,"%"]:e.endsWith("px")?[t,"px"]:e.endsWith("rem")?[t,"rem"]:e.endsWith("em")?[t,"em"]:e.endsWith("vh")?[t,"vh"]:e.endsWith("vw")?[t,"vw"]:[t,"%"]}}}(r);switch(l){case"%":n=o/100*e;break;case"px":n=o;break;case"rem":n=o*parseFloat(getComputedStyle(t.ownerDocument.body).fontSize);break;case"em":n=o*parseFloat(getComputedStyle(t).fontSize);break;case"vh":n=o/100*window.innerHeight;break;case"vw":n=o/100*window.innerWidth}return n}function j(e){return parseFloat(e.toFixed(3))}function C(e){let{panels:t}=e,r=y({group:e});return 0===r?t.map(e=>({collapsedSize:0,collapsible:!0===e.panelConstraints.collapsible,defaultSize:void 0,minSize:0,maxSize:100,panelId:e.id})):t.map(e=>{let t,{element:n,panelConstraints:o}=e,l=0;void 0!==o.collapsedSize&&(l=j(z({groupSize:r,panelElement:n,styleProp:o.collapsedSize})/r*100)),void 0!==o.defaultSize&&(t=j(z({groupSize:r,panelElement:n,styleProp:o.defaultSize})/r*100));let s=0;void 0!==o.minSize&&(s=j(z({groupSize:r,panelElement:n,styleProp:o.minSize})/r*100));let i=100;return void 0!==o.maxSize&&(i=j(z({groupSize:r,panelElement:n,styleProp:o.maxSize})/r*100)),{collapsedSize:l,collapsible:!0===o.collapsible,defaultSize:t,minSize:s,maxSize:i,panelId:e.id}})}function E(e,t,r=0){return Math.abs(j(e)-j(t))<=r}let M={cursorFlags:0,interactionState:{state:"inactive"},mountedGroups:new Map},R=new class{#e={};addListener(e,t){let r=this.#e[e];return void 0===r?this.#e[e]=[t]:r.includes(t)||r.push(t),()=>{this.removeListener(e,t)}}emit(e,t){let r=this.#e[e];if(void 0!==r)if(1===r.length)r[0].call(null,t);else{let e=!1,n=null,o=Array.from(r);for(let r=0;r=0&&r.splice(e,1)}}};function N(e){let t="function"==typeof e?e(M):e;if(M===t)return M;let r=M;return M={...M,...t},void 0!==t.cursorFlags&&R.emit("cursorFlagsChange",M.cursorFlags),void 0!==t.interactionState&&R.emit("interactionStateChange",M.interactionState),void 0!==t.mountedGroups&&(M.mountedGroups.forEach((e,t)=>{e.derivedPanelConstraints.forEach(n=>{if(n.collapsible){let{layout:o}=r.mountedGroups.get(t)??{};if(o){let r=E(n.collapsedSize,e.layout[n.panelId]),l=E(n.collapsedSize,o[n.panelId]);r&&!l&&(t.inMemoryLastExpandedPanelSizes[n.panelId]=o[n.panelId])}}})}),R.emit("mountedGroupsChange",M.mountedGroups)),M}function L(e,t){return E(e,t)?0:e>t?1:-1}function I({panelConstraints:e,size:t}){let{collapsedSize:r=0,collapsible:n,maxSize:o=100,minSize:l=0}=e;return 0>L(t,l)&&(t=n&&0>L(t,(r+l)/2)?r:l),j(t=Math.min(o,t))}function P({delta:e,initialLayout:t,panelConstraints:r,pivotIndices:n,prevLayout:o,trigger:l}){if(E(e,0))return t;let s=Object.values(t),i=Object.values(o),a=[...s],[d,u]=n;g(null!=d,"Invalid first pivot index"),g(null!=u,"Invalid second pivot index");let c=0;if("keyboard"===l){{let t=e<0?u:d,n=r[t];g(n,`Panel constraints not found for index ${t}`);let{collapsedSize:o=0,collapsible:l,minSize:i=0}=n;if(l){let r=s[t];if(g(null!=r,`Previous layout not found for panel index ${t}`),E(r,o)){let t=i-r;L(t,Math.abs(e))>0&&(e=e<0?0-t:t)}}}{let t=e<0?d:u,n=r[t];g(n,`No panel constraints found for index ${t}`);let{collapsedSize:o=0,collapsible:l,minSize:i=0}=n;if(l){let r=s[t];if(g(null!=r,`Previous layout not found for panel index ${t}`),E(r,i)){let t=r-o;L(t,Math.abs(e))>0&&(e=e<0?0-t:t)}}}}{let t=e<0?1:-1,n=e<0?u:d,o=0;for(;;){let e=s[n];if(g(null!=e,`Previous layout not found for panel index ${n}`),o+=I({panelConstraints:r[n],size:100})-e,(n+=t)<0||n>=r.length)break}let l=Math.min(Math.abs(e),Math.abs(o));e=e<0?0-l:l}{let t=e<0?d:u;for(;t>=0&&t=0))break;e<0?t--:t++}}if(function(e,t){if(e.length!==t.length)return!1;for(let r=0;r=0&&n0?n--:n++}}}if(!E(Object.values(a).reduce((e,t)=>t+e,0),100,.1))return o;let f=Object.keys(o);return a.reduce((e,t,r)=>(e[f[r]]=t,e),{})}function O(e){let{mountedGroups:t}=M;for(let[r]of t)if(r.separators.some(t=>t.element===e))return r;throw Error("Could not find parent Group for separator element")}function T(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(let r in e)if(void 0===t[r]||0!==L(e[r],t[r]))return!1;return!0}function A({layout:e,panelConstraints:t}){let r=[...Object.values(e)],n=r.reduce((e,t)=>e+t,0);if(r.length!==t.length)throw Error(`Invalid ${t.length} panel layout: ${r.map(e=>`${e}%`).join(", ")}`);if(!E(n,100)&&r.length>0)for(let e=0;e(e[l[r]]=t,e),{})}function D({groupId:e}){let t=()=>{let{mountedGroups:t}=M;for(let[r,n]of t)if(r.id===e)return{group:r,...n};throw Error(`Could not find Group with id "${e}"`)};return{getLayout(){let{defaultLayoutDeferred:e,layout:r}=t();return e?{}:r},setLayout(e){let{defaultLayoutDeferred:r,derivedPanelConstraints:n,group:o,layout:l,separatorToPanels:s}=t(),i=A({layout:e,panelConstraints:n});return r?l:(T(l,i)||N(e=>({mountedGroups:new Map(e.mountedGroups).set(o,{defaultLayoutDeferred:r,derivedPanelConstraints:n,layout:i,separatorToPanels:s})})),i)}}}function F(e){let{mountedGroups:t}=M,r=t.get(e);return g(r,`Mounted Group ${e.id} not found`),r}function $(e,t){let r=O(e),n=F(r),o=r.separators.find(t=>t.element===e);g(o,"Matching separator not found");let l=n.separatorToPanels.get(o);g(l,"Matching panels not found");let s=l.map(e=>r.panels.indexOf(e)),i=D({groupId:r.id}).getLayout(),a=A({layout:P({delta:t,initialLayout:i,panelConstraints:n.derivedPanelConstraints,pivotIndices:s,prevLayout:i,trigger:"keyboard"}),panelConstraints:n.derivedPanelConstraints});T(i,a)||N(e=>({mountedGroups:new Map(e.mountedGroups).set(r,{defaultLayoutDeferred:n.defaultLayoutDeferred,derivedPanelConstraints:n.derivedPanelConstraints,layout:a,separatorToPanels:n.separatorToPanels})}))}function _(e){if(e.defaultPrevented)return;let t=e.currentTarget,r=O(t);if(!r.disabled)switch(e.key){case"ArrowDown":e.preventDefault(),"vertical"===r.orientation&&$(t,5);break;case"ArrowLeft":e.preventDefault(),"horizontal"===r.orientation&&$(t,-5);break;case"ArrowRight":e.preventDefault(),"horizontal"===r.orientation&&$(t,5);break;case"ArrowUp":e.preventDefault(),"vertical"===r.orientation&&$(t,-5);break;case"End":e.preventDefault(),$(t,100);break;case"Enter":{e.preventDefault();let r=O(t),{derivedPanelConstraints:n,layout:o,separatorToPanels:l}=F(r),s=r.separators.find(e=>e.element===t);g(s,"Matching separator not found");let i=l.get(s);g(i,"Matching panels not found");let a=i[0],d=n.find(e=>e.panelId===a.id);if(g(d,"Panel metadata not found"),d.collapsible){let e=o[a.id];$(t,(d.collapsedSize===e?r.inMemoryLastExpandedPanelSizes[a.id]??d.minSize:d.collapsedSize)-e)}break}case"F6":{e.preventDefault();let r=O(t).separators.map(e=>e.element),n=Array.from(r).findIndex(t=>t===e.currentTarget);g(null!==n,"Index not found");let o=e.shiftKey?n>0?n-1:r.length-1:n+1e,W=()=>{},B=/\b(?:position|zIndex|opacity|transform|webkitTransform|mixBlendMode|filter|webkitFilter|isolation)\b/;function V(e){let t=e.length;for(;t--;){let r=e[t];if(g(r,"Missing node"),function(e){let t,r=getComputedStyle(e);return!!("fixed"===r.position||"auto"!==r.zIndex&&("static"!==r.position||"flex"===(t=getComputedStyle(U(e)??e).display)||"inline-flex"===t)||1>+r.opacity||"transform"in r&&"none"!==r.transform||"webkitTransform"in r&&"none"!==r.webkitTransform||"mixBlendMode"in r&&"normal"!==r.mixBlendMode||"filter"in r&&"none"!==r.filter||"webkitFilter"in r&&"none"!==r.webkitFilter||"isolation"in r&&"isolate"===r.isolation||B.test(r.willChange)||"touch"===r.webkitOverflowScrolling)}(r))return r}return null}function K(e){return e&&Number(getComputedStyle(e).zIndex)||0}function H(e){let t=[];for(;e;)t.push(e),e=U(e);return t}function U(e){let{parentNode:t}=e;return null!==t&&"object"==typeof t&&"nodeType"in t&&t.nodeType===Node.DOCUMENT_FRAGMENT_NODE?t.host:t}function q(e,r){let n=[];return r.forEach((r,o)=>{if(o.disabled)return;let l=(void 0===t&&(t="function"==typeof matchMedia&&!!matchMedia("(pointer:coarse)").matches),t)?10:5,s=S(o),i=function(e,t,r){let n,o={x:1/0,y:1/0};for(let l of t){let t=k(r,l.rect);switch(e){case"horizontal":t.x<=o.x&&(n=l,o=t);break;case"vertical":t.y<=o.y&&(n=l,o=t)}}return n?{distance:o,hitRegion:n}:void 0}(o.orientation,s,{x:e.clientX,y:e.clientY});i&&i.distance.x<=l&&i.distance.y<=l&&function({groupElement:e,hitRegion:t,pointerEventTarget:r}){if(!w(r)||r.contains(e)||e.contains(r))return!0;if(function(e,t){let r;if(e===t)throw Error("Cannot compare node with itself");let n={a:H(e),b:H(t)};for(;n.a.at(-1)===n.b.at(-1);)e=n.a.pop(),t=n.b.pop(),r=e;g(r,"Stacking order can only be calculated for elements with a common ancestor");let o={a:K(V(n.a)),b:K(V(n.b))};if(o.a===o.b){let e=r.childNodes,t={a:n.a.at(-1),b:n.b.at(-1)},o=e.length;for(;o--;){let r=e[o];if(r===t.a)return 1;if(r===t.b)return -1}}return Math.sign(o.a-o.b)}(r,e)>0){let o=r;for(;o;){var n;if(o.contains(e))break;if(n=o.getBoundingClientRect(),n.xt.x&&n.yt.y)return!1;o=o.parentElement}}return!0}({groupElement:o.element,hitRegion:i.hitRegion.rect,pointerEventTarget:e.target})&&n.push(i.hitRegion)}),n}function Y(e){if(e.defaultPrevented||"mouse"===e.pointerType&&e.button>0)return;let{mountedGroups:t}=M,r=q(e,t),n=new Set,o=new Set,l=new Set,s=new Map,i=!1;r.forEach(e=>{n.add(e.group),e.panels.forEach(e=>{o.add(e)}),e.separator&&(l.add(e.separator),i||(i=!0,e.separator.element.focus()));let r=t.get(e.group);r&&s.set(e.group,r.layout)}),N({interactionState:{hitRegions:r,initialLayoutMap:s,pointerDownAtPoint:{x:e.clientX,y:e.clientY},state:"active"}}),r.length&&e.preventDefault()}let Q=new WeakMap;function X(e){if(null===e.defaultView||void 0===e.defaultView)return;let{prevStyle:t,styleSheet:r}=Q.get(e)??{};void 0===r&&(r=new e.defaultView.CSSStyleSheet,e.adoptedStyleSheets=[r]);let{cursorFlags:n,interactionState:o}=M;switch(o.state){case"active":case"hover":{let e=function({cursorFlags:e,groups:t,state:r}){let n=0,o=0;switch(r){case"active":case"hover":t.forEach(e=>{if(!e.disableCursor)switch(e.orientation){case"horizontal":n++;break;case"vertical":o++}})}if(0===n&&0===o)return null;if("active"===r){let t=(4&e)!=0,r=(8&e)!=0;if(e){if((1&e)!=0)return t?"se-resize":r?"ne-resize":"e-resize";if((2&e)!=0)return t?"sw-resize":r?"nw-resize":"w-resize";if(t)return"s-resize";if(r)return"n-resize"}}return n>0&&o>0?"move":n>0?"ew-resize":"ns-resize"}({cursorFlags:n,groups:o.hitRegions.map(e=>e.group),state:o.state}),l=`*{cursor: ${e} !important; ${"active"===o.state?"touch-action: none;":""} }`;if(t===l)return;t=l,e?0===r.cssRules.length?r.insertRule(l):r.replaceSync(l):1===r.cssRules.length&&r.deleteRule(0);break}case"inactive":t=void 0,1===r.cssRules.length&&r.deleteRule(0)}Q.set(e,{prevStyle:t,styleSheet:r})}function Z({document:e,event:t,hitRegions:r,initialLayoutMap:n,mountedGroups:o,pointerDownAtPoint:l}){let s=0,i=new Map(o);r.forEach(e=>{let{group:r,groupSize:a}=e,{disableCursor:d,orientation:u,panels:c}=r,f=0;f=l?"horizontal"===u?(t.clientX-l.x)/a*100:(t.clientY-l.y)/a*100:"horizontal"===u?t.clientX<0?-100:100:t.clientY<0?-100:100;let p=n.get(r),{defaultLayoutDeferred:h,derivedPanelConstraints:m,layout:g,separatorToPanels:y}=o.get(r)??{defaultLayoutDeferred:!1};if(m&&p&&g&&y){let t=P({delta:f,initialLayout:p,panelConstraints:m,pivotIndices:e.panels.map(e=>c.indexOf(e)),prevLayout:g,trigger:"mouse-or-touch"});if(T(t,g)){if(0!==f&&!d)switch(u){case"horizontal":s|=f<0?1:2;break;case"vertical":s|=f<0?4:8}}else{i.set(e.group,{defaultLayoutDeferred:h,derivedPanelConstraints:m,layout:t,separatorToPanels:y});let r=e.group.panels.map(({id:e})=>e).join(",");e.group.inMemoryLayouts[r]=t}}}),N({cursorFlags:s,mountedGroups:i}),X(e)}function J(e){let{interactionState:t,mountedGroups:r}=M;"active"===t.state&&Z({document:e.currentTarget,event:e,hitRegions:t.hitRegions,initialLayoutMap:t.initialLayoutMap,mountedGroups:r})}function ee(e){if(e.defaultPrevented)return;let{interactionState:t,mountedGroups:r}=M;if("active"===t.state){if(0===e.buttons){N(e=>"inactive"===e.interactionState.state?e:{cursorFlags:0,interactionState:{state:"inactive"}}),N(e=>({mountedGroups:new Map(e.mountedGroups)}));return}Z({document:e.currentTarget,event:e,hitRegions:t.hitRegions,initialLayoutMap:t.initialLayoutMap,mountedGroups:r,pointerDownAtPoint:t.pointerDownAtPoint})}else{let n=q(e,r);0===n.length?"inactive"!==t.state&&N({interactionState:{state:"inactive"}}):N({interactionState:{hitRegions:n,state:"hover"}}),X(e.currentTarget)}}function et(e){if(e.defaultPrevented||"mouse"===e.pointerType&&e.button>0)return;let{interactionState:t}=M;"active"===t.state&&(N({cursorFlags:0,interactionState:{state:"inactive"}}),t.hitRegions.length>0&&(X(e.currentTarget),N(e=>({mountedGroups:new Map(e.mountedGroups)})),e.preventDefault()))}function er(e){let t=0,r=0,n={};for(let o of e)if(void 0!==o.defaultSize){t++;let e=j(o.defaultSize);r+=e,n[o.panelId]=e}else n[o.panelId]=void 0;let o=e.length-t;if(0!==o){let t=j((100-r)/o);for(let r of e)void 0===r.defaultSize&&(n[r.panelId]=t)}return n}let en=new Map;function eo(){let[e,t]=(0,u.useState)({});return[e,(0,u.useCallback)(()=>t({}),[])]}function el(e){let t=(0,u.useId)();return`${e??t}`}let es="u">typeof window?u.useLayoutEffect:u.useEffect;function ei(e){let t=(0,u.useRef)(e);return es(()=>{t.current=e},[e]),(0,u.useCallback)((...e)=>t.current?.(...e),[t])}function ea(...e){return ei(t=>{e.forEach(e=>{if(e)switch(typeof e){case"function":e(t);break;case"object":e.current=t}})})}let ed=(0,u.createContext)(null);function eu({children:e,className:t,defaultLayout:r,disableCursor:n,disabled:o,elementRef:l,groupRef:s,id:i,onLayoutChange:a,onLayoutChanged:c,orientation:f="horizontal",style:p,...h}){var m;let x,v,w=(0,u.useRef)({onLayoutChange:{},onLayoutChanged:{}}),k=ei(e=>{T(w.current.onLayoutChange,e)||(w.current.onLayoutChange=e,a?.(e))}),z=ei(e=>{T(w.current.onLayoutChanged,e)||(w.current.onLayoutChanged=e,c?.(e))}),E=el(i),L=(0,u.useRef)(null),[I,P]=eo(),O=(0,u.useRef)({lastExpandedPanelSizes:{},layouts:{},panels:[],separators:[]}),F=ea(L,l);x=(0,u.useRef)({getLayout:()=>({}),setLayout:G}),(0,u.useImperativeHandle)(s,()=>x.current,[]),es(()=>{Object.assign(x.current,D({groupId:E}))});let $=ei((e,t)=>{let{interactionState:n,mountedGroups:o}=M;for(let r of o.keys())if(r.id===e){let e=o.get(r);if(e){let o=!1;return"active"===n.state&&(o=n.hitRegions.some(e=>e.group===r)),{flexGrow:e.layout[t]??1,pointerEvents:o?"none":void 0}}}return{flexGrow:r?.[t]??1}}),W=(0,u.useMemo)(()=>({getPanelStyles:$,id:E,orientation:f,registerPanel:e=>{let t=O.current;return t.panels=b(f,[...t.panels,e]),P(),()=>{t.panels=t.panels.filter(t=>t!==e),P()}},registerSeparator:e=>{let t=O.current;return t.separators=b(f,[...t.separators,e]),P(),()=>{t.separators=t.separators.filter(t=>t!==e),P()}}}),[$,E,P,f]),B=(m={defaultLayout:r,disableCursor:n},v=(0,u.useRef)({...m}),es(()=>{for(let e in m)v.current[e]=m[e]},[m]),v.current),V=(0,u.useRef)(null);return es(()=>{let e,t,r,n,l,s,i,a,d,u,c,p,h=L.current;if(null===h)return;let m=O.current,b={defaultLayout:B.defaultLayout,disableCursor:!!B.disableCursor,disabled:!!o,element:h,id:E,inMemoryLastExpandedPanelSizes:O.current.lastExpandedPanelSizes,inMemoryLayouts:O.current.layouts,orientation:f,panels:m.panels,separators:m.separators};V.current=b;let x=(e=!0,g(b.element.ownerDocument.defaultView,"Cannot register an unmounted Group"),t=b.element.ownerDocument.defaultView.ResizeObserver,r=new Set,n=new Set,(l=new t(t=>{for(let r of t){let{borderBoxSize:t,target:n}=r;if(n===b.element){if(e){if(0===y({group:b}))return;N(e=>{let t=e.mountedGroups.get(b);if(t){let r=C(b),n=t.defaultLayoutDeferred?er(r):t.layout,o=A({layout:n,panelConstraints:r});return!t.defaultLayoutDeferred&&T(n,o)&&function(e,t){if(Object.keys(e).length!==Object.keys(t).length)return!1;for(let r in e)if(e[r]!==t[r])return!1;return!0}(t.derivedPanelConstraints,r)?e:{mountedGroups:new Map(e.mountedGroups).set(b,{defaultLayoutDeferred:!1,derivedPanelConstraints:r,layout:o,separatorToPanels:t.separatorToPanels})}}return e})}}else!function(e,t,r){if(!r[0])return;let n=e.panels.find(e=>e.element===t);if(!n||!n.onResize)return;let o=y({group:e}),l="horizontal"===e.orientation?n.element.offsetWidth:n.element.offsetHeight,s=n.mutableValues.prevSize,i={asPercentage:j(l/o*100),inPixels:l};n.mutableValues.prevSize=i,n.onResize(i,n.id,s)}(b,n,t)}})).observe(b.element),b.panels.forEach(e=>{g(!r.has(e.id),`Panel ids must be unique; id "${e.id}" was used more than once`),r.add(e.id),e.onResize&&l.observe(e.element)}),s=y({group:b}),i=C(b),a=b.panels.map(({id:e})=>e).join(","),(d=b.defaultLayout)&&(function(e,t){let r=e.map(e=>e.id),n=Object.keys(t);if(r.length!==n.length)return!1;for(let e of r)if(!n.includes(e))return!1;return!0}(b.panels,d)||(d=void 0)),u=A({layout:b.inMemoryLayouts[a]??d??er(i),panelConstraints:i}),c=S(b),p=b.element.ownerDocument,N(e=>{let t=new Map;return en.set(p,(en.get(p)??0)+1),c.forEach(e=>{e.separator&&t.set(e.separator,e.panels)}),{mountedGroups:new Map(e.mountedGroups).set(b,{defaultLayoutDeferred:0===s,derivedPanelConstraints:i,layout:u,separatorToPanels:t})}}),b.separators.forEach(e=>{g(!n.has(e.id),`Separator ids must be unique; id "${e.id}" was used more than once`),n.add(e.id),e.element.addEventListener("keydown",_)}),1===en.get(p)&&(p.addEventListener("pointerdown",Y,!0),p.addEventListener("pointerleave",J),p.addEventListener("pointermove",ee),p.addEventListener("pointerup",et,!0)),function(){e=!1,en.set(p,Math.max(0,(en.get(p)??0)-1)),N(e=>{let t=new Map(e.mountedGroups);return t.delete(b),{mountedGroups:t}}),b.separators.forEach(e=>{e.element.removeEventListener("keydown",_)}),en.get(p)||(p.removeEventListener("pointerdown",Y,!0),p.removeEventListener("pointerleave",J),p.removeEventListener("pointermove",ee),p.removeEventListener("pointerup",et,!0)),l.disconnect()}),v=M.mountedGroups.get(b);if(v){let{defaultLayoutDeferred:e,derivedPanelConstraints:t,layout:r}=v;!e&&t.length>0&&(k(r),z(r),m.panels.forEach(e=>{e.scheduleUpdate()}))}let w=R.addListener("interactionStateChange",()=>{m.panels.forEach(e=>{e.scheduleUpdate()})}),I=R.addListener("mountedGroupsChange",e=>{let t=e.get(b);if(t){let{defaultLayoutDeferred:e,derivedPanelConstraints:r,layout:n}=t;if(e||0===r.length)return;let{interactionState:o}=M,l="active"!==o.state;k(n),l&&z(n),m.panels.forEach(e=>{e.scheduleUpdate()})}});return()=>{V.current=null,x(),w(),I()}},[o,E,z,k,f,I,B]),(0,u.useEffect)(()=>{let e=V.current;e&&(e.defaultLayout=r,e.disableCursor=!!n)}),(0,d.jsx)(ed.Provider,{value:W,children:(0,d.jsx)("div",{...h,"aria-orientation":f,className:t,"data-group":!0,"data-testid":E,id:E,ref:F,style:{height:"100%",width:"100%",overflow:"hidden",...p,display:"flex",flexDirection:"horizontal"===f?"row":"column",flexWrap:"nowrap"},children:e})})}function ec(){let e=(0,u.useContext)(ed);return g(e,"Group Context not found; did you render a Panel or Separator outside of a Group?"),e}function ef({children:e,className:t,collapsedSize:r="0%",collapsible:n=!1,defaultSize:o,elementRef:l,id:s,maxSize:i="100%",minSize:a="0%",onResize:c,panelRef:f,style:p,...h}){let m=!!s,g=el(s),b=(0,u.useRef)(null),x=ea(b,l),[,v]=eo(),{getPanelStyles:w,id:k,registerPanel:S}=ec(),z=null!==c,C=ei((e,t,r)=>{c?.(e,s,r)});es(()=>{let e=b.current;if(null!==e)return S({element:e,id:g,idIsStable:m,mutableValues:{expandToSize:void 0,prevSize:void 0},onResize:z?C:void 0,panelConstraints:{collapsedSize:r,collapsible:n,defaultSize:o,maxSize:i,minSize:a},scheduleUpdate:v})},[r,n,o,v,z,g,m,i,a,C,S]),function(e,t){let{id:r}=ec(),n=(0,u.useRef)({collapse:W,expand:W,getSize:()=>({asPercentage:0,inPixels:0}),isCollapsed:()=>!1,resize:W});(0,u.useImperativeHandle)(t,()=>n.current,[]),es(()=>{Object.assign(n.current,function({groupId:e,panelId:t}){let r=()=>{let{mountedGroups:t}=M;for(let[r,{defaultLayoutDeferred:n,derivedPanelConstraints:o,layout:l,separatorToPanels:s}]of t)if(r.id===e)return{defaultLayoutDeferred:n,derivedPanelConstraints:o,group:r,layout:l,separatorToPanels:s};throw Error(`Group ${e} not found`)},n=()=>{let e=r().derivedPanelConstraints.find(e=>e.panelId===t);if(void 0!==e)return e;throw Error(`Panel constraints not found for Panel ${t}`)},o=()=>{let e=r().group.panels.find(e=>e.id===t);if(void 0!==e)return e;throw Error(`Layout not found for Panel ${t}`)},l=()=>{let e=r().layout[t];if(void 0!==e)return e;throw Error(`Layout not found for Panel ${t}`)},s=e=>{let n=l();if(e===n)return;let{defaultLayoutDeferred:o,derivedPanelConstraints:s,group:i,layout:a,separatorToPanels:d}=r(),u=i.panels.findIndex(e=>e.id===t),c=u===i.panels.length-1,f=A({layout:P({delta:c?n-e:e-n,initialLayout:a,panelConstraints:s,pivotIndices:c?[u-1,u]:[u,u+1],prevLayout:a,trigger:"imperative-api"}),panelConstraints:s});T(a,f)||N(e=>({mountedGroups:new Map(e.mountedGroups).set(i,{defaultLayoutDeferred:o,derivedPanelConstraints:s,layout:f,separatorToPanels:d})}))};return{collapse:()=>{let{collapsible:e,collapsedSize:t}=n(),{mutableValues:r}=o(),i=l();e&&i!==t&&(r.expandToSize=i,s(t))},expand:()=>{let{collapsible:e,collapsedSize:t,minSize:r}=n(),{mutableValues:i}=o(),a=l();if(e&&a===t){let e=i.expandToSize??r;0===e&&(e=1),s(e)}},getSize:()=>{let{group:e}=r(),t=l(),{element:n}=o();return{asPercentage:t,inPixels:"horizontal"===e.orientation?n.offsetWidth:n.offsetHeight}},isCollapsed:()=>{let{collapsible:e,collapsedSize:t}=n(),r=l();return e&&E(t,r)},resize:e=>{if(l()!==e){let t;switch(typeof e){case"number":{let{group:n}=r();t=j(e/y({group:n})*100);break}case"string":t=parseFloat(e)}s(t)}}}}({groupId:r,panelId:e}))})}(g,f);let R=w(k,g);return(0,d.jsx)("div",{...h,"data-panel":!0,"data-testid":g,id:g,ref:x,style:{...ep,flexBasis:0,flexShrink:1,overflow:"hidden",...R},children:(0,d.jsx)("div",{className:t,style:{width:"100%",height:"100%",...p},children:e})})}eu.displayName="Group",ef.displayName="Panel";let ep={minHeight:0,maxHeight:"100%",height:"auto",minWidth:0,maxWidth:"100%",width:"auto",border:"none",borderWidth:0,padding:0,margin:0};function eh({children:e,className:t,elementRef:r,id:n,style:o,...l}){let s=el(n),[i,a]=(0,u.useState)({}),[c,f]=(0,u.useState)("inactive"),p=(0,u.useRef)(null),h=ea(p,r),{id:m,orientation:g,registerSeparator:y}=ec();return es(()=>{let e=p.current;if(null!==e){let t={element:e,id:s},r=y(t),n=R.addListener("interactionStateChange",e=>{f("inactive"!==e.state&&e.hitRegions.some(e=>e.separator===t)?e.state:"inactive")}),o=R.addListener("mountedGroupsChange",e=>{e.forEach(({derivedPanelConstraints:e,layout:r,separatorToPanels:n},o)=>{if(o.id===m){let l=n.get(t);if(l){let t=l[0],n=o.panels.indexOf(t);a(function({layout:e,panelConstraints:t,panelId:r,panelIndex:n}){let o,l,s=e[r],i=t.find(e=>e.panelId===r);if(i){let a=i.maxSize,d=l=i.collapsible?i.collapsedSize:i.minSize,u=[n,n+1];l=A({layout:P({delta:d-s,initialLayout:e,panelConstraints:t,pivotIndices:u,prevLayout:e,trigger:"keyboard"}),panelConstraints:t})[r],o=A({layout:P({delta:a-s,initialLayout:e,panelConstraints:t,pivotIndices:u,prevLayout:e,trigger:"keyboard"}),panelConstraints:t})[r]}return{valueControls:r,valueMax:o,valueMin:l,valueNow:s}}({layout:r,panelConstraints:e,panelId:t.id,panelIndex:n}))}}})});return()=>{n(),o(),r()}}},[m,s,y]),(0,d.jsx)("div",{...l,"aria-controls":i.valueControls,"aria-orientation":"horizontal"===g?"vertical":"horizontal","aria-valuemax":i.valueMax,"aria-valuemin":i.valueMin,"aria-valuenow":i.valueNow,children:e,className:t,"data-separator":c,"data-testid":s,id:s,ref:h,role:"separator",style:{flexBasis:"auto",...o,flexGrow:0,flexShrink:0},tabIndex:0})}function em(){for(var e,t,r=0,n="",o=arguments.length;r({nextPart:e,validators:t,classGroupId:r}),ey=[],eb=(e,t,r)=>{if(0==e.length-t)return r.classGroupId;let n=e[t],o=r.nextPart.get(n);if(o){let r=eb(e,t+1,o);if(r)return r}let l=r.validators;if(null===l)return;let s=0===t?e.join("-"):e.slice(t).join("-"),i=l.length;for(let e=0;e{let r=eg();for(let n in e)ev(e[n],r,n,t);return r},ev=(e,t,r,n)=>{let o=e.length;for(let l=0;l{"string"==typeof e?ek(e,t,r):"function"==typeof e?eS(e,t,r,n):ez(e,t,r,n)},ek=(e,t,r)=>{(""===e?t:ej(t,e)).classGroupId=r},eS=(e,t,r,n)=>{eC(e)?ev(e(n),t,r,n):(null===t.validators&&(t.validators=[]),t.validators.push({classGroupId:r,validator:e}))},ez=(e,t,r,n)=>{let o=Object.entries(e),l=o.length;for(let e=0;e{let r=e,n=t.split("-"),o=n.length;for(let e=0;e"isThemeGetter"in e&&!0===e.isThemeGetter,eE=[],eM=(e,t,r,n,o)=>({modifiers:e,hasImportantModifier:t,baseClassName:r,maybePostfixModifierPosition:n,isExternal:o}),eR=/\s+/,eN=e=>{let t;if("string"==typeof e)return e;let r="";for(let n=0;n{let t=t=>t[e]||eL;return t.isThemeGetter=!0,t},eP=/^\[(?:(\w[\w-]*):)?(.+)\]$/i,eO=/^\((?:(\w[\w-]*):)?(.+)\)$/i,eT=/^\d+\/\d+$/,eA=/^(\d+(\.\d+)?)?(xs|sm|md|lg|xl)$/,eD=/\d+(%|px|r?em|[sdl]?v([hwib]|min|max)|pt|pc|in|cm|mm|cap|ch|ex|r?lh|cq(w|h|i|b|min|max))|\b(calc|min|max|clamp)\(.+\)|^0$/,eF=/^(rgba?|hsla?|hwb|(ok)?(lab|lch)|color-mix)\(.+\)$/,e$=/^(inset_)?-?((\d+)?\.?(\d+)[a-z]+|0)_-?((\d+)?\.?(\d+)[a-z]+|0)/,e_=/^(url|image|image-set|cross-fade|element|(repeating-)?(linear|radial|conic)-gradient)\(.+\)$/,eG=e=>eT.test(e),eW=e=>!!e&&!Number.isNaN(Number(e)),eB=e=>!!e&&Number.isInteger(Number(e)),eV=e=>e.endsWith("%")&&eW(e.slice(0,-1)),eK=e=>eA.test(e),eH=()=>!0,eU=e=>eD.test(e)&&!eF.test(e),eq=()=>!1,eY=e=>e$.test(e),eQ=e=>e_.test(e),eX=e=>!eJ(e)&&!e3(e),eZ=e=>tr(e,ts,eq),eJ=e=>eP.test(e),e0=e=>tr(e,ti,eU),e1=e=>tr(e,ta,eW),e2=e=>tr(e,to,eq),e5=e=>tr(e,tl,eQ),e4=e=>tr(e,tu,eY),e3=e=>eO.test(e),e6=e=>tn(e,ti),e8=e=>tn(e,td),e9=e=>tn(e,to),e7=e=>tn(e,ts),te=e=>tn(e,tl),tt=e=>tn(e,tu,!0),tr=(e,t,r)=>{let n=eP.exec(e);return!!n&&(n[1]?t(n[1]):r(n[2]))},tn=(e,t,r=!1)=>{let n=eO.exec(e);return!!n&&(n[1]?t(n[1]):r)},to=e=>"position"===e||"percentage"===e,tl=e=>"image"===e||"url"===e,ts=e=>"length"===e||"size"===e||"bg-size"===e,ti=e=>"length"===e,ta=e=>"number"===e,td=e=>"family-name"===e,tu=e=>"shadow"===e,tc=((e,...t)=>{let r,n,o,l,s=e=>{let t=n(e);if(t)return t;let l=((e,t)=>{let{parseClassName:r,getClassGroupId:n,getConflictingClassGroupIds:o,sortModifiers:l}=t,s=[],i=e.trim().split(eR),a="";for(let e=i.length-1;e>=0;e-=1){let t=i[e],{isExternal:d,modifiers:u,hasImportantModifier:c,baseClassName:f,maybePostfixModifierPosition:p}=r(t);if(d){a=t+(a.length>0?" "+a:a);continue}let h=!!p,m=n(h?f.substring(0,p):f);if(!m){if(!h||!(m=n(f))){a=t+(a.length>0?" "+a:a);continue}h=!1}let g=0===u.length?"":1===u.length?u[0]:l(u).join(":"),y=c?g+"!":g,b=y+m;if(s.indexOf(b)>-1)continue;s.push(b);let x=o(m,h);for(let e=0;e0?" "+a:a)}return a})(e,r);return o(e,l),l};return l=i=>{var a;let d;return n=(r={cache:(e=>{if(e<1)return{get:()=>void 0,set:()=>{}};let t=0,r=Object.create(null),n=Object.create(null),o=(o,l)=>{r[o]=l,++t>e&&(t=0,n=r,r=Object.create(null))};return{get(e){let t=r[e];return void 0!==t?t:void 0!==(t=n[e])?(o(e,t),t):void 0},set(e,t){e in r?r[e]=t:o(e,t)}}})((a=t.reduce((e,t)=>t(e),e())).cacheSize),parseClassName:(e=>{let{prefix:t,experimentalParseClassName:r}=e,n=e=>{let t,r=[],n=0,o=0,l=0,s=e.length;for(let i=0;il?t-l:void 0)};if(t){let e=t+":",r=n;n=t=>t.startsWith(e)?r(t.slice(e.length)):eM(eE,!1,t,void 0,!0)}if(r){let e=n;n=t=>r({className:t,parseClassName:e})}return n})(a),sortModifiers:(d=new Map,a.orderSensitiveModifiers.forEach((e,t)=>{d.set(e,1e6+t)}),e=>{let t=[],r=[];for(let n=0;n0&&(r.sort(),t.push(...r),r=[]),t.push(o)):r.push(o)}return r.length>0&&(r.sort(),t.push(...r)),t}),...(e=>{let t=(e=>{let{theme:t,classGroups:r}=e;return ex(r,t)})(e),{conflictingClassGroups:r,conflictingClassGroupModifiers:n}=e;return{getClassGroupId:e=>{if(e.startsWith("[")&&e.endsWith("]")){var r;let t,n,o;return -1===(r=e).slice(1,-1).indexOf(":")?void 0:(n=(t=r.slice(1,-1)).indexOf(":"),(o=t.slice(0,n))?"arbitrary.."+o:void 0)}let n=e.split("-"),o=+(""===n[0]&&n.length>1);return eb(n,o,t)},getConflictingClassGroupIds:(e,t)=>{if(t){let t=n[e],o=r[e];if(t){if(o){let e=Array(o.length+t.length);for(let t=0;tl(((...e)=>{let t,r,n=0,o="";for(;n{let e=eI("color"),t=eI("font"),r=eI("text"),n=eI("font-weight"),o=eI("tracking"),l=eI("leading"),s=eI("breakpoint"),i=eI("container"),a=eI("spacing"),d=eI("radius"),u=eI("shadow"),c=eI("inset-shadow"),f=eI("text-shadow"),p=eI("drop-shadow"),h=eI("blur"),m=eI("perspective"),g=eI("aspect"),y=eI("ease"),b=eI("animate"),x=()=>["auto","avoid","all","avoid-page","page","left","right","column"],v=()=>["center","top","bottom","left","right","top-left","left-top","top-right","right-top","bottom-right","right-bottom","bottom-left","left-bottom"],w=()=>[...v(),e3,eJ],k=()=>["auto","hidden","clip","visible","scroll"],S=()=>["auto","contain","none"],z=()=>[e3,eJ,a],j=()=>[eG,"full","auto",...z()],C=()=>[eB,"none","subgrid",e3,eJ],E=()=>["auto",{span:["full",eB,e3,eJ]},eB,e3,eJ],M=()=>[eB,"auto",e3,eJ],R=()=>["auto","min","max","fr",e3,eJ],N=()=>["start","end","center","between","around","evenly","stretch","baseline","center-safe","end-safe"],L=()=>["start","end","center","stretch","center-safe","end-safe"],I=()=>["auto",...z()],P=()=>[eG,"auto","full","dvw","dvh","lvw","lvh","svw","svh","min","max","fit",...z()],O=()=>[e,e3,eJ],T=()=>[...v(),e9,e2,{position:[e3,eJ]}],A=()=>["no-repeat",{repeat:["","x","y","space","round"]}],D=()=>["auto","cover","contain",e7,eZ,{size:[e3,eJ]}],F=()=>[eV,e6,e0],$=()=>["","none","full",d,e3,eJ],_=()=>["",eW,e6,e0],G=()=>["solid","dashed","dotted","double"],W=()=>["normal","multiply","screen","overlay","darken","lighten","color-dodge","color-burn","hard-light","soft-light","difference","exclusion","hue","saturation","color","luminosity"],B=()=>[eW,eV,e9,e2],V=()=>["","none",h,e3,eJ],K=()=>["none",eW,e3,eJ],H=()=>["none",eW,e3,eJ],U=()=>[eW,e3,eJ],q=()=>[eG,"full",...z()];return{cacheSize:500,theme:{animate:["spin","ping","pulse","bounce"],aspect:["video"],blur:[eK],breakpoint:[eK],color:[eH],container:[eK],"drop-shadow":[eK],ease:["in","out","in-out"],font:[eX],"font-weight":["thin","extralight","light","normal","medium","semibold","bold","extrabold","black"],"inset-shadow":[eK],leading:["none","tight","snug","normal","relaxed","loose"],perspective:["dramatic","near","normal","midrange","distant","none"],radius:[eK],shadow:[eK],spacing:["px",eW],text:[eK],"text-shadow":[eK],tracking:["tighter","tight","normal","wide","wider","widest"]},classGroups:{aspect:[{aspect:["auto","square",eG,eJ,e3,g]}],container:["container"],columns:[{columns:[eW,eJ,e3,i]}],"break-after":[{"break-after":x()}],"break-before":[{"break-before":x()}],"break-inside":[{"break-inside":["auto","avoid","avoid-page","avoid-column"]}],"box-decoration":[{"box-decoration":["slice","clone"]}],box:[{box:["border","content"]}],display:["block","inline-block","inline","flex","inline-flex","table","inline-table","table-caption","table-cell","table-column","table-column-group","table-footer-group","table-header-group","table-row-group","table-row","flow-root","grid","inline-grid","contents","list-item","hidden"],sr:["sr-only","not-sr-only"],float:[{float:["right","left","none","start","end"]}],clear:[{clear:["left","right","both","none","start","end"]}],isolation:["isolate","isolation-auto"],"object-fit":[{object:["contain","cover","fill","none","scale-down"]}],"object-position":[{object:w()}],overflow:[{overflow:k()}],"overflow-x":[{"overflow-x":k()}],"overflow-y":[{"overflow-y":k()}],overscroll:[{overscroll:S()}],"overscroll-x":[{"overscroll-x":S()}],"overscroll-y":[{"overscroll-y":S()}],position:["static","fixed","absolute","relative","sticky"],inset:[{inset:j()}],"inset-x":[{"inset-x":j()}],"inset-y":[{"inset-y":j()}],start:[{start:j()}],end:[{end:j()}],top:[{top:j()}],right:[{right:j()}],bottom:[{bottom:j()}],left:[{left:j()}],visibility:["visible","invisible","collapse"],z:[{z:[eB,"auto",e3,eJ]}],basis:[{basis:[eG,"full","auto",i,...z()]}],"flex-direction":[{flex:["row","row-reverse","col","col-reverse"]}],"flex-wrap":[{flex:["nowrap","wrap","wrap-reverse"]}],flex:[{flex:[eW,eG,"auto","initial","none",eJ]}],grow:[{grow:["",eW,e3,eJ]}],shrink:[{shrink:["",eW,e3,eJ]}],order:[{order:[eB,"first","last","none",e3,eJ]}],"grid-cols":[{"grid-cols":C()}],"col-start-end":[{col:E()}],"col-start":[{"col-start":M()}],"col-end":[{"col-end":M()}],"grid-rows":[{"grid-rows":C()}],"row-start-end":[{row:E()}],"row-start":[{"row-start":M()}],"row-end":[{"row-end":M()}],"grid-flow":[{"grid-flow":["row","col","dense","row-dense","col-dense"]}],"auto-cols":[{"auto-cols":R()}],"auto-rows":[{"auto-rows":R()}],gap:[{gap:z()}],"gap-x":[{"gap-x":z()}],"gap-y":[{"gap-y":z()}],"justify-content":[{justify:[...N(),"normal"]}],"justify-items":[{"justify-items":[...L(),"normal"]}],"justify-self":[{"justify-self":["auto",...L()]}],"align-content":[{content:["normal",...N()]}],"align-items":[{items:[...L(),{baseline:["","last"]}]}],"align-self":[{self:["auto",...L(),{baseline:["","last"]}]}],"place-content":[{"place-content":N()}],"place-items":[{"place-items":[...L(),"baseline"]}],"place-self":[{"place-self":["auto",...L()]}],p:[{p:z()}],px:[{px:z()}],py:[{py:z()}],ps:[{ps:z()}],pe:[{pe:z()}],pt:[{pt:z()}],pr:[{pr:z()}],pb:[{pb:z()}],pl:[{pl:z()}],m:[{m:I()}],mx:[{mx:I()}],my:[{my:I()}],ms:[{ms:I()}],me:[{me:I()}],mt:[{mt:I()}],mr:[{mr:I()}],mb:[{mb:I()}],ml:[{ml:I()}],"space-x":[{"space-x":z()}],"space-x-reverse":["space-x-reverse"],"space-y":[{"space-y":z()}],"space-y-reverse":["space-y-reverse"],size:[{size:P()}],w:[{w:[i,"screen",...P()]}],"min-w":[{"min-w":[i,"screen","none",...P()]}],"max-w":[{"max-w":[i,"screen","none","prose",{screen:[s]},...P()]}],h:[{h:["screen","lh",...P()]}],"min-h":[{"min-h":["screen","lh","none",...P()]}],"max-h":[{"max-h":["screen","lh",...P()]}],"font-size":[{text:["base",r,e6,e0]}],"font-smoothing":["antialiased","subpixel-antialiased"],"font-style":["italic","not-italic"],"font-weight":[{font:[n,e3,e1]}],"font-stretch":[{"font-stretch":["ultra-condensed","extra-condensed","condensed","semi-condensed","normal","semi-expanded","expanded","extra-expanded","ultra-expanded",eV,eJ]}],"font-family":[{font:[e8,eJ,t]}],"fvn-normal":["normal-nums"],"fvn-ordinal":["ordinal"],"fvn-slashed-zero":["slashed-zero"],"fvn-figure":["lining-nums","oldstyle-nums"],"fvn-spacing":["proportional-nums","tabular-nums"],"fvn-fraction":["diagonal-fractions","stacked-fractions"],tracking:[{tracking:[o,e3,eJ]}],"line-clamp":[{"line-clamp":[eW,"none",e3,e1]}],leading:[{leading:[l,...z()]}],"list-image":[{"list-image":["none",e3,eJ]}],"list-style-position":[{list:["inside","outside"]}],"list-style-type":[{list:["disc","decimal","none",e3,eJ]}],"text-alignment":[{text:["left","center","right","justify","start","end"]}],"placeholder-color":[{placeholder:O()}],"text-color":[{text:O()}],"text-decoration":["underline","overline","line-through","no-underline"],"text-decoration-style":[{decoration:[...G(),"wavy"]}],"text-decoration-thickness":[{decoration:[eW,"from-font","auto",e3,e0]}],"text-decoration-color":[{decoration:O()}],"underline-offset":[{"underline-offset":[eW,"auto",e3,eJ]}],"text-transform":["uppercase","lowercase","capitalize","normal-case"],"text-overflow":["truncate","text-ellipsis","text-clip"],"text-wrap":[{text:["wrap","nowrap","balance","pretty"]}],indent:[{indent:z()}],"vertical-align":[{align:["baseline","top","middle","bottom","text-top","text-bottom","sub","super",e3,eJ]}],whitespace:[{whitespace:["normal","nowrap","pre","pre-line","pre-wrap","break-spaces"]}],break:[{break:["normal","words","all","keep"]}],wrap:[{wrap:["break-word","anywhere","normal"]}],hyphens:[{hyphens:["none","manual","auto"]}],content:[{content:["none",e3,eJ]}],"bg-attachment":[{bg:["fixed","local","scroll"]}],"bg-clip":[{"bg-clip":["border","padding","content","text"]}],"bg-origin":[{"bg-origin":["border","padding","content"]}],"bg-position":[{bg:T()}],"bg-repeat":[{bg:A()}],"bg-size":[{bg:D()}],"bg-image":[{bg:["none",{linear:[{to:["t","tr","r","br","b","bl","l","tl"]},eB,e3,eJ],radial:["",e3,eJ],conic:[eB,e3,eJ]},te,e5]}],"bg-color":[{bg:O()}],"gradient-from-pos":[{from:F()}],"gradient-via-pos":[{via:F()}],"gradient-to-pos":[{to:F()}],"gradient-from":[{from:O()}],"gradient-via":[{via:O()}],"gradient-to":[{to:O()}],rounded:[{rounded:$()}],"rounded-s":[{"rounded-s":$()}],"rounded-e":[{"rounded-e":$()}],"rounded-t":[{"rounded-t":$()}],"rounded-r":[{"rounded-r":$()}],"rounded-b":[{"rounded-b":$()}],"rounded-l":[{"rounded-l":$()}],"rounded-ss":[{"rounded-ss":$()}],"rounded-se":[{"rounded-se":$()}],"rounded-ee":[{"rounded-ee":$()}],"rounded-es":[{"rounded-es":$()}],"rounded-tl":[{"rounded-tl":$()}],"rounded-tr":[{"rounded-tr":$()}],"rounded-br":[{"rounded-br":$()}],"rounded-bl":[{"rounded-bl":$()}],"border-w":[{border:_()}],"border-w-x":[{"border-x":_()}],"border-w-y":[{"border-y":_()}],"border-w-s":[{"border-s":_()}],"border-w-e":[{"border-e":_()}],"border-w-t":[{"border-t":_()}],"border-w-r":[{"border-r":_()}],"border-w-b":[{"border-b":_()}],"border-w-l":[{"border-l":_()}],"divide-x":[{"divide-x":_()}],"divide-x-reverse":["divide-x-reverse"],"divide-y":[{"divide-y":_()}],"divide-y-reverse":["divide-y-reverse"],"border-style":[{border:[...G(),"hidden","none"]}],"divide-style":[{divide:[...G(),"hidden","none"]}],"border-color":[{border:O()}],"border-color-x":[{"border-x":O()}],"border-color-y":[{"border-y":O()}],"border-color-s":[{"border-s":O()}],"border-color-e":[{"border-e":O()}],"border-color-t":[{"border-t":O()}],"border-color-r":[{"border-r":O()}],"border-color-b":[{"border-b":O()}],"border-color-l":[{"border-l":O()}],"divide-color":[{divide:O()}],"outline-style":[{outline:[...G(),"none","hidden"]}],"outline-offset":[{"outline-offset":[eW,e3,eJ]}],"outline-w":[{outline:["",eW,e6,e0]}],"outline-color":[{outline:O()}],shadow:[{shadow:["","none",u,tt,e4]}],"shadow-color":[{shadow:O()}],"inset-shadow":[{"inset-shadow":["none",c,tt,e4]}],"inset-shadow-color":[{"inset-shadow":O()}],"ring-w":[{ring:_()}],"ring-w-inset":["ring-inset"],"ring-color":[{ring:O()}],"ring-offset-w":[{"ring-offset":[eW,e0]}],"ring-offset-color":[{"ring-offset":O()}],"inset-ring-w":[{"inset-ring":_()}],"inset-ring-color":[{"inset-ring":O()}],"text-shadow":[{"text-shadow":["none",f,tt,e4]}],"text-shadow-color":[{"text-shadow":O()}],opacity:[{opacity:[eW,e3,eJ]}],"mix-blend":[{"mix-blend":[...W(),"plus-darker","plus-lighter"]}],"bg-blend":[{"bg-blend":W()}],"mask-clip":[{"mask-clip":["border","padding","content","fill","stroke","view"]},"mask-no-clip"],"mask-composite":[{mask:["add","subtract","intersect","exclude"]}],"mask-image-linear-pos":[{"mask-linear":[eW]}],"mask-image-linear-from-pos":[{"mask-linear-from":B()}],"mask-image-linear-to-pos":[{"mask-linear-to":B()}],"mask-image-linear-from-color":[{"mask-linear-from":O()}],"mask-image-linear-to-color":[{"mask-linear-to":O()}],"mask-image-t-from-pos":[{"mask-t-from":B()}],"mask-image-t-to-pos":[{"mask-t-to":B()}],"mask-image-t-from-color":[{"mask-t-from":O()}],"mask-image-t-to-color":[{"mask-t-to":O()}],"mask-image-r-from-pos":[{"mask-r-from":B()}],"mask-image-r-to-pos":[{"mask-r-to":B()}],"mask-image-r-from-color":[{"mask-r-from":O()}],"mask-image-r-to-color":[{"mask-r-to":O()}],"mask-image-b-from-pos":[{"mask-b-from":B()}],"mask-image-b-to-pos":[{"mask-b-to":B()}],"mask-image-b-from-color":[{"mask-b-from":O()}],"mask-image-b-to-color":[{"mask-b-to":O()}],"mask-image-l-from-pos":[{"mask-l-from":B()}],"mask-image-l-to-pos":[{"mask-l-to":B()}],"mask-image-l-from-color":[{"mask-l-from":O()}],"mask-image-l-to-color":[{"mask-l-to":O()}],"mask-image-x-from-pos":[{"mask-x-from":B()}],"mask-image-x-to-pos":[{"mask-x-to":B()}],"mask-image-x-from-color":[{"mask-x-from":O()}],"mask-image-x-to-color":[{"mask-x-to":O()}],"mask-image-y-from-pos":[{"mask-y-from":B()}],"mask-image-y-to-pos":[{"mask-y-to":B()}],"mask-image-y-from-color":[{"mask-y-from":O()}],"mask-image-y-to-color":[{"mask-y-to":O()}],"mask-image-radial":[{"mask-radial":[e3,eJ]}],"mask-image-radial-from-pos":[{"mask-radial-from":B()}],"mask-image-radial-to-pos":[{"mask-radial-to":B()}],"mask-image-radial-from-color":[{"mask-radial-from":O()}],"mask-image-radial-to-color":[{"mask-radial-to":O()}],"mask-image-radial-shape":[{"mask-radial":["circle","ellipse"]}],"mask-image-radial-size":[{"mask-radial":[{closest:["side","corner"],farthest:["side","corner"]}]}],"mask-image-radial-pos":[{"mask-radial-at":v()}],"mask-image-conic-pos":[{"mask-conic":[eW]}],"mask-image-conic-from-pos":[{"mask-conic-from":B()}],"mask-image-conic-to-pos":[{"mask-conic-to":B()}],"mask-image-conic-from-color":[{"mask-conic-from":O()}],"mask-image-conic-to-color":[{"mask-conic-to":O()}],"mask-mode":[{mask:["alpha","luminance","match"]}],"mask-origin":[{"mask-origin":["border","padding","content","fill","stroke","view"]}],"mask-position":[{mask:T()}],"mask-repeat":[{mask:A()}],"mask-size":[{mask:D()}],"mask-type":[{"mask-type":["alpha","luminance"]}],"mask-image":[{mask:["none",e3,eJ]}],filter:[{filter:["","none",e3,eJ]}],blur:[{blur:V()}],brightness:[{brightness:[eW,e3,eJ]}],contrast:[{contrast:[eW,e3,eJ]}],"drop-shadow":[{"drop-shadow":["","none",p,tt,e4]}],"drop-shadow-color":[{"drop-shadow":O()}],grayscale:[{grayscale:["",eW,e3,eJ]}],"hue-rotate":[{"hue-rotate":[eW,e3,eJ]}],invert:[{invert:["",eW,e3,eJ]}],saturate:[{saturate:[eW,e3,eJ]}],sepia:[{sepia:["",eW,e3,eJ]}],"backdrop-filter":[{"backdrop-filter":["","none",e3,eJ]}],"backdrop-blur":[{"backdrop-blur":V()}],"backdrop-brightness":[{"backdrop-brightness":[eW,e3,eJ]}],"backdrop-contrast":[{"backdrop-contrast":[eW,e3,eJ]}],"backdrop-grayscale":[{"backdrop-grayscale":["",eW,e3,eJ]}],"backdrop-hue-rotate":[{"backdrop-hue-rotate":[eW,e3,eJ]}],"backdrop-invert":[{"backdrop-invert":["",eW,e3,eJ]}],"backdrop-opacity":[{"backdrop-opacity":[eW,e3,eJ]}],"backdrop-saturate":[{"backdrop-saturate":[eW,e3,eJ]}],"backdrop-sepia":[{"backdrop-sepia":["",eW,e3,eJ]}],"border-collapse":[{border:["collapse","separate"]}],"border-spacing":[{"border-spacing":z()}],"border-spacing-x":[{"border-spacing-x":z()}],"border-spacing-y":[{"border-spacing-y":z()}],"table-layout":[{table:["auto","fixed"]}],caption:[{caption:["top","bottom"]}],transition:[{transition:["","all","colors","opacity","shadow","transform","none",e3,eJ]}],"transition-behavior":[{transition:["normal","discrete"]}],duration:[{duration:[eW,"initial",e3,eJ]}],ease:[{ease:["linear","initial",y,e3,eJ]}],delay:[{delay:[eW,e3,eJ]}],animate:[{animate:["none",b,e3,eJ]}],backface:[{backface:["hidden","visible"]}],perspective:[{perspective:[m,e3,eJ]}],"perspective-origin":[{"perspective-origin":w()}],rotate:[{rotate:K()}],"rotate-x":[{"rotate-x":K()}],"rotate-y":[{"rotate-y":K()}],"rotate-z":[{"rotate-z":K()}],scale:[{scale:H()}],"scale-x":[{"scale-x":H()}],"scale-y":[{"scale-y":H()}],"scale-z":[{"scale-z":H()}],"scale-3d":["scale-3d"],skew:[{skew:U()}],"skew-x":[{"skew-x":U()}],"skew-y":[{"skew-y":U()}],transform:[{transform:[e3,eJ,"","none","gpu","cpu"]}],"transform-origin":[{origin:w()}],"transform-style":[{transform:["3d","flat"]}],translate:[{translate:q()}],"translate-x":[{"translate-x":q()}],"translate-y":[{"translate-y":q()}],"translate-z":[{"translate-z":q()}],"translate-none":["translate-none"],accent:[{accent:O()}],appearance:[{appearance:["none","auto"]}],"caret-color":[{caret:O()}],"color-scheme":[{scheme:["normal","dark","light","light-dark","only-dark","only-light"]}],cursor:[{cursor:["auto","default","pointer","wait","text","move","help","not-allowed","none","context-menu","progress","cell","crosshair","vertical-text","alias","copy","no-drop","grab","grabbing","all-scroll","col-resize","row-resize","n-resize","e-resize","s-resize","w-resize","ne-resize","nw-resize","se-resize","sw-resize","ew-resize","ns-resize","nesw-resize","nwse-resize","zoom-in","zoom-out",e3,eJ]}],"field-sizing":[{"field-sizing":["fixed","content"]}],"pointer-events":[{"pointer-events":["auto","none"]}],resize:[{resize:["none","","y","x"]}],"scroll-behavior":[{scroll:["auto","smooth"]}],"scroll-m":[{"scroll-m":z()}],"scroll-mx":[{"scroll-mx":z()}],"scroll-my":[{"scroll-my":z()}],"scroll-ms":[{"scroll-ms":z()}],"scroll-me":[{"scroll-me":z()}],"scroll-mt":[{"scroll-mt":z()}],"scroll-mr":[{"scroll-mr":z()}],"scroll-mb":[{"scroll-mb":z()}],"scroll-ml":[{"scroll-ml":z()}],"scroll-p":[{"scroll-p":z()}],"scroll-px":[{"scroll-px":z()}],"scroll-py":[{"scroll-py":z()}],"scroll-ps":[{"scroll-ps":z()}],"scroll-pe":[{"scroll-pe":z()}],"scroll-pt":[{"scroll-pt":z()}],"scroll-pr":[{"scroll-pr":z()}],"scroll-pb":[{"scroll-pb":z()}],"scroll-pl":[{"scroll-pl":z()}],"snap-align":[{snap:["start","end","center","align-none"]}],"snap-stop":[{snap:["normal","always"]}],"snap-type":[{snap:["none","x","y","both"]}],"snap-strictness":[{snap:["mandatory","proximity"]}],touch:[{touch:["auto","none","manipulation"]}],"touch-x":[{"touch-pan":["x","left","right"]}],"touch-y":[{"touch-pan":["y","up","down"]}],"touch-pz":["touch-pinch-zoom"],select:[{select:["none","text","all","auto"]}],"will-change":[{"will-change":["auto","scroll","contents","transform",e3,eJ]}],fill:[{fill:["none",...O()]}],"stroke-w":[{stroke:[eW,e6,e0,e1]}],stroke:[{stroke:["none",...O()]}],"forced-color-adjust":[{"forced-color-adjust":["auto","none"]}]},conflictingClassGroups:{overflow:["overflow-x","overflow-y"],overscroll:["overscroll-x","overscroll-y"],inset:["inset-x","inset-y","start","end","top","right","bottom","left"],"inset-x":["right","left"],"inset-y":["top","bottom"],flex:["basis","grow","shrink"],gap:["gap-x","gap-y"],p:["px","py","ps","pe","pt","pr","pb","pl"],px:["pr","pl"],py:["pt","pb"],m:["mx","my","ms","me","mt","mr","mb","ml"],mx:["mr","ml"],my:["mt","mb"],size:["w","h"],"font-size":["leading"],"fvn-normal":["fvn-ordinal","fvn-slashed-zero","fvn-figure","fvn-spacing","fvn-fraction"],"fvn-ordinal":["fvn-normal"],"fvn-slashed-zero":["fvn-normal"],"fvn-figure":["fvn-normal"],"fvn-spacing":["fvn-normal"],"fvn-fraction":["fvn-normal"],"line-clamp":["display","overflow"],rounded:["rounded-s","rounded-e","rounded-t","rounded-r","rounded-b","rounded-l","rounded-ss","rounded-se","rounded-ee","rounded-es","rounded-tl","rounded-tr","rounded-br","rounded-bl"],"rounded-s":["rounded-ss","rounded-es"],"rounded-e":["rounded-se","rounded-ee"],"rounded-t":["rounded-tl","rounded-tr"],"rounded-r":["rounded-tr","rounded-br"],"rounded-b":["rounded-br","rounded-bl"],"rounded-l":["rounded-tl","rounded-bl"],"border-spacing":["border-spacing-x","border-spacing-y"],"border-w":["border-w-x","border-w-y","border-w-s","border-w-e","border-w-t","border-w-r","border-w-b","border-w-l"],"border-w-x":["border-w-r","border-w-l"],"border-w-y":["border-w-t","border-w-b"],"border-color":["border-color-x","border-color-y","border-color-s","border-color-e","border-color-t","border-color-r","border-color-b","border-color-l"],"border-color-x":["border-color-r","border-color-l"],"border-color-y":["border-color-t","border-color-b"],translate:["translate-x","translate-y","translate-none"],"translate-none":["translate","translate-x","translate-y","translate-z"],"scroll-m":["scroll-mx","scroll-my","scroll-ms","scroll-me","scroll-mt","scroll-mr","scroll-mb","scroll-ml"],"scroll-mx":["scroll-mr","scroll-ml"],"scroll-my":["scroll-mt","scroll-mb"],"scroll-p":["scroll-px","scroll-py","scroll-ps","scroll-pe","scroll-pt","scroll-pr","scroll-pb","scroll-pl"],"scroll-px":["scroll-pr","scroll-pl"],"scroll-py":["scroll-pt","scroll-pb"],touch:["touch-x","touch-y","touch-pz"],"touch-x":["touch"],"touch-y":["touch"],"touch-pz":["touch"]},conflictingClassGroupModifiers:{"font-size":["leading"]},orderSensitiveModifiers:["*","**","after","backdrop","before","details-content","file","first-letter","first-line","marker","placeholder","selection"]}});function tf(...e){return tc(em(e))}let tp=({className:e,...t})=>(0,d.jsx)(eu,{className:tf("flex h-full w-full data-[orientation=vertical]:flex-col",e),...t}),th=({withHandle:e,className:t,...r})=>(0,d.jsx)(eh,{className:tf("relative flex w-[3px] items-center justify-center bg-border/50 hover:bg-primary/50 transition-colors after:absolute after:inset-y-0 after:left-1/2 after:w-2 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring data-[orientation=vertical]:h-[3px] data-[orientation=vertical]:w-full data-[orientation=vertical]:after:left-0 data-[orientation=vertical]:after:h-2 data-[orientation=vertical]:after:w-full data-[orientation=vertical]:after:-translate-y-1/2 data-[orientation=vertical]:after:translate-x-0 [&[data-orientation=vertical]>div]:rotate-90",t),...r,children:e&&(0,d.jsx)("div",{className:"z-10 flex h-5 w-3 items-center justify-center rounded-sm border border-border bg-secondary",children:(0,d.jsx)(m,{className:"h-3 w-3 text-muted-foreground"})})});var tm=e.i(69941);function tg(e,t,r){let n,o=r.initialDeps??[];function l(){var l,s,i,a;let d,u;r.key&&(null==(l=r.debug)?void 0:l.call(r))&&(d=Date.now());let c=e();if(!(c.length!==o.length||c.some((e,t)=>o[t]!==e)))return n;if(o=c,r.key&&(null==(s=r.debug)?void 0:s.call(r))&&(u=Date.now()),n=t(...c),r.key&&(null==(i=r.debug)?void 0:i.call(r))){let e=Math.round((Date.now()-d)*100)/100,t=Math.round((Date.now()-u)*100)/100,n=t/16,o=(e,t)=>{for(e=String(e);e.length{o=e},l}function ty(e,t){if(void 0!==e)return e;throw Error(`Unexpected undefined${t?`: ${t}`:""}`)}e.i(39057);let tb=e=>{let{offsetWidth:t,offsetHeight:r}=e;return{width:t,height:r}},tx=e=>e,tv=e=>{let t=Math.max(e.startIndex-e.overscan,0),r=Math.min(e.endIndex+e.overscan,e.count-1),n=[];for(let e=t;e<=r;e++)n.push(e);return n},tw=(e,t)=>{let r=e.scrollElement;if(!r)return;let n=e.targetWindow;if(!n)return;let o=e=>{let{width:r,height:n}=e;t({width:Math.round(r),height:Math.round(n)})};if(o(tb(r)),!n.ResizeObserver)return()=>{};let l=new n.ResizeObserver(t=>{let n=()=>{let e=t[0];if(null==e?void 0:e.borderBoxSize){let t=e.borderBoxSize[0];if(t)return void o({width:t.inlineSize,height:t.blockSize})}o(tb(r))};e.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(n):n()});return l.observe(r,{box:"border-box"}),()=>{l.unobserve(r)}},tk={passive:!0},tS="undefined"==typeof window||"onscrollend"in window,tz=(e,t)=>{var r,n;let o,l=e.scrollElement;if(!l)return;let s=e.targetWindow;if(!s)return;let i=0,a=e.options.useScrollendEvent&&tS?()=>void 0:(r=()=>{t(i,!1)},n=e.options.isScrollingResetDelay,function(...e){s.clearTimeout(o),o=s.setTimeout(()=>r.apply(this,e),n)}),d=r=>()=>{let{horizontal:n,isRtl:o}=e.options;i=n?l.scrollLeft*(o&&-1||1):l.scrollTop,a(),t(i,r)},u=d(!0),c=d(!1);c(),l.addEventListener("scroll",u,tk);let f=e.options.useScrollendEvent&&tS;return f&&l.addEventListener("scrollend",c,tk),()=>{l.removeEventListener("scroll",u),f&&l.removeEventListener("scrollend",c)}},tj=(e,t,r)=>{if(null==t?void 0:t.borderBoxSize){let e=t.borderBoxSize[0];if(e)return Math.round(e[r.options.horizontal?"inlineSize":"blockSize"])}return e[r.options.horizontal?"offsetWidth":"offsetHeight"]},tC=(e,{adjustments:t=0,behavior:r},n)=>{var o,l;null==(l=null==(o=n.scrollElement)?void 0:o.scrollTo)||l.call(o,{[n.options.horizontal?"left":"top"]:e+t,behavior:r})};class tE{constructor(e){this.unsubs=[],this.scrollElement=null,this.targetWindow=null,this.isScrolling=!1,this.measurementsCache=[],this.itemSizeCache=new Map,this.pendingMeasuredCacheIndexes=[],this.scrollRect=null,this.scrollOffset=null,this.scrollDirection=null,this.scrollAdjustments=0,this.elementsCache=new Map,this.observer=(()=>{let e=null,t=()=>e||(this.targetWindow&&this.targetWindow.ResizeObserver?e=new this.targetWindow.ResizeObserver(e=>{e.forEach(e=>{let t=()=>{this._measureElement(e.target,e)};this.options.useAnimationFrameWithResizeObserver?requestAnimationFrame(t):t()})}):null);return{disconnect:()=>{var r;null==(r=t())||r.disconnect(),e=null},observe:e=>{var r;return null==(r=t())?void 0:r.observe(e,{box:"border-box"})},unobserve:e=>{var r;return null==(r=t())?void 0:r.unobserve(e)}}})(),this.range=null,this.setOptions=e=>{Object.entries(e).forEach(([t,r])=>{void 0===r&&delete e[t]}),this.options={debug:!1,initialOffset:0,overscan:1,paddingStart:0,paddingEnd:0,scrollPaddingStart:0,scrollPaddingEnd:0,horizontal:!1,getItemKey:tx,rangeExtractor:tv,onChange:()=>{},measureElement:tj,initialRect:{width:0,height:0},scrollMargin:0,gap:0,indexAttribute:"data-index",initialMeasurementsCache:[],lanes:1,isScrollingResetDelay:150,enabled:!0,isRtl:!1,useScrollendEvent:!1,useAnimationFrameWithResizeObserver:!1,...e}},this.notify=e=>{var t,r;null==(r=(t=this.options).onChange)||r.call(t,this,e)},this.maybeNotify=tg(()=>(this.calculateRange(),[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]),e=>{this.notify(e)},{key:!1,debug:()=>this.options.debug,initialDeps:[this.isScrolling,this.range?this.range.startIndex:null,this.range?this.range.endIndex:null]}),this.cleanup=()=>{this.unsubs.filter(Boolean).forEach(e=>e()),this.unsubs=[],this.observer.disconnect(),this.scrollElement=null,this.targetWindow=null},this._didMount=()=>()=>{this.cleanup()},this._willUpdate=()=>{var e;let t=this.options.enabled?this.options.getScrollElement():null;if(this.scrollElement!==t){if(this.cleanup(),!t)return void this.maybeNotify();this.scrollElement=t,this.scrollElement&&"ownerDocument"in this.scrollElement?this.targetWindow=this.scrollElement.ownerDocument.defaultView:this.targetWindow=(null==(e=this.scrollElement)?void 0:e.window)??null,this.elementsCache.forEach(e=>{this.observer.observe(e)}),this._scrollToOffset(this.getScrollOffset(),{adjustments:void 0,behavior:void 0}),this.unsubs.push(this.options.observeElementRect(this,e=>{this.scrollRect=e,this.maybeNotify()})),this.unsubs.push(this.options.observeElementOffset(this,(e,t)=>{this.scrollAdjustments=0,this.scrollDirection=t?this.getScrollOffset()this.options.enabled?(this.scrollRect=this.scrollRect??this.options.initialRect,this.scrollRect[this.options.horizontal?"width":"height"]):(this.scrollRect=null,0),this.getScrollOffset=()=>this.options.enabled?(this.scrollOffset=this.scrollOffset??("function"==typeof this.options.initialOffset?this.options.initialOffset():this.options.initialOffset),this.scrollOffset):(this.scrollOffset=null,0),this.getFurthestMeasurement=(e,t)=>{let r=new Map,n=new Map;for(let o=t-1;o>=0;o--){let t=e[o];if(r.has(t.lane))continue;let l=n.get(t.lane);if(null==l||t.end>l.end?n.set(t.lane,t):t.ende.end===t.end?e.index-t.index:e.end-t.end)[0]:void 0},this.getMeasurementOptions=tg(()=>[this.options.count,this.options.paddingStart,this.options.scrollMargin,this.options.getItemKey,this.options.enabled],(e,t,r,n,o)=>(this.pendingMeasuredCacheIndexes=[],{count:e,paddingStart:t,scrollMargin:r,getItemKey:n,enabled:o}),{key:!1}),this.getMeasurements=tg(()=>[this.getMeasurementOptions(),this.itemSizeCache],({count:e,paddingStart:t,scrollMargin:r,getItemKey:n,enabled:o},l)=>{if(!o)return this.measurementsCache=[],this.itemSizeCache.clear(),[];0===this.measurementsCache.length&&(this.measurementsCache=this.options.initialMeasurementsCache,this.measurementsCache.forEach(e=>{this.itemSizeCache.set(e.key,e.size)}));let s=this.pendingMeasuredCacheIndexes.length>0?Math.min(...this.pendingMeasuredCacheIndexes):0;this.pendingMeasuredCacheIndexes=[];let i=this.measurementsCache.slice(0,s);for(let o=s;othis.options.debug}),this.calculateRange=tg(()=>[this.getMeasurements(),this.getSize(),this.getScrollOffset(),this.options.lanes],(e,t,r,n)=>this.range=e.length>0&&t>0?function({measurements:e,outerSize:t,scrollOffset:r,lanes:n}){let o=e.length-1;if(e.length<=n)return{startIndex:0,endIndex:o};let l=tM(0,o,t=>e[t].start,r),s=l;if(1===n)for(;s1){let i=Array(n).fill(0);for(;se=0&&a.some(e=>e>=r);){let t=e[l];a[t.lane]=t.start,l--}l=Math.max(0,l-l%n),s=Math.min(o,s+(n-1-s%n))}return{startIndex:l,endIndex:s}}({measurements:e,outerSize:t,scrollOffset:r,lanes:n}):null,{key:!1,debug:()=>this.options.debug}),this.getVirtualIndexes=tg(()=>{let e=null,t=null,r=this.calculateRange();return r&&(e=r.startIndex,t=r.endIndex),this.maybeNotify.updateDeps([this.isScrolling,e,t]),[this.options.rangeExtractor,this.options.overscan,this.options.count,e,t]},(e,t,r,n,o)=>null===n||null===o?[]:e({startIndex:n,endIndex:o,overscan:t,count:r}),{key:!1,debug:()=>this.options.debug}),this.indexFromElement=e=>{let t=this.options.indexAttribute,r=e.getAttribute(t);return r?parseInt(r,10):(console.warn(`Missing attribute name '${t}={index}' on measured element.`),-1)},this._measureElement=(e,t)=>{let r=this.indexFromElement(e),n=this.measurementsCache[r];if(!n)return;let o=n.key,l=this.elementsCache.get(o);l!==e&&(l&&this.observer.unobserve(l),this.observer.observe(e),this.elementsCache.set(o,e)),e.isConnected&&this.resizeItem(r,this.options.measureElement(e,t,this))},this.resizeItem=(e,t)=>{let r=this.measurementsCache[e];if(!r)return;let n=t-(this.itemSizeCache.get(r.key)??r.size);0!==n&&((void 0!==this.shouldAdjustScrollPositionOnItemSizeChange?this.shouldAdjustScrollPositionOnItemSizeChange(r,n,this):r.start{e?this._measureElement(e,void 0):this.elementsCache.forEach((e,t)=>{e.isConnected||(this.observer.unobserve(e),this.elementsCache.delete(t))})},this.getVirtualItems=tg(()=>[this.getVirtualIndexes(),this.getMeasurements()],(e,t)=>{let r=[];for(let n=0,o=e.length;nthis.options.debug}),this.getVirtualItemForOffset=e=>{let t=this.getMeasurements();if(0!==t.length)return ty(t[tM(0,t.length-1,e=>ty(t[e]).start,e)])},this.getOffsetForAlignment=(e,t,r=0)=>{let n=this.getSize(),o=this.getScrollOffset();return"auto"===t&&(t=e>=o+n?"end":"start"),"center"===t?e+=(r-n)/2:"end"===t&&(e-=n),Math.max(Math.min(this.getTotalSize()+this.options.scrollMargin-n,e),0)},this.getOffsetForIndex=(e,t="auto")=>{e=Math.max(0,Math.min(e,this.options.count-1));let r=this.measurementsCache[e];if(!r)return;let n=this.getSize(),o=this.getScrollOffset();if("auto"===t)if(r.end>=o+n-this.options.scrollPaddingEnd)t="end";else{if(!(r.start<=o+this.options.scrollPaddingStart))return[o,t];t="start"}let l="end"===t?r.end+this.options.scrollPaddingEnd:r.start-this.options.scrollPaddingStart;return[this.getOffsetForAlignment(l,t,r.size),t]},this.isDynamicMode=()=>this.elementsCache.size>0,this.scrollToOffset=(e,{align:t="start",behavior:r}={})=>{"smooth"===r&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getOffsetForAlignment(e,t),{adjustments:void 0,behavior:r})},this.scrollToIndex=(e,{align:t="auto",behavior:r}={})=>{"smooth"===r&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),e=Math.max(0,Math.min(e,this.options.count-1));let n=0,o=t=>{if(!this.targetWindow)return;let n=this.getOffsetForIndex(e,t);if(!n)return void console.warn("Failed to get offset for index:",e);let[o,s]=n;this._scrollToOffset(o,{adjustments:void 0,behavior:r}),this.targetWindow.requestAnimationFrame(()=>{let t=this.getScrollOffset(),r=this.getOffsetForIndex(e,s);r?1.01>Math.abs(r[0]-t)||l(s):console.warn("Failed to get offset for index:",e)})},l=t=>{this.targetWindow&&(++n<10?this.targetWindow.requestAnimationFrame(()=>o(t)):console.warn(`Failed to scroll to index ${e} after 10 attempts.`))};o(t)},this.scrollBy=(e,{behavior:t}={})=>{"smooth"===t&&this.isDynamicMode()&&console.warn("The `smooth` scroll behavior is not fully supported with dynamic size."),this._scrollToOffset(this.getScrollOffset()+e,{adjustments:void 0,behavior:t})},this.getTotalSize=()=>{var e;let t,r=this.getMeasurements();if(0===r.length)t=this.options.paddingStart;else if(1===this.options.lanes)t=(null==(e=r[r.length-1])?void 0:e.end)??0;else{let e=Array(this.options.lanes).fill(null),n=r.length-1;for(;n>=0&&e.some(e=>null===e);){let t=r[n];null===e[t.lane]&&(e[t.lane]=t.end),n--}t=Math.max(...e.filter(e=>null!==e))}return Math.max(t-this.options.scrollMargin+this.options.paddingEnd,0)},this._scrollToOffset=(e,{adjustments:t,behavior:r})=>{this.options.scrollToFn(e,{behavior:r,adjustments:t},this)},this.measure=()=>{this.itemSizeCache=new Map,this.notify(!1)},this.setOptions(e)}}let tM=(e,t,r,n)=>{for(;e<=t;){let o=(e+t)/2|0,l=r(o);if(ln))return o;t=o-1}}return e>0?e-1:0},tR="undefined"!=typeof document?u.useLayoutEffect:u.useEffect,tN=e=>{let t,r=new Set,n=(e,n)=>{let o="function"==typeof e?e(t):e;if(!Object.is(o,t)){let e=t;t=(null!=n?n:"object"!=typeof o||null===o)?o:Object.assign({},t,o),r.forEach(r=>r(t,e))}},o=()=>t,l={setState:n,getState:o,getInitialState:()=>s,subscribe:e=>(r.add(e),()=>r.delete(e))},s=t=e(n,o,l);return l},tL=e=>{let t=e?tN(e):tN,r=e=>(function(e,t=e=>e){let r=u.default.useSyncExternalStore(e.subscribe,u.default.useCallback(()=>t(e.getState()),[e,t]),u.default.useCallback(()=>t(e.getInitialState()),[e,t]));return u.default.useDebugValue(r),r})(t,e);return Object.assign(r,t),r},tI=(n=(e,t)=>({datasetInfo:null,setDatasetInfo:t=>e({datasetInfo:t}),samples:[],totalSamples:0,samplesLoaded:0,setSamples:(t,r)=>e({samples:t,totalSamples:r,samplesLoaded:t.length}),appendSamples:t=>e(e=>{let r=new Set(e.samples.map(e=>e.id)),n=t.filter(e=>!r.has(e.id)),o=e.samplesLoaded+t.length;return 0===n.length?{samplesLoaded:o}:{samples:[...e.samples,...n],samplesLoaded:o}}),addSamplesIfMissing:t=>e(e=>{let r=new Set(e.samples.map(e=>e.id)),n=t.filter(e=>!r.has(e.id));return 0===n.length?e:{samples:[...e.samples,...n]}}),embeddings:null,setEmbeddings:t=>e({embeddings:t,currentLayoutKey:t?.layout_key??null}),currentLayoutKey:null,geometry:"euclidean",setGeometry:t=>e({geometry:t}),selectedIds:new Set,isLassoSelection:!1,selectionSource:null,setSelectedIds:(t,r="grid")=>e({selectedIds:t,selectionSource:t.size>0?r:null,isLassoSelection:!1,lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1}),toggleSelection:t=>e(e=>{let r=new Set(e.selectedIds);return r.has(t)?r.delete(t):r.add(t),{selectedIds:r,selectionSource:r.size>0?"grid":null,isLassoSelection:!1,lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1}}),addToSelection:t=>e(e=>{let r=new Set(e.selectedIds);return t.forEach(e=>r.add(e)),{selectedIds:r,selectionSource:r.size>0?"grid":null,isLassoSelection:!1,lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1}}),clearSelection:()=>e({selectedIds:new Set,selectionSource:null,isLassoSelection:!1,lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1}),lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1,beginLassoSelection:t=>e({isLassoSelection:!0,selectedIds:new Set,selectionSource:"lasso",lassoQuery:t,lassoSamples:[],lassoTotal:0,lassoIsLoading:!0}),setLassoResults:(t,r,n=!1)=>e(e=>({lassoSamples:n?[...e.lassoSamples,...t]:t,lassoTotal:r,lassoIsLoading:!1})),clearLassoSelection:()=>e({isLassoSelection:!1,selectionSource:null,lassoQuery:null,lassoSamples:[],lassoTotal:0,lassoIsLoading:!1}),hoveredId:null,setHoveredId:t=>e({hoveredId:t}),isLoading:!1,setIsLoading:t=>e({isLoading:t}),error:null,setError:t=>e({error:t})}))?tL(n):tL;function tP({children:e,className:t}){return(0,d.jsx)("div",{className:tf("flex flex-col h-full bg-card rounded-sm overflow-hidden border border-border",t),children:e})}function tO({children:e,className:t}){return(0,d.jsx)("div",{className:tf("px-2 py-1.5 text-[11px] text-muted-foreground/70 border-t border-border bg-card font-mono",t),children:e})}function tT({icon:e,title:t,subtitle:r,children:n,className:o}){return(0,d.jsxs)("div",{className:tf("h-9 min-h-[36px] flex items-center justify-between px-2 border-b border-border bg-secondary select-none",o),children:[(0,d.jsxs)("div",{className:"flex items-center gap-2 min-w-0",children:[e&&(0,d.jsx)("span",{className:"flex-shrink-0 w-4 h-4 text-muted-foreground",children:e}),(0,d.jsx)("span",{className:"text-sm font-medium text-foreground truncate",children:t}),r&&(0,d.jsx)("span",{className:"text-xs text-muted-foreground truncate",children:r})]}),n&&(0,d.jsx)("div",{className:"flex items-center gap-1",children:n})]})}let tA=()=>(0,d.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"w-4 h-4",children:[(0,d.jsx)("rect",{x:"3",y:"3",width:"7",height:"7"}),(0,d.jsx)("rect",{x:"14",y:"3",width:"7",height:"7"}),(0,d.jsx)("rect",{x:"3",y:"14",width:"7",height:"7"}),(0,d.jsx)("rect",{x:"14",y:"14",width:"7",height:"7"})]}),tD=()=>(0,d.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",className:"w-4 h-4",children:[(0,d.jsx)("circle",{cx:"8",cy:"8",r:"2"}),(0,d.jsx)("circle",{cx:"16",cy:"16",r:"2"}),(0,d.jsx)("circle",{cx:"18",cy:"8",r:"2"}),(0,d.jsx)("circle",{cx:"6",cy:"16",r:"2"}),(0,d.jsx)("circle",{cx:"12",cy:"12",r:"2"})]}),tF=()=>(0,d.jsxs)("svg",{viewBox:"0 0 24 24",fill:"none",className:"w-5 h-5",children:[(0,d.jsx)("circle",{cx:"12",cy:"12",r:"10",stroke:"currentColor",strokeWidth:"1.5"}),(0,d.jsx)("circle",{cx:"12",cy:"12",r:"6",stroke:"currentColor",strokeWidth:"1.5",opacity:"0.6"}),(0,d.jsx)("circle",{cx:"12",cy:"12",r:"2",fill:"currentColor"})]}),t$=()=>(0,d.jsx)("svg",{className:"w-3 h-3 text-white",fill:"none",stroke:"currentColor",viewBox:"0 0 24 24",children:(0,d.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:3,d:"M5 13l4 4L19 7"})}),t_=()=>(0,d.jsxs)("svg",{viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.25",className:"w-3.5 h-3.5",children:[(0,d.jsx)("rect",{x:"2",y:"2",width:"12",height:"12",rx:"1"}),(0,d.jsx)("line",{x1:"2",y1:"8",x2:"14",y2:"8"}),(0,d.jsx)("line",{x1:"8",y1:"2",x2:"8",y2:"14"})]}),tG=()=>(0,d.jsxs)("svg",{viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.25",className:"w-3.5 h-3.5",children:[(0,d.jsx)("circle",{cx:"8",cy:"8",r:"6"}),(0,d.jsx)("ellipse",{cx:"8",cy:"8",rx:"3",ry:"5.5"}),(0,d.jsx)("ellipse",{cx:"8",cy:"8",rx:"5.5",ry:"3"})]});function tW({samples:e,onLoadMore:t,hasMore:r}){let n=(0,u.useRef)(null),{selectedIds:o,isLassoSelection:l,selectionSource:s,lassoTotal:i,toggleSelection:a,addToSelection:c,setHoveredId:f,hoveredId:p}=tI(),[h,m]=(0,u.useState)(4);(0,u.useEffect)(()=>{let e=()=>{n.current&&m(Math.max(1,Math.floor((n.current.clientWidth-16+8)/208)))};e();let t=new ResizeObserver(e);return n.current&&t.observe(n.current),()=>t.disconnect()},[]);let g=function(e){let t=u.useReducer(()=>({}),{})[1],r={...e,onChange:(r,n)=>{var o;n?(0,tm.flushSync)(t):t(),null==(o=e.onChange)||o.call(e,r,n)}},[n]=u.useState(()=>new tE(r));return n.setOptions(r),tR(()=>n._didMount(),[]),tR(()=>n._willUpdate()),n}({observeElementRect:tw,observeElementOffset:tz,scrollToFn:tC,...{count:Math.ceil(e.length/h),getScrollElement:()=>n.current,estimateSize:()=>208,overscan:5,getItemKey:(0,u.useCallback)(t=>{let r=t*h;return e.slice(r,r+h).map(e=>e.id).join("-")||`row-${t}`},[e,h])}});(0,u.useEffect)(()=>{let e=n.current;if(!e||!t||!r)return;let o=()=>{let{scrollTop:r,scrollHeight:n,clientHeight:o}=e;n-r-o<500&&t()};return e.addEventListener("scroll",o),()=>e.removeEventListener("scroll",o)},[t,r]),(0,u.useEffect)(()=>{g.measure()},[o,l,g]),(0,u.useEffect)(()=>{if(!l&&"scatter"===s&&0!==o.size)try{g.scrollToIndex(0,{align:"start"})}catch{n.current?.scrollTo({top:0})}},[l,o,s,g]);let y=(0,u.useCallback)((t,r)=>{if(r.metaKey||r.ctrlKey)a(t.id);else if(r.shiftKey&&o.size>0){let r=Array.from(o),n=r[r.length-1],l=e.findIndex(e=>e.id===n),s=e.findIndex(e=>e.id===t.id);if(-1!==l&&-1!==s){let t=Math.min(l,s),r=Math.max(l,s);c(e.slice(t,r+1).map(e=>e.id))}}else{let e=new Set;e.add(t.id),tI.getState().setSelectedIds(e,"grid")}},[e,o,a,c]),b=g.getVirtualItems();return(0,d.jsxs)(tP,{children:[(0,d.jsx)(tT,{icon:(0,d.jsx)(tA,{}),title:"Samples",subtitle:l?`${i} selected`:o.size>0?`${o.size} selected`:`${e.length} items`}),(0,d.jsx)("div",{ref:n,className:"flex-1 overflow-auto p-2",children:(0,d.jsx)("div",{style:{height:`${g.getTotalSize()}px`,width:"100%",position:"relative"},children:b.map(t=>{let r=t.index*h,n=e.slice(r,r+h);return(0,d.jsxs)("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"200px",transform:`translateY(${t.start}px)`},className:"flex gap-2 px-1",children:[n.map(e=>{let t=!!l||o.has(e.id),r=p===e.id;return(0,d.jsxs)("div",{className:` + relative flex-1 rounded-md overflow-hidden cursor-pointer + transition-all duration-150 ease-out + ${t?"ring-2 ring-primary":""} + ${r?"ring-2 ring-primary/50":""} + `,onClick:t=>y(e,t),onMouseEnter:()=>f(e.id),onMouseLeave:()=>f(null),children:[e.thumbnail?(0,d.jsx)("img",{src:`data:image/jpeg;base64,${e.thumbnail}`,alt:e.filename,className:"w-full h-full object-cover",loading:"lazy"}):(0,d.jsx)("div",{className:"w-full h-full bg-muted flex items-center justify-center",children:(0,d.jsx)("span",{className:"text-muted-foreground text-xs",children:"No image"})}),e.label&&(0,d.jsx)("div",{className:"absolute bottom-1 left-1 right-1",children:(0,d.jsx)("span",{className:"inline-block px-1.5 py-0.5 text-xs rounded truncate max-w-full",style:{backgroundColor:"rgba(0,0,0,0.7)",color:"#fff"},children:e.label})}),t&&(0,d.jsx)("div",{className:"absolute top-1 right-1 w-5 h-5 rounded-full bg-primary flex items-center justify-center",children:(0,d.jsx)(t$,{})})]},e.id)}),Array.from({length:h-n.length}).map((e,t)=>(0,d.jsx)("div",{className:"flex-1"},`empty-${t}`))]},t.key)})})}),(0,d.jsx)(tO,{children:(0,d.jsx)("span",{children:"Click • ⌘+click multi • ⇧+click range"})})]})}function tB(e){return{shift:e.shiftKey,ctrl:e.ctrlKey,alt:e.altKey,meta:e.metaKey}}function tV(e){if(!e)return;let t=e.getContext("2d");t&&(t.setTransform(1,0,0,1,0,0),t.clearRect(0,0,e.width,e.height))}function tK(e,t){if(!e)return;let r=e.getContext("2d");if(r&&(tV(e),!(t.length<6))){r.save(),r.lineWidth=2,r.strokeStyle="rgba(79,70,229,0.9)",r.fillStyle="rgba(79,70,229,0.15)",r.beginPath(),r.moveTo(t[0],t[1]);for(let e=2;e{let t=r.map(e=>u.createContext(e));return function(r){let n=r?.[e]||t;return u.useMemo(()=>({[`__scope${e}`]:{...r,[e]:n}}),[r,n])}};return n.scopeName=e,[function(t,n){let o=u.createContext(n),l=r.length;r=[...r,n];let s=t=>{let{scope:r,children:n,...s}=t,i=r?.[e]?.[l]||o,a=u.useMemo(()=>s,Object.values(s));return(0,d.jsx)(i.Provider,{value:a,children:n})};return s.displayName=t+"Provider",[s,function(r,s){let i=s?.[e]?.[l]||o,a=u.useContext(i);if(a)return a;if(void 0!==n)return n;throw Error(`\`${r}\` must be used within \`${t}\``)}]},function(...e){let t=e[0];if(1===e.length)return t;let r=()=>{let r=e.map(e=>({useScope:e(),scopeName:e.scopeName}));return function(e){let n=r.reduce((t,{useScope:r,scopeName:n})=>{let o=r(e)[`__scope${n}`];return{...t,...o}},{});return u.useMemo(()=>({[`__scope${t.scopeName}`]:n}),[n])}};return r.scopeName=t.scopeName,r}(n,...t)]}function tU(e,t){if("function"==typeof e)return e(t);null!=e&&(e.current=t)}function tq(...e){return t=>{let r=!1,n=e.map(e=>{let n=tU(e,t);return r||"function"!=typeof n||(r=!0),n});if(r)return()=>{for(let t=0;t{var r,n;let o,l,s,i=(n=r=`Primitive.${t}`,(o=u.forwardRef((e,t)=>{let{children:r,...n}=e;if(u.isValidElement(r)){var o;let e,l,s=(o=r,(l=(e=Object.getOwnPropertyDescriptor(o.props,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.ref:(l=(e=Object.getOwnPropertyDescriptor(o,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.props.ref:o.props.ref||o.ref),i=function(e,t){let r={...t};for(let n in t){let o=e[n],l=t[n];/^on[A-Z]/.test(n)?o&&l?r[n]=(...e)=>{let t=l(...e);return o(...e),t}:o&&(r[n]=o):"style"===n?r[n]={...o,...l}:"className"===n&&(r[n]=[o,l].filter(Boolean).join(" "))}return{...e,...r}}(n,r.props);return r.type!==u.Fragment&&(i.ref=t?tq(t,s):s),u.cloneElement(r,i)}return u.Children.count(r)>1?u.Children.only(null):null})).displayName=`${n}.SlotClone`,l=o,(s=u.forwardRef((e,t)=>{let{children:r,...n}=e,o=u.Children.toArray(r),s=o.find(tX);if(s){let e=s.props.children,r=o.map(t=>t!==s?t:u.Children.count(e)>1?u.Children.only(null):u.isValidElement(e)?e.props.children:null);return(0,d.jsx)(l,{...n,ref:t,children:u.isValidElement(e)?u.cloneElement(e,void 0,r):null})}return(0,d.jsx)(l,{...n,ref:t,children:r})})).displayName=`${r}.Slot`,s),a=u.forwardRef((e,r)=>{let{asChild:n,...o}=e;return"undefined"!=typeof window&&(window[Symbol.for("radix-ui")]=!0),(0,d.jsx)(n?i:t,{...o,ref:r})});return a.displayName=`Primitive.${t}`,{...e,[t]:a}},{});function tJ(e,t,{checkForDefaultPrevented:r=!0}={}){return function(n){if(e?.(n),!1===r||!n.defaultPrevented)return t?.(n)}}function t0(e){var t;let r,n=(t=e,(r=u.forwardRef((e,t)=>{let{children:r,...n}=e;if(u.isValidElement(r)){var o;let e,l,s=(o=r,(l=(e=Object.getOwnPropertyDescriptor(o.props,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.ref:(l=(e=Object.getOwnPropertyDescriptor(o,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.props.ref:o.props.ref||o.ref),i=function(e,t){let r={...t};for(let n in t){let o=e[n],l=t[n];/^on[A-Z]/.test(n)?o&&l?r[n]=(...e)=>{let t=l(...e);return o(...e),t}:o&&(r[n]=o):"style"===n?r[n]={...o,...l}:"className"===n&&(r[n]=[o,l].filter(Boolean).join(" "))}return{...e,...r}}(n,r.props);return r.type!==u.Fragment&&(i.ref=t?tq(t,s):s),u.cloneElement(r,i)}return u.Children.count(r)>1?u.Children.only(null):null})).displayName=`${t}.SlotClone`,r),o=u.forwardRef((e,t)=>{let{children:r,...o}=e,l=u.Children.toArray(r),s=l.find(t2);if(s){let e=s.props.children,r=l.map(t=>t!==s?t:u.Children.count(e)>1?u.Children.only(null):u.isValidElement(e)?e.props.children:null);return(0,d.jsx)(n,{...o,ref:t,children:u.isValidElement(e)?u.cloneElement(e,void 0,r):null})}return(0,d.jsx)(n,{...o,ref:t,children:r})});return o.displayName=`${e}.Slot`,o}"undefined"!=typeof window&&window.document&&window.document.createElement;var t1=Symbol("radix.slottable");function t2(e){return u.isValidElement(e)&&"function"==typeof e.type&&"__radixId"in e.type&&e.type.__radixId===t1}var t5=new WeakMap;function t4(e,t){var r,n;let o,l,s;if("at"in Array.prototype)return Array.prototype.at.call(e,t);let i=(r=e,n=t,o=r.length,(s=(l=t3(n))>=0?l:o+l)<0||s>=o?-1:s);return -1===i?void 0:e[i]}function t3(e){return e!=e||0===e?0:Math.trunc(e)}(class e extends Map{#t;constructor(e){super(e),this.#t=[...super.keys()],t5.set(this,!0)}set(e,t){return t5.get(this)&&(this.has(e)?this.#t[this.#t.indexOf(e)]=e:this.#t.push(e)),super.set(e,t),this}insert(e,t,r){let n,o=this.has(t),l=this.#t.length,s=t3(e),i=s>=0?s:l+s,a=i<0||i>=l?-1:i;if(a===this.size||o&&a===this.size-1||-1===a)return this.set(t,r),this;let d=this.size+ +!o;s<0&&i++;let u=[...this.#t],c=!1;for(let e=i;e=this.size&&(n=this.size-1),this.at(n)}keyFrom(e,t){let r=this.indexOf(e);if(-1===r)return;let n=r+t;return n<0&&(n=0),n>=this.size&&(n=this.size-1),this.keyAt(n)}find(e,t){let r=0;for(let n of this){if(Reflect.apply(e,t,[n,r,this]))return n;r++}}findIndex(e,t){let r=0;for(let n of this){if(Reflect.apply(e,t,[n,r,this]))return r;r++}return -1}filter(t,r){let n=[],o=0;for(let e of this)Reflect.apply(t,r,[e,o,this])&&n.push(e),o++;return new e(n)}map(t,r){let n=[],o=0;for(let e of this)n.push([e[0],Reflect.apply(t,r,[e,o,this])]),o++;return new e(n)}reduce(...e){let[t,r]=e,n=0,o=r??this.at(0);for(let r of this)o=0===n&&1===e.length?r:Reflect.apply(t,this,[o,r,n,this]),n++;return o}reduceRight(...e){let[t,r]=e,n=r??this.at(-1);for(let r=this.size-1;r>=0;r--){let o=this.at(r);n=r===this.size-1&&1===e.length?o:Reflect.apply(t,this,[n,o,r,this])}return n}toSorted(t){return new e([...this.entries()].sort(t))}toReversed(){let t=new e;for(let e=this.size-1;e>=0;e--){let r=this.keyAt(e),n=this.get(r);t.set(r,n)}return t}toSpliced(...t){let r=[...this.entries()];return r.splice(...t),new e(r)}slice(t,r){let n=new e,o=this.size-1;if(void 0===t)return n;t<0&&(t+=this.size),void 0!==r&&r>0&&(o=r-1);for(let e=t;e<=o;e++){let t=this.keyAt(e),r=this.get(t);n.set(t,r)}return n}every(e,t){let r=0;for(let n of this){if(!Reflect.apply(e,t,[n,r,this]))return!1;r++}return!0}some(e,t){let r=0;for(let n of this){if(Reflect.apply(e,t,[n,r,this]))return!0;r++}return!1}});var t6=globalThis?.document?u.useLayoutEffect:()=>{},t8=u[" useId ".trim().toString()]||(()=>void 0),t9=0;u[" useEffectEvent ".trim().toString()],u[" useInsertionEffect ".trim().toString()];var t7=u[" useInsertionEffect ".trim().toString()]||t6;function re({prop:e,defaultProp:t,onChange:r=()=>{},caller:n}){let[o,l,s]=function({defaultProp:e,onChange:t}){let[r,n]=u.useState(e),o=u.useRef(r),l=u.useRef(t);return t7(()=>{l.current=t},[t]),u.useEffect(()=>{o.current!==r&&(l.current?.(r),o.current=r)},[r,o]),[r,n,l]}({defaultProp:t,onChange:r}),i=void 0!==e,a=i?e:o;{let t=u.useRef(void 0!==e);u.useEffect(()=>{let e=t.current;if(e!==i){let t=i?"controlled":"uncontrolled";console.warn(`${n} is changing from ${e?"controlled":"uncontrolled"} to ${t}. Components should not switch from controlled to uncontrolled (or vice versa). Decide between using a controlled or uncontrolled value for the lifetime of the component.`)}t.current=i},[i,n])}return[a,u.useCallback(t=>{if(i){let r="function"==typeof t?t(e):t;r!==e&&s.current?.(r)}else l(t)},[i,e,l,s])]}Symbol("RADIX:SYNC_STATE");var rt=u.createContext(void 0);function rr(e){let t=u.useContext(rt);return e||t||"ltr"}var rn="rovingFocusGroup.onEntryFocus",ro={bubbles:!1,cancelable:!0},rl="RovingFocusGroup",[rs,ri,ra]=function(e){let t=e+"CollectionProvider",[r,n]=tH(t),[o,l]=r(t,{collectionRef:{current:null},itemMap:new Map}),s=e=>{let{scope:t,children:r}=e,n=u.default.useRef(null),l=u.default.useRef(new Map).current;return(0,d.jsx)(o,{scope:t,itemMap:l,collectionRef:n,children:r})};s.displayName=t;let i=e+"CollectionSlot",a=t0(i),c=u.default.forwardRef((e,t)=>{let{scope:r,children:n}=e,o=tY(t,l(i,r).collectionRef);return(0,d.jsx)(a,{ref:o,children:n})});c.displayName=i;let f=e+"CollectionItemSlot",p="data-radix-collection-item",h=t0(f),m=u.default.forwardRef((e,t)=>{let{scope:r,children:n,...o}=e,s=u.default.useRef(null),i=tY(t,s),a=l(f,r);return u.default.useEffect(()=>(a.itemMap.set(s,{ref:s,...o}),()=>void a.itemMap.delete(s))),(0,d.jsx)(h,{...{[p]:""},ref:i,children:n})});return m.displayName=f,[{Provider:s,Slot:c,ItemSlot:m},function(t){let r=l(e+"CollectionConsumer",t);return u.default.useCallback(()=>{let e=r.collectionRef.current;if(!e)return[];let t=Array.from(e.querySelectorAll(`[${p}]`));return Array.from(r.itemMap.values()).sort((e,r)=>t.indexOf(e.ref.current)-t.indexOf(r.ref.current))},[r.collectionRef,r.itemMap])},n]}(rl),[rd,ru]=tH(rl,[ra]),[rc,rf]=rd(rl),rp=u.forwardRef((e,t)=>(0,d.jsx)(rs.Provider,{scope:e.__scopeRovingFocusGroup,children:(0,d.jsx)(rs.Slot,{scope:e.__scopeRovingFocusGroup,children:(0,d.jsx)(rh,{...e,ref:t})})}));rp.displayName=rl;var rh=u.forwardRef((e,t)=>{let r,{__scopeRovingFocusGroup:n,orientation:o,loop:l=!1,dir:s,currentTabStopId:i,defaultCurrentTabStopId:a,onCurrentTabStopIdChange:c,onEntryFocus:f,preventScrollOnEntryFocus:p=!1,...h}=e,m=u.useRef(null),g=tY(t,m),y=rr(s),[b,x]=re({prop:i,defaultProp:a??null,onChange:c,caller:rl}),[v,w]=u.useState(!1),k=(r=u.useRef(f),u.useEffect(()=>{r.current=f}),u.useMemo(()=>(...e)=>r.current?.(...e),[])),S=ri(n),z=u.useRef(!1),[j,C]=u.useState(0);return u.useEffect(()=>{let e=m.current;if(e)return e.addEventListener(rn,k),()=>e.removeEventListener(rn,k)},[k]),(0,d.jsx)(rc,{scope:n,orientation:o,dir:y,loop:l,currentTabStopId:b,onItemFocus:u.useCallback(e=>x(e),[x]),onItemShiftTab:u.useCallback(()=>w(!0),[]),onFocusableItemAdd:u.useCallback(()=>C(e=>e+1),[]),onFocusableItemRemove:u.useCallback(()=>C(e=>e-1),[]),children:(0,d.jsx)(tZ.div,{tabIndex:v||0===j?-1:0,"data-orientation":o,...h,ref:g,style:{outline:"none",...e.style},onMouseDown:tJ(e.onMouseDown,()=>{z.current=!0}),onFocus:tJ(e.onFocus,e=>{let t=!z.current;if(e.target===e.currentTarget&&t&&!v){let t=new CustomEvent(rn,ro);if(e.currentTarget.dispatchEvent(t),!t.defaultPrevented){let e=S().filter(e=>e.focusable);rb([e.find(e=>e.active),e.find(e=>e.id===b),...e].filter(Boolean).map(e=>e.ref.current),p)}}z.current=!1}),onBlur:tJ(e.onBlur,()=>w(!1))})})}),rm="RovingFocusGroupItem",rg=u.forwardRef((e,t)=>{let{__scopeRovingFocusGroup:r,focusable:n=!0,active:o=!1,tabStopId:l,children:s,...i}=e,a=function(e){let[t,r]=u.useState(t8());return t6(()=>{r(e=>e??String(t9++))},[void 0]),t?`radix-${t}`:""}(),c=l||a,f=rf(rm,r),p=f.currentTabStopId===c,h=ri(r),{onFocusableItemAdd:m,onFocusableItemRemove:g,currentTabStopId:y}=f;return u.useEffect(()=>{if(n)return m(),()=>g()},[n,m,g]),(0,d.jsx)(rs.ItemSlot,{scope:r,id:c,focusable:n,active:o,children:(0,d.jsx)(tZ.span,{tabIndex:p?0:-1,"data-orientation":f.orientation,...i,ref:t,onMouseDown:tJ(e.onMouseDown,e=>{n?f.onItemFocus(c):e.preventDefault()}),onFocus:tJ(e.onFocus,()=>f.onItemFocus(c)),onKeyDown:tJ(e.onKeyDown,e=>{if("Tab"===e.key&&e.shiftKey)return void f.onItemShiftTab();if(e.target!==e.currentTarget)return;let t=function(e,t,r){var n;let o=(n=e.key,"rtl"!==r?n:"ArrowLeft"===n?"ArrowRight":"ArrowRight"===n?"ArrowLeft":n);if(!("vertical"===t&&["ArrowLeft","ArrowRight"].includes(o))&&!("horizontal"===t&&["ArrowUp","ArrowDown"].includes(o)))return ry[o]}(e,f.orientation,f.dir);if(void 0!==t){if(e.metaKey||e.ctrlKey||e.altKey||e.shiftKey)return;e.preventDefault();let o=h().filter(e=>e.focusable).map(e=>e.ref.current);if("last"===t)o.reverse();else if("prev"===t||"next"===t){var r,n;"prev"===t&&o.reverse();let l=o.indexOf(e.currentTarget);o=f.loop?(r=o,n=l+1,r.map((e,t)=>r[(n+t)%r.length])):o.slice(l+1)}setTimeout(()=>rb(o))}}),children:"function"==typeof s?s({isCurrentTabStop:p,hasTabStop:null!=y}):s})})});rg.displayName=rm;var ry={ArrowLeft:"prev",ArrowUp:"prev",ArrowRight:"next",ArrowDown:"next",PageUp:"first",Home:"first",PageDown:"last",End:"last"};function rb(e,t=!1){let r=document.activeElement;for(let n of e)if(n===r||(n.focus({preventScroll:t}),document.activeElement!==r))return}var rx="Toggle",rv=u.forwardRef((e,t)=>{let{pressed:r,defaultPressed:n,onPressedChange:o,...l}=e,[s,i]=re({prop:r,onChange:o,defaultProp:n??!1,caller:rx});return(0,d.jsx)(tZ.button,{type:"button","aria-pressed":s,"data-state":s?"on":"off","data-disabled":e.disabled?"":void 0,...l,ref:t,onClick:tJ(e.onClick,()=>{e.disabled||i(!s)})})});rv.displayName=rx;var rw="ToggleGroup",[rk,rS]=tH(rw,[ru]),rz=ru(),rj=u.default.forwardRef((e,t)=>{let{type:r,...n}=e;if("single"===r)return(0,d.jsx)(rM,{...n,ref:t});if("multiple"===r)return(0,d.jsx)(rR,{...n,ref:t});throw Error(`Missing prop \`type\` expected on \`${rw}\``)});rj.displayName=rw;var[rC,rE]=rk(rw),rM=u.default.forwardRef((e,t)=>{let{value:r,defaultValue:n,onValueChange:o=()=>{},...l}=e,[s,i]=re({prop:r,defaultProp:n??"",onChange:o,caller:rw});return(0,d.jsx)(rC,{scope:e.__scopeToggleGroup,type:"single",value:u.default.useMemo(()=>s?[s]:[],[s]),onItemActivate:i,onItemDeactivate:u.default.useCallback(()=>i(""),[i]),children:(0,d.jsx)(rI,{...l,ref:t})})}),rR=u.default.forwardRef((e,t)=>{let{value:r,defaultValue:n,onValueChange:o=()=>{},...l}=e,[s,i]=re({prop:r,defaultProp:n??[],onChange:o,caller:rw}),a=u.default.useCallback(e=>i((t=[])=>[...t,e]),[i]),c=u.default.useCallback(e=>i((t=[])=>t.filter(t=>t!==e)),[i]);return(0,d.jsx)(rC,{scope:e.__scopeToggleGroup,type:"multiple",value:s,onItemActivate:a,onItemDeactivate:c,children:(0,d.jsx)(rI,{...l,ref:t})})});rj.displayName=rw;var[rN,rL]=rk(rw),rI=u.default.forwardRef((e,t)=>{let{__scopeToggleGroup:r,disabled:n=!1,rovingFocus:o=!0,orientation:l,dir:s,loop:i=!0,...a}=e,u=rz(r),c=rr(s),f={role:"group",dir:c,...a};return(0,d.jsx)(rN,{scope:r,rovingFocus:o,disabled:n,children:o?(0,d.jsx)(rp,{asChild:!0,...u,orientation:l,dir:c,loop:i,children:(0,d.jsx)(tZ.div,{...f,ref:t})}):(0,d.jsx)(tZ.div,{...f,ref:t})})}),rP="ToggleGroupItem",rO=u.default.forwardRef((e,t)=>{let r=rE(rP,e.__scopeToggleGroup),n=rL(rP,e.__scopeToggleGroup),o=rz(e.__scopeToggleGroup),l=r.value.includes(e.value),s=n.disabled||e.disabled,i={...e,pressed:l,disabled:s},a=u.default.useRef(null);return n.rovingFocus?(0,d.jsx)(rg,{asChild:!0,...o,focusable:!s,active:l,ref:a,children:(0,d.jsx)(rT,{...i,ref:t})}):(0,d.jsx)(rT,{...i,ref:t})});rO.displayName=rP;var rT=u.default.forwardRef((e,t)=>{let{__scopeToggleGroup:r,value:n,...o}=e,l=rE(rP,r),s={role:"radio","aria-checked":e.pressed,"aria-pressed":void 0},i="single"===l.type?s:void 0;return(0,d.jsx)(rv,{...i,...o,ref:t,onPressedChange:e=>{e?l.onItemActivate(n):l.onItemDeactivate(n)}})});let rA=e=>"boolean"==typeof e?`${e}`:0===e?"0":e,rD=(e,t)=>r=>{var n;if((null==t?void 0:t.variants)==null)return em(e,null==r?void 0:r.class,null==r?void 0:r.className);let{variants:o,defaultVariants:l}=t,s=Object.keys(o).map(e=>{let t=null==r?void 0:r[e],n=null==l?void 0:l[e];if(null===t)return null;let s=rA(t)||rA(n);return o[e][s]}),i=r&&Object.entries(r).reduce((e,t)=>{let[r,n]=t;return void 0===n||(e[r]=n),e},{});return em(e,s,null==t||null==(n=t.compoundVariants)?void 0:n.reduce((e,t)=>{let{class:r,className:n,...o}=t;return Object.entries(o).every(e=>{let[t,r]=e;return Array.isArray(r)?r.includes({...l,...i}[t]):({...l,...i})[t]===r})?[...e,r,n]:e},[]),null==r?void 0:r.class,null==r?void 0:r.className)},rF=rD("inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-primary data-[state=on]:text-primary-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-transparent",outline:"border border-input bg-transparent shadow-sm hover:bg-accent hover:text-accent-foreground data-[state=on]:border-primary"},size:{default:"h-9 px-2 min-w-9",sm:"h-8 px-1.5 min-w-8",lg:"h-10 px-2.5 min-w-10"}},defaultVariants:{variant:"default",size:"default"}});u.forwardRef(({className:e,variant:t,size:r,...n},o)=>(0,d.jsx)(rv,{ref:o,className:tf(rF({variant:t,size:r,className:e})),...n})).displayName=rv.displayName;let r$=u.createContext({size:"default",variant:"default"}),r_=u.forwardRef(({className:e,variant:t,size:r,children:n,...o},l)=>(0,d.jsx)(rj,{ref:l,className:tf("flex items-center justify-center gap-1",e),...o,children:(0,d.jsx)(r$.Provider,{value:{variant:t,size:r},children:n})}));r_.displayName=rj.displayName;let rG=u.forwardRef(({className:e,children:t,variant:r,size:n,...o},l)=>{let s=u.useContext(r$);return(0,d.jsx)(rO,{ref:l,className:tf(rF({variant:s.variant||r,size:s.size||n}),e),...o,children:t})});function rW({className:t=""}){let{datasetInfo:r,embeddings:n,selectedIds:o,setSelectedIds:l,beginLassoSelection:s,hoveredId:i,setHoveredId:a,geometry:c,setGeometry:f}=tI(),p=(0,u.useMemo)(()=>(function(e){let t=new Set;for(let r of e)t.add(r.geometry);return Array.from(t)})(r?.layouts??[]),[r?.layouts]),h=(0,u.useMemo)(()=>{if(!n||!r)return null;let e=n.layout_key,t=r.layouts.find(t=>t.layout_key===e),o=t?.space_key??e.split("__")[0],l=r.spaces.find(e=>e.space_key===o);return l?.model_id??l?.space_key??o},[r,n]),m=(0,u.useMemo)(()=>{if(!n)return null;let e=[...new Set(n.labels.map(e=>e||"undefined"))],t={};for(let r=0;r"undefined"===e?"#008080":n.label_colors[e]||"#808080");return{uniqueLabels:e,categories:r,palette:o}},[n]),{canvasRef:g,overlayCanvasRef:y,containerRef:b,handlePointerDown:x,handlePointerMove:v,handlePointerUp:w,handlePointerLeave:k,handleDoubleClick:S,rendererError:z}=function({embeddings:t,labelsInfo:r,selectedIds:n,hoveredId:o,setSelectedIds:l,beginLassoSelection:s,setHoveredId:i}){let a=(0,u.useRef)(null),d=(0,u.useRef)(null),c=(0,u.useRef)(null),f=(0,u.useRef)(null),[p,h]=(0,u.useState)(null),m=(0,u.useRef)(!1),g=(0,u.useRef)(!1),y=(0,u.useRef)(!1),b=(0,u.useRef)(0),x=(0,u.useRef)(0),v=(0,u.useRef)(0),w=(0,u.useRef)(0),k=(0,u.useRef)([]),S=(0,u.useRef)(-1),z=(0,u.useMemo)(()=>{if(!t)return null;let e=new Map;for(let r=0;r{m.current||(m.current=!0,requestAnimationFrame(()=>{m.current=!1;let e=f.current;if(e){try{e.render()}catch(t){console.error("hyper-scatter renderer.render() failed:",t);try{e.destroy()}catch{}f.current=null,h("This browser can't render the scatter plot (WebGL2 is required). Please use Chrome/Edge/Firefox."),tV(d.current);return}y.current&&tK(d.current,k.current)}}))},[]),C=(0,u.useCallback)(e=>{let t=a.current;if(!t)return{x:0,y:0};let r=t.getBoundingClientRect();return{x:e.clientX-r.left,y:e.clientY-r.top}},[]),E=(0,u.useCallback)(()=>{g.current=!1,y.current=!1,k.current=[],tV(d.current)},[]);(0,u.useEffect)(()=>{if(!t||!r||!a.current||!c.current)return;let n=!1;return(async()=>{if(h(null),!function(){try{if("undefined"==typeof document)return!1;return!!document.createElement("canvas").getContext("webgl2")}catch{return!1}}())return h("This browser doesn't support WebGL2, so the scatter plot can't be displayed. Please use Chrome/Edge/Firefox.");try{let o=await e.A(20606);if(n)return;let l=c.current,s=a.current;if(!l||!s)return;f.current&&(f.current.destroy(),f.current=null);let i=l.getBoundingClientRect(),u=Math.floor(i.width),p=Math.floor(i.height);d.current&&(d.current.width=Math.max(1,u),d.current.height=Math.max(1,p),d.current.style.width=`${u}px`,d.current.style.height=`${p}px`,tV(d.current));let m=t.coords,g=new Float32Array(2*m.length);for(let e=0;e{n=!0,E(),f.current&&(f.current.destroy(),f.current=null)}},[t,r,j,E]),(0,u.useEffect)(()=>{let e=f.current;if(!e||!t||!z)return;let r=new Set;for(let e of n){let t=z.get(e);"number"==typeof t&&r.add(t)}e.setSelection(r);let l=o?z.get(o)??-1:-1;e.setHovered(l),S.current=l,j()},[t,o,z,j,n]),(0,u.useEffect)(()=>{let e=c.current;if(!e)return;let t=()=>{let t=e.getBoundingClientRect(),r=Math.floor(t.width),n=Math.floor(t.height);if(!(r>0)||!(n>0))return;d.current&&(d.current.width=Math.max(1,r),d.current.height=Math.max(1,n),d.current.style.width=`${r}px`,d.current.style.height=`${n}px`);let o=f.current;o&&(o.resize(r,n),j())};t();let r=new ResizeObserver(t);return r.observe(e),()=>r.disconnect()},[j]),(0,u.useEffect)(()=>{let e=a.current;if(!e)return;let t=e=>{let t=f.current;if(!t)return;e.preventDefault();let r=C(e),n=-e.deltaY/100;t.zoom(r.x,r.y,n,tB(e)),j()};return e.addEventListener("wheel",t,{passive:!1}),()=>e.removeEventListener("wheel",t)},[C,j]);let M=(0,u.useCallback)(e=>{if(!f.current||"number"==typeof e.button&&0!==e.button)return;let t=C(e);b.current=t.x,x.current=t.y,v.current=t.x,w.current=t.y,e.shiftKey?(y.current=!0,g.current=!1,k.current=[t.x,t.y],tK(d.current,k.current)):(g.current=!0,y.current=!1);try{e.currentTarget.setPointerCapture(e.pointerId)}catch{}e.preventDefault()},[C]),R=(0,u.useCallback)(e=>{let r=f.current;if(!r)return;let n=C(e);if(g.current){let t=n.x-v.current,o=n.y-w.current;v.current=n.x,w.current=n.y,r.pan(t,o,tB(e)),j();return}if(y.current){let e=k.current,t=e[e.length-2]??n.x,r=e[e.length-1]??n.y,o=n.x-t,l=n.y-r;o*o+l*l>=4&&(e.push(n.x,n.y),tK(d.current,e));return}let o=r.hitTest(n.x,n.y),l=o?o.index:-1;l===S.current||(S.current=l,r.setHovered(l),t&&(l>=0&&l{let r=f.current;if(!r||!t)return void E();if(y.current){let e=k.current;if(E(),e.length>=6)try{let n=new Float32Array(e),o=r.lassoSelect(n),l=o.geometry?.coords;if(!l||l.length<6)return;r.setSelection(new Set);let i=function(e,t){let r=Math.floor(e.length/2);if(r<=512)return Array.from(e);let n=Array(1024);for(let t=0;t<512;t++){let o=Math.floor(t*r/512);n[2*t]=e[2*o],n[2*t+1]=e[2*o+1]}return n}(l,0);if(i.length<6)return;s({layoutKey:t.layout_key,polygon:i})}catch(e){console.error("Lasso selection failed:",e)}j();return}let o=C(e),i=o.x-b.current,a=o.y-x.current;if(i*i+a*a<=36){let s=r.hitTest(o.x,o.y),i=s?s.index:-1;if(i>=0&&i{let t=f.current;t&&(S.current=-1,i(null),t.setHovered(-1),j()),E()},[j,i,E]),handleDoubleClick:(0,u.useCallback)(e=>{let t=f.current;t&&(E(),t.setSelection(new Set),l(new Set,"scatter"),j())},[j,l,E]),rendererError:p}}({embeddings:n,labelsInfo:m,selectedIds:o,hoveredId:i,setSelectedIds:l,beginLassoSelection:s,setHoveredId:a}),j=m?.uniqueLabels??[];return(0,d.jsxs)(tP,{className:t,children:[(0,d.jsx)(tT,{icon:(0,d.jsx)(tD,{}),title:"Embeddings",subtitle:n?h??"":"Loading...",children:p.length>1&&(0,d.jsxs)(r_,{type:"single",value:c,onValueChange:e=>e&&f(e),size:"sm",variant:"outline",className:"bg-muted/50 rounded-md p-0.5 gap-0.5",children:[(0,d.jsxs)(rG,{value:"euclidean","aria-label":"Euclidean geometry",className:"h-6 px-2 gap-1.5 text-[11px] border-0 data-[state=on]:bg-background data-[state=on]:text-foreground data-[state=on]:shadow-sm data-[state=off]:bg-transparent data-[state=off]:text-muted-foreground",children:[(0,d.jsx)(t_,{}),(0,d.jsx)("span",{className:"hidden sm:inline",children:"Euclidean"})]}),(0,d.jsxs)(rG,{value:"poincare","aria-label":"Poincaré disk (hyperbolic)",className:"h-6 px-2 gap-1.5 text-[11px] border-0 data-[state=on]:bg-background data-[state=on]:text-foreground data-[state=on]:shadow-sm data-[state=off]:bg-transparent data-[state=off]:text-muted-foreground",children:[(0,d.jsx)(tG,{}),(0,d.jsx)("span",{className:"hidden sm:inline",children:"Poincaré"})]})]})}),(0,d.jsxs)("div",{className:"flex-1 flex",children:[(0,d.jsxs)("div",{ref:b,className:"flex-1 relative",children:[(0,d.jsx)("canvas",{ref:g,className:"absolute inset-0",style:{zIndex:1},onPointerDown:x,onPointerMove:v,onPointerUp:w,onPointerCancel:w,onPointerLeave:k,onDoubleClick:S}),(0,d.jsx)("canvas",{ref:y,className:"absolute inset-0 pointer-events-none",style:{zIndex:20}}),z?(0,d.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-card/85 z-10 p-6",children:(0,d.jsxs)("div",{className:"max-w-md text-center",children:[(0,d.jsx)("div",{className:"text-sm font-semibold text-foreground mb-2",children:"Browser not supported"}),(0,d.jsx)("div",{className:"text-sm text-muted-foreground",children:z})]})}):!n&&(0,d.jsx)("div",{className:"absolute inset-0 flex items-center justify-center bg-card/80 z-10",children:(0,d.jsx)("div",{className:"text-muted-foreground",children:"Loading embeddings..."})})]}),j.length>0&&(0,d.jsxs)("div",{className:"w-36 border-l border-border bg-card p-2 overflow-y-auto",children:[(0,d.jsx)("div",{className:"text-[11px] font-medium mb-2 text-muted-foreground uppercase tracking-wide",children:"Labels"}),(0,d.jsxs)("div",{className:"space-y-1",children:[j.slice(0,20).map(e=>(0,d.jsxs)("div",{className:"flex items-center gap-2",children:[(0,d.jsx)("div",{className:"w-2.5 h-2.5 rounded-full flex-shrink-0",style:{backgroundColor:"undefined"===e?"hsl(var(--accent-cyan))":n?.label_colors[e]||"hsl(var(--muted-foreground))"}}),(0,d.jsx)("span",{className:"text-[11px] text-muted-foreground truncate font-mono",title:e,children:e})]},e)),j.length>20&&(0,d.jsxs)("div",{className:"text-[11px] text-muted-foreground/70",children:["+",j.length-20," more"]})]})]})]}),(0,d.jsx)(tO,{children:(0,d.jsx)("span",{children:"⇧+drag lasso • scroll zoom • drag pan"})})]})}rG.displayName=rO.displayName;var rB=Symbol.for("react.lazy"),rV=u[" use ".trim().toString()];function rK(e){var t;return null!=e&&"object"==typeof e&&"$$typeof"in e&&e.$$typeof===rB&&"_payload"in e&&"object"==typeof(t=e._payload)&&null!==t&&"then"in t}var rH=((s=u.forwardRef((e,t)=>{let{children:r,...n}=e;if(rK(r)&&"function"==typeof rV&&(r=rV(r._payload)),u.isValidElement(r)){var o;let e,l,s=(o=r,(l=(e=Object.getOwnPropertyDescriptor(o.props,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.ref:(l=(e=Object.getOwnPropertyDescriptor(o,"ref")?.get)&&"isReactWarning"in e&&e.isReactWarning)?o.props.ref:o.props.ref||o.ref),i=function(e,t){let r={...t};for(let n in t){let o=e[n],l=t[n];/^on[A-Z]/.test(n)?o&&l?r[n]=(...e)=>{let t=l(...e);return o(...e),t}:o&&(r[n]=o):"style"===n?r[n]={...o,...l}:"className"===n&&(r[n]=[o,l].filter(Boolean).join(" "))}return{...e,...r}}(n,r.props);return r.type!==u.Fragment&&(i.ref=t?tq(t,s):s),u.cloneElement(r,i)}return u.Children.count(r)>1?u.Children.only(null):null})).displayName="Slot.SlotClone",o=s,(l=u.forwardRef((e,t)=>{let{children:r,...n}=e;rK(r)&&"function"==typeof rV&&(r=rV(r._payload));let l=u.Children.toArray(r),s=l.find(rq);if(s){let e=s.props.children,r=l.map(t=>t!==s?t:u.Children.count(e)>1?u.Children.only(null):u.isValidElement(e)?e.props.children:null);return(0,d.jsx)(o,{...n,ref:t,children:u.isValidElement(e)?u.cloneElement(e,void 0,r):null})}return(0,d.jsx)(o,{...n,ref:t,children:r})})).displayName="Slot.Slot",l),rU=Symbol("radix.slottable");function rq(e){return u.isValidElement(e)&&"function"==typeof e.type&&"__radixId"in e.type&&e.type.__radixId===rU}let rY=rD("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",{variants:{variant:{default:"bg-primary text-primary-foreground shadow hover:bg-primary/90",destructive:"bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",outline:"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",secondary:"bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",ghost:"hover:bg-accent hover:text-accent-foreground",link:"text-primary underline-offset-4 hover:underline"},size:{default:"h-9 px-4 py-2",sm:"h-8 rounded-md px-3 text-xs",lg:"h-10 rounded-md px-8",icon:"h-9 w-9"}},defaultVariants:{variant:"default",size:"default"}}),rQ=u.forwardRef(({className:e,variant:t,size:r,asChild:n=!1,...o},l)=>(0,d.jsx)(n?rH:"button",{className:tf(rY({variant:t,size:r,className:e})),ref:l,...o}));function rX(){let{datasetInfo:e,selectedIds:t,clearSelection:r}=tI();return(0,d.jsxs)("header",{className:"h-10 min-h-[40px] bg-secondary border-b border-border flex items-center justify-between px-3",children:[(0,d.jsxs)("div",{className:"flex items-center gap-2",children:[(0,d.jsx)("div",{className:"w-7 h-7 rounded flex items-center justify-center text-primary",children:(0,d.jsx)(tF,{})}),(0,d.jsxs)("div",{className:"flex items-center gap-2",children:[(0,d.jsx)("h1",{className:"text-sm font-semibold text-foreground",children:"HyperView"}),e&&(0,d.jsx)("span",{className:"text-xs text-muted-foreground/70 font-mono",children:e.name})]})]}),(0,d.jsxs)("div",{className:"flex items-center gap-3",children:[e&&(0,d.jsxs)("div",{className:"flex items-center gap-3 text-[11px] font-mono",children:[(0,d.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,d.jsx)("span",{className:"text-muted-foreground/70",children:"samples"}),(0,d.jsx)("span",{className:"text-muted-foreground",children:e.num_samples.toLocaleString()})]}),(0,d.jsxs)("div",{className:"flex items-center gap-1.5",children:[(0,d.jsx)("span",{className:"text-muted-foreground/70",children:"labels"}),(0,d.jsx)("span",{className:"text-muted-foreground",children:e.labels.length})]})]}),t.size>0&&(0,d.jsxs)(rQ,{variant:"secondary",size:"sm",onClick:r,className:"h-6 text-[11px]",children:["Clear (",t.size,")"]})]})]})}async function rZ(){let e=await fetch("/api/dataset");if(!e.ok)throw Error(`Failed to fetch dataset: ${e.statusText}`);return e.json()}async function rJ(e=0,t=100,r){let n=new URLSearchParams({offset:e.toString(),limit:t.toString()});r&&n.set("label",r);let o=await fetch(`/api/samples?${n}`);if(!o.ok)throw Error(`Failed to fetch samples: ${o.statusText}`);return o.json()}async function r0(e){let t=new URLSearchParams;e&&t.set("layout_key",e);let r=t.toString(),n=await fetch(`/api/embeddings${r?`?${r}`:""}`);if(!n.ok)throw Error(`Failed to fetch embeddings: ${n.statusText}`);return n.json()}async function r1(e){let t=await fetch("/api/samples/batch",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({sample_ids:e})});if(!t.ok)throw Error(`Failed to fetch samples batch: ${t.statusText}`);return(await t.json()).samples}async function r2(e){let t=await fetch("/api/selection/lasso",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({layout_key:e.layoutKey,polygon:Array.from(e.polygon),offset:e.offset??0,limit:e.limit??100,include_thumbnails:e.includeThumbnails??!0}),signal:e.signal});if(!t.ok)throw Error(`Failed to fetch lasso selection: ${t.statusText}`);return t.json()}function r5(){let{datasetInfo:e,samples:t,totalSamples:r,samplesLoaded:n,setSamples:o,appendSamples:l,addSamplesIfMissing:s,setDatasetInfo:i,setEmbeddings:a,setIsLoading:c,isLoading:f,error:p,setError:h,selectedIds:m,isLassoSelection:g,selectionSource:y,lassoQuery:b,lassoSamples:x,lassoTotal:v,lassoIsLoading:w,setLassoResults:k,geometry:S}=tI(),[z,j]=(0,u.useState)(!1),[C,E]=(0,u.useState)(!1);(0,u.useEffect)(()=>{(async()=>{c(!0),h(null);try{let[e,t,r]=await Promise.all([rZ(),rJ(0,100),r0()]);i(e),o(t.samples,t.total),a(r)}catch(e){console.error("Failed to load data:",e),h(e instanceof Error?e.message:"Failed to load data")}finally{c(!1)}})()},[]),(0,u.useEffect)(()=>{if(!e)return;let t=e.layouts.find(e=>e.geometry===S);t&&tI.getState().currentLayoutKey!==t.layout_key&&(async()=>{E(!0);try{let e=await r0(t.layout_key);a(e)}catch(e){console.error("Failed to load geometry:",e)}finally{E(!1)}})()},[S,e,a]),(0,u.useEffect)(()=>{(async()=>{if(g||0===m.size)return;let e=new Set(t.map(e=>e.id)),r=Array.from(m).filter(t=>!e.has(t));if(0!==r.length)try{let e=await r1(r);s(e)}catch(e){console.error("Failed to fetch selected samples:",e)}})()},[m,t,s,g]),(0,u.useEffect)(()=>{if(!g||!b||!w)return;let e=new AbortController;return(async()=>{try{let t=await r2({layoutKey:b.layoutKey,polygon:b.polygon,offset:0,limit:100,signal:e.signal});if(e.signal.aborted)return;k(t.samples,t.total,!1)}catch(e){if(e instanceof DOMException&&"AbortError"===e.name)return;console.error("Failed to fetch lasso selection:",e),k([],0,!1)}})(),()=>e.abort()},[g,w,b,k]);let M=(0,u.useCallback)(async()=>{if(!z){if(g){if(!b||w||!w&&x.length>=v)return;j(!0);try{let e=await r2({layoutKey:b.layoutKey,polygon:b.polygon,offset:x.length,limit:100});k(e.samples,e.total,!0)}catch(e){console.error("Failed to load more lasso samples:",e)}finally{j(!1)}return}if(!(n>=r)){j(!0);try{let e=await rJ(n,100);l(e.samples)}catch(e){console.error("Failed to load more samples:",e)}finally{j(!1)}}}},[z,l,g,w,b,x.length,v,n,r,k]),R=(0,u.useMemo)(()=>{if(g)return x;if("scatter"===y&&m.size>0){let e=new Map;for(let r of t)e.set(r.id,r);let r=[];for(let t of m){let n=e.get(t);n&&r.push(n)}if(r.length>0)return[...r,...t.filter(e=>!m.has(e.id))]}return t},[g,x,t,m,y]),N=g?v:r,L=g?R.lengthr5],50912)}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js b/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js new file mode 100644 index 0000000000000000000000000000000000000000..ab422b94a4fbe76275d31c0bf7ef334768b39cae --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/a6dad97d9634a72d.js @@ -0,0 +1 @@ +!function(){var t="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{};function e(t){var e={exports:{}};return t(e,e.exports),e.exports}var r,n,o=function(t){return t&&t.Math===Math&&t},i=o("object"==typeof globalThis&&globalThis)||o("object"==typeof window&&window)||o("object"==typeof self&&self)||o("object"==typeof t&&t)||o("object"==typeof t&&t)||function(){return this}()||Function("return this")(),a=function(t){try{return!!t()}catch(t){return!0}},u=!a(function(){return 7!==Object.defineProperty({},1,{get:function(){return 7}})[1]}),s=!a(function(){var t=function(){}.bind();return"function"!=typeof t||t.hasOwnProperty("prototype")}),c=Function.prototype.call,f=s?c.bind(c):function(){return c.apply(c,arguments)},l={}.propertyIsEnumerable,h=Object.getOwnPropertyDescriptor,p=h&&!l.call({1:2},1)?function(t){var e=h(this,t);return!!e&&e.enumerable}:l,v={f:p},d=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}},g=Function.prototype,y=g.call,m=s&&g.bind.bind(y,y),b=s?m:function(t){return function(){return y.apply(t,arguments)}},w=b({}.toString),S=b("".slice),E=function(t){return S(w(t),8,-1)},O=Object,x=b("".split),R=a(function(){return!O("z").propertyIsEnumerable(0)})?function(t){return"String"===E(t)?x(t,""):O(t)}:O,P=function(t){return null==t},A=TypeError,j=function(t){if(P(t))throw new A("Can't call method on "+t);return t},k=function(t){return R(j(t))},I="object"==typeof document&&document.all,T=void 0===I&&void 0!==I?function(t){return"function"==typeof t||t===I}:function(t){return"function"==typeof t},M=function(t){return"object"==typeof t?null!==t:T(t)},L=function(t,e){return arguments.length<2?T(r=i[t])?r:void 0:i[t]&&i[t][e];var r},U=b({}.isPrototypeOf),N=i.navigator,C=N&&N.userAgent,_=C?String(C):"",F=i.process,B=i.Deno,D=F&&F.versions||B&&B.version,z=D&&D.v8;z&&(n=(r=z.split("."))[0]>0&&r[0]<4?1:+(r[0]+r[1])),!n&&_&&(!(r=_.match(/Edge\/(\d+)/))||r[1]>=74)&&(r=_.match(/Chrome\/(\d+)/))&&(n=+r[1]);var W=n,q=i.String,H=!!Object.getOwnPropertySymbols&&!a(function(){var t=Symbol("symbol detection");return!q(t)||!(Object(t)instanceof Symbol)||!Symbol.sham&&W&&W<41}),$=H&&!Symbol.sham&&"symbol"==typeof Symbol.iterator,K=Object,G=$?function(t){return"symbol"==typeof t}:function(t){var e=L("Symbol");return T(e)&&U(e.prototype,K(t))},V=String,Y=function(t){try{return V(t)}catch(t){return"Object"}},X=TypeError,J=function(t){if(T(t))return t;throw new X(Y(t)+" is not a function")},Q=function(t,e){var r=t[e];return P(r)?void 0:J(r)},Z=TypeError,tt=Object.defineProperty,et=function(t,e){try{tt(i,t,{value:e,configurable:!0,writable:!0})}catch(r){i[t]=e}return e},rt=e(function(t){var e="__core-js_shared__",r=t.exports=i[e]||et(e,{});(r.versions||(r.versions=[])).push({version:"3.38.1",mode:"global",copyright:"© 2014-2024 Denis Pushkarev (zloirock.ru)",license:"https://github.com/zloirock/core-js/blob/v3.38.1/LICENSE",source:"https://github.com/zloirock/core-js"})}),nt=function(t,e){return rt[t]||(rt[t]=e||{})},ot=Object,it=function(t){return ot(j(t))},at=b({}.hasOwnProperty),ut=Object.hasOwn||function(t,e){return at(it(t),e)},st=0,ct=Math.random(),ft=b(1..toString),lt=function(t){return"Symbol("+(void 0===t?"":t)+")_"+ft(++st+ct,36)},ht=i.Symbol,pt=nt("wks"),vt=$?ht.for||ht:ht&&ht.withoutSetter||lt,dt=function(t){return ut(pt,t)||(pt[t]=H&&ut(ht,t)?ht[t]:vt("Symbol."+t)),pt[t]},gt=TypeError,yt=dt("toPrimitive"),mt=function(t,e){if(!M(t)||G(t))return t;var r,n=Q(t,yt);if(n){if(void 0===e&&(e="default"),r=f(n,t,e),!M(r)||G(r))return r;throw new gt("Can't convert object to primitive value")}return void 0===e&&(e="number"),function(t,e){var r,n;if("string"===e&&T(r=t.toString)&&!M(n=f(r,t)))return n;if(T(r=t.valueOf)&&!M(n=f(r,t)))return n;if("string"!==e&&T(r=t.toString)&&!M(n=f(r,t)))return n;throw new Z("Can't convert object to primitive value")}(t,e)},bt=function(t){var e=mt(t,"string");return G(e)?e:e+""},wt=i.document,St=M(wt)&&M(wt.createElement),Et=function(t){return St?wt.createElement(t):{}},Ot=!u&&!a(function(){return 7!==Object.defineProperty(Et("div"),"a",{get:function(){return 7}}).a}),xt=Object.getOwnPropertyDescriptor,Rt={f:u?xt:function(t,e){if(t=k(t),e=bt(e),Ot)try{return xt(t,e)}catch(t){}if(ut(t,e))return d(!f(v.f,t,e),t[e])}},Pt=u&&a(function(){return 42!==Object.defineProperty(function(){},"prototype",{value:42,writable:!1}).prototype}),At=String,jt=TypeError,kt=function(t){if(M(t))return t;throw new jt(At(t)+" is not an object")},It=TypeError,Tt=Object.defineProperty,Mt=Object.getOwnPropertyDescriptor,Lt="enumerable",Ut="configurable",Nt="writable",Ct={f:u?Pt?function(t,e,r){if(kt(t),e=bt(e),kt(r),"function"==typeof t&&"prototype"===e&&"value"in r&&Nt in r&&!r[Nt]){var n=Mt(t,e);n&&n[Nt]&&(t[e]=r.value,r={configurable:Ut in r?r[Ut]:n[Ut],enumerable:Lt in r?r[Lt]:n[Lt],writable:!1})}return Tt(t,e,r)}:Tt:function(t,e,r){if(kt(t),e=bt(e),kt(r),Ot)try{return Tt(t,e,r)}catch(t){}if("get"in r||"set"in r)throw new It("Accessors not supported");return"value"in r&&(t[e]=r.value),t}},_t=u?function(t,e,r){return Ct.f(t,e,d(1,r))}:function(t,e,r){return t[e]=r,t},Ft=Function.prototype,Bt=u&&Object.getOwnPropertyDescriptor,Dt=ut(Ft,"name"),zt={EXISTS:Dt,PROPER:Dt&&"something"===function(){}.name,CONFIGURABLE:Dt&&(!u||u&&Bt(Ft,"name").configurable)},Wt=b(Function.toString);T(rt.inspectSource)||(rt.inspectSource=function(t){return Wt(t)});var qt,Ht,$t,Kt=rt.inspectSource,Gt=i.WeakMap,Vt=T(Gt)&&/native code/.test(String(Gt)),Yt=nt("keys"),Xt=function(t){return Yt[t]||(Yt[t]=lt(t))},Jt={},Qt="Object already initialized",Zt=i.TypeError;if(Vt||rt.state){var te=rt.state||(rt.state=new(0,i.WeakMap));te.get=te.get,te.has=te.has,te.set=te.set,qt=function(t,e){if(te.has(t))throw new Zt(Qt);return e.facade=t,te.set(t,e),e},Ht=function(t){return te.get(t)||{}},$t=function(t){return te.has(t)}}else{var ee=Xt("state");Jt[ee]=!0,qt=function(t,e){if(ut(t,ee))throw new Zt(Qt);return e.facade=t,_t(t,ee,e),e},Ht=function(t){return ut(t,ee)?t[ee]:{}},$t=function(t){return ut(t,ee)}}var re,ne={set:qt,get:Ht,has:$t,enforce:function(t){return $t(t)?Ht(t):qt(t,{})},getterFor:function(t){return function(e){var r;if(!M(e)||(r=Ht(e)).type!==t)throw new Zt("Incompatible receiver, "+t+" required");return r}}},oe=e(function(t){var e=zt.CONFIGURABLE,r=ne.enforce,n=ne.get,o=String,i=Object.defineProperty,s=b("".slice),c=b("".replace),f=b([].join),l=u&&!a(function(){return 8!==i(function(){},"length",{value:8}).length}),h=String(String).split("String"),p=t.exports=function(t,n,a){"Symbol("===s(o(n),0,7)&&(n="["+c(o(n),/^Symbol\(([^)]*)\).*$/,"$1")+"]"),a&&a.getter&&(n="get "+n),a&&a.setter&&(n="set "+n),(!ut(t,"name")||e&&t.name!==n)&&(u?i(t,"name",{value:n,configurable:!0}):t.name=n),l&&a&&ut(a,"arity")&&t.length!==a.arity&&i(t,"length",{value:a.arity});try{a&&ut(a,"constructor")&&a.constructor?u&&i(t,"prototype",{writable:!1}):t.prototype&&(t.prototype=void 0)}catch(t){}var p=r(t);return ut(p,"source")||(p.source=f(h,"string"==typeof n?n:"")),t};Function.prototype.toString=p(function(){return T(this)&&n(this).source||Kt(this)},"toString")}),ie=function(t,e,r,n){n||(n={});var o=n.enumerable,i=void 0!==n.name?n.name:e;if(T(r)&&oe(r,i,n),n.global)o?t[e]=r:et(e,r);else{try{n.unsafe?t[e]&&(o=!0):delete t[e]}catch(t){}o?t[e]=r:Ct.f(t,e,{value:r,enumerable:!1,configurable:!n.nonConfigurable,writable:!n.nonWritable})}return t},ae=Math.ceil,ue=Math.floor,se=Math.trunc||function(t){var e=+t;return(e>0?ue:ae)(e)},ce=function(t){var e=+t;return e!=e||0===e?0:se(e)},fe=Math.max,le=Math.min,he=function(t,e){var r=ce(t);return r<0?fe(r+e,0):le(r,e)},pe=Math.min,ve=function(t){var e=ce(t);return e>0?pe(e,9007199254740991):0},de=function(t){return ve(t.length)},ge=function(t){return function(e,r,n){var o=k(e),i=de(o);if(0===i)return!t&&-1;var a,u=he(n,i);if(t&&r!=r){for(;i>u;)if((a=o[u++])!=a)return!0}else for(;i>u;u++)if((t||u in o)&&o[u]===r)return t||u||0;return!t&&-1}},ye={includes:ge(!0),indexOf:ge(!1)},me=ye.indexOf,be=b([].push),we=function(t,e){var r,n=k(t),o=0,i=[];for(r in n)!ut(Jt,r)&&ut(n,r)&&be(i,r);for(;e.length>o;)ut(n,r=e[o++])&&(~me(i,r)||be(i,r));return i},Se=["constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumerable","toLocaleString","toString","valueOf"],Ee=Se.concat("length","prototype"),Oe={f:Object.getOwnPropertyNames||function(t){return we(t,Ee)}},xe={f:Object.getOwnPropertySymbols},Re=b([].concat),Pe=L("Reflect","ownKeys")||function(t){var e=Oe.f(kt(t)),r=xe.f;return r?Re(e,r(t)):e},Ae=function(t,e,r){for(var n=Pe(e),o=Ct.f,i=Rt.f,a=0;aa;)Ct.f(t,r=o[a++],n[r]);return t},Be={f:Fe},De=L("document","documentElement"),ze="prototype",We="script",qe=Xt("IE_PROTO"),He=function(){},$e=function(t){return"<"+We+">"+t+""},Ke=function(t){t.write($e("")),t.close();var e=t.parentWindow.Object;return t=null,e},Ge=function(){try{re=new ActiveXObject("htmlfile")}catch(t){}var t,e,r;Ge="undefined"!=typeof document?document.domain&&re?Ke(re):(e=Et("iframe"),r="java"+We+":",e.style.display="none",De.appendChild(e),e.src=String(r),(t=e.contentWindow.document).open(),t.write($e("document.F=Object")),t.close(),t.F):Ke(re);for(var n=Se.length;n--;)delete Ge[ze][Se[n]];return Ge()};Jt[qe]=!0;var Ve=Object.create||function(t,e){var r;return null!==t?(He[ze]=kt(t),r=new He,He[ze]=null,r[qe]=t):r=Ge(),void 0===e?r:Be.f(r,e)},Ye=Ct.f,Xe=dt("unscopables"),Je=Array.prototype;void 0===Je[Xe]&&Ye(Je,Xe,{configurable:!0,value:Ve(null)});var Qe=function(t){Je[Xe][t]=!0};Ce({target:"Array",proto:!0},{at:function(t){var e=it(this),r=de(e),n=ce(t),o=n>=0?n:r+n;return o<0||o>=r?void 0:e[o]}}),Qe("at");var Ze=function(t,e){return b(i[t].prototype[e])},tr=(Ze("Array","at"),TypeError),er=function(t,e){if(!delete t[e])throw new tr("Cannot delete property "+Y(e)+" of "+Y(t))},rr=Math.min,nr=[].copyWithin||function(t,e){var r=it(this),n=de(r),o=he(t,n),i=he(e,n),a=arguments.length>2?arguments[2]:void 0,u=rr((void 0===a?n:he(a,n))-i,n-o),s=1;for(i0;)i in r?r[o]=r[i]:er(r,o),o+=s,i+=s;return r};Ce({target:"Array",proto:!0},{copyWithin:nr}),Qe("copyWithin"),Ze("Array","copyWithin"),Ce({target:"Array",proto:!0},{fill:function(t){for(var e=it(this),r=de(e),n=arguments.length,o=he(n>1?arguments[1]:void 0,r),i=n>2?arguments[2]:void 0,a=void 0===i?r:he(i,r);a>o;)e[o++]=t;return e}}),Qe("fill"),Ze("Array","fill");var or=function(t){if("Function"===E(t))return b(t)},ir=or(or.bind),ar=function(t,e){return J(t),void 0===e?t:s?ir(t,e):function(){return t.apply(e,arguments)}},ur=Array.isArray||function(t){return"Array"===E(t)},sr={};sr[dt("toStringTag")]="z";var cr="[object z]"===String(sr),fr=dt("toStringTag"),lr=Object,hr="Arguments"===E(function(){return arguments}()),pr=cr?E:function(t){var e,r,n;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(r=function(t,e){try{return t[e]}catch(t){}}(e=lr(t),fr))?r:hr?E(e):"Object"===(n=E(e))&&T(e.callee)?"Arguments":n},vr=function(){},dr=L("Reflect","construct"),gr=/^\s*(?:class|function)\b/,yr=b(gr.exec),mr=!gr.test(vr),br=function(t){if(!T(t))return!1;try{return dr(vr,[],t),!0}catch(t){return!1}},wr=function(t){if(!T(t))return!1;switch(pr(t)){case"AsyncFunction":case"GeneratorFunction":case"AsyncGeneratorFunction":return!1}try{return mr||!!yr(gr,Kt(t))}catch(t){return!0}};wr.sham=!0;var Sr=!dr||a(function(){var t;return br(br.call)||!br(Object)||!br(function(){t=!0})||t})?wr:br,Er=dt("species"),Or=Array,xr=function(t,e){return new(function(t){var e;return ur(t)&&(Sr(e=t.constructor)&&(e===Or||ur(e.prototype))||M(e)&&null===(e=e[Er]))&&(e=void 0),void 0===e?Or:e}(t))(0===e?0:e)},Rr=b([].push),Pr=function(t){var e=1===t,r=2===t,n=3===t,o=4===t,i=6===t,a=7===t,u=5===t||i;return function(s,c,f,l){for(var h,p,v=it(s),d=R(v),g=de(d),y=ar(c,f),m=0,b=l||xr,w=e?b(s,g):r||a?b(s,0):void 0;g>m;m++)if((u||m in d)&&(p=y(h=d[m],m,v),t))if(e)w[m]=p;else if(p)switch(t){case 3:return!0;case 5:return h;case 6:return m;case 2:Rr(w,h)}else switch(t){case 4:return!1;case 7:Rr(w,h)}return i?-1:n||o?o:w}},Ar={forEach:Pr(0),map:Pr(1),filter:Pr(2),some:Pr(3),every:Pr(4),find:Pr(5),findIndex:Pr(6),filterReject:Pr(7)},jr=Ar.find,kr="find",Ir=!0;kr in[]&&Array(1)[kr](function(){Ir=!1}),Ce({target:"Array",proto:!0,forced:Ir},{find:function(t){return jr(this,t,arguments.length>1?arguments[1]:void 0)}}),Qe(kr),Ze("Array","find");var Tr=Ar.findIndex,Mr="findIndex",Lr=!0;Mr in[]&&Array(1)[Mr](function(){Lr=!1}),Ce({target:"Array",proto:!0,forced:Lr},{findIndex:function(t){return Tr(this,t,arguments.length>1?arguments[1]:void 0)}}),Qe(Mr),Ze("Array","findIndex");var Ur=TypeError,Nr=function(t){if(t>9007199254740991)throw Ur("Maximum allowed index exceeded");return t},Cr=function(t,e,r,n,o,i,a,u){for(var s,c,f=o,l=0,h=!!a&&ar(a,u);l0&&ur(s)?(c=de(s),f=Cr(t,e,s,c,f,i-1)-1):(Nr(f+1),t[f]=s),f++),l++;return f},_r=Cr;Ce({target:"Array",proto:!0},{flatMap:function(t){var e,r=it(this),n=de(r);return J(t),(e=xr(r,0)).length=_r(e,r,r,n,0,1,t,arguments.length>1?arguments[1]:void 0),e}}),Qe("flatMap"),Ze("Array","flatMap"),Ce({target:"Array",proto:!0},{flat:function(){var t=arguments.length?arguments[0]:void 0,e=it(this),r=de(e),n=xr(e,0);return n.length=_r(n,e,e,r,0,void 0===t?1:ce(t)),n}}),Qe("flat"),Ze("Array","flat");var Fr,Br,Dr,zr=String,Wr=function(t){if("Symbol"===pr(t))throw new TypeError("Cannot convert a Symbol value to a string");return zr(t)},qr=b("".charAt),Hr=b("".charCodeAt),$r=b("".slice),Kr=function(t){return function(e,r){var n,o,i=Wr(j(e)),a=ce(r),u=i.length;return a<0||a>=u?t?"":void 0:(n=Hr(i,a))<55296||n>56319||a+1===u||(o=Hr(i,a+1))<56320||o>57343?t?qr(i,a):n:t?$r(i,a,a+2):o-56320+(n-55296<<10)+65536}},Gr={codeAt:Kr(!1),charAt:Kr(!0)},Vr=!a(function(){function t(){}return t.prototype.constructor=null,Object.getPrototypeOf(new t)!==t.prototype}),Yr=Xt("IE_PROTO"),Xr=Object,Jr=Xr.prototype,Qr=Vr?Xr.getPrototypeOf:function(t){var e=it(t);if(ut(e,Yr))return e[Yr];var r=e.constructor;return T(r)&&e instanceof r?r.prototype:e instanceof Xr?Jr:null},Zr=dt("iterator"),tn=!1;[].keys&&("next"in(Dr=[].keys())?(Br=Qr(Qr(Dr)))!==Object.prototype&&(Fr=Br):tn=!0);var en=!M(Fr)||a(function(){var t={};return Fr[Zr].call(t)!==t});en&&(Fr={}),T(Fr[Zr])||ie(Fr,Zr,function(){return this});var rn={IteratorPrototype:Fr,BUGGY_SAFARI_ITERATORS:tn},nn=Ct.f,on=dt("toStringTag"),an=function(t,e,r){t&&!r&&(t=t.prototype),t&&!ut(t,on)&&nn(t,on,{configurable:!0,value:e})},un={},sn=rn.IteratorPrototype,cn=function(){return this},fn=function(t,e,r,n){var o=e+" Iterator";return t.prototype=Ve(sn,{next:d(+!n,r)}),an(t,o,!1),un[o]=cn,t},ln=function(t,e,r){try{return b(J(Object.getOwnPropertyDescriptor(t,e)[r]))}catch(t){}},hn=String,pn=TypeError,vn=function(t){if(function(t){return M(t)||null===t}(t))return t;throw new pn("Can't set "+hn(t)+" as a prototype")},dn=Object.setPrototypeOf||("__proto__"in{}?function(){var t,e=!1,r={};try{(t=ln(Object.prototype,"__proto__","set"))(r,[]),e=r instanceof Array}catch(t){}return function(r,n){return j(r),vn(n),M(r)?(e?t(r,n):r.__proto__=n,r):r}}():void 0),gn=zt.PROPER,yn=zt.CONFIGURABLE,mn=rn.IteratorPrototype,bn=rn.BUGGY_SAFARI_ITERATORS,wn=dt("iterator"),Sn="keys",En="values",On="entries",xn=function(){return this},Rn=function(t,e,r,n,o,i,a){fn(r,e,n);var u,s,c,l=function(t){if(t===o&&g)return g;if(!bn&&t&&t in v)return v[t];switch(t){case Sn:case En:case On:return function(){return new r(this,t)}}return function(){return new r(this)}},h=e+" Iterator",p=!1,v=t.prototype,d=v[wn]||v["@@iterator"]||o&&v[o],g=!bn&&d||l(o),y="Array"===e&&v.entries||d;if(y&&(u=Qr(y.call(new t)))!==Object.prototype&&u.next&&(Qr(u)!==mn&&(dn?dn(u,mn):T(u[wn])||ie(u,wn,xn)),an(u,h,!0)),gn&&o===En&&d&&d.name!==En&&(yn?_t(v,"name",En):(p=!0,g=function(){return f(d,this)})),o)if(s={values:l(En),keys:i?g:l(Sn),entries:l(On)},a)for(c in s)(bn||p||!(c in v))&&ie(v,c,s[c]);else Ce({target:e,proto:!0,forced:bn||p},s);return v[wn]!==g&&ie(v,wn,g,{name:o}),un[e]=g,s},Pn=function(t,e){return{value:t,done:e}},An=Gr.charAt,jn="String Iterator",kn=ne.set,In=ne.getterFor(jn);Rn(String,"String",function(t){kn(this,{type:jn,string:Wr(t),index:0})},function(){var t,e=In(this),r=e.string,n=e.index;return n>=r.length?Pn(void 0,!0):(t=An(r,n),e.index+=t.length,Pn(t,!1))});var Tn=function(t,e,r){var n,o;kt(t);try{if(!(n=Q(t,"return"))){if("throw"===e)throw r;return r}n=f(n,t)}catch(t){o=!0,n=t}if("throw"===e)throw r;if(o)throw n;return kt(n),r},Mn=function(t,e,r,n){try{return n?e(kt(r)[0],r[1]):e(r)}catch(e){Tn(t,"throw",e)}},Ln=dt("iterator"),Un=Array.prototype,Nn=function(t){return void 0!==t&&(un.Array===t||Un[Ln]===t)},Cn=function(t,e,r){u?Ct.f(t,e,d(0,r)):t[e]=r},_n=dt("iterator"),Fn=function(t){if(!P(t))return Q(t,_n)||Q(t,"@@iterator")||un[pr(t)]},Bn=TypeError,Dn=function(t,e){var r=arguments.length<2?Fn(t):e;if(J(r))return kt(f(r,t));throw new Bn(Y(t)+" is not iterable")},zn=Array,Wn=function(t){var e=it(t),r=Sr(this),n=arguments.length,o=n>1?arguments[1]:void 0,i=void 0!==o;i&&(o=ar(o,n>2?arguments[2]:void 0));var a,u,s,c,l,h,p=Fn(e),v=0;if(!p||this===zn&&Nn(p))for(a=de(e),u=r?new this(a):zn(a);a>v;v++)h=i?o(e[v],v):e[v],Cn(u,v,h);else for(u=r?new this:[],l=(c=Dn(e,p)).next;!(s=f(l,c)).done;v++)h=i?Mn(c,o,[s.value,v],!0):s.value,Cn(u,v,h);return u.length=v,u},qn=dt("iterator"),Hn=!1;try{var $n=0,Kn={next:function(){return{done:!!$n++}},return:function(){Hn=!0}};Kn[qn]=function(){return this},Array.from(Kn,function(){throw 2})}catch(t){}var Gn=function(t,e){try{if(!e&&!Hn)return!1}catch(t){return!1}var r=!1;try{var n={};n[qn]=function(){return{next:function(){return{done:r=!0}}}},t(n)}catch(t){}return r},Vn=!Gn(function(t){Array.from(t)});Ce({target:"Array",stat:!0,forced:Vn},{from:Wn});var Yn=i,Xn=ye.includes,Jn=a(function(){return!Array(1).includes()});Ce({target:"Array",proto:!0,forced:Jn},{includes:function(t){return Xn(this,t,arguments.length>1?arguments[1]:void 0)}}),Qe("includes"),Ze("Array","includes");var Qn=Ct.f,Zn="Array Iterator",to=ne.set,eo=ne.getterFor(Zn),ro=Rn(Array,"Array",function(t,e){to(this,{type:Zn,target:k(t),index:0,kind:e})},function(){var t=eo(this),e=t.target,r=t.index++;if(!e||r>=e.length)return t.target=null,Pn(void 0,!0);switch(t.kind){case"keys":return Pn(r,!1);case"values":return Pn(e[r],!1)}return Pn([r,e[r]],!1)},"values"),no=un.Arguments=un.Array;if(Qe("keys"),Qe("values"),Qe("entries"),u&&"values"!==no.name)try{Qn(no,"name",{value:"values"})}catch(t){}cr||ie(Object.prototype,"toString",cr?{}.toString:function(){return"[object "+pr(this)+"]"},{unsafe:!0}),Ze("Array","values");var oo=Array,io=a(function(){function t(){}return!(oo.of.call(t)instanceof t)});Ce({target:"Array",stat:!0,forced:io},{of:function(){for(var t=0,e=arguments.length,r=new(Sr(this)?this:oo)(e);e>t;)Cn(r,t,arguments[t++]);return r.length=e,r}});var ao=dt("hasInstance"),uo=Function.prototype;ao in uo||Ct.f(uo,ao,{value:oe(function(t){if(!T(this)||!M(t))return!1;var e=this.prototype;return M(e)?U(e,t):t instanceof this},ao)}),dt("hasInstance");var so=function(t,e,r){return r.get&&oe(r.get,e,{getter:!0}),r.set&&oe(r.set,e,{setter:!0}),Ct.f(t,e,r)},co=zt.EXISTS,fo=Function.prototype,lo=b(fo.toString),ho=/function\b(?:\s|\/\*[\S\s]*?\*\/|\/\/[^\n\r]*[\n\r]+)*([^\s(/]*)/,po=b(ho.exec);u&&!co&&so(fo,"name",{configurable:!0,get:function(){try{return po(ho,lo(this))[1]}catch(t){return""}}});var vo=b([].slice),go=Oe.f,yo="object"==typeof window&&window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],mo={f:function(t){return yo&&"Window"===E(t)?function(t){try{return go(t)}catch(t){return vo(yo)}}(t):go(k(t))}},bo=a(function(){if("function"==typeof ArrayBuffer){var t=new ArrayBuffer(8);Object.isExtensible(t)&&Object.defineProperty(t,"a",{value:8})}}),wo=Object.isExtensible,So=a(function(){wo(1)})||bo?function(t){return!!M(t)&&(!bo||"ArrayBuffer"!==E(t))&&(!wo||wo(t))}:wo,Eo=!a(function(){return Object.isExtensible(Object.preventExtensions({}))}),Oo=e(function(t){var e=Ct.f,r=!1,n=lt("meta"),o=0,i=function(t){e(t,n,{value:{objectID:"O"+o++,weakData:{}}})},a=t.exports={enable:function(){a.enable=function(){},r=!0;var t=Oe.f,e=b([].splice),o={};o[n]=1,t(o).length&&(Oe.f=function(r){for(var o=t(r),i=0,a=o.length;ii;i++)if((u=y(t[i]))&&U(Po,u))return u;return new Ro(!1)}n=Dn(t,o)}for(s=h?t.next:n.next;!(c=f(s,n)).done;){try{u=y(c.value)}catch(t){Tn(n,"throw",t)}if("object"==typeof u&&u&&U(Po,u))return u}return new Ro(!1)},jo=TypeError,ko=function(t,e){if(U(e,t))return t;throw new jo("Incorrect invocation")},Io=function(t,e,r){var n,o;return dn&&T(n=e.constructor)&&n!==r&&M(o=n.prototype)&&o!==r.prototype&&dn(t,o),t},To=function(t,e,r){var n=-1!==t.indexOf("Map"),o=-1!==t.indexOf("Weak"),u=n?"set":"add",s=i[t],c=s&&s.prototype,f=s,l={},h=function(t){var e=b(c[t]);ie(c,t,"add"===t?function(t){return e(this,0===t?0:t),this}:"delete"===t?function(t){return!(o&&!M(t))&&e(this,0===t?0:t)}:"get"===t?function(t){return o&&!M(t)?void 0:e(this,0===t?0:t)}:"has"===t?function(t){return!(o&&!M(t))&&e(this,0===t?0:t)}:function(t,r){return e(this,0===t?0:t,r),this})};if(Ue(t,!T(s)||!(o||c.forEach&&!a(function(){(new s).entries().next()}))))f=r.getConstructor(e,t,n,u),Oo.enable();else if(Ue(t,!0)){var p=new f,v=p[u](o?{}:-0,1)!==p,d=a(function(){p.has(1)}),g=Gn(function(t){new s(t)}),y=!o&&a(function(){for(var t=new s,e=5;e--;)t[u](e,e);return!t.has(-0)});g||((f=e(function(t,e){ko(t,c);var r=Io(new s,t,f);return P(e)||Ao(e,r[u],{that:r,AS_ENTRIES:n}),r})).prototype=c,c.constructor=f),(d||y)&&(h("delete"),h("has"),n&&h("get")),(y||v)&&h(u),o&&c.clear&&delete c.clear}return l[t]=f,Ce({global:!0,constructor:!0,forced:f!==s},l),an(f,t),o||r.setStrong(f,t,n),f},Mo=function(t,e,r){for(var n in e)ie(t,n,e[n],r);return t},Lo=dt("species"),Uo=function(t){var e=L(t);u&&e&&!e[Lo]&&so(e,Lo,{configurable:!0,get:function(){return this}})},No=Oo.fastKey,Co=ne.set,_o=ne.getterFor,Fo={getConstructor:function(t,e,r,n){var o=t(function(t,o){ko(t,i),Co(t,{type:e,index:Ve(null),first:null,last:null,size:0}),u||(t.size=0),P(o)||Ao(o,t[n],{that:t,AS_ENTRIES:r})}),i=o.prototype,a=_o(e),s=function(t,e,r){var n,o,i=a(t),s=c(t,e);return s?s.value=r:(i.last=s={index:o=No(e,!0),key:e,value:r,previous:n=i.last,next:null,removed:!1},i.first||(i.first=s),n&&(n.next=s),u?i.size++:t.size++,"F"!==o&&(i.index[o]=s)),t},c=function(t,e){var r,n=a(t),o=No(e);if("F"!==o)return n.index[o];for(r=n.first;r;r=r.next)if(r.key===e)return r};return Mo(i,{clear:function(){for(var t=a(this),e=t.first;e;)e.removed=!0,e.previous&&(e.previous=e.previous.next=null),e=e.next;t.first=t.last=null,t.index=Ve(null),u?t.size=0:this.size=0},delete:function(t){var e=this,r=a(e),n=c(e,t);if(n){var o=n.next,i=n.previous;delete r.index[n.index],n.removed=!0,i&&(i.next=o),o&&(o.previous=i),r.first===n&&(r.first=o),r.last===n&&(r.last=i),u?r.size--:e.size--}return!!n},forEach:function(t){for(var e,r=a(this),n=ar(t,arguments.length>1?arguments[1]:void 0);e=e?e.next:r.first;)for(n(e.value,e.key,this);e&&e.removed;)e=e.previous},has:function(t){return!!c(this,t)}}),Mo(i,r?{get:function(t){var e=c(this,t);return e&&e.value},set:function(t,e){return s(this,0===t?0:t,e)}}:{add:function(t){return s(this,t=0===t?0:t,t)}}),u&&so(i,"size",{configurable:!0,get:function(){return a(this).size}}),o},setStrong:function(t,e,r){var n=e+" Iterator",o=_o(e),i=_o(n);Rn(t,e,function(t,e){Co(this,{type:n,target:t,state:o(t),kind:e,last:null})},function(){for(var t=i(this),e=t.kind,r=t.last;r&&r.removed;)r=r.previous;return t.target&&(t.last=r=r?r.next:t.state.first)?Pn("keys"===e?r.key:"values"===e?r.value:[r.key,r.value],!1):(t.target=null,Pn(void 0,!0))},r?"entries":"values",!r,!0),Uo(e)}};To("Map",function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},Fo);var Bo=Map.prototype,Do={Map:Map,set:b(Bo.set),get:b(Bo.get),has:b(Bo.has),remove:b(Bo.delete),proto:Bo},zo=Do.Map,Wo=Do.has,qo=Do.get,Ho=Do.set,$o=b([].push),Ko=a(function(){return 1!==zo.groupBy("ab",function(t){return t}).get("a").length});Ce({target:"Map",stat:!0,forced:Ko},{groupBy:function(t,e){j(t),J(e);var r=new zo,n=0;return Ao(t,function(t){var o=e(t,n++);Wo(r,o)?$o(qo(r,o),t):Ho(r,o,[t])}),r}});var Go={CSSRuleList:0,CSSStyleDeclaration:0,CSSValueList:0,ClientRectList:0,DOMRectList:0,DOMStringList:0,DOMTokenList:1,DataTransferItemList:0,FileList:0,HTMLAllCollection:0,HTMLCollection:0,HTMLFormElement:0,HTMLSelectElement:0,MediaList:0,MimeTypeArray:0,NamedNodeMap:0,NodeList:1,PaintRequestList:0,Plugin:0,PluginArray:0,SVGLengthList:0,SVGNumberList:0,SVGPathSegList:0,SVGPointList:0,SVGStringList:0,SVGTransformList:0,SourceBufferList:0,StyleSheetList:0,TextTrackCueList:0,TextTrackList:0,TouchList:0},Vo=Et("span").classList,Yo=Vo&&Vo.constructor&&Vo.constructor.prototype,Xo=Yo===Object.prototype?void 0:Yo,Jo=dt("iterator"),Qo=ro.values,Zo=function(t,e){if(t){if(t[Jo]!==Qo)try{_t(t,Jo,Qo)}catch(e){t[Jo]=Qo}if(an(t,e,!0),Go[e])for(var r in ro)if(t[r]!==ro[r])try{_t(t,r,ro[r])}catch(e){t[r]=ro[r]}}};for(var ti in Go)Zo(i[ti]&&i[ti].prototype,ti);Zo(Xo,"DOMTokenList");var ei=function(t,e,r){return function(n){var o=it(n),i=arguments.length,a=i>1?arguments[1]:void 0,u=void 0!==a,s=u?ar(a,i>2?arguments[2]:void 0):void 0,c=new t,f=0;return Ao(o,function(t){var n=u?s(t,f++):t;r?e(c,kt(n)[0],n[1]):e(c,n)}),c}};Ce({target:"Map",stat:!0,forced:!0},{from:ei(Do.Map,Do.set,!0)});var ri=function(t,e,r){return function(){for(var n=new t,o=arguments.length,i=0;i1?arguments[1]:void 0);return!1!==di(e,function(t,n){if(!r(t,n,e))return!1},!0)}});var gi=Do.Map,yi=Do.set;Ce({target:"Map",proto:!0,real:!0,forced:!0},{filter:function(t){var e=oi(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=new gi;return di(e,function(t,o){r(t,o,e)&&yi(n,o,t)}),n}}),Ce({target:"Map",proto:!0,real:!0,forced:!0},{find:function(t){var e=oi(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=di(e,function(t,n){if(r(t,n,e))return{value:t}},!0);return n&&n.value}}),Ce({target:"Map",proto:!0,real:!0,forced:!0},{findKey:function(t){var e=oi(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=di(e,function(t,n){if(r(t,n,e))return{key:n}},!0);return n&&n.key}}),Ce({target:"Map",proto:!0,real:!0,forced:!0},{includes:function(t){return!0===di(oi(this),function(e){if((r=e)===(n=t)||r!=r&&n!=n)return!0;var r,n},!0)}});var mi=Do.Map;Ce({target:"Map",stat:!0,forced:!0},{keyBy:function(t,e){var r=new(T(this)?this:mi);J(e);var n=J(r.set);return Ao(t,function(t){f(n,r,e(t),t)}),r}}),Ce({target:"Map",proto:!0,real:!0,forced:!0},{keyOf:function(t){var e=di(oi(this),function(e,r){if(e===t)return{key:r}},!0);return e&&e.key}});var bi=Do.Map,wi=Do.set;Ce({target:"Map",proto:!0,real:!0,forced:!0},{mapKeys:function(t){var e=oi(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=new bi;return di(e,function(t,o){wi(n,r(t,o,e),t)}),n}});var Si=Do.Map,Ei=Do.set;Ce({target:"Map",proto:!0,real:!0,forced:!0},{mapValues:function(t){var e=oi(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=new Si;return di(e,function(t,o){Ei(n,o,r(t,o,e))}),n}});var Oi=Do.set;Ce({target:"Map",proto:!0,real:!0,arity:1,forced:!0},{merge:function(t){for(var e=oi(this),r=arguments.length,n=0;n1?arguments[1]:void 0);return!0===di(e,function(t,n){if(r(t,n,e))return!0},!0)}});var Ri=TypeError,Pi=Do.get,Ai=Do.has,ji=Do.set;Ce({target:"Map",proto:!0,real:!0,forced:!0},{update:function(t,e){var r=oi(this),n=arguments.length;J(e);var o=Ai(r,t);if(!o&&n<3)throw new Ri("Updating absent value");var i=o?Pi(r,t):J(n>2?arguments[2]:void 0)(t,r);return ji(r,t,e(i,t,r)),r}});var ki=TypeError,Ii=function(t,e){var r,n=kt(this),o=J(n.get),i=J(n.has),a=J(n.set),u=arguments.length>2?arguments[2]:void 0;if(!T(e)&&!T(u))throw new ki("At least one callback required");return f(i,n,t)?(r=f(o,n,t),T(e)&&(r=e(r),f(a,n,t,r))):T(u)&&(r=u(),f(a,n,t,r)),r};Ce({target:"Map",proto:!0,real:!0,forced:!0},{upsert:Ii}),Ce({target:"Map",proto:!0,real:!0,name:"upsert",forced:!0},{updateOrInsert:Ii});var Ti=b(1..valueOf),Mi="\t\n\v\f\r                 \u2028\u2029\ufeff",Li=b("".replace),Ui=RegExp("^["+Mi+"]+"),Ni=RegExp("(^|[^"+Mi+"])["+Mi+"]+$"),Ci=function(t){return function(e){var r=Wr(j(e));return 1&t&&(r=Li(r,Ui,"")),2&t&&(r=Li(r,Ni,"$1")),r}},_i={start:Ci(1),end:Ci(2),trim:Ci(3)},Fi=Oe.f,Bi=Rt.f,Di=Ct.f,zi=_i.trim,Wi="Number",qi=i[Wi],Hi=qi.prototype,$i=i.TypeError,Ki=b("".slice),Gi=b("".charCodeAt),Vi=Ue(Wi,!qi(" 0o1")||!qi("0b1")||qi("+0x1")),Yi=function(t){var e,r=arguments.length<1?0:qi(function(t){var e=mt(t,"number");return"bigint"==typeof e?e:function(t){var e,r,n,o,i,a,u,s,c=mt(t,"number");if(G(c))throw new $i("Cannot convert a Symbol value to a number");if("string"==typeof c&&c.length>2)if(c=zi(c),43===(e=Gi(c,0))||45===e){if(88===(r=Gi(c,2))||120===r)return NaN}else if(48===e){switch(Gi(c,1)){case 66:case 98:n=2,o=49;break;case 79:case 111:n=8,o=55;break;default:return+c}for(a=(i=Ki(c,2)).length,u=0;uo)return NaN;return parseInt(i,n)}return+c}(e)}(t));return U(Hi,e=this)&&a(function(){Ti(e)})?Io(Object(r),this,Yi):r};Yi.prototype=Hi,Vi&&(Hi.constructor=Yi),Ce({global:!0,constructor:!0,wrap:!0,forced:Vi},{Number:Yi}),Vi&&function(t,e){for(var r,n=u?Fi(e):"MAX_VALUE,MIN_VALUE,NaN,NEGATIVE_INFINITY,POSITIVE_INFINITY,EPSILON,MAX_SAFE_INTEGER,MIN_SAFE_INTEGER,isFinite,isInteger,isNaN,isSafeInteger,parseFloat,parseInt,fromString,range".split(","),o=0;n.length>o;o++)ut(e,r=n[o])&&!ut(t,r)&&Di(t,r,Bi(e,r))}(Yn[Wi],qi),Ce({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{EPSILON:Math.pow(2,-52)});var Xi=i.isFinite;Ce({target:"Number",stat:!0},{isFinite:Number.isFinite||function(t){return"number"==typeof t&&Xi(t)}});var Ji=Math.floor,Qi=Number.isInteger||function(t){return!M(t)&&isFinite(t)&&Ji(t)===t};Ce({target:"Number",stat:!0},{isInteger:Qi}),Ce({target:"Number",stat:!0},{isNaN:function(t){return t!=t}});var Zi=Math.abs;Ce({target:"Number",stat:!0},{isSafeInteger:function(t){return Qi(t)&&Zi(t)<=9007199254740991}}),Ce({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MAX_SAFE_INTEGER:9007199254740991}),Ce({target:"Number",stat:!0,nonConfigurable:!0,nonWritable:!0},{MIN_SAFE_INTEGER:-9007199254740991});var ta=_i.trim,ea=b("".charAt),ra=i.parseFloat,na=i.Symbol,oa=na&&na.iterator,ia=1/ra(Mi+"-0")!=-Infinity||oa&&!a(function(){ra(Object(oa))})?function(t){var e=ta(Wr(t)),r=ra(e);return 0===r&&"-"===ea(e,0)?-0:r}:ra;Ce({target:"Number",stat:!0,forced:Number.parseFloat!==ia},{parseFloat:ia});var aa=_i.trim,ua=i.parseInt,sa=i.Symbol,ca=sa&&sa.iterator,fa=/^[+-]?0x/i,la=b(fa.exec),ha=8!==ua(Mi+"08")||22!==ua(Mi+"0x16")||ca&&!a(function(){ua(Object(ca))})?function(t,e){var r=aa(Wr(t));return ua(r,e>>>0||(la(fa,r)?16:10))}:ua;Ce({target:"Number",stat:!0,forced:Number.parseInt!==ha},{parseInt:ha});var pa=b(v.f),va=b([].push),da=u&&a(function(){var t=Object.create(null);return t[2]=2,!pa(t,2)}),ga=function(t){return function(e){for(var r,n=k(e),o=_e(n),i=da&&null===Qr(n),a=o.length,s=0,c=[];a>s;)r=o[s++],u&&!(i?r in n:pa(n,r))||va(c,t?[r,n[r]]:n[r]);return c}},ya={entries:ga(!0),values:ga(!1)},ma=ya.entries;Ce({target:"Object",stat:!0},{entries:function(t){return ma(t)}}),Ce({target:"Object",stat:!0,sham:!u},{getOwnPropertyDescriptors:function(t){for(var e,r,n=k(t),o=Rt.f,i=Pe(n),a={},u=0;i.length>u;)void 0!==(r=o(n,e=i[u++]))&&Cn(a,e,r);return a}});var ba=a(function(){_e(1)});Ce({target:"Object",stat:!0,forced:ba},{keys:function(t){return _e(it(t))}});var wa=Object.is||function(t,e){return t===e?0!==t||1/t==1/e:t!=t&&e!=e};Ce({target:"Object",stat:!0},{is:wa});var Sa=ya.values;Ce({target:"Object",stat:!0},{values:function(t){return Sa(t)}}),Ce({target:"Object",stat:!0},{hasOwn:ut});var Ea=Function.prototype,Oa=Ea.apply,xa=Ea.call,Ra="object"==typeof Reflect&&Reflect.apply||(s?xa.bind(Oa):function(){return xa.apply(Oa,arguments)}),Pa=!a(function(){Reflect.apply(function(){})});Ce({target:"Reflect",stat:!0,forced:Pa},{apply:function(t,e,r){return Ra(J(t),e,kt(r))}});var Aa=Function,ja=b([].concat),ka=b([].join),Ia={},Ta=s?Aa.bind:function(t){var e=J(this),r=e.prototype,n=vo(arguments,1),o=function(){var r=ja(n,vo(arguments));return this instanceof o?function(t,e,r){if(!ut(Ia,e)){for(var n=[],o=0;ob)","g");return"b"!==t.exec("b").groups.a||"bc"!=="b".replace(t,"$c")}),gs=Oe.f,ys=ne.enforce,ms=dt("match"),bs=i.RegExp,ws=bs.prototype,Ss=i.SyntaxError,Es=b(ws.exec),Os=b("".charAt),xs=b("".replace),Rs=b("".indexOf),Ps=b("".slice),As=/^\?<[^\s\d!#%&*+<=>@^][^\s!#%&*+<=>@^]*>/,js=/a/g,ks=/a/g,Is=new bs(js)!==js,Ts=cs.MISSED_STICKY,Ms=cs.UNSUPPORTED_Y,Ls=u&&(!Is||Ts||ps||ds||a(function(){return ks[ms]=!1,bs(js)!==js||bs(ks)===ks||"/a/i"!==String(bs(js,"i"))}));if(Ue("RegExp",Ls)){for(var Us=function(t,e){var r,n,o,i,a,u,s=U(ws,this),c=es(t),f=void 0===e,l=[],h=t;if(!s&&c&&f&&t.constructor===Us)return t;if((c||U(ws,t))&&(t=t.source,f&&(e=os(h))),t=void 0===t?"":Wr(t),e=void 0===e?"":Wr(e),h=t,ps&&"dotAll"in js&&(n=!!e&&Rs(e,"s")>-1)&&(e=xs(e,/s/g,"")),r=e,Ts&&"sticky"in js&&(o=!!e&&Rs(e,"y")>-1)&&Ms&&(e=xs(e,/y/g,"")),ds&&(i=function(t){for(var e,r=t.length,n=0,o="",i=[],a=Ve(null),u=!1,s=!1,c=0,f="";n<=r;n++){if("\\"===(e=Os(t,n)))e+=Os(t,++n);else if("]"===e)u=!1;else if(!u)switch(!0){case"["===e:u=!0;break;case"("===e:if(o+=e,"?:"===Ps(t,n+1,n+3))continue;Es(As,Ps(t,n+1))&&(n+=2,s=!0),c++;continue;case">"===e&&s:if(""===f||ut(a,f))throw new Ss("Invalid capture group name");a[f]=!0,i[i.length]=[f,c],s=!1,f="";continue}s?f+=e:o+=e}return[o,i]}(t),t=i[0],l=i[1]),a=Io(bs(t,e),s?this:ws,Us),(n||o||l.length)&&(u=ys(a),n&&(u.dotAll=!0,u.raw=Us(function(t){for(var e,r=t.length,n=0,o="",i=!1;n<=r;n++)"\\"!==(e=Os(t,n))?i||"."!==e?("["===e?i=!0:"]"===e&&(i=!1),o+=e):o+="[\\s\\S]":o+=e+Os(t,++n);return o}(t),r)),o&&(u.sticky=!0),l.length&&(u.groups=l)),t!==h)try{_t(a,"source",""===h?"(?:)":h)}catch(t){}return a},Ns=gs(bs),Cs=0;Ns.length>Cs;)ls(Us,bs,Ns[Cs++]);ws.constructor=Us,Us.prototype=ws,ie(i,"RegExp",Us,{constructor:!0})}Uo("RegExp");var _s=zt.PROPER,Fs="toString",Bs=RegExp.prototype,Ds=Bs[Fs];(a(function(){return"/a/b"!==Ds.call({source:"a",flags:"b"})})||_s&&Ds.name!==Fs)&&ie(Bs,Fs,function(){var t=kt(this);return"/"+Wr(t.source)+"/"+Wr(os(t))},{unsafe:!0});var zs=ne.get,Ws=RegExp.prototype,qs=TypeError;u&&ps&&so(Ws,"dotAll",{configurable:!0,get:function(){if(this!==Ws){if("RegExp"===E(this))return!!zs(this).dotAll;throw new qs("Incompatible receiver, RegExp required")}}});var Hs=ne.get,$s=nt("native-string-replace",String.prototype.replace),Ks=RegExp.prototype.exec,Gs=Ks,Vs=b("".charAt),Ys=b("".indexOf),Xs=b("".replace),Js=b("".slice),Qs=function(){var t=/a/,e=/b*/g;return f(Ks,t,"a"),f(Ks,e,"a"),0!==t.lastIndex||0!==e.lastIndex}(),Zs=cs.BROKEN_CARET,tc=void 0!==/()??/.exec("")[1];(Qs||tc||Zs||ps||ds)&&(Gs=function(t){var e,r,n,o,i,a,u,s=this,c=Hs(s),l=Wr(t),h=c.raw;if(h)return h.lastIndex=s.lastIndex,e=f(Gs,h,l),s.lastIndex=h.lastIndex,e;var p=c.groups,v=Zs&&s.sticky,d=f(rs,s),g=s.source,y=0,m=l;if(v&&(d=Xs(d,"y",""),-1===Ys(d,"g")&&(d+="g"),m=Js(l,s.lastIndex),s.lastIndex>0&&(!s.multiline||s.multiline&&"\n"!==Vs(l,s.lastIndex-1))&&(g="(?: "+g+")",m=" "+m,y++),r=new RegExp("^(?:"+g+")",d)),tc&&(r=new RegExp("^"+g+"$(?!\\s)",d)),Qs&&(n=s.lastIndex),o=f(Ks,v?r:s,m),v?o?(o.input=Js(o.input,y),o[0]=Js(o[0],y),o.index=s.lastIndex,s.lastIndex+=o[0].length):s.lastIndex=0:Qs&&o&&(s.lastIndex=s.global?o.index+o[0].length:n),tc&&o&&o.length>1&&f($s,o[0],r,function(){for(i=1;i]*>)/g,Oc=/\$([$&'`]|\d{1,2})/g,xc=function(t,e,r,n,o,i){var a=r+t.length,u=n.length,s=Oc;return void 0!==o&&(o=it(o),s=Ec),wc(i,s,function(i,s){var c;switch(bc(s,0)){case"$":return"$";case"&":return t;case"`":return Sc(e,0,r);case"'":return Sc(e,a);case"<":c=o[Sc(s,1,-1)];break;default:var f=+s;if(0===f)return i;if(f>u){var l=mc(f/10);return 0===l?i:l<=u?void 0===n[l-1]?bc(s,1):n[l-1]+bc(s,1):i}c=n[f-1]}return void 0===c?"":c})},Rc=dt("replace"),Pc=Math.max,Ac=Math.min,jc=b([].concat),kc=b([].push),Ic=b("".indexOf),Tc=b("".slice),Mc="$0"==="a".replace(/./,"$0"),Lc=!!/./[Rc]&&""===/./[Rc]("a","$0"),Uc=!a(function(){var t=/./;return t.exec=function(){var t=[];return t.groups={a:"7"},t},"7"!=="".replace(t,"$")});pc("replace",function(t,e,r){var n=Lc?"$":"$0";return[function(t,r){var n=j(this),o=P(t)?void 0:Q(t,Rc);return o?f(o,t,n,r):f(e,Wr(n),t,r)},function(t,o){var i=kt(this),a=Wr(t);if("string"==typeof o&&-1===Ic(o,n)&&-1===Ic(o,"$<")){var u=r(e,i,a,o);if(u.done)return u.value}var s=T(o);s||(o=Wr(o));var c,f=i.global;f&&(c=i.unicode,i.lastIndex=0);for(var l,h=[];null!==(l=yc(i,a))&&(kc(h,l),f);)""===Wr(l[0])&&(i.lastIndex=dc(a,ve(i.lastIndex),c));for(var p,v="",d=0,g=0;g=d&&(v+=Tc(a,d,b)+y,d=b+m.length)}return v+Tc(a,d)}]},!Uc||!Mc||Lc),pc("search",function(t,e,r){return[function(e){var r=j(this),n=P(e)?void 0:Q(e,t);return n?f(n,e,r):new RegExp(e)[t](Wr(r))},function(t){var n=kt(this),o=Wr(t),i=r(e,n,o);if(i.done)return i.value;var a=n.lastIndex;wa(a,0)||(n.lastIndex=0);var u=yc(n,o);return wa(n.lastIndex,a)||(n.lastIndex=a),null===u?-1:u.index}]});var Nc=dt("species"),Cc=function(t,e){var r,n=kt(t).constructor;return void 0===n||P(r=kt(n)[Nc])?e:La(r)},_c=cs.UNSUPPORTED_Y,Fc=Math.min,Bc=b([].push),Dc=b("".slice),zc=!a(function(){var t=/(?:)/,e=t.exec;t.exec=function(){return e.apply(this,arguments)};var r="ab".split(t);return 2!==r.length||"a"!==r[0]||"b"!==r[1]}),Wc="c"==="abbc".split(/(b)*/)[1]||4!=="test".split(/(?:)/,-1).length||2!=="ab".split(/(?:ab)*/).length||4!==".".split(/(.?)(.?)/).length||".".split(/()()/).length>1||"".split(/.?/).length;pc("split",function(t,e,r){var n="0".split(void 0,0).length?function(t,r){return void 0===t&&0===r?[]:f(e,this,t,r)}:e;return[function(e,r){var o=j(this),i=P(e)?void 0:Q(e,t);return i?f(i,e,o,r):f(n,Wr(o),e,r)},function(t,o){var i=kt(this),a=Wr(t);if(!Wc){var u=r(n,i,a,o,n!==e);if(u.done)return u.value}var s=Cc(i,RegExp),c=i.unicode,f=new s(_c?"^(?:"+i.source+")":i,(i.ignoreCase?"i":"")+(i.multiline?"m":"")+(i.unicode?"u":"")+(_c?"g":"y")),l=void 0===o?4294967295:o>>>0;if(0===l)return[];if(0===a.length)return null===yc(f,a)?[a]:[];for(var h=0,p=0,v=[];p0;(n>>>=1)&&(e+=e))1&n&&(r+=e);return r},Kc=b($c),Gc=b("".slice),Vc=Math.ceil,Yc=function(t){return function(e,r,n){var o,i,a=Wr(j(e)),u=ve(r),s=a.length,c=void 0===n?" ":Wr(n);return u<=s||""===c?a:((i=Kc(c,Vc((o=u-s)/c.length))).length>o&&(i=Gc(i,0,o)),t?a+i:i+a)}},Xc={start:Yc(!1),end:Yc(!0)},Jc=Xc.start,Qc=Array,Zc=RegExp.escape,tf=b("".charAt),ef=b("".charCodeAt),rf=b(1.1.toString),nf=b([].join),of=/^[0-9a-z]/i,af=/^[$()*+./?[\\\]^{|}]/,uf=RegExp("^[!\"#%&',\\-:;<=>@`~"+Mi+"]"),sf=b(of.exec),cf={"\t":"t","\n":"n","\v":"v","\f":"f","\r":"r"},ff=function(t){var e=rf(ef(t,0),16);return e.length<3?"\\x"+Jc(e,2,"0"):"\\u"+Jc(e,4,"0")},lf=!Zc||"\\x61b"!==Zc("ab");Ce({target:"RegExp",stat:!0,forced:lf},{escape:function(t){!function(t){if("string"==typeof t)return t;throw new qc("Argument is not a string")}(t);for(var e=t.length,r=Qc(e),n=0;n=56320||n+1>=e||56320!=(64512&ef(t,n+1))?r[n]=ff(o):(r[n]=o,r[++n]=tf(t,n))}}return nf(r,"")}}),To("Set",function(t){return function(){return t(this,arguments.length?arguments[0]:void 0)}},Fo);var hf=Set.prototype,pf={Set:Set,add:b(hf.add),has:b(hf.has),remove:b(hf.delete),proto:hf},vf=pf.has,df=function(t){return vf(t),t},gf=pf.Set,yf=pf.proto,mf=b(yf.forEach),bf=b(yf.keys),wf=bf(new gf).next,Sf=function(t,e,r){return r?ci({iterator:bf(t),next:wf},e):mf(t,e)},Ef=pf.Set,Of=pf.add,xf=function(t){var e=new Ef;return Sf(t,function(t){Of(e,t)}),e},Rf=ln(pf.proto,"size","get")||function(t){return t.size},Pf="Invalid size",Af=RangeError,jf=TypeError,kf=Math.max,If=function(t,e){this.set=t,this.size=kf(e,0),this.has=J(t.has),this.keys=J(t.keys)};If.prototype={getIterator:function(){return{iterator:t=kt(f(this.keys,this.set)),next:t.next,done:!1};var t},includes:function(t){return f(this.has,this.set,t)}};var Tf=function(t){kt(t);var e=+t.size;if(e!=e)throw new jf(Pf);var r=ce(e);if(r<0)throw new Af(Pf);return new If(t,r)},Mf=pf.has,Lf=pf.remove,Uf=function(t){var e=df(this),r=Tf(t),n=xf(e);return Rf(e)<=r.size?Sf(e,function(t){r.includes(t)&&Lf(n,t)}):ci(r.getIterator(),function(t){Mf(e,t)&&Lf(n,t)}),n},Nf=function(t){return{size:t,has:function(){return!1},keys:function(){return{next:function(){return{done:!0}}}}}},Cf=function(t){var e=L("Set");try{(new e)[t](Nf(0));try{return(new e)[t](Nf(-1)),!1}catch(t){return!0}}catch(t){return!1}};Ce({target:"Set",proto:!0,real:!0,forced:!Cf("difference")},{difference:Uf});var _f=pf.Set,Ff=pf.add,Bf=pf.has,Df=function(t){var e=df(this),r=Tf(t),n=new _f;return Rf(e)>r.size?ci(r.getIterator(),function(t){Bf(e,t)&&Ff(n,t)}):Sf(e,function(t){r.includes(t)&&Ff(n,t)}),n},zf=!Cf("intersection")||a(function(){return"3,2"!==String(Array.from(new Set([1,2,3]).intersection(new Set([3,2]))))});Ce({target:"Set",proto:!0,real:!0,forced:zf},{intersection:Df});var Wf=pf.has,qf=function(t){var e=df(this),r=Tf(t);if(Rf(e)<=r.size)return!1!==Sf(e,function(t){if(r.includes(t))return!1},!0);var n=r.getIterator();return!1!==ci(n,function(t){if(Wf(e,t))return Tn(n,"normal",!1)})};Ce({target:"Set",proto:!0,real:!0,forced:!Cf("isDisjointFrom")},{isDisjointFrom:qf});var Hf=function(t){var e=df(this),r=Tf(t);return!(Rf(e)>r.size)&&!1!==Sf(e,function(t){if(!r.includes(t))return!1},!0)};Ce({target:"Set",proto:!0,real:!0,forced:!Cf("isSubsetOf")},{isSubsetOf:Hf});var $f=pf.has,Kf=function(t){var e=df(this),r=Tf(t);if(Rf(e)1?arguments[1]:void 0);return!1!==Sf(e,function(t){if(!r(t,t,e))return!1},!0)}});var el=dt("iterator"),rl=Object,nl=L("Set"),ol=function(t){return function(t){return M(t)&&"number"==typeof t.size&&T(t.has)&&T(t.keys)}(t)?t:function(t){if(P(t))return!1;var e=rl(t);return void 0!==e[el]||"@@iterator"in e||ut(un,pr(e))}(t)?new nl(t):t};Ce({target:"Set",proto:!0,real:!0,forced:!0},{difference:function(t){return f(Uf,this,ol(t))}});var il=pf.Set,al=pf.add;Ce({target:"Set",proto:!0,real:!0,forced:!0},{filter:function(t){var e=df(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=new il;return Sf(e,function(t){r(t,t,e)&&al(n,t)}),n}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{find:function(t){var e=df(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=Sf(e,function(t){if(r(t,t,e))return{value:t}},!0);return n&&n.value}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{intersection:function(t){return f(Df,this,ol(t))}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{isDisjointFrom:function(t){return f(qf,this,ol(t))}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{isSubsetOf:function(t){return f(Hf,this,ol(t))}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{isSupersetOf:function(t){return f(Kf,this,ol(t))}});var ul=b([].join),sl=b([].push);Ce({target:"Set",proto:!0,real:!0,forced:!0},{join:function(t){var e=df(this),r=void 0===t?",":Wr(t),n=[];return Sf(e,function(t){sl(n,t)}),ul(n,r)}});var cl=pf.Set,fl=pf.add;Ce({target:"Set",proto:!0,real:!0,forced:!0},{map:function(t){var e=df(this),r=ar(t,arguments.length>1?arguments[1]:void 0),n=new cl;return Sf(e,function(t){fl(n,r(t,t,e))}),n}});var ll=TypeError;Ce({target:"Set",proto:!0,real:!0,forced:!0},{reduce:function(t){var e=df(this),r=arguments.length<2,n=r?void 0:arguments[1];if(J(t),Sf(e,function(o){r?(r=!1,n=o):n=t(n,o,o,e)}),r)throw new ll("Reduce of empty set with no initial value");return n}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{some:function(t){var e=df(this),r=ar(t,arguments.length>1?arguments[1]:void 0);return!0===Sf(e,function(t){if(r(t,t,e))return!0},!0)}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{symmetricDifference:function(t){return f(Xf,this,ol(t))}}),Ce({target:"Set",proto:!0,real:!0,forced:!0},{union:function(t){return f(Qf,this,ol(t))}});var hl=dt("species"),pl=dt("isConcatSpreadable"),vl=W>=51||!a(function(){var t=[];return t[pl]=!1,t.concat()[0]!==t}),dl=function(t){if(!M(t))return!1;var e=t[pl];return void 0!==e?!!e:ur(t)},gl=!(vl&&(W>=51||!a(function(){var t=[];return(t.constructor={})[hl]=function(){return{foo:1}},1!==t.concat(Boolean).foo})));Ce({target:"Array",proto:!0,arity:1,forced:gl},{concat:function(t){var e,r,n,o,i,a=it(this),u=xr(a,0),s=0;for(e=-1,n=arguments.length;e1?arguments[1]:void 0,n=e.length,o=void 0===r?n:ip(ve(r),n),i=Wr(t);return op(e,o-i.length,o)===i}}),Ze("String","endsWith");var sp=RangeError,cp=String.fromCharCode,fp=String.fromCodePoint,lp=b([].join);Ce({target:"String",stat:!0,arity:1,forced:!!fp&&1!==fp.length},{fromCodePoint:function(t){for(var e,r=[],n=arguments.length,o=0;n>o;){if(e=+arguments[o++],he(e,1114111)!==e)throw new sp(e+" is not a valid code point");r[o]=e<65536?cp(e):cp(55296+((e-=65536)>>10),e%1024+56320)}return lp(r,"")}});var hp=b("".indexOf);Ce({target:"String",proto:!0,forced:!rp("includes")},{includes:function(t){return!!~hp(Wr(j(this)),Wr(tp(t)),arguments.length>1?arguments[1]:void 0)}}),Ze("String","includes"),b(un.String);var pp=/Version\/10(?:\.\d+){1,2}(?: [\w./]+)?(?: Mobile\/\w+)? Safari\//.test(_),vp=Xc.start;Ce({target:"String",proto:!0,forced:pp},{padStart:function(t){return vp(this,t,arguments.length>1?arguments[1]:void 0)}}),Ze("String","padStart");var dp=Xc.end;Ce({target:"String",proto:!0,forced:pp},{padEnd:function(t){return dp(this,t,arguments.length>1?arguments[1]:void 0)}}),Ze("String","padEnd");var gp=b([].push),yp=b([].join);Ce({target:"String",stat:!0},{raw:function(t){var e=k(it(t).raw),r=de(e);if(!r)return"";for(var n=arguments.length,o=[],i=0;;){if(gp(o,Wr(e[i++])),i===r)return yp(o,"");i1?arguments[1]:void 0,e.length)),n=Wr(t);return bp(e,r,r+n.length)===n}}),Ze("String","startsWith");var Op=zt.PROPER,xp=function(t){return a(function(){return!!Mi[t]()||"​…᠎"!=="​…᠎"[t]()||Op&&Mi[t].name!==t})},Rp=_i.start,Pp=xp("trimStart")?function(){return Rp(this)}:"".trimStart;Ce({target:"String",proto:!0,name:"trimStart",forced:"".trimLeft!==Pp},{trimLeft:Pp}),Ce({target:"String",proto:!0,name:"trimStart",forced:"".trimStart!==Pp},{trimStart:Pp}),Ze("String","trimLeft");var Ap=_i.end,jp=xp("trimEnd")?function(){return Ap(this)}:"".trimEnd;Ce({target:"String",proto:!0,name:"trimEnd",forced:"".trimRight!==jp},{trimRight:jp}),Ce({target:"String",proto:!0,name:"trimEnd",forced:"".trimEnd!==jp},{trimEnd:jp}),Ze("String","trimRight");var kp=Object.getOwnPropertyDescriptor,Ip=function(t){if(!u)return i[t];var e=kp(i,t);return e&&e.value},Tp=dt("iterator"),Mp=!a(function(){var t=new URL("b?a=1&b=2&c=3","https://a"),e=t.searchParams,r=new URLSearchParams("a=1&a=2&b=3"),n="";return t.pathname="c%20d",e.forEach(function(t,r){e.delete("b"),n+=r+t}),r.delete("a",2),r.delete("b",void 0),!e.size&&!u||!e.sort||"https://a/c%20d?a=1&c=3"!==t.href||"3"!==e.get("c")||"a=1"!==String(new URLSearchParams("?a=1"))||!e[Tp]||"a"!==new URL("https://a@b").username||"b"!==new URLSearchParams(new URLSearchParams("a=b")).get("a")||"xn--e1aybc"!==new URL("https://тест").host||"#%D0%B1"!==new URL("https://a#б").hash||"a1c3"!==n||"x"!==new URL("https://x",void 0).host}),Lp=TypeError,Up=function(t,e){if(t0;)t[o]=t[--o];o!==i++&&(t[o]=n)}else for(var a=Np(r/2),u=Cp(vo(t,0,a),e),s=Cp(vo(t,a),e),c=u.length,f=s.length,l=0,h=0;l0&&0!=(t&r);r>>=1)e++;return e},pv=function(t){var e=null;switch(t.length){case 1:e=t[0];break;case 2:e=(31&t[0])<<6|63&t[1];break;case 3:e=(15&t[0])<<12|(63&t[1])<<6|63&t[2];break;case 4:e=(7&t[0])<<18|(63&t[1])<<12|(63&t[2])<<6|63&t[3]}return e>1114111?null:e},vv=function(t){for(var e=(t=nv(t,cv," ")).length,r="",n=0;ne){r+="%",n++;continue}var i=lv(t,n+1);if(i!=i){r+=o,n++;continue}n+=2;var a=hv(i);if(0===a)o=Jp(i);else{if(1===a||a>4){r+="�",n++;continue}for(var u=[i],s=1;se||"%"!==tv(t,n));){var c=lv(t,n+1);if(c!=c){n+=3;break}if(c>191||c<128)break;rv(u,c),n+=2,s++}if(u.length!==a){r+="�";continue}var f=pv(u);null===f?r+="�":o=Qp(f)}}r+=o,n++}return r},dv=/[!'()~]|%20/g,gv={"!":"%21","'":"%27","(":"%28",")":"%29","~":"%7E","%20":"+"},yv=function(t){return gv[t]},mv=function(t){return nv(Xp(t),dv,yv)},bv=fn(function(t,e){zp(this,{type:Dp,target:Wp(t).entries,index:0,kind:e})},Bp,function(){var t=qp(this),e=t.target,r=t.index++;if(!e||r>=e.length)return t.target=null,Pn(void 0,!0);var n=e[r];switch(t.kind){case"keys":return Pn(n.key,!1);case"values":return Pn(n.value,!1)}return Pn([n.key,n.value],!1)},!0),wv=function(t){this.entries=[],this.url=null,void 0!==t&&(M(t)?this.parseObject(t):this.parseQuery("string"==typeof t?"?"===tv(t,0)?uv(t,1):t:Wr(t)))};wv.prototype={type:Bp,bindURL:function(t){this.url=t,this.update()},parseObject:function(t){var e,r,n,o,i,a,u,s=this.entries,c=Fn(t);if(c)for(r=(e=Dn(t,c)).next;!(n=f(r,e)).done;){if(o=Dn(kt(n.value)),(a=f(i=o.next,o)).done||(u=f(i,o)).done||!f(i,o).done)throw new Yp("Expected sequence with length 2");rv(s,{key:Wr(a.value),value:Wr(u.value)})}else for(var l in t)ut(t,l)&&rv(s,{key:l,value:Wr(t[l])})},parseQuery:function(t){if(t)for(var e,r,n=this.entries,o=av(t,"&"),i=0;i0?arguments[0]:void 0));u||(this.size=t.entries.length)},Ev=Sv.prototype;if(Mo(Ev,{append:function(t,e){var r=Wp(this);Up(arguments.length,2),rv(r.entries,{key:Wr(t),value:Wr(e)}),u||this.length++,r.updateURL()},delete:function(t){for(var e=Wp(this),r=Up(arguments.length,1),n=e.entries,o=Wr(t),i=r<2?void 0:arguments[1],a=void 0===i?i:Wr(i),s=0;se.key?1:-1}),t.updateURL()},forEach:function(t){for(var e,r=Wp(this).entries,n=ar(t,arguments.length>1?arguments[1]:void 0),o=0;o1?Rv(arguments[1]):{})}}),T($p)){var Pv=function(t){return ko(this,Gp),new $p(t,arguments.length>1?Rv(arguments[1]):{})};Gp.constructor=Pv,Pv.prototype=Gp,Ce({global:!0,constructor:!0,dontCallGetSet:!0,forced:!0},{Request:Pv})}}var Av={URLSearchParams:Sv,getState:Wp},jv=URLSearchParams,kv=jv.prototype,Iv=b(kv.append),Tv=b(kv.delete),Mv=b(kv.forEach),Lv=b([].push),Uv=new jv("a=1&a=2&b=3");Uv.delete("a",1),Uv.delete("b",void 0),Uv+""!="a=2"&&ie(kv,"delete",function(t){var e=arguments.length,r=e<2?void 0:arguments[1];if(e&&void 0===r)return Tv(this,t);var n=[];Mv(this,function(t,e){Lv(n,{key:e,value:t})}),Up(e,1);for(var o,i=Wr(t),a=Wr(r),u=0,s=0,c=!1,f=n.length;uo;)for(var s,c=R(arguments[o++]),l=i?$v(_e(c),i(c)):_e(c),h=l.length,p=0;h>p;)s=l[p++],u&&!f(a,c,s)||(r[s]=c[s]);return r}:qv,Gv=2147483647,Vv=/[^\0-\u007E]/,Yv=/[.\u3002\uFF0E\uFF61]/g,Xv="Overflow: input needs wider integers to process",Jv=RangeError,Qv=b(Yv.exec),Zv=Math.floor,td=String.fromCharCode,ed=b("".charCodeAt),rd=b([].join),nd=b([].push),od=b("".replace),id=b("".split),ad=b("".toLowerCase),ud=function(t){return t+22+75*(t<26)},sd=function(t,e,r){var n=0;for(t=r?Zv(t/700):t>>1,t+=Zv(t/e);t>455;)t=Zv(t/35),n+=36;return Zv(n+36*t/(t+38))},cd=function(t){var e=[];t=function(t){for(var e=[],r=0,n=t.length;r=55296&&o<=56319&&r=i&&nZv((Gv-a)/l))throw new Jv(Xv);for(a+=(f-i)*l,i=f,r=0;rGv)throw new Jv(Xv);if(n===i){for(var h=a,p=36;;){var v=p<=u?1:p>=u+26?26:p-u;if(h?@[\\\]^|]/,qd=/[\0\t\n\r #/:<>?@[\\\]^|]/,Hd=/^[\u0000-\u0020]+/,$d=/(^|[^\u0000-\u0020])[\u0000-\u0020]+$/,Kd=/[\t\n\r]/g,Gd=function(t){var e,r,n,o;if("number"==typeof t){for(e=[],r=0;r<4;r++)Td(e,t%256),t=md(t/256);return Ed(e,".")}if("object"==typeof t){for(e="",n=function(t){for(var e=null,r=1,n=null,o=0,i=0;i<8;i++)0!==t[i]?(o>r&&(e=n,r=o),n=null,o=0):(null===n&&(n=i),++o);return o>r?n:e}(t),r=0;r<8;r++)o&&0===t[r]||(o&&(o=!1),n===r?(e+=r?":":"::",o=!0):(e+=Od(t[r],16),r<7&&(e+=":")));return"["+e+"]"}return t},Vd={},Yd=Kv({},Vd,{" ":1,'"':1,"<":1,">":1,"`":1}),Xd=Kv({},Yd,{"#":1,"?":1,"{":1,"}":1}),Jd=Kv({},Xd,{"/":1,":":1,";":1,"=":1,"@":1,"[":1,"\\":1,"]":1,"^":1,"|":1}),Qd=function(t,e){var r=fd(t,0);return r>32&&r<127&&!ut(e,t)?t:encodeURIComponent(t)},Zd={ftp:21,file:null,http:80,https:443,ws:80,wss:443},tg=function(t,e){var r;return 2===t.length&&Sd(Nd,wd(t,0))&&(":"===(r=wd(t,1))||!e&&"|"===r)},eg=function(t){var e;return t.length>1&&tg(kd(t,0,2))&&(2===t.length||"/"===(e=wd(t,2))||"\\"===e||"?"===e||"#"===e)},rg=function(t){return"."===t||"%2e"===Id(t)},ng={},og={},ig={},ag={},ug={},sg={},cg={},fg={},lg={},hg={},pg={},vg={},dg={},gg={},yg={},mg={},bg={},wg={},Sg={},Eg={},Og={},xg=function(t,e,r){var n,o,i,a=Wr(t);if(e){if(o=this.parse(a))throw new gd(o);this.searchParams=null}else{if(void 0!==r&&(n=new xg(r,!0)),o=this.parse(a,null,n))throw new gd(o);(i=vd(new pd)).bindURL(this),this.searchParams=i}};xg.prototype={type:"URL",parse:function(t,e,r){var n,o,i,a,u,s=this,c=e||ng,f=0,l="",h=!1,p=!1,v=!1;for(t=Wr(t),e||(s.scheme="",s.username="",s.password="",s.host=null,s.port=null,s.path=[],s.query=null,s.fragment=null,s.cannotBeABaseURL=!1,t=Pd(t,Hd,""),t=Pd(t,$d,"$1")),t=Pd(t,Kd,""),n=Wn(t);f<=n.length;){switch(o=n[f],c){case ng:if(!o||!Sd(Nd,o)){if(e)return Md;c=ig;continue}l+=Id(o),c=og;break;case og:if(o&&(Sd(Cd,o)||"+"===o||"-"===o||"."===o))l+=Id(o);else{if(":"!==o){if(e)return Md;l="",c=ig,f=0;continue}if(e&&(s.isSpecial()!==ut(Zd,l)||"file"===l&&(s.includesCredentials()||null!==s.port)||"file"===s.scheme&&!s.host))return;if(s.scheme=l,e)return void(s.isSpecial()&&Zd[s.scheme]===s.port&&(s.port=null));l="","file"===s.scheme?c=gg:s.isSpecial()&&r&&r.scheme===s.scheme?c=ag:s.isSpecial()?c=fg:"/"===n[f+1]?(c=ug,f++):(s.cannotBeABaseURL=!0,Rd(s.path,""),c=Sg)}break;case ig:if(!r||r.cannotBeABaseURL&&"#"!==o)return Md;if(r.cannotBeABaseURL&&"#"===o){s.scheme=r.scheme,s.path=vo(r.path),s.query=r.query,s.fragment="",s.cannotBeABaseURL=!0,c=Og;break}c="file"===r.scheme?gg:sg;continue;case ag:if("/"!==o||"/"!==n[f+1]){c=sg;continue}c=lg,f++;break;case ug:if("/"===o){c=hg;break}c=wg;continue;case sg:if(s.scheme=r.scheme,o===Wv)s.username=r.username,s.password=r.password,s.host=r.host,s.port=r.port,s.path=vo(r.path),s.query=r.query;else if("/"===o||"\\"===o&&s.isSpecial())c=cg;else if("?"===o)s.username=r.username,s.password=r.password,s.host=r.host,s.port=r.port,s.path=vo(r.path),s.query="",c=Eg;else{if("#"!==o){s.username=r.username,s.password=r.password,s.host=r.host,s.port=r.port,s.path=vo(r.path),s.path.length--,c=wg;continue}s.username=r.username,s.password=r.password,s.host=r.host,s.port=r.port,s.path=vo(r.path),s.query=r.query,s.fragment="",c=Og}break;case cg:if(!s.isSpecial()||"/"!==o&&"\\"!==o){if("/"!==o){s.username=r.username,s.password=r.password,s.host=r.host,s.port=r.port,c=wg;continue}c=hg}else c=lg;break;case fg:if(c=lg,"/"!==o||"/"!==wd(l,f+1))continue;f++;break;case lg:if("/"!==o&&"\\"!==o){c=hg;continue}break;case hg:if("@"===o){h&&(l="%40"+l),h=!0,i=Wn(l);for(var d=0;d65535)return Ud;s.port=s.isSpecial()&&m===Zd[s.scheme]?null:m,l=""}if(e)return;c=bg;continue}return Ud}l+=o;break;case gg:if(s.scheme="file","/"===o||"\\"===o)c=yg;else{if(!r||"file"!==r.scheme){c=wg;continue}switch(o){case Wv:s.host=r.host,s.path=vo(r.path),s.query=r.query;break;case"?":s.host=r.host,s.path=vo(r.path),s.query="",c=Eg;break;case"#":s.host=r.host,s.path=vo(r.path),s.query=r.query,s.fragment="",c=Og;break;default:eg(Ed(vo(n,f),""))||(s.host=r.host,s.path=vo(r.path),s.shortenPath()),c=wg;continue}}break;case yg:if("/"===o||"\\"===o){c=mg;break}r&&"file"===r.scheme&&!eg(Ed(vo(n,f),""))&&(tg(r.path[0],!0)?Rd(s.path,r.path[0]):s.host=r.host),c=wg;continue;case mg:if(o===Wv||"/"===o||"\\"===o||"?"===o||"#"===o){if(!e&&tg(l))c=wg;else if(""===l){if(s.host="",e)return;c=bg}else{if(a=s.parseHost(l))return a;if("localhost"===s.host&&(s.host=""),e)return;l="",c=bg}continue}l+=o;break;case bg:if(s.isSpecial()){if(c=wg,"/"!==o&&"\\"!==o)continue}else if(e||"?"!==o)if(e||"#"!==o){if(o!==Wv&&(c=wg,"/"!==o))continue}else s.fragment="",c=Og;else s.query="",c=Eg;break;case wg:if(o===Wv||"/"===o||"\\"===o&&s.isSpecial()||!e&&("?"===o||"#"===o)){if(".."===(u=Id(u=l))||"%2e."===u||".%2e"===u||"%2e%2e"===u?(s.shortenPath(),"/"===o||"\\"===o&&s.isSpecial()||Rd(s.path,"")):rg(l)?"/"===o||"\\"===o&&s.isSpecial()||Rd(s.path,""):("file"===s.scheme&&!s.path.length&&tg(l)&&(s.host&&(s.host=""),l=wd(l,0)+":"),Rd(s.path,l)),l="","file"===s.scheme&&(o===Wv||"?"===o||"#"===o))for(;s.path.length>1&&""===s.path[0];)Ad(s.path);"?"===o?(s.query="",c=Eg):"#"===o&&(s.fragment="",c=Og)}else l+=Qd(o,Xd);break;case Sg:"?"===o?(s.query="",c=Eg):"#"===o?(s.fragment="",c=Og):o!==Wv&&(s.path[0]+=Qd(o,Vd));break;case Eg:e||"#"!==o?o!==Wv&&("'"===o&&s.isSpecial()?s.query+="%27":s.query+="#"===o?"%23":Qd(o,Vd)):(s.fragment="",c=Og);break;case Og:o!==Wv&&(s.fragment+=Qd(o,Yd))}f++}},parseHost:function(t){var e,r,n;if("["===wd(t,0)){if("]"!==wd(t,t.length-1))return Ld;if(e=function(t){var e,r,n,o,i,a,u,s=[0,0,0,0,0,0,0,0],c=0,f=null,l=0,h=function(){return wd(t,l)};if(":"===h()){if(":"!==wd(t,1))return;l+=2,f=++c}for(;h();){if(8===c)return;if(":"!==h()){for(e=r=0;r<4&&Sd(zd,h());)e=16*e+yd(h(),16),l++,r++;if("."===h()){if(0===r)return;if(l-=r,c>6)return;for(n=0;h();){if(o=null,n>0){if(!("."===h()&&n<4))return;l++}if(!Sd(_d,h()))return;for(;Sd(_d,h());){if(i=yd(h(),10),null===o)o=i;else{if(0===o)return;o=10*o+i}if(o>255)return;l++}s[c]=256*s[c]+o,2!=++n&&4!==n||c++}if(4!==n)return;break}if(":"===h()){if(l++,!h())return}else if(h())return;s[c++]=e}else{if(null!==f)return;l++,f=++c}}if(null!==f)for(a=c-f,c=7;0!==c&&a>0;)u=s[c],s[c--]=s[f+a-1],s[f+--a]=u;else if(8!==c)return;return s}(kd(t,1,-1)),!e)return Ld;this.host=e}else if(this.isSpecial()){if(t=function(t){var e,r,n=[],o=id(od(ad(t),Yv,"."),".");for(e=0;e4)return t;for(r=[],n=0;n1&&"0"===wd(o,0)&&(i=Sd(Fd,o)?16:8,o=kd(o,8===i?1:2)),""===o)a=0;else{if(!Sd(10===i?Dd:8===i?Bd:zd,o))return t;a=yd(o,i)}Rd(r,a)}for(n=0;n=bd(256,5-e))return null}else if(a>255)return null;for(u=xd(r),n=0;n1?arguments[1]:void 0,n=ld(e,new xg(t,!1,r));u||(e.href=n.serialize(),e.origin=n.getOrigin(),e.protocol=n.getProtocol(),e.username=n.getUsername(),e.password=n.getPassword(),e.host=n.getHost(),e.hostname=n.getHostname(),e.port=n.getPort(),e.pathname=n.getPathname(),e.search=n.getSearch(),e.searchParams=n.getSearchParams(),e.hash=n.getHash())},Pg=Rg.prototype,Ag=function(t,e){return{get:function(){return hd(this)[t]()},set:e&&function(t){return hd(this)[e](t)},configurable:!0,enumerable:!0}};if(u&&(so(Pg,"href",Ag("serialize","setHref")),so(Pg,"origin",Ag("getOrigin")),so(Pg,"protocol",Ag("getProtocol","setProtocol")),so(Pg,"username",Ag("getUsername","setUsername")),so(Pg,"password",Ag("getPassword","setPassword")),so(Pg,"host",Ag("getHost","setHost")),so(Pg,"hostname",Ag("getHostname","setHostname")),so(Pg,"port",Ag("getPort","setPort")),so(Pg,"pathname",Ag("getPathname","setPathname")),so(Pg,"search",Ag("getSearch","setSearch")),so(Pg,"searchParams",Ag("getSearchParams")),so(Pg,"hash",Ag("getHash","setHash"))),ie(Pg,"toJSON",function(){return hd(this).serialize()},{enumerable:!0}),ie(Pg,"toString",function(){return hd(this).serialize()},{enumerable:!0}),dd){var jg=dd.createObjectURL,kg=dd.revokeObjectURL;jg&&ie(Rg,"createObjectURL",ar(jg,dd)),kg&&ie(Rg,"revokeObjectURL",ar(kg,dd))}an(Rg,"URL"),Ce({global:!0,constructor:!0,forced:!Mp,sham:!u},{URL:Rg});var Ig=L("URL"),Tg=Mp&&a(function(){Ig.canParse()}),Mg=a(function(){return 1!==Ig.canParse.length});Ce({target:"URL",stat:!0,forced:!Tg||Mg},{canParse:function(t){var e=Up(arguments.length,1),r=Wr(t),n=e<2||void 0===arguments[1]?void 0:Wr(arguments[1]);try{return!!new Ig(r,n)}catch(t){return!1}}});var Lg=L("URL");Ce({target:"URL",stat:!0,forced:!Mp},{parse:function(t){var e=Up(arguments.length,1),r=Wr(t),n=e<2||void 0===arguments[1]?void 0:Wr(arguments[1]);try{return new Lg(r,n)}catch(t){return null}}}),Ce({target:"URL",proto:!0,enumerable:!0},{toJSON:function(){return f(URL.prototype.toString,this)}});var Ug=WeakMap.prototype,Ng={WeakMap:WeakMap,set:b(Ug.set),get:b(Ug.get),has:b(Ug.has),remove:b(Ug.delete)},Cg=Ng.has,_g=function(t){return Cg(t),t},Fg=Ng.get,Bg=Ng.has,Dg=Ng.set;Ce({target:"WeakMap",proto:!0,real:!0,forced:!0},{emplace:function(t,e){var r,n,o=_g(this);return Bg(o,t)?(r=Fg(o,t),"update"in e&&(r=e.update(r,t,o),Dg(o,t,r)),r):(n=e.insert(t,o),Dg(o,t,n),n)}}),Ce({target:"WeakMap",stat:!0,forced:!0},{from:ei(Ng.WeakMap,Ng.set,!0)}),Ce({target:"WeakMap",stat:!0,forced:!0},{of:ri(Ng.WeakMap,Ng.set,!0)});var zg=Ng.remove;Ce({target:"WeakMap",proto:!0,real:!0,forced:!0},{deleteAll:function(){for(var t,e=_g(this),r=!0,n=0,o=arguments.length;n2&&(n=r,M(o=arguments[2])&&"cause"in o&&_t(n,"cause",o.cause));var s=[];return Ao(t,ny,{that:s}),_t(r,"errors",s),r};dn?dn(oy,ry):Ae(oy,ry,{name:!0});var iy=oy.prototype=Ve(ry.prototype,{constructor:d(1,oy),message:d(1,""),name:d(1,"AggregateError")});Ce({global:!0,constructor:!0,arity:2},{AggregateError:oy});var ay,uy,sy,cy,fy=function(t){return _.slice(0,t.length)===t},ly=fy("Bun/")?"BUN":fy("Cloudflare-Workers")?"CLOUDFLARE":fy("Deno/")?"DENO":fy("Node.js/")?"NODE":i.Bun&&"string"==typeof Bun.version?"BUN":i.Deno&&"object"==typeof Deno.version?"DENO":"process"===E(i.process)?"NODE":i.window&&i.document?"BROWSER":"REST",hy="NODE"===ly,py=/(?:ipad|iphone|ipod).*applewebkit/i.test(_),vy=i.setImmediate,dy=i.clearImmediate,gy=i.process,yy=i.Dispatch,my=i.Function,by=i.MessageChannel,wy=i.String,Sy=0,Ey={},Oy="onreadystatechange";a(function(){ay=i.location});var xy=function(t){if(ut(Ey,t)){var e=Ey[t];delete Ey[t],e()}},Ry=function(t){return function(){xy(t)}},Py=function(t){xy(t.data)},Ay=function(t){i.postMessage(wy(t),ay.protocol+"//"+ay.host)};vy&&dy||(vy=function(t){Up(arguments.length,1);var e=T(t)?t:my(t),r=vo(arguments,1);return Ey[++Sy]=function(){Ra(e,void 0,r)},uy(Sy),Sy},dy=function(t){delete Ey[t]},hy?uy=function(t){gy.nextTick(Ry(t))}:yy&&yy.now?uy=function(t){yy.now(Ry(t))}:by&&!py?(cy=(sy=new by).port2,sy.port1.onmessage=Py,uy=ar(cy.postMessage,cy)):i.addEventListener&&T(i.postMessage)&&!i.importScripts&&ay&&"file:"!==ay.protocol&&!a(Ay)?(uy=Ay,i.addEventListener("message",Py,!1)):uy=Oy in Et("script")?function(t){De.appendChild(Et("script"))[Oy]=function(){De.removeChild(this),xy(t)}}:function(t){setTimeout(Ry(t),0)});var jy={set:vy,clear:dy},ky=function(){this.head=null,this.tail=null};ky.prototype={add:function(t){var e={item:t,next:null},r=this.tail;r?r.next=e:this.head=e,this.tail=e},get:function(){var t=this.head;if(t)return null===(this.head=t.next)&&(this.tail=null),t.item}};var Iy,Ty,My,Ly,Uy,Ny=ky,Cy=/ipad|iphone|ipod/i.test(_)&&"undefined"!=typeof Pebble,_y=/web0s(?!.*chrome)/i.test(_),Fy=jy.set,By=i.MutationObserver||i.WebKitMutationObserver,Dy=i.document,zy=i.process,Wy=i.Promise,qy=Ip("queueMicrotask");if(!qy){var Hy=new Ny,$y=function(){var t,e;for(hy&&(t=zy.domain)&&t.exit();e=Hy.get();)try{e()}catch(t){throw Hy.head&&Iy(),t}t&&t.enter()};py||hy||_y||!By||!Dy?!Cy&&Wy&&Wy.resolve?((Ly=Wy.resolve(void 0)).constructor=Wy,Uy=ar(Ly.then,Ly),Iy=function(){Uy($y)}):hy?Iy=function(){zy.nextTick($y)}:(Fy=ar(Fy,i),Iy=function(){Fy($y)}):(Ty=!0,My=Dy.createTextNode(""),new By($y).observe(My,{characterData:!0}),Iy=function(){My.data=Ty=!Ty}),qy=function(t){Hy.head||Iy(),Hy.add(t)}}var Ky,Gy,Vy,Yy=qy,Xy=function(t){try{return{error:!1,value:t()}}catch(t){return{error:!0,value:t}}},Jy=i.Promise,Qy=dt("species"),Zy=!1,tm=T(i.PromiseRejectionEvent),em=Ue("Promise",function(){var t=Kt(Jy),e=t!==String(Jy);if(!e&&66===W)return!0;if(!W||W<51||!/native code/.test(t)){var r=new Jy(function(t){t(1)}),n=function(t){t(function(){},function(){})};if((r.constructor={})[Qy]=n,!(Zy=r.then(function(){})instanceof n))return!0}return!(e||"BROWSER"!==ly&&"DENO"!==ly||tm)}),rm={CONSTRUCTOR:em,REJECTION_EVENT:tm,SUBCLASSING:Zy},nm=TypeError,om=function(t){var e,r;this.promise=new t(function(t,n){if(void 0!==e||void 0!==r)throw new nm("Bad Promise constructor");e=t,r=n}),this.resolve=J(e),this.reject=J(r)},im={f:function(t){return new om(t)}},am=jy.set,um="Promise",sm=rm.CONSTRUCTOR,cm=rm.REJECTION_EVENT,fm=rm.SUBCLASSING,lm=ne.getterFor(um),hm=ne.set,pm=Jy&&Jy.prototype,vm=Jy,dm=pm,gm=i.TypeError,ym=i.document,mm=i.process,bm=im.f,wm=bm,Sm=!!(ym&&ym.createEvent&&i.dispatchEvent),Em="unhandledrejection",Om=function(t){var e;return!(!M(t)||!T(e=t.then))&&e},xm=function(t,e){var r,n,o,i=e.value,a=1===e.state,u=a?t.ok:t.fail,s=t.resolve,c=t.reject,l=t.domain;try{u?(a||(2===e.rejection&&km(e),e.rejection=1),!0===u?r=i:(l&&l.enter(),r=u(i),l&&(l.exit(),o=!0)),r===t.promise?c(new gm("Promise-chain cycle")):(n=Om(r))?f(n,r,s,c):s(r)):c(i)}catch(t){l&&!o&&l.exit(),c(t)}},Rm=function(t,e){t.notified||(t.notified=!0,Yy(function(){for(var r,n=t.reactions;r=n.get();)xm(r,t);t.notified=!1,e&&!t.rejection&&Am(t)}))},Pm=function(t,e,r){var n,o;Sm?((n=ym.createEvent("Event")).promise=e,n.reason=r,n.initEvent(t,!1,!0),i.dispatchEvent(n)):n={promise:e,reason:r},!cm&&(o=i["on"+t])?o(n):t===Em&&function(t,e){try{1===arguments.length?console.error(t):console.error(t,e)}catch(t){}}("Unhandled promise rejection",r)},Am=function(t){f(am,i,function(){var e,r=t.facade,n=t.value;if(jm(t)&&(e=Xy(function(){hy?mm.emit("unhandledRejection",n,r):Pm(Em,r,n)}),t.rejection=hy||jm(t)?2:1,e.error))throw e.value})},jm=function(t){return 1!==t.rejection&&!t.parent},km=function(t){f(am,i,function(){var e=t.facade;hy?mm.emit("rejectionHandled",e):Pm("rejectionhandled",e,t.value)})},Im=function(t,e,r){return function(n){t(e,n,r)}},Tm=function(t,e,r){t.done||(t.done=!0,r&&(t=r),t.value=e,t.state=2,Rm(t,!0))},Mm=function(t,e,r){if(!t.done){t.done=!0,r&&(t=r);try{if(t.facade===e)throw new gm("Promise can't be resolved itself");var n=Om(e);n?Yy(function(){var r={done:!1};try{f(n,e,Im(Mm,r,t),Im(Tm,r,t))}catch(e){Tm(r,e,t)}}):(t.value=e,t.state=1,Rm(t,!1))}catch(e){Tm({done:!1},e,t)}}};if(sm&&(vm=function(t){ko(this,dm),J(t),f(Ky,this);var e=lm(this);try{t(Im(Mm,e),Im(Tm,e))}catch(t){Tm(e,t)}},(Ky=function(t){hm(this,{type:um,done:!1,notified:!1,parent:!1,reactions:new Ny,rejection:!1,state:0,value:null})}).prototype=ie(dm=vm.prototype,"then",function(t,e){var r=lm(this),n=bm(Cc(this,vm));return r.parent=!0,n.ok=!T(t)||t,n.fail=T(e)&&e,n.domain=hy?mm.domain:void 0,0===r.state?r.reactions.add(n):Yy(function(){xm(n,r)}),n.promise}),Gy=function(){var t=new Ky,e=lm(t);this.promise=t,this.resolve=Im(Mm,e),this.reject=Im(Tm,e)},im.f=bm=function(t){return t===vm||void 0===t?new Gy(t):wm(t)},T(Jy)&&pm!==Object.prototype)){Vy=pm.then,fm||ie(pm,"then",function(t,e){var r=this;return new vm(function(t,e){f(Vy,r,t,e)}).then(t,e)},{unsafe:!0});try{delete pm.constructor}catch(t){}dn&&dn(pm,dm)}Ce({global:!0,constructor:!0,wrap:!0,forced:sm},{Promise:vm}),an(vm,um,!1),Uo(um);var Lm=rm.CONSTRUCTOR||!Gn(function(t){Jy.all(t).then(void 0,function(){})});Ce({target:"Promise",stat:!0,forced:Lm},{all:function(t){var e=this,r=im.f(e),n=r.resolve,o=r.reject,i=Xy(function(){var r=J(e.resolve),i=[],a=0,u=1;Ao(t,function(t){var s=a++,c=!1;u++,f(r,e,t).then(function(t){c||(c=!0,i[s]=t,--u||n(i))},o)}),--u||n(i)});return i.error&&o(i.value),r.promise}});var Um=Jy&&Jy.prototype;if(Ce({target:"Promise",proto:!0,forced:rm.CONSTRUCTOR,real:!0},{catch:function(t){return this.then(void 0,t)}}),T(Jy)){var Nm=L("Promise").prototype.catch;Um.catch!==Nm&&ie(Um,"catch",Nm,{unsafe:!0})}Ce({target:"Promise",stat:!0,forced:Lm},{race:function(t){var e=this,r=im.f(e),n=r.reject,o=Xy(function(){var o=J(e.resolve);Ao(t,function(t){f(o,e,t).then(r.resolve,n)})});return o.error&&n(o.value),r.promise}}),Ce({target:"Promise",stat:!0,forced:rm.CONSTRUCTOR},{reject:function(t){var e=im.f(this);return(0,e.reject)(t),e.promise}});var Cm=function(t,e){if(kt(t),M(e)&&e.constructor===t)return e;var r=im.f(t);return(0,r.resolve)(e),r.promise};Ce({target:"Promise",stat:!0,forced:rm.CONSTRUCTOR},{resolve:function(t){return Cm(this,t)}}),Ce({target:"Promise",stat:!0,forced:Lm},{allSettled:function(t){var e=this,r=im.f(e),n=r.resolve,o=r.reject,i=Xy(function(){var r=J(e.resolve),o=[],i=0,a=1;Ao(t,function(t){var u=i++,s=!1;a++,f(r,e,t).then(function(t){s||(s=!0,o[u]={status:"fulfilled",value:t},--a||n(o))},function(t){s||(s=!0,o[u]={status:"rejected",reason:t},--a||n(o))})}),--a||n(o)});return i.error&&o(i.value),r.promise}});var _m="No one promise resolved";Ce({target:"Promise",stat:!0,forced:Lm},{any:function(t){var e=this,r=L("AggregateError"),n=im.f(e),o=n.resolve,i=n.reject,a=Xy(function(){var n=J(e.resolve),a=[],u=0,s=1,c=!1;Ao(t,function(t){var l=u++,h=!1;s++,f(n,e,t).then(function(t){h||c||(c=!0,o(t))},function(t){h||c||(h=!0,a[l]=t,--s||i(new r(a,_m)))})}),--s||i(new r(a,_m))});return a.error&&i(a.value),n.promise}}),Ce({target:"Promise",stat:!0},{withResolvers:function(){var t=im.f(this);return{promise:t.promise,resolve:t.resolve,reject:t.reject}}});var Fm=Jy&&Jy.prototype,Bm=!!Jy&&a(function(){Fm.finally.call({then:function(){}},function(){})});if(Ce({target:"Promise",proto:!0,real:!0,forced:Bm},{finally:function(t){var e=Cc(this,L("Promise")),r=T(t);return this.then(r?function(r){return Cm(e,t()).then(function(){return r})}:t,r?function(r){return Cm(e,t()).then(function(){throw r})}:t)}}),T(Jy)){var Dm=L("Promise").prototype.finally;Fm.finally!==Dm&&ie(Fm,"finally",Dm,{unsafe:!0})}var zm=i.Promise,Wm=!1,qm=!zm||!zm.try||Xy(function(){zm.try(function(t){Wm=8===t},8)}).error||!Wm;Ce({target:"Promise",stat:!0,forced:qm},{try:function(t){var e=arguments.length>1?vo(arguments,1):[],r=im.f(this),n=Xy(function(){return Ra(J(t),void 0,e)});return(n.error?r.reject:r.resolve)(n.value),r.promise}}),Ze("Promise","finally");var Hm="URLSearchParams"in self,$m="Symbol"in self&&"iterator"in Symbol,Km="FileReader"in self&&"Blob"in self&&function(){try{return new Blob,!0}catch(t){return!1}}(),Gm="FormData"in self,Vm="ArrayBuffer"in self;if(Vm)var Ym=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],Xm=ArrayBuffer.isView||function(t){return t&&Ym.indexOf(Object.prototype.toString.call(t))>-1};function Jm(t){if("string"!=typeof t&&(t=String(t)),/[^a-z0-9\-#$%&'*+.^_`|~]/i.test(t))throw new TypeError("Invalid character in header field name");return t.toLowerCase()}function Qm(t){return"string"!=typeof t&&(t=String(t)),t}function Zm(t){var e={next:function(){var e=t.shift();return{done:void 0===e,value:e}}};return $m&&(e[Symbol.iterator]=function(){return e}),e}function tb(t){this.map={},t instanceof tb?t.forEach(function(t,e){this.append(e,t)},this):Array.isArray(t)?t.forEach(function(t){this.append(t[0],t[1])},this):t&&Object.getOwnPropertyNames(t).forEach(function(e){this.append(e,t[e])},this)}function eb(t){if(t.bodyUsed)return Promise.reject(new TypeError("Already read"));t.bodyUsed=!0}function rb(t){return new Promise(function(e,r){t.onload=function(){e(t.result)},t.onerror=function(){r(t.error)}})}function nb(t){var e=new FileReader,r=rb(e);return e.readAsArrayBuffer(t),r}function ob(t){if(t.slice)return t.slice(0);var e=new Uint8Array(t.byteLength);return e.set(new Uint8Array(t)),e.buffer}function ib(){return this.bodyUsed=!1,this._initBody=function(t){var e;this._bodyInit=t,t?"string"==typeof t?this._bodyText=t:Km&&Blob.prototype.isPrototypeOf(t)?this._bodyBlob=t:Gm&&FormData.prototype.isPrototypeOf(t)?this._bodyFormData=t:Hm&&URLSearchParams.prototype.isPrototypeOf(t)?this._bodyText=t.toString():Vm&&Km&&(e=t)&&DataView.prototype.isPrototypeOf(e)?(this._bodyArrayBuffer=ob(t.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer])):Vm&&(ArrayBuffer.prototype.isPrototypeOf(t)||Xm(t))?this._bodyArrayBuffer=ob(t):this._bodyText=t=Object.prototype.toString.call(t):this._bodyText="",this.headers.get("content-type")||("string"==typeof t?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):Hm&&URLSearchParams.prototype.isPrototypeOf(t)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},Km&&(this.blob=function(){var t=eb(this);if(t)return t;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?eb(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(nb)}),this.text=function(){var t=eb(this);if(t)return t;if(this._bodyBlob)return function(t){var e=new FileReader,r=rb(e);return e.readAsText(t),r}(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(function(t){for(var e=new Uint8Array(t),r=new Array(e.length),n=0;n-1?e:t}(e.method||this.method||"GET"),this.mode=e.mode||this.mode||null,this.signal=e.signal||this.signal,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&r)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(r)}function sb(t){var e=new FormData;return t.trim().split("&").forEach(function(t){if(t){var r=t.split("="),n=r.shift().replace(/\+/g," "),o=r.join("=").replace(/\+/g," ");e.append(decodeURIComponent(n),decodeURIComponent(o))}}),e}function cb(t,e){e||(e={}),this.type="default",this.status=void 0===e.status?200:e.status,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in e?e.statusText:"OK",this.headers=new tb(e.headers),this.url=e.url||"",this._initBody(t)}ub.prototype.clone=function(){return new ub(this,{body:this._bodyInit})},ib.call(ub.prototype),ib.call(cb.prototype),cb.prototype.clone=function(){return new cb(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new tb(this.headers),url:this.url})},cb.error=function(){var t=new cb(null,{status:0,statusText:""});return t.type="error",t};var fb=[301,302,303,307,308];cb.redirect=function(t,e){if(-1===fb.indexOf(e))throw new RangeError("Invalid status code");return new cb(null,{status:e,headers:{location:t}})};var lb=self.DOMException;try{new lb}catch(t){(lb=function(t,e){this.message=t,this.name=e;var r=Error(t);this.stack=r.stack}).prototype=Object.create(Error.prototype),lb.prototype.constructor=lb}function hb(t,e){return new Promise(function(r,n){var o=new ub(t,e);if(o.signal&&o.signal.aborted)return n(new lb("Aborted","AbortError"));var i=new XMLHttpRequest;function a(){i.abort()}i.onload=function(){var t,e,n={status:i.status,statusText:i.statusText,headers:(t=i.getAllResponseHeaders()||"",e=new tb,t.replace(/\r?\n[\t ]+/g," ").split(/\r?\n/).forEach(function(t){var r=t.split(":"),n=r.shift().trim();if(n){var o=r.join(":").trim();e.append(n,o)}}),e)};n.url="responseURL"in i?i.responseURL:n.headers.get("X-Request-URL"),r(new cb("response"in i?i.response:i.responseText,n))},i.onerror=function(){n(new TypeError("Network request failed"))},i.ontimeout=function(){n(new TypeError("Network request failed"))},i.onabort=function(){n(new lb("Aborted","AbortError"))},i.open(o.method,o.url,!0),"include"===o.credentials?i.withCredentials=!0:"omit"===o.credentials&&(i.withCredentials=!1),"responseType"in i&&Km&&(i.responseType="blob"),o.headers.forEach(function(t,e){i.setRequestHeader(e,t)}),o.signal&&(o.signal.addEventListener("abort",a),i.onreadystatechange=function(){4===i.readyState&&o.signal.removeEventListener("abort",a)}),i.send(void 0===o._bodyInit?null:o._bodyInit)})}hb.polyfill=!0,self.fetch||(self.fetch=hb,self.Headers=tb,self.Request=ub,self.Response=cb);var pb=Object.getOwnPropertySymbols,vb=Object.prototype.hasOwnProperty,db=Object.prototype.propertyIsEnumerable,gb=function(){try{if(!Object.assign)return!1;var t=new String("abc");if(t[5]="de","5"===Object.getOwnPropertyNames(t)[0])return!1;for(var e={},r=0;r<10;r++)e["_"+String.fromCharCode(r)]=r;if("0123456789"!==Object.getOwnPropertyNames(e).map(function(t){return e[t]}).join(""))return!1;var n={};return"abcdefghijklmnopqrst".split("").forEach(function(t){n[t]=t}),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},n)).join("")}catch(t){return!1}}()?Object.assign:function(t,e){for(var r,n,o=function(t){if(null==t)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(t)}(t),i=1;i{t.v(e=>Promise.all(["static/chunks/3686d57edf1023fb.js"].map(e=>t.l(e))).then(()=>e(54214)))}]); \ No newline at end of file diff --git a/src/hyperview/server/static/_next/static/chunks/d6d93a0a04227147.css b/src/hyperview/server/static/_next/static/chunks/d6d93a0a04227147.css new file mode 100644 index 0000000000000000000000000000000000000000..daf1c3bece25158d11ea279e678bf97c5654e985 --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/d6d93a0a04227147.css @@ -0,0 +1 @@ +*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border:0 solid #e5e7eb}:before,:after{--tw-content:""}html,:host{-webkit-text-size-adjust:100%;tab-size:4;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}body{line-height:inherit;margin:0}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-feature-settings:normal;font-variation-settings:normal;font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-feature-settings:inherit;font-variation-settings:inherit;font-family:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:#0000;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{margin:0;padding:0;list-style:none}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder{opacity:1;color:#9ca3af}textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}:root{--background:215 28% 7%;--foreground:213 27% 92%;--card:215 21% 11%;--card-foreground:213 27% 92%;--popover:215 21% 11%;--popover-foreground:213 27% 92%;--primary:212 100% 67%;--primary-foreground:215 28% 7%;--secondary:215 14% 17%;--secondary-foreground:213 27% 92%;--muted:215 14% 17%;--muted-foreground:213 12% 58%;--accent:215 14% 17%;--accent-foreground:213 27% 92%;--destructive:0 62% 50%;--destructive-foreground:0 0% 98%;--border:215 14% 22%;--input:215 14% 22%;--ring:212 100% 67%;--radius:.375rem;--surface:215 21% 11%;--surface-light:215 14% 17%;--surface-elevated:215 14% 22%;--border-subtle:215 14% 17%;--text:213 27% 92%;--text-muted:213 12% 58%;--text-subtle:215 10% 46%;--accent-cyan:176 60% 53%;--accent-orange:27 86% 59%}*{border-color:hsl(var(--border))}body{background-color:hsl(var(--background));color:hsl(var(--foreground));-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.\!container{width:100%!important}.container{width:100%}@media (min-width:640px){.\!container{max-width:640px!important}.container{max-width:640px}}@media (min-width:768px){.\!container{max-width:768px!important}.container{max-width:768px}}@media (min-width:1024px){.\!container{max-width:1024px!important}.container{max-width:1024px}}@media (min-width:1280px){.\!container{max-width:1280px!important}.container{max-width:1280px}}@media (min-width:1536px){.\!container{max-width:1536px!important}.container{max-width:1536px}}.pointer-events-none{pointer-events:none}.visible{visibility:visible}.absolute{position:absolute}.relative{position:relative}.inset-0{inset:0}.bottom-1{bottom:.25rem}.left-1{left:.25rem}.right-1{right:.25rem}.top-1{top:.25rem}.z-10{z-index:10}.mx-auto{margin-left:auto;margin-right:auto}.mb-2{margin-bottom:.5rem}.mb-4{margin-bottom:1rem}.mt-4{margin-top:1rem}.inline-block{display:inline-block}.inline{display:inline}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.hidden{display:none}.h-10{height:2.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-3\.5{height:.875rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-9{height:2.25rem}.h-full{height:100%}.h-screen{height:100vh}.min-h-\[36px\]{min-height:36px}.min-h-\[40px\]{min-height:40px}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-3\.5{width:.875rem}.w-36{width:9rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-9{width:2.25rem}.w-\[3px\]{width:3px}.w-full{width:100%}.min-w-0{min-width:0}.min-w-10{min-width:2.5rem}.min-w-8{min-width:2rem}.min-w-9{min-width:2.25rem}.max-w-full{max-width:100%}.max-w-md{max-width:28rem}.flex-1{flex:1}.flex-shrink-0{flex-shrink:0}.transform{transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}@keyframes spin{to{transform:rotate(360deg)}}.animate-spin{animation:1s linear infinite spin}.cursor-pointer{cursor:pointer}.select-none{-webkit-user-select:none;user-select:none}.resize{resize:both}.flex-col{flex-direction:column}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-0\.5{gap:.125rem}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse:0;margin-top:calc(.25rem*calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem*var(--tw-space-y-reverse))}.overflow-auto{overflow:auto}.overflow-hidden{overflow:hidden}.overflow-y-auto{overflow-y:auto}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.whitespace-nowrap{white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-sm{border-radius:calc(var(--radius) - 4px)}.border{border-width:1px}.border-0{border-width:0}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-l{border-left-width:1px}.border-t{border-top-width:1px}.border-border{border-color:hsl(var(--border))}.border-input{border-color:hsl(var(--input))}.border-primary{border-color:hsl(var(--primary))}.border-t-transparent{border-top-color:#0000}.bg-background{background-color:hsl(var(--background))}.bg-border\/50{background-color:hsl(var(--border)/.5)}.bg-card{background-color:hsl(var(--card))}.bg-card\/80{background-color:hsl(var(--card)/.8)}.bg-card\/85{background-color:hsl(var(--card)/.85)}.bg-destructive{background-color:hsl(var(--destructive))}.bg-muted{background-color:hsl(var(--muted))}.bg-muted\/50{background-color:hsl(var(--muted)/.5)}.bg-primary{background-color:hsl(var(--primary))}.bg-secondary{background-color:hsl(var(--secondary))}.bg-transparent{background-color:#0000}.object-cover{-o-object-fit:cover;object-fit:cover}.p-0\.5{padding:.125rem}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-6{padding:1.5rem}.px-1{padding-left:.25rem;padding-right:.25rem}.px-1\.5{padding-left:.375rem;padding-right:.375rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-2\.5{padding-left:.625rem;padding-right:.625rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-8{padding-left:2rem;padding-right:2rem}.py-0\.5{padding-top:.125rem;padding-bottom:.125rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-\[11px\]{font-size:11px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xs{font-size:.75rem;line-height:1rem}.font-medium{font-weight:500}.font-semibold{font-weight:600}.uppercase{text-transform:uppercase}.tracking-wide{letter-spacing:.025em}.text-destructive{color:hsl(var(--destructive))}.text-destructive-foreground{color:hsl(var(--destructive-foreground))}.text-foreground{color:hsl(var(--foreground))}.text-muted-foreground{color:hsl(var(--muted-foreground))}.text-muted-foreground\/70{color:hsl(var(--muted-foreground)/.7)}.text-primary{color:hsl(var(--primary))}.text-primary-foreground{color:hsl(var(--primary-foreground))}.text-secondary-foreground{color:hsl(var(--secondary-foreground))}.text-white{--tw-text-opacity:1;color:rgb(255 255 255/var(--tw-text-opacity,1))}.underline-offset-4{text-underline-offset:4px}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.shadow{--tw-shadow:0 1px 3px 0 #0000001a,0 1px 2px -1px #0000001a;--tw-shadow-colored:0 1px 3px 0 var(--tw-shadow-color),0 1px 2px -1px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.outline{outline-style:solid}.ring-2{--tw-ring-offset-shadow:var(--tw-ring-inset)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.ring-primary{--tw-ring-color:hsl(var(--primary))}.ring-primary\/50{--tw-ring-color:hsl(var(--primary)/.5)}.filter{filter:var(--tw-blur)var(--tw-brightness)var(--tw-contrast)var(--tw-grayscale)var(--tw-hue-rotate)var(--tw-invert)var(--tw-saturate)var(--tw-sepia)var(--tw-drop-shadow)}.transition-all{transition-property:all;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-duration:.15s;transition-timing-function:cubic-bezier(.4,0,.2,1)}.duration-150{transition-duration:.15s}.ease-out{transition-timing-function:cubic-bezier(0,0,.2,1)}@keyframes enter{0%{opacity:var(--tw-enter-opacity,1);transform:translate3d(var(--tw-enter-translate-x,0),var(--tw-enter-translate-y,0),0)scale3d(var(--tw-enter-scale,1),var(--tw-enter-scale,1),var(--tw-enter-scale,1))rotate(var(--tw-enter-rotate,0))}}@keyframes exit{to{opacity:var(--tw-exit-opacity,1);transform:translate3d(var(--tw-exit-translate-x,0),var(--tw-exit-translate-y,0),0)scale3d(var(--tw-exit-scale,1),var(--tw-exit-scale,1),var(--tw-exit-scale,1))rotate(var(--tw-exit-rotate,0))}}.duration-150{animation-duration:.15s}.ease-out{animation-timing-function:cubic-bezier(0,0,.2,1)}.running{animation-play-state:running}::-webkit-scrollbar{width:6px;height:6px}::-webkit-scrollbar-track{background:0 0}::-webkit-scrollbar-thumb{background:hsl(var(--surface-elevated));border-radius:3px}::-webkit-scrollbar-thumb:hover{background:hsl(var(--text-subtle))}.hide-scrollbar::-webkit-scrollbar{display:none}.hide-scrollbar{-ms-overflow-style:none;scrollbar-width:none}.after\:absolute:after{content:var(--tw-content);position:absolute}.after\:inset-y-0:after{content:var(--tw-content);top:0;bottom:0}.after\:left-1\/2:after{content:var(--tw-content);left:50%}.after\:w-2:after{content:var(--tw-content);width:.5rem}.after\:-translate-x-1\/2:after{content:var(--tw-content);--tw-translate-x:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.hover\:bg-accent:hover{background-color:hsl(var(--accent))}.hover\:bg-destructive\/90:hover{background-color:hsl(var(--destructive)/.9)}.hover\:bg-muted:hover{background-color:hsl(var(--muted))}.hover\:bg-primary\/50:hover{background-color:hsl(var(--primary)/.5)}.hover\:bg-primary\/90:hover{background-color:hsl(var(--primary)/.9)}.hover\:bg-secondary\/80:hover{background-color:hsl(var(--secondary)/.8)}.hover\:text-accent-foreground:hover{color:hsl(var(--accent-foreground))}.hover\:text-muted-foreground:hover{color:hsl(var(--muted-foreground))}.hover\:underline:hover{text-decoration-line:underline}.focus-visible\:outline-none:focus-visible{outline-offset:2px;outline:2px solid #0000}.focus-visible\:ring-1:focus-visible{--tw-ring-offset-shadow:var(--tw-ring-inset)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color);--tw-ring-shadow:var(--tw-ring-inset)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.focus-visible\:ring-ring:focus-visible{--tw-ring-color:hsl(var(--ring))}.disabled\:pointer-events-none:disabled{pointer-events:none}.disabled\:opacity-50:disabled{opacity:.5}.data-\[orientation\=vertical\]\:h-\[3px\][data-orientation=vertical]{height:3px}.data-\[orientation\=vertical\]\:w-full[data-orientation=vertical]{width:100%}.data-\[orientation\=vertical\]\:flex-col[data-orientation=vertical]{flex-direction:column}.data-\[state\=on\]\:border-primary[data-state=on]{border-color:hsl(var(--primary))}.data-\[state\=off\]\:bg-transparent[data-state=off]{background-color:#0000}.data-\[state\=on\]\:bg-background[data-state=on]{background-color:hsl(var(--background))}.data-\[state\=on\]\:bg-primary[data-state=on]{background-color:hsl(var(--primary))}.data-\[state\=off\]\:text-muted-foreground[data-state=off]{color:hsl(var(--muted-foreground))}.data-\[state\=on\]\:text-foreground[data-state=on]{color:hsl(var(--foreground))}.data-\[state\=on\]\:text-primary-foreground[data-state=on]{color:hsl(var(--primary-foreground))}.data-\[state\=on\]\:shadow-sm[data-state=on]{--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow)}.data-\[orientation\=vertical\]\:after\:left-0[data-orientation=vertical]:after{content:var(--tw-content);left:0}.data-\[orientation\=vertical\]\:after\:h-2[data-orientation=vertical]:after{content:var(--tw-content);height:.5rem}.data-\[orientation\=vertical\]\:after\:w-full[data-orientation=vertical]:after{content:var(--tw-content);width:100%}.data-\[orientation\=vertical\]\:after\:-translate-y-1\/2[data-orientation=vertical]:after{content:var(--tw-content);--tw-translate-y:-50%;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.data-\[orientation\=vertical\]\:after\:translate-x-0[data-orientation=vertical]:after{content:var(--tw-content);--tw-translate-x:0px;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}@media (min-width:640px){.sm\:inline{display:inline}}.\[\&\[data-orientation\=vertical\]\>div\]\:rotate-90[data-orientation=vertical]>div{--tw-rotate:90deg;transform:translate(var(--tw-translate-x),var(--tw-translate-y))rotate(var(--tw-rotate))skewX(var(--tw-skew-x))skewY(var(--tw-skew-y))scaleX(var(--tw-scale-x))scaleY(var(--tw-scale-y))}.\[\&_svg\]\:pointer-events-none svg{pointer-events:none}.\[\&_svg\]\:size-4 svg{width:1rem;height:1rem}.\[\&_svg\]\:shrink-0 svg{flex-shrink:0} diff --git a/src/hyperview/server/static/_next/static/chunks/turbopack-ce3658797261f2db.js b/src/hyperview/server/static/_next/static/chunks/turbopack-ce3658797261f2db.js new file mode 100644 index 0000000000000000000000000000000000000000..517cdb1473daa4e3cee9e440e93b75e6b438474d --- /dev/null +++ b/src/hyperview/server/static/_next/static/chunks/turbopack-ce3658797261f2db.js @@ -0,0 +1,3 @@ +(globalThis.TURBOPACK||(globalThis.TURBOPACK=[])).push(["object"==typeof document?document.currentScript:void 0,{otherChunks:["static/chunks/10c3a2ade180023c.js","static/chunks/5a5ec5690ca4254a.js","static/chunks/118bac1f0e1f8b45.js"],runtimeModuleIds:[24153]}]),(()=>{let e;if(!Array.isArray(globalThis.TURBOPACK))return;let t="/_next/",r=new WeakMap;function n(e,t){this.m=e,this.e=t}let o=n.prototype,l=Object.prototype.hasOwnProperty,i="undefined"!=typeof Symbol&&Symbol.toStringTag;function s(e,t,r){l.call(e,t)||Object.defineProperty(e,t,r)}function u(e,t){let r=e[t];return r||(r=a(t),e[t]=r),r}function a(e){return{exports:{},error:void 0,id:e,namespaceObject:void 0}}function c(e,t){s(e,"__esModule",{value:!0}),i&&s(e,i,{value:"Module"});let r=0;for(;rObject.getPrototypeOf(e):e=>e.__proto__,p=[null,f({}),f([]),f(f)];function h(e,t,r){let n=[],o=-1;for(let t=e;("object"==typeof t||"function"==typeof t)&&!p.includes(t);t=f(t))for(let r of Object.getOwnPropertyNames(t))n.push(r,function(e,t){return()=>e[t]}(e,r)),-1===o&&"default"===r&&(o=n.length-1);return r&&o>=0||(o>=0?n.splice(o,1,0,e):n.push("default",0,e)),c(t,n),t}function d(e){let t=N(e,this.m);if(t.namespaceObject)return t.namespaceObject;let r=t.exports;return t.namespaceObject=h(r,"function"==typeof r?function(...e){return r.apply(this,e)}:Object.create(null),r&&r.__esModule)}function m(){let e,t;return{promise:new Promise((r,n)=>{t=n,e=r}),resolve:e,reject:t}}o.i=d,o.A=function(e){return this.r(e)(d.bind(this))},o.t="function"==typeof require?require:function(){throw Error("Unexpected use of runtime require")},o.r=function(e){return N(e,this.m).exports},o.f=function(e){function t(t){if(l.call(e,t))return e[t].module();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r}return t.keys=()=>Object.keys(e),t.resolve=t=>{if(l.call(e,t))return e[t].id();let r=Error(`Cannot find module '${t}'`);throw r.code="MODULE_NOT_FOUND",r},t.import=async e=>await t(e),t};let b=Symbol("turbopack queues"),y=Symbol("turbopack exports"),O=Symbol("turbopack error");function g(e){e&&1!==e.status&&(e.status=1,e.forEach(e=>e.queueCount--),e.forEach(e=>e.queueCount--?e.queueCount++:e()))}o.a=function(e,t){let r=this.m,n=t?Object.assign([],{status:-1}):void 0,o=new Set,{resolve:l,reject:i,promise:s}=m(),u=Object.assign(s,{[y]:r.exports,[b]:e=>{n&&e(n),o.forEach(e),u.catch(()=>{})}}),a={get:()=>u,set(e){e!==u&&(u[y]=e)}};Object.defineProperty(r,"exports",a),Object.defineProperty(r,"namespaceObject",a),e(function(e){let t=e.map(e=>{if(null!==e&&"object"==typeof e){if(b in e)return e;if(null!=e&&"object"==typeof e&&"then"in e&&"function"==typeof e.then){let t=Object.assign([],{status:0}),r={[y]:{},[b]:e=>e(t)};return e.then(e=>{r[y]=e,g(t)},e=>{r[O]=e,g(t)}),r}}return{[y]:e,[b]:()=>{}}}),r=()=>t.map(e=>{if(e[O])throw e[O];return e[y]}),{promise:l,resolve:i}=m(),s=Object.assign(()=>i(r),{queueCount:0});function u(e){e!==n&&!o.has(e)&&(o.add(e),e&&0===e.status&&(s.queueCount++,e.push(s)))}return t.map(e=>e[b](u)),s.queueCount?l:r()},function(e){e?i(u[O]=e):l(u[y]),g(n)}),n&&-1===n.status&&(n.status=0)};let w=function(e){let t=new URL(e,"x:/"),r={};for(let e in t)r[e]=t[e];for(let t in r.href=e,r.pathname=e.replace(/[?#].*/,""),r.origin=r.protocol="",r.toString=r.toJSON=(...t)=>e,r)Object.defineProperty(this,t,{enumerable:!0,configurable:!0,value:r[t]})};function j(e,t){throw Error(`Invariant: ${t(e)}`)}w.prototype=URL.prototype,o.U=w,o.z=function(e){throw Error("dynamic usage of require is not supported")},o.g=globalThis;let R=n.prototype;var C,U=((C=U||{})[C.Runtime=0]="Runtime",C[C.Parent=1]="Parent",C[C.Update=2]="Update",C);let k=new Map;o.M=k;let v=new Map,_=new Map;async function P(e,t,r){let n;if("string"==typeof r)return A(e,t,S(r));let o=r.included||[],l=o.map(e=>!!k.has(e)||v.get(e));if(l.length>0&&l.every(e=>e))return void await Promise.all(l);let i=r.moduleChunks||[],s=i.map(e=>_.get(e)).filter(e=>e);if(s.length>0){if(s.length===i.length)return void await Promise.all(s);let r=new Set;for(let e of i)_.has(e)||r.add(e);for(let n of r){let r=A(e,t,S(n));_.set(n,r),s.push(r)}n=Promise.all(s)}else{for(let o of(n=A(e,t,S(r.path)),i))_.has(o)||_.set(o,n)}for(let e of o)v.has(e)||v.set(e,n);await n}R.l=function(e){return P(1,this.m.id,e)};let $=Promise.resolve(void 0),T=new WeakMap;function A(t,r,n){let o=e.loadChunkCached(t,n),l=T.get(o);if(void 0===l){let e=T.set.bind(T,o,$);l=o.then(e).catch(e=>{let o;switch(t){case 0:o=`as a runtime dependency of chunk ${r}`;break;case 1:o=`from module ${r}`;break;case 2:o="from an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}throw Error(`Failed to load chunk ${n} ${o}${e?`: ${e}`:""}`,e?{cause:e}:void 0)}),T.set(o,l)}return l}function S(e){return`${t}${e.split("/").map(e=>encodeURIComponent(e)).join("/")}`}R.L=function(e){return A(1,this.m.id,e)},R.R=function(e){let t=this.r(e);return t?.default??t},R.P=function(e){return`/ROOT/${e??""}`},R.b=function(e){let t=new Blob([`self.TURBOPACK_WORKER_LOCATION = ${JSON.stringify(location.origin)}; +self.TURBOPACK_NEXT_CHUNK_URLS = ${JSON.stringify(e.reverse().map(S),null,2)}; +importScripts(...self.TURBOPACK_NEXT_CHUNK_URLS.map(c => self.TURBOPACK_WORKER_LOCATION + c).reverse());`],{type:"text/javascript"});return URL.createObjectURL(t)};let E=/\.js(?:\?[^#]*)?(?:#.*)?$/,K=/\.css(?:\?[^#]*)?(?:#.*)?$/;function x(e){return K.test(e)}o.w=function(t,r,n){return e.loadWebAssembly(1,this.m.id,t,r,n)},o.u=function(t,r){return e.loadWebAssemblyModule(1,this.m.id,t,r)};let M={};o.c=M;let N=(e,t)=>{let r=M[e];if(r){if(r.error)throw r.error;return r}return L(e,U.Parent,t.id)};function L(e,t,r){let o=k.get(e);if("function"!=typeof o)throw Error(function(e,t,r){let n;switch(t){case 0:n=`as a runtime entry of chunk ${r}`;break;case 1:n=`because it was required from module ${r}`;break;case 2:n="because of an HMR update";break;default:j(t,e=>`Unknown source type: ${e}`)}return`Module ${e} was instantiated ${n}, but the module factory is not available.`}(e,t,r));let l=a(e),i=l.exports;M[e]=l;let s=new n(l,i);try{o(s,l,i)}catch(e){throw l.error=e,e}return l.namespaceObject&&l.exports!==l.namespaceObject&&h(l.exports,l.namespaceObject),l}function q(r){let n,o=function(e){if("string"==typeof e)return e;let r=decodeURIComponent(("undefined"!=typeof TURBOPACK_NEXT_CHUNK_URLS?TURBOPACK_NEXT_CHUNK_URLS.pop():e.getAttribute("src")).replace(/[?#].*$/,""));return r.startsWith(t)?r.slice(t.length):r}(r[0]);return 2===r.length?n=r[1]:(n=void 0,!function(e,t,r,n){let o=1;for(;o{r=e,n=t}),resolve:()=>{t.resolved=!0,r()},reject:n},B.set(e,t)}return t}e={async registerChunk(e,t){if(W(S(e)).resolve(),null!=t){for(let e of t.otherChunks)W(S("string"==typeof e?e:e.path));if(await Promise.all(t.otherChunks.map(t=>P(0,e,t))),t.runtimeModuleIds.length>0)for(let r of t.runtimeModuleIds)!function(e,t){let r=M[t];if(r){if(r.error)throw r.error;return}L(t,U.Runtime,e)}(e,r)}},loadChunkCached:(e,t)=>(function(e,t){let r=W(t);if(r.loadingStarted)return r.promise;if(e===U.Runtime)return r.loadingStarted=!0,x(t)&&r.resolve(),r.promise;if("function"==typeof importScripts)if(x(t));else if(E.test(t))self.TURBOPACK_NEXT_CHUNK_URLS.push(t),importScripts(TURBOPACK_WORKER_LOCATION+t);else throw Error(`can't infer type of chunk from URL ${t} in worker`);else{let e=decodeURI(t);if(x(t))if(document.querySelectorAll(`link[rel=stylesheet][href="${t}"],link[rel=stylesheet][href^="${t}?"],link[rel=stylesheet][href="${e}"],link[rel=stylesheet][href^="${e}?"]`).length>0)r.resolve();else{let e=document.createElement("link");e.rel="stylesheet",e.href=t,e.onerror=()=>{r.reject()},e.onload=()=>{r.resolve()},document.head.appendChild(e)}else if(E.test(t)){let n=document.querySelectorAll(`script[src="${t}"],script[src^="${t}?"],script[src="${e}"],script[src^="${e}?"]`);if(n.length>0)for(let e of Array.from(n))e.addEventListener("error",()=>{r.reject()});else{let e=document.createElement("script");e.src=t,e.onerror=()=>{r.reject()},document.head.appendChild(e)}}else throw Error(`can't infer type of chunk from URL ${t}`)}return r.loadingStarted=!0,r.promise})(e,t),async loadWebAssembly(e,t,r,n,o){let l=fetch(S(r)),{instance:i}=await WebAssembly.instantiateStreaming(l,o);return i.exports},async loadWebAssemblyModule(e,t,r,n){let o=fetch(S(r));return await WebAssembly.compileStreaming(o)}};let I=globalThis.TURBOPACK;globalThis.TURBOPACK={push:q},I.forEach(q)})(); \ No newline at end of file diff --git a/src/hyperview/server/static/_not-found/__next._full.txt b/src/hyperview/server/static/_not-found/__next._full.txt new file mode 100644 index 0000000000000000000000000000000000000000..3c90da5b15dbc77b7fbdfb3716b61661f5a7b323 --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._full.txt @@ -0,0 +1,13 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +4:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +5:"$Sreact.suspense" +7:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +9:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +b:I[75115,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"P":null,"b":"8FqA-ERyePplcUaEYWohc","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/48c5753aca325314.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L7",null,{"children":"$@8"}],["$","div",null,{"hidden":true,"children":["$","$L9",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@a"}]}]}],null]}],false]],"m":"$undefined","G":["$b","$undefined"],"S":true} +8:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +a:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] +6:null diff --git a/src/hyperview/server/static/_not-found/__next._head.txt b/src/hyperview/server/static/_not-found/__next._head.txt new file mode 100644 index 0000000000000000000000000000000000000000..7feb987f781af7dbc62aac3f6a9a16fc7b2dbf17 --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._head.txt @@ -0,0 +1,7 @@ +1:"$Sreact.fragment" +2:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +4:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +5:"$Sreact.suspense" +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L2",null,{"children":"$@3"}],["$","div",null,{"hidden":true,"children":["$","$L4",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@6"}]}]}],null]}],"loading":null,"isPartial":false} +3:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +6:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] diff --git a/src/hyperview/server/static/_not-found/__next._index.txt b/src/hyperview/server/static/_not-found/__next._index.txt new file mode 100644 index 0000000000000000000000000000000000000000..9a2da0599d5c34332d068076200219dc9f64999b --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._index.txt @@ -0,0 +1,5 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next"}],["$","script","script-0",{"src":"/_next/static/chunks/48c5753aca325314.js","async":true}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}]}]}]]}],"loading":null,"isPartial":false} diff --git a/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt b/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt new file mode 100644 index 0000000000000000000000000000000000000000..1b5253fa78ca94050cd8866605f25f6e55d77fc7 --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._not-found.__PAGE__.txt @@ -0,0 +1,5 @@ +1:"$Sreact.fragment" +2:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +3:"$Sreact.suspense" +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],null,["$","$L2",null,{"children":["$","$3",null,{"name":"Next.MetadataOutlet","children":"$@4"}]}]]}],"loading":null,"isPartial":false} +4:null diff --git a/src/hyperview/server/static/_not-found/__next._not-found.txt b/src/hyperview/server/static/_not-found/__next._not-found.txt new file mode 100644 index 0000000000000000000000000000000000000000..1528054d91c12d4a99ec5e2947124e09e65d8855 --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._not-found.txt @@ -0,0 +1,4 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +0:{"buildId":"8FqA-ERyePplcUaEYWohc","rsc":["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","template":["$","$L3",null,{}]}]]}],"loading":null,"isPartial":false} diff --git a/src/hyperview/server/static/_not-found/__next._tree.txt b/src/hyperview/server/static/_not-found/__next._tree.txt new file mode 100644 index 0000000000000000000000000000000000000000..068e4b30681be8b9fa8d338db4cca76674e5fe71 --- /dev/null +++ b/src/hyperview/server/static/_not-found/__next._tree.txt @@ -0,0 +1,2 @@ +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"buildId":"8FqA-ERyePplcUaEYWohc","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"/_not-found","paramType":null,"paramKey":"/_not-found","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":false}},"isRootLayout":true},"staleTime":300} diff --git a/src/hyperview/server/static/_not-found/index.html b/src/hyperview/server/static/_not-found/index.html new file mode 100644 index 0000000000000000000000000000000000000000..7d84c4644e74ddb20f4cbd03dfb1c8ba576a6fa8 --- /dev/null +++ b/src/hyperview/server/static/_not-found/index.html @@ -0,0 +1 @@ +404: This page could not be found.HyperView

404

This page could not be found.

\ No newline at end of file diff --git a/src/hyperview/server/static/_not-found/index.txt b/src/hyperview/server/static/_not-found/index.txt new file mode 100644 index 0000000000000000000000000000000000000000..3c90da5b15dbc77b7fbdfb3716b61661f5a7b323 --- /dev/null +++ b/src/hyperview/server/static/_not-found/index.txt @@ -0,0 +1,13 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +4:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +5:"$Sreact.suspense" +7:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +9:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +b:I[75115,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"P":null,"b":"8FqA-ERyePplcUaEYWohc","c":["","_not-found",""],"q":"","i":false,"f":[[["",{"children":["/_not-found",{"children":["__PAGE__",{}]}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","script","script-0",{"src":"/_next/static/chunks/48c5753aca325314.js","async":true,"nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[null,["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}],{"children":[["$","$1","c",{"children":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:style","children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:1:props:style","children":404}],["$","div",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:style","children":["$","h2",null,{"style":"$0:f:0:1:0:props:children:1:props:children:props:children:props:notFound:0:1:props:children:props:children:2:props:children:props:style","children":"This page could not be found."}]}]]}]}]],null,["$","$L4",null,{"children":["$","$5",null,{"name":"Next.MetadataOutlet","children":"$@6"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],["$","$1","h",{"children":[["$","meta",null,{"name":"robots","content":"noindex"}],["$","$L7",null,{"children":"$@8"}],["$","div",null,{"hidden":true,"children":["$","$L9",null,{"children":["$","$5",null,{"name":"Next.Metadata","children":"$@a"}]}]}],null]}],false]],"m":"$undefined","G":["$b","$undefined"],"S":true} +8:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +a:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] +6:null diff --git a/src/hyperview/server/static/index.html b/src/hyperview/server/static/index.html new file mode 100644 index 0000000000000000000000000000000000000000..73ff68fcfd0d6d6b1dc08ab783e86240f8943785 --- /dev/null +++ b/src/hyperview/server/static/index.html @@ -0,0 +1 @@ +HyperView

HyperView

Samples0 items
Click • ⌘+click multi • ⇧+click range
EmbeddingsLoading...
Loading embeddings...
⇧+drag lasso • scroll zoom • drag pan
\ No newline at end of file diff --git a/src/hyperview/server/static/index.txt b/src/hyperview/server/static/index.txt new file mode 100644 index 0000000000000000000000000000000000000000..119a8ae23b7651880eba7af4b5a33a1c990f395a --- /dev/null +++ b/src/hyperview/server/static/index.txt @@ -0,0 +1,17 @@ +1:"$Sreact.fragment" +2:I[32035,["/_next/static/chunks/48c5753aca325314.js"],"default"] +3:I[91168,["/_next/static/chunks/48c5753aca325314.js"],"default"] +4:I[73440,["/_next/static/chunks/48c5753aca325314.js"],"ClientPageRoot"] +5:I[50912,["/_next/static/chunks/b3cfdd883c96563c.js","/_next/static/chunks/a096ec8e6ed56d42.js"],"default"] +8:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"OutletBoundary"] +9:"$Sreact.suspense" +b:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"ViewportBoundary"] +d:I[64381,["/_next/static/chunks/48c5753aca325314.js"],"MetadataBoundary"] +f:I[75115,["/_next/static/chunks/48c5753aca325314.js"],"default"] +:HL["/_next/static/chunks/d6d93a0a04227147.css","style"] +0:{"P":null,"b":"8FqA-ERyePplcUaEYWohc","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/d6d93a0a04227147.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","children":["$","body",null,{"className":"antialiased","children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/b3cfdd883c96563c.js","async":true,"nonce":"$undefined"}],["$","script","script-1",{"src":"/_next/static/chunks/a096ec8e6ed56d42.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$@c"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$@e"}]}]}],null]}],false]],"m":"$undefined","G":["$f",[]],"S":true} +6:{} +7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params" +c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] +e:[["$","title","0",{"children":"HyperView"}],["$","meta","1",{"name":"description","content":"Dataset visualization with hyperbolic embeddings"}]] +a:null diff --git a/src/hyperview/storage/__init__.py b/src/hyperview/storage/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..690bb7d15eabbeb3f21664473d5ba6019cecf08f --- /dev/null +++ b/src/hyperview/storage/__init__.py @@ -0,0 +1,19 @@ +"""Storage backends for HyperView.""" + +from hyperview.storage.backend import StorageBackend +from hyperview.storage.config import ( + StorageConfig, + get_default_datasets_dir, + get_default_media_dir, +) +from hyperview.storage.lancedb_backend import LanceDBBackend +from hyperview.storage.memory_backend import MemoryBackend + +__all__ = [ + "StorageBackend", + "StorageConfig", + "get_default_datasets_dir", + "get_default_media_dir", + "LanceDBBackend", + "MemoryBackend", +] diff --git a/src/hyperview/storage/backend.py b/src/hyperview/storage/backend.py new file mode 100644 index 0000000000000000000000000000000000000000..04cb05e082a57669ffe5e8af50019197c7f9569d --- /dev/null +++ b/src/hyperview/storage/backend.py @@ -0,0 +1,196 @@ +"""Abstract storage backend interface for HyperView.""" + +from abc import ABC, abstractmethod +from collections.abc import Callable, Iterator +from typing import Any + +import numpy as np + +from hyperview.core.sample import Sample + + +class StorageBackend(ABC): + """Abstract base class for storage backends.""" + + @abstractmethod + def add_sample(self, sample: Sample) -> None: + """Add a single sample (idempotent upsert).""" + + @abstractmethod + def add_samples_batch(self, samples: list[Sample]) -> None: + """Add multiple samples (idempotent upsert).""" + + @abstractmethod + def get_sample(self, sample_id: str) -> Sample | None: + """Retrieve a sample by ID.""" + + @abstractmethod + def get_samples_paginated( + self, + offset: int = 0, + limit: int = 100, + label: str | None = None, + ) -> tuple[list[Sample], int]: + """Get paginated samples. Returns (samples, total_count).""" + + @abstractmethod + def get_all_samples(self) -> list[Sample]: + """Get all samples.""" + + @abstractmethod + def update_sample(self, sample: Sample) -> None: + """Update an existing sample.""" + + @abstractmethod + def update_samples_batch(self, samples: list[Sample]) -> None: + """Batch update samples.""" + + @abstractmethod + def delete_sample(self, sample_id: str) -> bool: + """Delete a sample by ID.""" + + @abstractmethod + def __len__(self) -> int: + """Return total number of samples.""" + + @abstractmethod + def __iter__(self) -> Iterator[Sample]: + """Iterate over all samples.""" + + @abstractmethod + def __contains__(self, sample_id: str) -> bool: + """Check if sample exists.""" + + @abstractmethod + def get_unique_labels(self) -> list[str]: + """Get all unique labels.""" + + @abstractmethod + def get_existing_ids(self, sample_ids: list[str]) -> set[str]: + """Return set of sample_ids that already exist in storage.""" + + @abstractmethod + def get_samples_by_ids(self, sample_ids: list[str]) -> list[Sample]: + """Retrieve multiple samples by ID.""" + + @abstractmethod + def get_labels_by_ids(self, sample_ids: list[str]) -> dict[str, str | None]: + """Get labels for sample IDs. Missing IDs not included in result.""" + + @abstractmethod + def filter(self, predicate: Callable[[Sample], bool]) -> list[Sample]: + """Filter samples based on a predicate function.""" + + @abstractmethod + def list_spaces(self) -> list[Any]: + """List all embedding spaces.""" + + @abstractmethod + def get_space(self, space_key: str) -> Any | None: + """Get info for a specific embedding space.""" + + @abstractmethod + def ensure_space( + self, + model_id: str, + dim: int, + config: dict | None = None, + space_key: str | None = None, + ) -> Any: + """Ensure an embedding space exists, creating if needed. + + Args: + model_id: Model identifier for this space. + dim: Vector dimension. + config: Optional config dict for SpaceInfo.config_json. + space_key: Optional explicit space key. If None, derived from model_id. + """ + + @abstractmethod + def delete_space(self, space_key: str) -> bool: + """Delete an embedding space and its embeddings.""" + + @abstractmethod + def add_embeddings(self, space_key: str, ids: list[str], vectors: np.ndarray) -> None: + """Add embeddings to a space.""" + + @abstractmethod + def get_embeddings(self, space_key: str, ids: list[str] | None = None) -> tuple[list[str], np.ndarray]: + """Get embeddings from a space. Returns (ids, vectors).""" + + @abstractmethod + def get_embedded_ids(self, space_key: str) -> set[str]: + """Get sample IDs that have embeddings in a space.""" + + @abstractmethod + def get_missing_embedding_ids(self, space_key: str) -> list[str]: + """Get sample IDs without embeddings in a space.""" + + @abstractmethod + def list_layouts(self) -> list[Any]: + """List all layouts.""" + + @abstractmethod + def get_layout(self, layout_key: str) -> Any | None: + """Get layout info.""" + + @abstractmethod + def ensure_layout( + self, + layout_key: str, + space_key: str, + method: str, + geometry: str, + params: dict | None = None, + ) -> Any: + """Ensure a layout exists.""" + + @abstractmethod + def delete_layout(self, layout_key: str) -> bool: + """Delete a layout.""" + + @abstractmethod + def add_layout_coords(self, layout_key: str, ids: list[str], coords: np.ndarray) -> None: + """Add layout coordinates (N x 2).""" + + @abstractmethod + def get_layout_coords( + self, + layout_key: str, + ids: list[str] | None = None, + ) -> tuple[list[str], np.ndarray]: + """Get layout coordinates. Returns (ids, coords).""" + + @abstractmethod + def get_lasso_candidates_aabb( + self, + *, + layout_key: str, + x_min: float, + x_max: float, + y_min: float, + y_max: float, + ) -> tuple[list[str], np.ndarray]: + """Return candidate (id, xy) rows within an axis-aligned bounding box.""" + + @abstractmethod + def find_similar( + self, + sample_id: str, + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + """Find k nearest neighbors.""" + + @abstractmethod + def find_similar_by_vector( + self, + vector: list[float] | np.ndarray, + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + """Find k nearest neighbors to a query vector.""" + + @abstractmethod + def close(self) -> None: + """Close the storage connection.""" diff --git a/src/hyperview/storage/config.py b/src/hyperview/storage/config.py new file mode 100644 index 0000000000000000000000000000000000000000..47ad1e5012f16e59d12a9bb7d15943d8d651f09d --- /dev/null +++ b/src/hyperview/storage/config.py @@ -0,0 +1,71 @@ +"""Storage configuration for HyperView.""" + +import os +from dataclasses import dataclass, field +from pathlib import Path + + +def get_default_datasets_dir() -> Path: + """Get the default datasets directory. + + Uses HYPERVIEW_DATASETS_DIR env var if set, otherwise ~/.hyperview/datasets/ + Each dataset gets its own subdirectory with isolated LanceDB tables. + """ + env_dir = os.environ.get("HYPERVIEW_DATASETS_DIR") + if env_dir: + return Path(env_dir) + return Path.home() / ".hyperview" / "datasets" + + +def get_default_media_dir() -> Path: + """Get the default media directory for downloaded images. + + Uses HYPERVIEW_MEDIA_DIR env var if set, otherwise ~/.hyperview/media/ + Similar to FiftyOne's ~/fiftyone/huggingface/hub/ pattern. + """ + env_dir = os.environ.get("HYPERVIEW_MEDIA_DIR") + if env_dir: + return Path(env_dir) + return Path.home() / ".hyperview" / "media" + + +@dataclass +class StorageConfig: + """Configuration for storage backend.""" + + datasets_dir: Path = field(default_factory=get_default_datasets_dir) + media_dir: Path = field(default_factory=get_default_media_dir) + + @classmethod + def default(cls) -> "StorageConfig": + """Create a default configuration.""" + return cls( + datasets_dir=get_default_datasets_dir(), + media_dir=get_default_media_dir(), + ) + + def ensure_dir_exists(self) -> None: + """Ensure the datasets directory exists.""" + self.datasets_dir.mkdir(parents=True, exist_ok=True) + + def ensure_media_dir_exists(self) -> None: + """Ensure the media directory exists.""" + self.media_dir.mkdir(parents=True, exist_ok=True) + + def get_huggingface_media_dir(self, dataset_name: str, split: str) -> Path: + """Get the directory for storing HuggingFace dataset media. + + Creates: ~/.hyperview/media/huggingface/{dataset_name}/{split}/ + + Args: + dataset_name: Name of the HuggingFace dataset (e.g., "cifar100") + split: Dataset split (e.g., "train", "test") + + Returns: + Path to the media directory for this dataset/split. + """ + # Sanitize dataset name for filesystem (replace / with _) + safe_name = dataset_name.replace("/", "_") + media_path = self.media_dir / "huggingface" / safe_name / split + media_path.mkdir(parents=True, exist_ok=True) + return media_path diff --git a/src/hyperview/storage/lancedb_backend.py b/src/hyperview/storage/lancedb_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..f85b6357b7d0de9ef2a90fe0e1c00dbcb1fd1ac8 --- /dev/null +++ b/src/hyperview/storage/lancedb_backend.py @@ -0,0 +1,438 @@ +"""LanceDB storage backend for HyperView.""" + +import time +from collections.abc import Callable, Iterator + +import lancedb +import numpy as np +import pyarrow as pa + +from hyperview.core.sample import Sample +from hyperview.storage.backend import StorageBackend +from hyperview.storage.config import StorageConfig +from hyperview.storage.schema import ( + LayoutInfo, + SpaceInfo, + create_embeddings_schema, + create_layouts_registry_schema, + create_layouts_schema, + create_sample_schema, + create_spaces_schema, + dict_to_sample, + make_space_key, + sample_to_dict, +) + + +def _sql_escape(value: str) -> str: + """Escape single quotes for SQL WHERE clauses.""" + return value.replace("'", "''") + + +class LanceDBBackend(StorageBackend): + """LanceDB-based storage backend for HyperView datasets.""" + + def __init__(self, dataset_name: str, config: StorageConfig | None = None): + self.dataset_name = dataset_name + self.config = config or StorageConfig.default() + self._dataset_dir = self.config.datasets_dir / dataset_name + self._dataset_dir.mkdir(parents=True, exist_ok=True) + self._db = lancedb.connect(str(self._dataset_dir)) + + self._samples_table = self._get_or_create_samples_table() + self._spaces_table = self._get_or_create_spaces_table() + + def _table_names(self) -> set[str]: + """Return the set of table names in this LanceDB database.""" + try: + res = self._db.list_tables() + # LanceDB may return a response object with a `.tables` field. + names = res.tables if hasattr(res, "tables") else res + except Exception: + # Back-compat for older LanceDB. + names = self._db.table_names() + return set(names) + + def _get_or_create_samples_table(self) -> lancedb.table.Table | None: + if "samples" in self._table_names(): + return self._db.open_table("samples") + return None + + def _ensure_samples_table(self, data: list[dict]) -> lancedb.table.Table: + if self._samples_table is None: + schema = create_sample_schema() + arrow_table = pa.Table.from_pylist(data, schema=schema) + self._samples_table = self._db.create_table("samples", data=arrow_table) + return self._samples_table + + def _get_or_create_spaces_table(self) -> lancedb.table.Table: + if "spaces" in self._table_names(): + return self._db.open_table("spaces") + return self._db.create_table("spaces", schema=create_spaces_schema()) + + def add_sample(self, sample: Sample) -> None: + data = [sample_to_dict(sample)] + if self._samples_table is None: + self._ensure_samples_table(data) + else: + arrow = pa.Table.from_pylist(data, schema=self._samples_table.schema) + self._samples_table.merge_insert("id").when_matched_update_all().when_not_matched_insert_all().execute(arrow) + + def add_samples_batch(self, samples: list[Sample]) -> None: + if not samples: + return + data = [sample_to_dict(s) for s in samples] + if self._samples_table is None: + self._ensure_samples_table(data) + else: + arrow = pa.Table.from_pylist(data, schema=self._samples_table.schema) + self._samples_table.merge_insert("id").when_matched_update_all().when_not_matched_insert_all().execute(arrow) + + def get_sample(self, sample_id: str) -> Sample | None: + if self._samples_table is None: + return None + results = self._samples_table.search().where(f"id = '{_sql_escape(sample_id)}'").limit(1).to_list() + return dict_to_sample(results[0]) if results else None + + def get_samples_paginated( + self, + offset: int = 0, + limit: int = 100, + label: str | None = None, + ) -> tuple[list[Sample], int]: + if self._samples_table is None: + return [], 0 + + import pyarrow.compute as pc + + if label: + arrow_table = self._samples_table.search().select(["label"]).to_arrow() + mask = pc.fill_null(pc.equal(arrow_table.column("label"), pa.scalar(label)), False) + total = pc.sum(pc.cast(mask, pa.int64())).as_py() + results = self._samples_table.search().where(f"label = '{_sql_escape(label)}'").offset(offset).limit(limit).to_list() + else: + total = self._samples_table.count_rows() + results = self._samples_table.search().offset(offset).limit(limit).to_list() + + return [dict_to_sample(row) for row in results], total + + def get_all_samples(self) -> list[Sample]: + if self._samples_table is None: + return [] + return [dict_to_sample(row) for row in self._samples_table.to_arrow().to_pylist()] + + def update_sample(self, sample: Sample) -> None: + self.add_sample(sample) + + def update_samples_batch(self, samples: list[Sample]) -> None: + self.add_samples_batch(samples) + + def delete_sample(self, sample_id: str) -> bool: + if self._samples_table is None: + return False + self._samples_table.delete(f"id = '{_sql_escape(sample_id)}'") + return True + + def __len__(self) -> int: + return self._samples_table.count_rows() if self._samples_table else 0 + + def __iter__(self) -> Iterator[Sample]: + if self._samples_table is None: + return iter([]) + for batch in self._samples_table.to_arrow().to_batches(max_chunksize=1000): + batch_dict = batch.to_pydict() + for i in range(batch.num_rows): + yield dict_to_sample({k: batch_dict[k][i] for k in batch_dict}) + + def __contains__(self, sample_id: str) -> bool: + if self._samples_table is None: + return False + return len(self._samples_table.search().where(f"id = '{_sql_escape(sample_id)}'").limit(1).to_list()) > 0 + + def get_unique_labels(self) -> list[str]: + if self._samples_table is None: + return [] + import pyarrow.compute as pc + labels = pc.unique(self._samples_table.search().select(["label"]).to_arrow().column("label")).to_pylist() + return sorted([l for l in labels if l is not None]) + + def get_existing_ids(self, sample_ids: list[str]) -> set[str]: + if self._samples_table is None or not sample_ids: + return set() + existing: set[str] = set() + for i in range(0, len(sample_ids), 1000): + chunk = sample_ids[i : i + 1000] + id_list = "', '".join(_sql_escape(sid) for sid in chunk) + results = self._samples_table.search().where(f"id IN ('{id_list}')").select(["id"]).to_list() + existing.update(r["id"] for r in results) + return existing + + def get_samples_by_ids(self, sample_ids: list[str]) -> list[Sample]: + if self._samples_table is None or not sample_ids: + return [] + rows_by_id: dict[str, dict] = {} + for i in range(0, len(sample_ids), 1000): + chunk = sample_ids[i : i + 1000] + id_list = "', '".join(_sql_escape(sid) for sid in chunk) + for r in self._samples_table.search().where(f"id IN ('{id_list}')").to_list(): + rows_by_id[r["id"]] = r + return [dict_to_sample(rows_by_id[sid]) for sid in sample_ids if sid in rows_by_id] + + def get_labels_by_ids(self, sample_ids: list[str]) -> dict[str, str | None]: + if self._samples_table is None or not sample_ids: + return {} + labels: dict[str, str | None] = {} + for i in range(0, len(sample_ids), 1000): + chunk = sample_ids[i : i + 1000] + id_list = "', '".join(_sql_escape(sid) for sid in chunk) + for r in self._samples_table.search().select(["id", "label"]).where(f"id IN ('{id_list}')").to_list(): + labels[r["id"]] = r.get("label") + return labels + + def filter(self, predicate: Callable[[Sample], bool]) -> list[Sample]: + return [s for s in self if predicate(s)] + + def list_spaces(self) -> list[SpaceInfo]: + return [SpaceInfo.from_dict(r) for r in self._spaces_table.to_arrow().to_pylist()] + + def get_space(self, space_key: str) -> SpaceInfo | None: + results = self._spaces_table.search().where(f"space_key = '{_sql_escape(space_key)}'").limit(1).to_list() + return SpaceInfo.from_dict(results[0]) if results else None + + def ensure_space( + self, + model_id: str, + dim: int, + config: dict | None = None, + space_key: str | None = None, + ) -> SpaceInfo: + if space_key is None: + space_key = make_space_key(model_id) + existing = self.get_space(space_key) + if existing is not None: + if existing.dim != dim: + raise ValueError(f"Space '{space_key}' exists with dim={existing.dim}, requested dim={dim}") + return existing + + now = int(time.time()) + space_info = SpaceInfo( + space_key=space_key, model_id=model_id, dim=dim, count=0, + created_at=now, updated_at=now, config=config, + ) + self._spaces_table.add(pa.Table.from_pylist([space_info.to_dict()], schema=create_spaces_schema())) + self._db.create_table(f"embeddings__{space_key}", schema=create_embeddings_schema(dim)) + return space_info + + def delete_space(self, space_key: str) -> bool: + self._spaces_table.delete(f"space_key = '{_sql_escape(space_key)}'") + emb_table = f"embeddings__{space_key}" + if emb_table in self._table_names(): + self._db.drop_table(emb_table) + return True + + def add_embeddings(self, space_key: str, ids: list[str], vectors: np.ndarray) -> None: + if len(ids) != len(vectors) or len(ids) == 0: + return + space = self.get_space(space_key) + if space is None: + raise ValueError(f"Space not found: {space_key}") + + emb_table_name = f"embeddings__{space_key}" + if emb_table_name not in self._table_names(): + self._db.create_table(emb_table_name, schema=create_embeddings_schema(space.dim)) + + emb_table = self._db.open_table(emb_table_name) + data = [{"id": id_, "vector": vec.astype(np.float32).tolist()} for id_, vec in zip(ids, vectors)] + emb_table.merge_insert("id").when_matched_update_all().when_not_matched_insert_all().execute( + pa.Table.from_pylist(data, schema=create_embeddings_schema(space.dim)) + ) + + # Update space count + self._spaces_table.update(where=f"space_key = '{_sql_escape(space_key)}'", values={ + "count": emb_table.count_rows(), "updated_at": int(time.time()) + }) + + def get_embeddings(self, space_key: str, ids: list[str] | None = None) -> tuple[list[str], np.ndarray]: + space = self.get_space(space_key) + if space is None: + raise ValueError(f"Space not found: {space_key}") + + emb_table_name = f"embeddings__{space_key}" + if emb_table_name not in self._table_names(): + return [], np.empty((0, space.dim), dtype=np.float32) + + emb_table = self._db.open_table(emb_table_name) + if ids is not None: + id_list = "', '".join(_sql_escape(sid) for sid in ids) + rows = emb_table.search().where(f"id IN ('{id_list}')").to_list() + else: + rows = emb_table.to_arrow().to_pylist() + + if not rows: + return [], np.empty((0, space.dim), dtype=np.float32) + return [r["id"] for r in rows], np.array([r["vector"] for r in rows], dtype=np.float32) + + def get_embedded_ids(self, space_key: str) -> set[str]: + emb_table_name = f"embeddings__{space_key}" + if emb_table_name not in self._table_names(): + return set() + return {r["id"] for r in self._db.open_table(emb_table_name).search().select(["id"]).to_list()} + + def get_missing_embedding_ids(self, space_key: str) -> list[str]: + if self._samples_table is None: + return [] + all_ids = {r["id"] for r in self._samples_table.search().select(["id"]).to_list()} + return list(all_ids - self.get_embedded_ids(space_key)) + + def _get_layouts_registry_table(self) -> lancedb.table.Table | None: + return self._db.open_table("layouts_registry") if "layouts_registry" in self._table_names() else None + + def _ensure_layouts_registry_table(self) -> lancedb.table.Table: + if "layouts_registry" not in self._table_names(): + self._db.create_table("layouts_registry", schema=create_layouts_registry_schema()) + return self._db.open_table("layouts_registry") + + def list_layouts(self) -> list[LayoutInfo]: + table = self._get_layouts_registry_table() + return [LayoutInfo.from_dict(row) for row in table.search().to_list()] if table else [] + + def get_layout(self, layout_key: str) -> LayoutInfo | None: + table = self._get_layouts_registry_table() + if table is None: + return None + rows = table.search().where(f"layout_key = '{_sql_escape(layout_key)}'").limit(1).to_list() + return LayoutInfo.from_dict(rows[0]) if rows else None + + def ensure_layout( + self, + layout_key: str, + space_key: str, + method: str, + geometry: str, + params: dict | None = None, + ) -> LayoutInfo: + existing = self.get_layout(layout_key) + if existing is not None: + return existing + + layout_info = LayoutInfo( + layout_key=layout_key, space_key=space_key, method=method, geometry=geometry, + count=0, created_at=int(time.time()), params=params, + ) + registry_table = self._ensure_layouts_registry_table() + registry_table.add(pa.Table.from_pylist([layout_info.to_dict()], schema=create_layouts_registry_schema())) + + table_name = f"layouts__{layout_key}" + if table_name not in self._table_names(): + self._db.create_table(table_name, schema=create_layouts_schema()) + return layout_info + + def delete_layout(self, layout_key: str) -> bool: + table_name = f"layouts__{layout_key}" + if table_name in self._table_names(): + self._db.drop_table(table_name) + registry = self._get_layouts_registry_table() + if registry: + registry.delete(f"layout_key = '{_sql_escape(layout_key)}'") + return True + + def add_layout_coords(self, layout_key: str, ids: list[str], coords: np.ndarray) -> None: + if len(ids) != len(coords) or len(ids) == 0: + return + if self.get_layout(layout_key) is None: + raise ValueError(f"Layout '{layout_key}' not registered") + + table_name = f"layouts__{layout_key}" + if table_name not in self._table_names(): + self._db.create_table(table_name, schema=create_layouts_schema()) + + table = self._db.open_table(table_name) + data = [{"id": id_, "x": float(c[0]), "y": float(c[1])} for id_, c in zip(ids, coords)] + table.merge_insert("id").when_matched_update_all().when_not_matched_insert_all().execute( + pa.Table.from_pylist(data, schema=create_layouts_schema()) + ) + + # Update count + registry = self._get_layouts_registry_table() + if registry: + registry.update(where=f"layout_key = '{_sql_escape(layout_key)}'", values={"count": table.count_rows()}) + + def get_layout_coords(self, layout_key: str, ids: list[str] | None = None) -> tuple[list[str], np.ndarray]: + table_name = f"layouts__{layout_key}" + if table_name not in self._table_names(): + return [], np.empty((0, 2), dtype=np.float32) + + table = self._db.open_table(table_name) + if ids is not None: + id_list = "', '".join(_sql_escape(sid) for sid in ids) + rows = table.search().where(f"id IN ('{id_list}')").to_list() + else: + rows = table.to_arrow().to_pylist() + + if not rows: + return [], np.empty((0, 2), dtype=np.float32) + return [r["id"] for r in rows], np.array([[r["x"], r["y"]] for r in rows], dtype=np.float32) + + def get_lasso_candidates_aabb( + self, + *, + layout_key: str, + x_min: float, + x_max: float, + y_min: float, + y_max: float, + ) -> tuple[list[str], np.ndarray]: + table_name = f"layouts__{layout_key}" + if table_name not in self._table_names(): + return [], np.empty((0, 2), dtype=np.float32) + + rows = self._db.open_table(table_name).search().where( + f"x >= {x_min} AND x <= {x_max} AND y >= {y_min} AND y <= {y_max}" + ).to_list() + + if not rows: + return [], np.empty((0, 2), dtype=np.float32) + return [r["id"] for r in rows], np.array([[r["x"], r["y"]] for r in rows], dtype=np.float32) + + def find_similar(self, sample_id: str, k: int = 10, space_key: str | None = None) -> list[tuple[Sample, float]]: + if space_key is None: + spaces = self.list_spaces() + if not spaces: + raise ValueError("No embedding spaces available") + space_key = spaces[0].space_key + + ids, vecs = self.get_embeddings(space_key, [sample_id]) + if not ids: + raise ValueError(f"Sample {sample_id} has no embedding in space {space_key}") + + results = self.find_similar_by_vector(vecs[0], k + 1, space_key) + return [(s, d) for s, d in results if s.id != sample_id][:k] + + def find_similar_by_vector( + self, + vector: list[float] | np.ndarray, + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + import math + + if space_key is None: + spaces = self.list_spaces() + if not spaces: + raise ValueError("No embedding spaces available") + space_key = spaces[0].space_key + + emb_table_name = f"embeddings__{space_key}" + if emb_table_name not in self._table_names(): + return [] + + results = self._db.open_table(emb_table_name).search(vector, vector_column_name="vector").metric("cosine").limit(k).to_list() + samples_by_id = {s.id: s for s in self.get_samples_by_ids([r["id"] for r in results])} + + return [ + (samples_by_id[r["id"]], 0.0 if math.isnan(d := r.get("_distance", 0.0)) else float(d)) + for r in results if r["id"] in samples_by_id + ] + + def close(self) -> None: + return diff --git a/src/hyperview/storage/memory_backend.py b/src/hyperview/storage/memory_backend.py new file mode 100644 index 0000000000000000000000000000000000000000..7189e08d1cbff4592dfc67595625ec00061220a4 --- /dev/null +++ b/src/hyperview/storage/memory_backend.py @@ -0,0 +1,279 @@ +"""In-memory storage backend for testing and development.""" + +import time +from collections.abc import Callable, Iterator + +import numpy as np + +from hyperview.core.sample import Sample +from hyperview.storage.backend import StorageBackend +from hyperview.storage.schema import LayoutInfo, SpaceInfo, make_space_key + + +class MemoryBackend(StorageBackend): + """In-memory storage backend for testing and development.""" + + def __init__(self, dataset_name: str): + self.dataset_name = dataset_name + self._samples: dict[str, Sample] = {} + self._spaces: dict[str, SpaceInfo] = {} + self._embeddings: dict[str, dict[str, np.ndarray]] = {} + self._layout_registry: dict[str, LayoutInfo] = {} + self._layouts: dict[str, dict[str, tuple[float, float]]] = {} + + def add_sample(self, sample: Sample) -> None: + self._samples[sample.id] = sample + + def add_samples_batch(self, samples: list[Sample]) -> None: + for sample in samples: + self._samples[sample.id] = sample + + def get_sample(self, sample_id: str) -> Sample | None: + return self._samples.get(sample_id) + + def get_samples_paginated( + self, + offset: int = 0, + limit: int = 100, + label: str | None = None, + ) -> tuple[list[Sample], int]: + samples = list(self._samples.values()) + if label: + samples = [s for s in samples if s.label == label] + total = len(samples) + return samples[offset : offset + limit], total + + def get_all_samples(self) -> list[Sample]: + return list(self._samples.values()) + + def update_sample(self, sample: Sample) -> None: + self._samples[sample.id] = sample + + def update_samples_batch(self, samples: list[Sample]) -> None: + for sample in samples: + self._samples[sample.id] = sample + + def delete_sample(self, sample_id: str) -> bool: + if sample_id in self._samples: + del self._samples[sample_id] + return True + return False + + def __len__(self) -> int: + return len(self._samples) + + def __iter__(self) -> Iterator[Sample]: + return iter(self._samples.values()) + + def __contains__(self, sample_id: str) -> bool: + return sample_id in self._samples + + def get_unique_labels(self) -> list[str]: + return sorted({s.label for s in self._samples.values() if s.label}) + + def get_existing_ids(self, sample_ids: list[str]) -> set[str]: + return {sid for sid in sample_ids if sid in self._samples} + + def get_samples_by_ids(self, sample_ids: list[str]) -> list[Sample]: + return [s for sid in sample_ids if (s := self._samples.get(sid)) is not None] + + def get_labels_by_ids(self, sample_ids: list[str]) -> dict[str, str | None]: + return {sid: s.label for sid in sample_ids if (s := self._samples.get(sid)) is not None} + + def filter(self, predicate: Callable[[Sample], bool]) -> list[Sample]: + return [s for s in self._samples.values() if predicate(s)] + + def list_spaces(self) -> list[SpaceInfo]: + return list(self._spaces.values()) + + def get_space(self, space_key: str) -> SpaceInfo | None: + return self._spaces.get(space_key) + + def ensure_space( + self, + model_id: str, + dim: int, + config: dict | None = None, + space_key: str | None = None, + ) -> SpaceInfo: + if space_key is None: + space_key = make_space_key(model_id) + if space_key in self._spaces: + existing = self._spaces[space_key] + if existing.dim != dim: + raise ValueError(f"Space '{space_key}' exists with dim={existing.dim}, requested dim={dim}") + return existing + + now = int(time.time()) + space_info = SpaceInfo( + space_key=space_key, + model_id=model_id, + dim=dim, + count=0, + created_at=now, + updated_at=now, + config=config, + ) + self._spaces[space_key] = space_info + self._embeddings[space_key] = {} + return space_info + + def delete_space(self, space_key: str) -> bool: + if space_key in self._spaces: + del self._spaces[space_key] + self._embeddings.pop(space_key, None) + return True + return False + + def add_embeddings(self, space_key: str, ids: list[str], vectors: np.ndarray) -> None: + if len(ids) != len(vectors) or len(ids) == 0: + return + if space_key not in self._spaces: + raise ValueError(f"Space not found: {space_key}") + + space = self._spaces[space_key] + emb_store = self._embeddings.setdefault(space_key, {}) + for id_, vec in zip(ids, vectors): + emb_store[id_] = vec.astype(np.float32) + space.count = len(emb_store) + space.updated_at = int(time.time()) + + def get_embeddings(self, space_key: str, ids: list[str] | None = None) -> tuple[list[str], np.ndarray]: + if space_key not in self._spaces: + raise ValueError(f"Space not found: {space_key}") + + space = self._spaces[space_key] + emb_store = self._embeddings.get(space_key, {}) + + if ids is not None: + out_ids = [id_ for id_ in ids if id_ in emb_store] + else: + out_ids = list(emb_store.keys()) + + if not out_ids: + return [], np.empty((0, space.dim), dtype=np.float32) + return out_ids, np.array([emb_store[id_] for id_ in out_ids], dtype=np.float32) + + def get_embedded_ids(self, space_key: str) -> set[str]: + return set(self._embeddings.get(space_key, {}).keys()) + + def get_missing_embedding_ids(self, space_key: str) -> list[str]: + embedded = self.get_embedded_ids(space_key) + return [id_ for id_ in self._samples.keys() if id_ not in embedded] + + def list_layouts(self) -> list[LayoutInfo]: + return list(self._layout_registry.values()) + + def get_layout(self, layout_key: str) -> LayoutInfo | None: + return self._layout_registry.get(layout_key) + + def ensure_layout( + self, + layout_key: str, + space_key: str, + method: str, + geometry: str, + params: dict | None = None, + ) -> LayoutInfo: + if layout_key in self._layout_registry: + return self._layout_registry[layout_key] + + layout_info = LayoutInfo( + layout_key=layout_key, + space_key=space_key, + method=method, + geometry=geometry, + count=0, + created_at=int(time.time()), + params=params, + ) + self._layout_registry[layout_key] = layout_info + self._layouts[layout_key] = {} + return layout_info + + def delete_layout(self, layout_key: str) -> bool: + deleted = layout_key in self._layouts or layout_key in self._layout_registry + self._layouts.pop(layout_key, None) + self._layout_registry.pop(layout_key, None) + return deleted + + def add_layout_coords(self, layout_key: str, ids: list[str], coords: np.ndarray) -> None: + if len(ids) != len(coords): + raise ValueError("ids and coords must have same length") + if layout_key not in self._layout_registry: + raise ValueError(f"Layout '{layout_key}' not registered") + + layout_store = self._layouts.setdefault(layout_key, {}) + for id_, coord in zip(ids, coords): + layout_store[id_] = (float(coord[0]), float(coord[1])) + self._layout_registry[layout_key].count = len(layout_store) + + def get_layout_coords(self, layout_key: str, ids: list[str] | None = None) -> tuple[list[str], np.ndarray]: + layout_store = self._layouts.get(layout_key, {}) + out_ids = [id_ for id_ in ids if id_ in layout_store] if ids is not None else list(layout_store.keys()) + if not out_ids: + return [], np.empty((0, 2), dtype=np.float32) + return out_ids, np.array([layout_store[id_] for id_ in out_ids], dtype=np.float32) + + def get_lasso_candidates_aabb( + self, + *, + layout_key: str, + x_min: float, + x_max: float, + y_min: float, + y_max: float, + ) -> tuple[list[str], np.ndarray]: + layout_store = self._layouts.get(layout_key, {}) + ids, coords = [], [] + for id_, (x, y) in layout_store.items(): + if x_min <= x <= x_max and y_min <= y <= y_max: + ids.append(id_) + coords.append([x, y]) + return ids, np.array(coords, dtype=np.float32) if coords else np.empty((0, 2), dtype=np.float32) + + def find_similar(self, sample_id: str, k: int = 10, space_key: str | None = None) -> list[tuple[Sample, float]]: + if space_key is None: + if not self._spaces: + raise ValueError("No embedding spaces available") + space_key = next(iter(self._spaces)) + + emb_store = self._embeddings.get(space_key, {}) + if sample_id not in emb_store: + raise ValueError(f"Sample {sample_id} has no embedding in space {space_key}") + + results = self.find_similar_by_vector(emb_store[sample_id], k + 1, space_key) + return [(s, d) for s, d in results if s.id != sample_id][:k] + + def find_similar_by_vector( + self, + vector: list[float] | np.ndarray, + k: int = 10, + space_key: str | None = None, + ) -> list[tuple[Sample, float]]: + if space_key is None: + if not self._spaces: + raise ValueError("No embedding spaces available") + space_key = next(iter(self._spaces)) + + emb_store = self._embeddings.get(space_key, {}) + query = np.array(vector, dtype=np.float32) + norm_query = np.linalg.norm(query) + + distances: list[tuple[Sample, float]] = [] + for id_, vec in emb_store.items(): + sample = self._samples.get(id_) + if sample is None: + continue + norm_vec = np.linalg.norm(vec) + if norm_query == 0 or norm_vec == 0: + distance = 1.0 + else: + distance = 1 - np.dot(query, vec) / (norm_query * norm_vec) + distances.append((sample, float(distance))) + + distances.sort(key=lambda x: x[1]) + return distances[:k] + + def close(self) -> None: + pass diff --git a/src/hyperview/storage/schema.py b/src/hyperview/storage/schema.py new file mode 100644 index 0000000000000000000000000000000000000000..aea95519ea57510291e2c248b27835e55e672d94 --- /dev/null +++ b/src/hyperview/storage/schema.py @@ -0,0 +1,284 @@ +"""LanceDB schema definitions for HyperView. + +Storage architecture: +- samples: Core sample metadata (no embeddings) +- metadata: Key-value pairs for dataset config +- spaces: Registry of embedding spaces +- embeddings__: One table per embedding space (id + vector) +- layouts__: One table per layout (id + x + y) +""" + +import json +import re +from dataclasses import dataclass +from typing import Any + +import pyarrow as pa + +from hyperview.core.sample import Sample + + +def create_sample_schema() -> pa.Schema: + """Create the PyArrow schema for samples. + + Samples are pure metadata - embeddings and layouts are stored separately. + """ + return pa.schema( + [ + pa.field("id", pa.utf8(), nullable=False), + pa.field("filepath", pa.utf8(), nullable=False), + pa.field("label", pa.utf8(), nullable=True), + pa.field("metadata_json", pa.utf8(), nullable=True), + pa.field("thumbnail_base64", pa.utf8(), nullable=True), + ] + ) + + +def create_metadata_schema() -> pa.Schema: + """Create the PyArrow schema for dataset metadata (key-value store).""" + return pa.schema( + [ + pa.field("key", pa.utf8(), nullable=False), + pa.field("value", pa.utf8(), nullable=True), + ] + ) + + +def create_spaces_schema() -> pa.Schema: + """Create the PyArrow schema for the spaces registry. + + Each row represents an embedding space (one per model). + """ + return pa.schema( + [ + pa.field("space_key", pa.utf8(), nullable=False), + pa.field("model_id", pa.utf8(), nullable=False), + pa.field("dim", pa.int32(), nullable=False), + pa.field("count", pa.int64(), nullable=False), + pa.field("created_at", pa.int64(), nullable=False), + pa.field("updated_at", pa.int64(), nullable=False), + pa.field("config_json", pa.utf8(), nullable=True), + ] + ) + + +def create_embeddings_schema(dim: int) -> pa.Schema: + """Create the PyArrow schema for an embeddings table. + + Args: + dim: Vector dimension for this embedding space. + """ + return pa.schema( + [ + pa.field("id", pa.utf8(), nullable=False), + pa.field("vector", pa.list_(pa.float32(), dim), nullable=False), + ] + ) + + +def create_layouts_schema() -> pa.Schema: + """Create the PyArrow schema for a layouts table. + + Layouts store 2D coordinates for visualization. + """ + return pa.schema( + [ + pa.field("id", pa.utf8(), nullable=False), + pa.field("x", pa.float32(), nullable=False), + pa.field("y", pa.float32(), nullable=False), + ] + ) + + +@dataclass +class SpaceInfo: + """Metadata for an embedding space.""" + + space_key: str + model_id: str + dim: int + count: int + created_at: int + updated_at: int + config: dict[str, Any] | None = None + + @property + def provider(self) -> str: + return (self.config or {}).get("provider", "unknown") + + @property + def geometry(self) -> str: + return (self.config or {}).get("geometry", "euclidean") + + def to_dict(self) -> dict[str, Any]: + return { + "space_key": self.space_key, + "model_id": self.model_id, + "dim": self.dim, + "count": self.count, + "created_at": self.created_at, + "updated_at": self.updated_at, + "config_json": json.dumps(self.config) if self.config else None, + } + + def to_api_dict(self) -> dict[str, Any]: + return { + "space_key": self.space_key, + "model_id": self.model_id, + "dim": self.dim, + "count": self.count, + "provider": self.provider, + "geometry": self.geometry, + "config": self.config, + } + + @classmethod + def from_dict(cls, row: dict[str, Any]) -> "SpaceInfo": + config_json = row.get("config_json") + config = json.loads(config_json) if config_json else None + return cls( + space_key=row["space_key"], + model_id=row["model_id"], + dim=row["dim"], + count=row["count"], + created_at=row["created_at"], + updated_at=row["updated_at"], + config=config, + ) + + +def create_layouts_registry_schema() -> pa.Schema: + """Create the PyArrow schema for the layouts registry. + + Each row represents a layout (2D projection of an embedding space). + """ + return pa.schema( + [ + pa.field("layout_key", pa.utf8(), nullable=False), + pa.field("space_key", pa.utf8(), nullable=False), + pa.field("method", pa.utf8(), nullable=False), + pa.field("geometry", pa.utf8(), nullable=False), + pa.field("count", pa.int64(), nullable=False), + pa.field("created_at", pa.int64(), nullable=False), + pa.field("params_json", pa.utf8(), nullable=True), + ] + ) + + +@dataclass +class LayoutInfo: + """Metadata for a layout (2D projection).""" + + layout_key: str + space_key: str + method: str + geometry: str + count: int + created_at: int + params: dict[str, Any] | None = None + + def to_dict(self) -> dict[str, Any]: + return { + "layout_key": self.layout_key, + "space_key": self.space_key, + "method": self.method, + "geometry": self.geometry, + "count": self.count, + "created_at": self.created_at, + "params_json": json.dumps(self.params) if self.params else None, + } + + def to_api_dict(self) -> dict[str, Any]: + return { + "layout_key": self.layout_key, + "space_key": self.space_key, + "method": self.method, + "geometry": self.geometry, + "count": self.count, + "params": self.params, + } + + @classmethod + def from_dict(cls, row: dict[str, Any]) -> "LayoutInfo": + params_json = row.get("params_json") + params = json.loads(params_json) if params_json else None + return cls( + layout_key=row["layout_key"], + space_key=row["space_key"], + method=row["method"], + geometry=row["geometry"], + count=row["count"], + created_at=row["created_at"], + params=params, + ) + + +def slugify_model_id(model_id: str) -> str: + """Convert a model ID to a safe table name component. + + Examples: + "openai/clip-vit-base-patch32" -> "openai_clip-vit-base-patch32" + "sentence-transformers/all-MiniLM-L6-v2" -> "sentence-transformers_all-MiniLM-L6-v2" + """ + # Replace / with _ + slug = model_id.replace("/", "_") + # Replace any other unsafe characters with _ + slug = re.sub(r"[^a-zA-Z0-9_\-]", "_", slug) + # Collapse multiple underscores + slug = re.sub(r"_+", "_", slug) + return slug.strip("_") + + +def make_space_key(model_id: str) -> str: + """Generate a space_key from a model_id. + + For simplicity, this is just the slugified model_id. + For provider-aware keys, use `make_provider_aware_space_key` from providers.py. + """ + return slugify_model_id(model_id) + + +def make_layout_key( + space_key: str, + method: str = "umap", + geometry: str = "euclidean", + params: dict | None = None, +) -> str: + """Generate a layout_key from space, method, geometry, and params. + + The params are hashed to ensure different parameter sets get different keys. + """ + base = f"{space_key}__{geometry}_{method}" + if params: + # Create a stable hash of params + import hashlib + params_str = "_".join(f"{k}={v}" for k, v in sorted(params.items())) + params_hash = hashlib.md5(params_str.encode()).hexdigest()[:8] + return f"{base}_{params_hash}" + return base + + +def sample_to_dict(sample: Sample) -> dict[str, Any]: + """Convert a Sample to a dictionary for LanceDB insertion.""" + return { + "id": sample.id, + "filepath": sample.filepath, + "label": sample.label, + "metadata_json": json.dumps(sample.metadata) if sample.metadata else None, + "thumbnail_base64": sample.thumbnail_base64, + } + + +def dict_to_sample(row: dict[str, Any]) -> Sample: + """Convert a LanceDB row to a Sample object.""" + metadata_json = row.get("metadata_json") + metadata = json.loads(metadata_json) if metadata_json else {} + + return Sample( + id=row["id"], + filepath=row["filepath"], + label=row.get("label"), + metadata=metadata, + thumbnail_base64=row.get("thumbnail_base64"), + ) +