From e8c890197387ac61c010bb29c5fdc51a2c818ab8 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 15 Aug 2026 13:15:43 +0000 Subject: [PATCH 1/4] Add load-path overlays, merge gate, and SCM fetch for a full review. Walk GraphQL, Channels, Django templates/HTMX, cache/flags/on_commit, and in-repo FastAPI as sinks on the same architecture graph. Classify contract breaks, surface auth, suggest tests, what-if a node, and trend confidence. Review dirty trees, fetch GitHub/GitLab/Bitbucket PRs into a local clone, and fail CI via a composite Action plus --fail-on. Co-authored-by: zord.lack.net --- README.md | 49 ++- action.yml | 62 ++++ desktop/urls.mjs | 2 + desktop/urls.test.mjs | 3 +- .../backend/billing/consumers.py | 13 + .../demo_monorepo/backend/billing/gateway.py | 18 + .../demo_monorepo/backend/billing/routing.py | 7 + .../demo_monorepo/backend/billing/schema.py | 37 ++ .../billing/templates/billing/base.html | 5 + .../templates/billing/invoice_board.html | 10 + .../demo_monorepo/backend/billing/urls.py | 4 +- .../demo_monorepo/backend/billing/views.py | 24 ++ .../src/features/billing/InvoicePage.tsx | 11 + fixtures/demo_monorepo/loadpath.yml | 2 + fixtures/demo_monorepo/openapi.yaml | 18 + src/loadpath/architecture/snapshot.py | 10 + src/loadpath/cli.py | 103 +++++- src/loadpath/extractors/__init__.py | 3 +- src/loadpath/extractors/django.py | 340 +++++++++++++++++- src/loadpath/extractors/react.py | 32 ++ src/loadpath/extractors/templates.py | 106 ++++++ src/loadpath/graph/store.py | 24 +- src/loadpath/index.py | 13 +- src/loadpath/mcp/compact.py | 4 + src/loadpath/mcp/server.py | 12 +- src/loadpath/mcp/tools.py | 66 +++- src/loadpath/providers/oauth.py | 156 +++++++- src/loadpath/providers/pr_fetch.py | 173 +++++++++ src/loadpath/providers/scm.py | 202 ++++++++++- src/loadpath/review/auth.py | 93 +++++ src/loadpath/review/cluster.py | 18 + src/loadpath/review/contract.py | 131 +++++++ src/loadpath/review/diff.py | 72 ++++ src/loadpath/review/engine.py | 97 ++++- src/loadpath/review/gate.py | 58 +++ src/loadpath/review/render.py | 24 ++ src/loadpath/review/suggested_tests.py | 170 +++++++++ src/loadpath/review/trend.py | 73 ++++ src/loadpath/review/whatif.py | 104 ++++++ src/loadpath/server/app.py | 142 +++++++- src/loadpath/settings.py | 16 + src/loadpath/stitch/openapi.py | 76 +++- src/loadpath/types.py | 44 +++ tests/e2e/test_api_flow.py | 57 +++ tests/e2e/test_cli_review.py | 44 +++ tests/unit/test_overlays.py | 123 +++++++ tests/unit/test_providers_and_api.py | 63 +++- tests/unit/test_review_features.py | 196 ++++++++++ ui/src/App.tsx | 305 +++++++++++++++- ui/src/ImpactGraph.tsx | 29 +- ui/src/api.ts | 34 +- ui/src/graphView.test.ts | 7 + ui/src/graphView.ts | 14 +- ui/src/nodeInspector.test.ts | 3 + ui/src/nodeInspector.ts | 25 ++ ui/src/styles.css | 7 +- ui/src/types.ts | 23 ++ 57 files changed, 3451 insertions(+), 106 deletions(-) create mode 100644 action.yml create mode 100644 fixtures/demo_monorepo/backend/billing/consumers.py create mode 100644 fixtures/demo_monorepo/backend/billing/gateway.py create mode 100644 fixtures/demo_monorepo/backend/billing/routing.py create mode 100644 fixtures/demo_monorepo/backend/billing/schema.py create mode 100644 fixtures/demo_monorepo/backend/billing/templates/billing/base.html create mode 100644 fixtures/demo_monorepo/backend/billing/templates/billing/invoice_board.html create mode 100644 src/loadpath/extractors/templates.py create mode 100644 src/loadpath/providers/pr_fetch.py create mode 100644 src/loadpath/review/auth.py create mode 100644 src/loadpath/review/contract.py create mode 100644 src/loadpath/review/gate.py create mode 100644 src/loadpath/review/suggested_tests.py create mode 100644 src/loadpath/review/trend.py create mode 100644 src/loadpath/review/whatif.py create mode 100644 tests/unit/test_overlays.py create mode 100644 tests/unit/test_review_features.py diff --git a/README.md b/README.md index 20cdefe..8fefcb0 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ Toggle **This review** (impact subgraph) vs **Indexed architecture** (the repo m ### Pull requests -GitHub and Bitbucket via **Sign in** (OAuth) or a token in Settings. After connecting, **My repos** lists every repository the account can access. Pick one and jump to a branch-range review. Review still runs against a **local clone** — if that clone is already a Loadpath workspace, selecting the remote repo fills the local path from `git remote`. The screenshot uses a fixture PR so the tab is not empty. +GitHub, GitLab, and Bitbucket via **Sign in** (OAuth) or a token in Settings. GitHub Enterprise and self-hosted GitLab take a host in Settings. After connecting, **My repos** lists every repository the account can access. Pick one and **Review this PR** — Loadpath fetches the PR refs into a local clone if this machine does not already have one. Review still runs against that clone. The screenshot uses a fixture PR so the tab is not empty. ![Pull requests list](docs/screenshots/pull-requests.png) @@ -75,9 +75,11 @@ Browse the filesystem, pick a project root. Loadpath remembers recent workspaces ### Settings -Appearance (all 24 themes), GitHub / Bitbucket **OAuth sign-in** (or a classic PAT / app password), and AI providers (Anthropic, OpenAI, Grok/xAI, DeepSeek, Cursor-compatible, Ollama). Residual analysis only — Loadpath does not comment every hunk. +Appearance (all 24 themes), GitHub / GitLab / Bitbucket **OAuth sign-in** (or a classic PAT / app password), GitHub Enterprise host, and AI providers (Anthropic, OpenAI, Grok/xAI, DeepSeek, Cursor-compatible, Ollama). Residual analysis only — Loadpath does not comment every hunk. -GitHub uses device flow (`repo read:user read:org`). Create an OAuth App, enable Device Flow, then set `LOADPATH_GITHUB_CLIENT_ID` or paste the client ID in Settings. +GitHub uses device flow (`repo read:user read:org`). Create an OAuth App, enable Device Flow, then set `LOADPATH_GITHUB_CLIENT_ID` or paste the client ID in Settings. For GitHub Enterprise, set the host (API is `{host}/api/v3`). + +GitLab uses authorization code. Create an OAuth application whose callback is `http://127.0.0.1:7345/api/oauth/gitlab/callback`, then set `LOADPATH_GITLAB_CLIENT_ID` / `LOADPATH_GITLAB_CLIENT_SECRET` (or paste them in Settings). Self-managed GitLab takes a host. Bitbucket uses authorization code. Create an OAuth consumer whose callback is `http://127.0.0.1:7345/api/oauth/bitbucket/callback`, then set `LOADPATH_BITBUCKET_CLIENT_ID` / `LOADPATH_BITBUCKET_CLIENT_SECRET` or paste the key and secret in Settings. Access tokens are refreshed automatically. SCM sign-in and repo listing are local-only (loopback) so a tunneled MCP server does not expose private repos. @@ -167,6 +169,11 @@ loadpath architecture /path/to/repo # Review a git range against the index (three-dot / merge-base by default) loadpath review /path/to/repo --base HEAD~1 --head HEAD loadpath review /path/to/repo --base origin/main --head HEAD --no-reindex +loadpath review /path/to/repo --dirty # include the working tree +loadpath review /path/to/repo --fail-on blocker # CI merge gate (never|blocker|low|medium) + +# Walk sinks from one indexed node — no git range +loadpath whatif /path/to/repo django.field:billing.Invoice.total # Cross-platform app (API + visual graph + PR list + MCP /mcp with OAuth) loadpath serve --port 7345 @@ -198,7 +205,22 @@ loadpath index /tmp/acme-billing loadpath serve --open ``` -Then point the UI at `/tmp/acme-billing`, or pick it from the repo explorer. `loadpath serve` always boots the app; it does not take a repo path. Default range is `HEAD~1`…`HEAD`. +Then point the UI at `/tmp/acme-billing`, or pick it from the repo explorer. `loadpath serve` always boots the app; it does not take a repo path. Default range is `HEAD~1`…`HEAD`. Toggle **Include uncommitted** to walk the working tree. Click a node → **What if this changes** to walk sinks without a git range. The read-order list is a guided tour (prev/next highlights the file on the graph). + +## GitHub Action merge gate + +Use this repo as a composite action. It indexes the checkout, reviews `origin/$GITHUB_BASE_REF...HEAD`, optionally upserts the single Loadpath brief, and fails the job on architecture blockers (or on low/medium confidence if you ask). + +```yaml +- uses: Modsofthenation/PR-Reviewer@main + with: + fail-on: blocker # never | blocker | low | medium + comment: true +``` + +Outputs: `level`, `passed`, `title`, `contract_break` (`none` | `additive` | `breaking` | `drift`). + +CLI equivalent: `loadpath review . --fail-on blocker --comment --provider github --pr $N --repo $SLUG`. `--github-output` (or `GITHUB_OUTPUT`) writes the same fields for Actions. ## MCP (Cursor, Claude, ChatGPT, Gemini) @@ -225,7 +247,7 @@ MCP URL: `https://your-tunnel.example/mcp` (or `http://127.0.0.1:7345/mcp` on th **Cursor / Claude / ChatGPT / Gemini (HTTP + OAuth)** — add that MCP URL in the host’s connectors. The first connect opens a consent page on the Loadpath machine. -Tools: `list_workspaces`, `init_repo`, `index_repo`, `architecture`, `review`, `detect_repo`, `list_pull_requests`, `list_remote_repositories`, `post_review_comment`. `review` returns the load-path brief (confidence, sinks, reviewers) — not hunk comments. +Tools: `list_workspaces`, `init_repo`, `index_repo`, `architecture`, `review`, `detect_repo`, `list_pull_requests`, `list_remote_repositories`, `post_review_comment`, `what_if`, `review_pull_request`. `review` returns the load-path brief (confidence, sinks, reviewers, contract-break, auth, suggested tests, trend) — not hunk comments. `review_pull_request` fetches GitHub / GitLab / Bitbucket refs into a local clone first. Put `loadpath.yml` at the repo root (see [`loadpath.yml.example`](loadpath.yml.example) and [`fixtures/demo_monorepo/loadpath.yml`](fixtures/demo_monorepo/loadpath.yml)). The tool is opinionated about *your* architecture, not a generic module graph. @@ -240,6 +262,11 @@ AST is the default extractor. It is a **framework overlay**, not an import graph | Views | DRF ViewSets / APIViews, `serializer_class`, `get_serializer_class` (residual), `permission_classes`, `get_queryset`, `filterset_class`, `authentication_classes`, `pagination_class` | | Function views | `@api_view`, `@login_required`, `@csrf_exempt`, … | | Django Ninja | `@router.get/post/…` routes and views | +| FastAPI (same repo) | `@app.get/post/…` and Pydantic `BaseModel` — only when the file imports FastAPI, so Ninja is not stolen | +| GraphQL | Strawberry `@strawberry.type` / `@strawberry.field` and Graphene `ObjectType` / `Mutation`; client `gql` documents stitch by operation/selection name | +| Channels | `WebsocketConsumer` subclasses and `path(..., Consumer.as_asgi())` websocket routes | +| Templates + HTMX | `.html` files, `{% url %}` / include / extends, `hx-get/post/…` stitched to Django routes | +| Cache / flags / on_commit | `cache.get/set/delete`, waffle-style `flag_is_active`, `transaction.on_commit` as sinks | | URLs | `path` / `re_path`, DRF `router.register`, `include()` mount composition (`/api` + `invoices//` → `/api/invoices/{id}`) | | Signals | `@receiver`, `signal.connect()` residual, `AppConfig.ready()` residual | | Management commands | `BaseCommand` + `handle()`, including `.delay(` / `.send(` enqueue edges | @@ -253,7 +280,7 @@ AST is the default extractor. It is a **framework overlay**, not an import graph - Enqueue: `.delay(`, `.apply_async(` - Signatures / canvas: `.s(`, `.si(`, `chain` / `group` / `chord` (canvas is a residual; inner signatures are `enqueues` edges) - `current_app.send_task("billing.tasks.send_invoice_email")` — residual + inferred enqueue -- `transaction.on_commit(lambda: task.apply_async(...))` — residual, nested enqueue walked +- `transaction.on_commit(lambda: task.apply_async(...))` — `SIDE_EFFECT` sink + residual; nested enqueue walked - `CELERY_BEAT_SCHEDULE` / `beat_schedule` in settings ### Dramatiq @@ -276,7 +303,7 @@ AST is enough for review. If you need live `_meta` (db_table, resolved relations **React:** react-router tables, composition, TanStack Query `queryKey` + fetch/axios URL templates, Zod schemas, feature-folder imports, RTL `render()` as `tested_by`. -**Stitch (the moat):** OpenAPI from Spectacular/schema files first; generated clients (`generated/`, orval, openapi-typescript) as high-confidence `consumed_by_client`; fallback URL-template matching and serializer/Zod field overlap marked **inferred**. +**Stitch (the moat):** OpenAPI from Spectacular/schema files first; generated clients (`generated/`, orval, openapi-typescript) as high-confidence `consumed_by_client`; FastAPI routes and GraphQL operations stitch the same way; HTMX URLs match Django routes; fallback URL-template matching and serializer/Zod field overlap marked **inferred**. Frontend roots prefer `frontend/src`, `frontend`, `web/src`, `client/src`, `ui/src`, `src-ui/src` — not a Python package `src/` and not `docs` / docs-site trees. `app/` is a Django root candidate. @@ -315,7 +342,9 @@ Line coverage on changed files is the wrong metric. Loadpath scores the **impact | Architecture | No new cross-context edges; published seams hold | `crosses_context` or a leaked queryset seam | | Graph | Resolved edges | Many inferred/dynamic edges | -`high` / `medium` / `low` plus three reasons. Isolated leaf UI with green tests and no rule hits is labeled `loadpath:low-risk`. +`high` / `medium` / `low` plus three reasons. Isolated leaf UI with green tests and no rule hits is labeled `loadpath:low-risk`. The same PR/range stores a **confidence trend** so a second review on that range can say whether confidence rose, dropped, or the sink count moved. + +Auth is a first-class load path: permission_classes, get_queryset object scope, and websocket routes without a gate. Untested seams get **suggested tests** (pytest / RTL / GraphQL / Channels / HTMX). Contract diffs are labeled `additive`, `breaking`, or `drift`. ## Tests @@ -327,7 +356,7 @@ node --test desktop/*.test.mjs | Suite | What it covers | | --- | --- | -| `tests/unit/` | Django/React extractors, architecture rules, depth/seam survey, stitch, SCM/AI providers | +| `tests/unit/` | Django/React extractors, architecture rules, depth/seam survey, stitch, overlays (GraphQL/Channels/HTMX/FastAPI), SCM/AI providers | | `tests/integration/test_review_vertical_slice.py` | Serializer field change reaches InvoicePage/Zod, not MePage; reviewers `billing-team` | | `tests/e2e/test_cli_review.py` | `loadpath index` / `architecture` / `review` markdown, JSON, HTML | | `tests/e2e/test_api_flow.py` | health, index, architecture, review-from-index, graph, settings, GitHub + Bitbucket PR list | @@ -345,7 +374,7 @@ LOADPATH_SCREENSHOT_DIR=docs/screenshots python -m pytest tests/e2e/test_ui_scre ## Demo fixture -[`fixtures/demo_monorepo`](fixtures/demo_monorepo) is a billing/identity split: DRF ViewSet, FBV, Ninja ledger route, Celery tasks + beat + canvas, Dramatiq actor + GenericActor, management command, signal, FK string ref, React InvoicePage/Zod. +[`fixtures/demo_monorepo`](fixtures/demo_monorepo) is a billing/identity split: DRF ViewSet, FBV, Ninja ledger route, FastAPI sidecar gateway, Strawberry + Graphene schema, Channels consumer, Django template + HTMX board, cache keys / feature flags / `on_commit`, Celery tasks + beat + canvas, Dramatiq actor + GenericActor, management command, signal, FK string ref, React InvoicePage/Zod + a `gql` document. ## What this is not diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..5ea333d --- /dev/null +++ b/action.yml @@ -0,0 +1,62 @@ +name: "Loadpath Review" +description: "Review a pull request as a load path and fail the check on blockers or low confidence." +author: Loadpath +branding: + icon: git-pull-request + color: purple +inputs: + fail-on: + description: "Gate: never, blocker, low, or medium. blocker fails on architecture blockers; low also fails on low confidence; medium fails unless confidence is high." + required: false + default: "blocker" + comment: + description: "Post or update the single Loadpath brief on the pull request." + required: false + default: "true" + python-version: + description: "Python version used to install Loadpath." + required: false + default: "3.12" + extra-args: + description: "Extra arguments passed to `loadpath review`." + required: false + default: "" +outputs: + level: + description: "Confidence level (high, medium, low)." + value: ${{ steps.review.outputs.level }} + passed: + description: "Whether the gate passed." + value: ${{ steps.review.outputs.passed }} + title: + description: "Review title." + value: ${{ steps.review.outputs.title }} + contract_break: + description: "none, additive, breaking, or drift." + value: ${{ steps.review.outputs.contract_break }} +runs: + using: composite + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ inputs.python-version }} + - name: Install Loadpath + shell: bash + run: python -m pip install --quiet "${{ github.action_path }}" + - name: Index + shell: bash + run: loadpath index . + - name: Review + id: review + shell: bash + env: + GITHUB_TOKEN: ${{ github.token }} + run: | + set -euo pipefail + ARGS=(review . --base "origin/${GITHUB_BASE_REF:-main}" --head HEAD --fail-on "${{ inputs.fail-on }}") + if [ "${{ inputs.comment }}" = "true" ] && [ -n "${{ github.event.pull_request.number }}" ]; then + ARGS+=(--comment --provider github --pr "${{ github.event.pull_request.number }}" --repo "${{ github.repository }}") + fi + # shellcheck disable=SC2206 + EXTRA=(${{ inputs.extra-args }}) + loadpath "${ARGS[@]}" "${EXTRA[@]}" diff --git a/desktop/urls.mjs b/desktop/urls.mjs index 397733e..8ac6547 100644 --- a/desktop/urls.mjs +++ b/desktop/urls.mjs @@ -13,6 +13,8 @@ export function isAllowedExternalUrl(url) { host.endsWith(".github.com") || host === "bitbucket.org" || host.endsWith(".bitbucket.org") || + host === "gitlab.com" || + host.endsWith(".gitlab.com") || host === "id.atlassian.com" || host.endsWith(".atlassian.com") ); diff --git a/desktop/urls.test.mjs b/desktop/urls.test.mjs index cd1e871..94493b0 100644 --- a/desktop/urls.test.mjs +++ b/desktop/urls.test.mjs @@ -4,9 +4,10 @@ import { describe, it } from "node:test"; import { isAllowedExternalUrl, isAppOrigin } from "./urls.mjs"; describe("isAllowedExternalUrl", () => { - it("allows GitHub and Bitbucket https PR links", () => { + it("allows GitHub, GitLab, and Bitbucket https PR links", () => { assert.equal(isAllowedExternalUrl("https://github.com/acme/demo/pull/12"), true); assert.equal(isAllowedExternalUrl("https://bitbucket.org/acme/demo/pull-requests/3"), true); + assert.equal(isAllowedExternalUrl("https://gitlab.com/acme/demo/-/merge_requests/4"), true); assert.equal(isAllowedExternalUrl("https://id.atlassian.com/login"), true); }); diff --git a/fixtures/demo_monorepo/backend/billing/consumers.py b/fixtures/demo_monorepo/backend/billing/consumers.py new file mode 100644 index 0000000..001b27b --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/consumers.py @@ -0,0 +1,13 @@ +from channels.generic.websocket import AsyncJsonWebsocketConsumer + +from billing.models import Invoice + + +class InvoiceConsumer(AsyncJsonWebsocketConsumer): + async def connect(self): + await self.accept() + + async def receive_json(self, content, **kwargs): + invoice_id = content.get("id") + invoice = Invoice.objects.get(pk=invoice_id) + await self.send_json({"id": invoice.id, "total": str(invoice.total)}) diff --git a/fixtures/demo_monorepo/backend/billing/gateway.py b/fixtures/demo_monorepo/backend/billing/gateway.py new file mode 100644 index 0000000..61f5046 --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/gateway.py @@ -0,0 +1,18 @@ +from fastapi import FastAPI +from pydantic import BaseModel + +from billing.models import Invoice + +app = FastAPI() + + +class InvoiceOut(BaseModel): + id: int + total: float + status: str + + +@app.get("/internal/invoices/{id}", response_model=InvoiceOut) +def get_invoice(id: int) -> InvoiceOut: + row = Invoice.objects.get(pk=id) + return InvoiceOut(id=row.id, total=float(row.total), status=row.status) diff --git a/fixtures/demo_monorepo/backend/billing/routing.py b/fixtures/demo_monorepo/backend/billing/routing.py new file mode 100644 index 0000000..320d061 --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/routing.py @@ -0,0 +1,7 @@ +from django.urls import path + +from billing.consumers import InvoiceConsumer + +websocket_urlpatterns = [ + path("ws/invoices/", InvoiceConsumer.as_asgi()), +] diff --git a/fixtures/demo_monorepo/backend/billing/schema.py b/fixtures/demo_monorepo/backend/billing/schema.py new file mode 100644 index 0000000..294f816 --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/schema.py @@ -0,0 +1,37 @@ +import graphene +import strawberry + +from billing.models import Invoice + + +@strawberry.type +class InvoiceType: + id: int + total: float + status: str + + +@strawberry.type +class Query: + @strawberry.field + def invoice(self, id: int) -> InvoiceType: + row = Invoice.objects.get(pk=id) + return InvoiceType(id=row.id, total=float(row.total), status=row.status) + + +schema = strawberry.Schema(query=Query) + + +class CreditInvoice(graphene.Mutation): + class Arguments: + id = graphene.ID(required=True) + + ok = graphene.Boolean() + + def mutate(self, info, id): + Invoice.objects.filter(pk=id).update(status="credited") + return CreditInvoice(ok=True) + + +class Mutation(graphene.ObjectType): + credit_invoice = CreditInvoice.Field() diff --git a/fixtures/demo_monorepo/backend/billing/templates/billing/base.html b/fixtures/demo_monorepo/backend/billing/templates/billing/base.html new file mode 100644 index 0000000..ef872e6 --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/templates/billing/base.html @@ -0,0 +1,5 @@ + + + {% block content %}{% endblock %} + + diff --git a/fixtures/demo_monorepo/backend/billing/templates/billing/invoice_board.html b/fixtures/demo_monorepo/backend/billing/templates/billing/invoice_board.html new file mode 100644 index 0000000..507d1d6 --- /dev/null +++ b/fixtures/demo_monorepo/backend/billing/templates/billing/invoice_board.html @@ -0,0 +1,10 @@ +{% extends "billing/base.html" %} +{% block content %} +
+

Invoice board

+
+ Loading totals… +
+ Refresh +
+{% endblock %} diff --git a/fixtures/demo_monorepo/backend/billing/urls.py b/fixtures/demo_monorepo/backend/billing/urls.py index d25e864..d343f27 100644 --- a/fixtures/demo_monorepo/backend/billing/urls.py +++ b/fixtures/demo_monorepo/backend/billing/urls.py @@ -1,7 +1,7 @@ from django.urls import include, path from rest_framework.routers import DefaultRouter -from billing.views import InvoiceViewSet, invoice_totals +from billing.views import InvoiceBoardView, InvoiceViewSet, graphql_http, invoice_totals router = DefaultRouter() router.register("invoices", InvoiceViewSet, basename="invoice") @@ -9,6 +9,8 @@ urlpatterns = [ path("", include(router.urls)), path("invoices/totals/", invoice_totals, name="invoice-totals"), + path("invoices/board/", InvoiceBoardView.as_view(), name="invoice-board"), + path("graphql/", graphql_http, name="graphql"), path( "invoices//", InvoiceViewSet.as_view({"get": "retrieve", "put": "update"}), diff --git a/fixtures/demo_monorepo/backend/billing/views.py b/fixtures/demo_monorepo/backend/billing/views.py index d5f8a2c..bdb6e41 100644 --- a/fixtures/demo_monorepo/backend/billing/views.py +++ b/fixtures/demo_monorepo/backend/billing/views.py @@ -1,7 +1,11 @@ +from django.core.cache import cache +from django.db import transaction +from django.views.generic import TemplateView from rest_framework import viewsets from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response +from waffle import flag_is_active from billing.actors import rebuild_ledger from billing.models import Invoice @@ -24,13 +28,33 @@ def get_queryset(self): def perform_create(self, serializer): invoice = serializer.save() + cache.delete("invoice:list") send_invoice_email.delay(invoice.id) rebuild_ledger.send(invoice.id) rebuild_ledger.send_with_options(args=(invoice.id,)) + if flag_is_active(self.request, "async_ledger"): + transaction.on_commit(lambda: rebuild_ledger.send(invoice.id)) return invoice +class InvoiceBoardView(TemplateView): + template_name = "billing/invoice_board.html" + + @api_view(["GET"]) @permission_classes([IsAuthenticated]) def invoice_totals(request): + if flag_is_active(request, "new_totals"): + cached = cache.get("invoice:totals") + if cached is not None: + return Response({"count": cached}) + count = Invoice.objects.count() + cache.set("invoice:totals", count) + return Response({"count": count}) return Response({"count": Invoice.objects.count()}) + + +@api_view(["GET", "POST"]) +@permission_classes([IsAuthenticated]) +def graphql_http(request): + return Response({"data": {}}) diff --git a/fixtures/demo_monorepo/frontend/src/features/billing/InvoicePage.tsx b/fixtures/demo_monorepo/frontend/src/features/billing/InvoicePage.tsx index b73f66f..559e538 100644 --- a/fixtures/demo_monorepo/frontend/src/features/billing/InvoicePage.tsx +++ b/fixtures/demo_monorepo/frontend/src/features/billing/InvoicePage.tsx @@ -1,8 +1,19 @@ +import { gql } from "@apollo/client"; import { InvoiceForm } from "./InvoiceForm"; import { useInvoice } from "./useInvoice"; +const INVOICE_QUERY = gql` + query Invoice($id: ID!) { + invoice { + total + status + } + } +`; + export function InvoicePage() { const { data } = useInvoice("1"); + void INVOICE_QUERY; return (

Invoice {data?.id}

diff --git a/fixtures/demo_monorepo/loadpath.yml b/fixtures/demo_monorepo/loadpath.yml index 223ffc8..7e49888 100644 --- a/fixtures/demo_monorepo/loadpath.yml +++ b/fixtures/demo_monorepo/loadpath.yml @@ -8,6 +8,8 @@ contexts: - "POST /api/invoices" - "GET /api/invoices/{id}" - "PUT /api/invoices/{id}" + - "GET /api/invoices/totals" + - "POST /graphql" owners: [billing-team] identity: django_apps: [accounts] diff --git a/fixtures/demo_monorepo/openapi.yaml b/fixtures/demo_monorepo/openapi.yaml index 4749932..9d918dd 100644 --- a/fixtures/demo_monorepo/openapi.yaml +++ b/fixtures/demo_monorepo/openapi.yaml @@ -37,3 +37,21 @@ paths: responses: "200": description: ok + /api/invoices/totals/: + get: + operationId: invoiceTotals + responses: + "200": + description: ok + /internal/invoices/{id}: + get: + operationId: getInvoiceInternal + responses: + "200": + description: ok + /graphql: + post: + operationId: graphql + responses: + "200": + description: ok diff --git a/src/loadpath/architecture/snapshot.py b/src/loadpath/architecture/snapshot.py index 8cb50dd..7b3e8b5 100644 --- a/src/loadpath/architecture/snapshot.py +++ b/src/loadpath/architecture/snapshot.py @@ -30,6 +30,16 @@ NodeType.HOOK.value, NodeType.API_CLIENT.value, NodeType.FORM_SCHEMA.value, + NodeType.GRAPHQL_TYPE.value, + NodeType.GRAPHQL_OPERATION.value, + NodeType.FASTAPI_ROUTE.value, + NodeType.PYDANTIC_MODEL.value, + NodeType.CONSUMER.value, + NodeType.WEBSOCKET_ROUTE.value, + NodeType.TEMPLATE.value, + NodeType.CACHE_KEY.value, + NodeType.FEATURE_FLAG.value, + NodeType.SIDE_EFFECT.value, } diff --git a/src/loadpath/cli.py b/src/loadpath/cli.py index 0d079b3..07e327f 100644 --- a/src/loadpath/cli.py +++ b/src/loadpath/cli.py @@ -87,10 +87,43 @@ def review( reindex: bool = typer.Option(True, "--reindex/--no-reindex", help="Refresh the index before walking the diff"), full: bool = typer.Option(False, "--full", help="Full reindex instead of incremental"), three_dot: bool = typer.Option(True, "--three-dot/--two-dot", help="PR-shaped range (merge-base...head)"), + dirty: bool = typer.Option(False, "--dirty", help="Include uncommitted files in the review"), + fail_on: str = typer.Option( + "never", + "--fail-on", + help="CI gate: never | blocker | low | medium", + ), + comment: bool = typer.Option(False, "--comment", help="Upsert the Loadpath brief on --pr"), + provider: Optional[str] = typer.Option(None, "--provider", help="github | gitlab | bitbucket"), + pr: Optional[int] = typer.Option(None, "--pr", help="Pull/merge request number to comment on or fetch"), + scm_repo: Optional[str] = typer.Option(None, "--repo", help="owner/name for --comment / --pr fetch"), + fetch_pr: bool = typer.Option(False, "--fetch-pr", help="Fetch --pr refs into this clone before reviewing"), + github_output: Optional[Path] = typer.Option(None, "--github-output", help="Append gate fields for GitHub Actions"), ) -> None: """Review a git range as clustered load paths + confidence brief.""" + import os + + from loadpath.review.gate import FAIL_ON_CHOICES, gate_result, write_github_output + from loadpath.review.render import render_html, render_markdown + + repo_path = repo + if fetch_pr and pr and provider and scm_repo: + from loadpath.providers.pr_fetch import prepare_pull_request + + prepared = prepare_pull_request(provider, scm_repo, pr, repo_path=str(repo)) + repo_path = Path(prepared["repo_path"]) + base = prepared["base"] + head = prepared["head"] + console.print(f"Fetched {provider} #{pr} → {head} (base {base})") + payload = run_review( - repo, base=base, head=head, reindex=reindex, incremental=not full, three_dot=three_dot + repo_path, + base=base, + head=head, + reindex=reindex, + incremental=not full, + three_dot=three_dot, + dirty=dirty, ) if format == "json": import json @@ -101,14 +134,78 @@ def review( else: text = render_markdown(payload) console.print(Markdown(text)) - if out is None: - return + if out is None and not comment and fail_on == "never" and github_output is None and not os.environ.get("GITHUB_OUTPUT"): + gate = gate_result(payload, fail_on) + raise typer.Exit(code=gate["exit_code"]) if out: out.write_text(text, encoding="utf-8") console.print(f"Wrote {out}") elif format != "markdown": console.print(text) + if comment: + from loadpath.providers.scm import provider_for + from loadpath.settings import AppSettings + + settings = AppSettings.load() + name = provider or "github" + number = pr + slug = scm_repo + if not number or not slug: + console.print("--comment needs --pr and --repo owner/name") + raise typer.Exit(code=1) + token = "" + username = "" + host = "" + if name == "github": + token = settings.github_token or os.environ.get("GITHUB_TOKEN") or os.environ.get("LOADPATH_GITHUB_TOKEN") or "" + host = settings.github_host + elif name == "gitlab": + token = settings.gitlab_token or os.environ.get("GITLAB_TOKEN") or os.environ.get("LOADPATH_GITLAB_TOKEN") or "" + host = settings.gitlab_host + else: + token = settings.bitbucket_token + username = settings.bitbucket_username + if not token: + console.print(f"No {name} token in settings or environment") + raise typer.Exit(code=1) + posted = provider_for(name, token, username=username, host=host).upsert_pull_request_comment( + slug, number, render_markdown(payload) + ) + action = "Updated" if posted.get("updated") else "Posted" + console.print(f"{action} Loadpath comment on {slug}#{number}") + + output_path = github_output or (Path(os.environ["GITHUB_OUTPUT"]) if os.environ.get("GITHUB_OUTPUT") else None) + gate = gate_result(payload, fail_on if fail_on in FAIL_ON_CHOICES else "never") + if output_path: + write_github_output(str(output_path), gate, payload) + if fail_on != "never" or gate["exit_code"]: + if not gate["passed"]: + console.print(gate["annotation"]) + raise typer.Exit(code=gate["exit_code"]) + + +@app.command("whatif") +def whatif_cmd( + repo: Path = typer.Argument(Path("."), exists=True, file_okay=False), + node: str = typer.Argument(..., help="Node id from the index (e.g. django.field:billing.Invoice.total)"), +) -> None: + """Walk sinks from one indexed node — no git range required.""" + from loadpath.review.whatif import simulate_node + + try: + payload = simulate_node(repo, node) + except (FileNotFoundError, KeyError) as exc: + console.print(str(exc)) + raise typer.Exit(code=1) from exc + console.print(f"{payload['title']}") + console.print(f"Confidence: {payload['confidence']['level']}") + sinks = payload.get("sinks") or [] + if sinks: + console.print("Sinks: " + ", ".join(s.get("name") or "" for s in sinks[:8])) + for sketch in (payload.get("suggested_tests") or [])[:3]: + console.print(f"Test: {sketch['title']}") + @app.command() def architecture( diff --git a/src/loadpath/extractors/__init__.py b/src/loadpath/extractors/__init__.py index 1eaca3e..de80cb8 100644 --- a/src/loadpath/extractors/__init__.py +++ b/src/loadpath/extractors/__init__.py @@ -2,5 +2,6 @@ from loadpath.extractors.django import extract_django_file, extract_django_paths from loadpath.extractors.react import extract_react_file +from loadpath.extractors.templates import extract_template_file -__all__ = ["extract_django_file", "extract_django_paths", "extract_react_file"] +__all__ = ["extract_django_file", "extract_django_paths", "extract_react_file", "extract_template_file"] diff --git a/src/loadpath/extractors/django.py b/src/loadpath/extractors/django.py index c836e5d..dd61657 100644 --- a/src/loadpath/extractors/django.py +++ b/src/loadpath/extractors/django.py @@ -43,6 +43,26 @@ CELERY_TASK_BASES = {"Task"} DRAMATIQ_TASK_BASES = {"GenericActor"} NINJA_HTTP = {"get", "post", "put", "patch", "delete", "api_operation"} +FASTAPI_HTTP = {"get", "post", "put", "patch", "delete", "options", "head", "trace", "api_route", "websocket"} +CONSUMER_BASES = { + "WebsocketConsumer", + "AsyncWebsocketConsumer", + "JsonWebsocketConsumer", + "AsyncJsonWebsocketConsumer", + "AsyncHttpConsumer", +} +GRAPHENE_BASES = {"ObjectType", "Mutation", "InputObjectType", "Interface", "ScalarType", "DjangoObjectType"} +STRAWBERRY_TYPE_DECS = {"type", "input", "interface", "enum"} +CACHE_METHODS = {"get", "set", "delete", "add", "get_or_set", "incr", "decr", "touch"} +FLAG_FUNCS = { + "flag_is_active", + "switch_is_active", + "sample_is_active", + "flag_enabled", + "is_flag_enabled", + "feature_enabled", + "is_feature_enabled", +} REL_FIELD_TYPES = { "ForeignKey", "OneToOneField", @@ -153,6 +173,10 @@ def _app_from_path(rel: str) -> str | None: "tasks.py", "admin.py", "apps.py", + "consumers.py", + "schema.py", + "routing.py", + "gateway.py", }: return parts[i - 1] if i > 0 else None if part == "management" and i > 0: @@ -246,6 +270,12 @@ def visit_ClassDef(self, node: ast.ClassDef) -> None: ) elif self._task_class(node): pass + elif _has_base(node, CONSUMER_BASES) or node.name.endswith("Consumer"): + self._consumer(node) + elif self._graphql_class(node): + self._graphql_type(node) + elif _has_base(node, {"BaseModel"}) and not _has_base(node, MODEL_BASES): + self._pydantic_model(node) elif _has_base(node, ADMIN_BASES) or node.name.endswith("Admin"): self._admin(node) elif any(x.endswith("Config") for x in _bases(node)) or node.name.endswith("Config"): @@ -264,6 +294,8 @@ def visit_FunctionDef(self, node: ast.FunctionDef) -> None: self._maybe_service_fn(node) self._maybe_fbv(node) self._maybe_ninja(node) + self._maybe_fastapi(node) + self._maybe_graphql_operation(node) self.generic_visit(node) visit_AsyncFunctionDef = visit_FunctionDef # type: ignore[assignment] @@ -293,10 +325,11 @@ def visit_Call(self, node: ast.Call) -> None: elif short in DRAMATIQ_ENQUEUE and self._looks_like_dramatiq_send(fname): self._enqueue(node, fname, broker="dramatiq") elif short == "on_commit": - self.graph.residuals.append( - f"transaction.on_commit() at {self.rel_path}:{node.lineno} — async work may be hidden in a lambda" - ) - self._enqueue_from_on_commit(node) + self._side_effect_on_commit(node) + elif short in CACHE_METHODS and self._looks_like_cache(fname): + self._cache_call(node, fname, short) + elif short in FLAG_FUNCS or self._looks_like_flag(fname): + self._flag_call(node, fname) elif short in {"raw", "execute"} or (short == "extra" and _kw(node, "where")): self.graph.residuals.append(f"Raw SQL ({fname}) in {self.rel_path}:{node.lineno}") elif short in {"select_related", "prefetch_related"}: @@ -452,6 +485,8 @@ def _view(self, node: ast.ClassDef) -> None: extra["authentication"] = _list_names(stmt.value) elif key == "pagination_class": extra["pagination"] = _name(stmt.value) + elif key == "template_name": + extra["template"] = _const_str(stmt.value) if isinstance(stmt, ast.FunctionDef) and stmt.name == "get_queryset": extra["get_queryset"] = True dumped = ast.dump(stmt) @@ -506,6 +541,10 @@ def _view(self, node: ast.ClassDef) -> None: self.add_edge(view.id, tid, EdgeType.HAS_PERMISSION) if extra.get("pagination"): extra["pagination_sink"] = True + if extra.get("template"): + tmpl = extra["template"] + tn = self.add_node(NodeType.TEMPLATE, Path(tmpl).name, tmpl, node.lineno, {"app": self.app}) + self.add_edge(view.id, tn.id, EdgeType.SERVES_TEMPLATE) if queryset_model: self.add_edge( view.id, @@ -768,6 +807,7 @@ def _maybe_fbv(self, node: ast.FunctionDef) -> None: extra = {"app": self.app, "fbv": True, "decorators": decs} view = self.add_node(NodeType.VIEW, node.name, qname, node.lineno, extra) self._note_cross_app_model_imports(view.id) + self._link_model_queries(view.id, node) def _maybe_ninja(self, node: ast.FunctionDef) -> None: for dec in node.decorator_list: @@ -798,6 +838,275 @@ def _maybe_ninja(self, node: ast.FunctionDef) -> None: ) self.add_edge(rn.id, view.id, EdgeType.PUBLISHES_ROUTE) + def _owner_id(self) -> tuple[NodeType, str]: + owner = self.class_stack[-1] if self.class_stack else Path(self.rel_path).stem + owner_type = NodeType.VIEW + if "management/commands" in self.rel_path: + owner_type = NodeType.MANAGEMENT_COMMAND + owner = Path(self.rel_path).stem + elif Path(self.rel_path).name in {"tasks.py", "actors.py"}: + owner_type = NodeType.TASK + elif Path(self.rel_path).name in {"services.py", "use_cases.py"}: + owner_type = NodeType.SERVICE + return owner_type, f"{self.app}.{owner}" + + def _maybe_fastapi(self, node: ast.FunctionDef) -> None: + blob = " ".join(self.imports.values()) + " " + " ".join(self.from_imports.values()) + if "fastapi" not in blob.lower(): + return + for dec in node.decorator_list: + if not isinstance(dec, ast.Call): + continue + fname = _name(dec.func) or "" + short = fname.split(".")[-1] + if short not in FASTAPI_HTTP: + continue + route = _const_str(dec.args[0]) if dec.args else None + if not route: + continue + qname = f"{self.app}.{node.name}" + extra = { + "app": self.app, + "fastapi": True, + "method": "WS" if short == "websocket" else short.upper(), + "route": route, + } + view = self.add_node(NodeType.VIEW, node.name, qname, node.lineno, extra) + rn = self.add_node( + NodeType.FASTAPI_ROUTE, + f"{extra['method']} {route}", + f"{self.app}:{extra['method']} {route}", + node.lineno, + extra, + ) + self.add_edge(rn.id, view.id, EdgeType.PUBLISHES_ROUTE) + self._link_model_queries(view.id, node) + response_model = _name(_kw(dec, "response_model")) + if response_model: + self.add_edge( + rn.id, + node_id(NodeType.PYDANTIC_MODEL, f"{self.app}.{response_model.split('.')[-1]}"), + EdgeType.USES_SERIALIZER, + confidence=0.85, + ) + + def _graphql_class(self, node: ast.ClassDef) -> bool: + decs = _decorator_names(node) + if any("strawberry" in d.lower() and d.split(".")[-1] in STRAWBERRY_TYPE_DECS | {"type"} for d in decs): + return True + bases = {b.split(".")[-1] for b in _bases(node)} + if not (bases & GRAPHENE_BASES): + return False + blob = " ".join(self.imports.values()) + " " + " ".join(self.from_imports.values()) + return any(tok in blob.lower() for tok in ("graphene", "strawberry", "graphql")) + + def _graphql_type(self, node: ast.ClassDef) -> None: + qname = f"{self.app}.{node.name}" + kind = "type" + for d in _decorator_names(node): + if "strawberry" in d.lower(): + kind = d.split(".")[-1] + break + bases = {b.split(".")[-1] for b in _bases(node)} + if "Mutation" in bases: + kind = "mutation" + extra = {"app": self.app, "kind": kind, "graphql": True} + gql = self.add_node(NodeType.GRAPHQL_TYPE, node.name, qname, node.lineno, extra) + root = node.name in {"Query", "Mutation", "Subscription"} or kind == "mutation" + for stmt in node.body: + fname = None + if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name): + fname = stmt.target.id + elif isinstance(stmt, ast.Assign) and stmt.targets and isinstance(stmt.targets[0], ast.Name): + cand = stmt.targets[0].id + if not cand.startswith("_") and cand not in {"Meta"}: + fname = cand + elif isinstance(stmt, ast.FunctionDef) and stmt.name == "mutate": + op = self.add_node( + NodeType.GRAPHQL_OPERATION, + node.name, + f"graphql.{node.name}", + stmt.lineno, + {"app": self.app, "kind": "mutation"}, + ) + self.add_edge(gql.id, op.id, EdgeType.PUBLISHES_GRAPHQL) + self._link_model_queries(op.id, stmt) + if not fname: + continue + field = self.add_node( + NodeType.GRAPHQL_FIELD, + fname, + f"{qname}.{fname}", + stmt.lineno, + {"app": self.app}, + ) + self.add_edge(gql.id, field.id, EdgeType.HAS_FIELD) + if root and not any( + n.type is NodeType.GRAPHQL_OPERATION and n.name == fname for n in self.graph.nodes + ): + op_kind = ( + "query" + if node.name == "Query" + else ("subscription" if node.name == "Subscription" else "mutation") + ) + op = self.add_node( + NodeType.GRAPHQL_OPERATION, + fname, + f"graphql.{fname}", + stmt.lineno, + {"app": self.app, "kind": op_kind}, + ) + self.add_edge(gql.id, op.id, EdgeType.PUBLISHES_GRAPHQL) + if kind == "mutation" or node.name in {"Query", "Mutation", "Subscription"}: + op_kind = "query" if node.name == "Query" else ("subscription" if node.name == "Subscription" else "mutation") + if not any(n.type is NodeType.GRAPHQL_OPERATION and n.name == node.name for n in self.graph.nodes): + op = self.add_node( + NodeType.GRAPHQL_OPERATION, + node.name, + f"graphql.{node.name}", + node.lineno, + {"app": self.app, "kind": op_kind}, + ) + self.add_edge(gql.id, op.id, EdgeType.PUBLISHES_GRAPHQL) + + def _maybe_graphql_operation(self, node: ast.FunctionDef) -> None: + for dec in node.decorator_list: + dname = _name(dec.func if isinstance(dec, ast.Call) else dec) or "" + if "strawberry" not in dname.lower(): + continue + short = dname.split(".")[-1] + if short not in {"mutation", "field", "subscription"}: + continue + kind = "query" if short == "field" else short + op = self.add_node( + NodeType.GRAPHQL_OPERATION, + node.name, + f"graphql.{node.name}", + node.lineno, + {"app": self.app, "kind": kind, "strawberry": True}, + ) + self._link_model_queries(op.id, node) + if self.class_stack: + self.add_edge( + node_id(NodeType.GRAPHQL_TYPE, f"{self.app}.{self.class_stack[-1]}"), + op.id, + EdgeType.PUBLISHES_GRAPHQL, + ) + + def _pydantic_model(self, node: ast.ClassDef) -> None: + qname = f"{self.app}.{node.name}" + extra: dict = {"app": self.app, "pydantic": True} + model = self.add_node(NodeType.PYDANTIC_MODEL, node.name, qname, node.lineno, extra) + for stmt in node.body: + if isinstance(stmt, ast.AnnAssign) and isinstance(stmt.target, ast.Name): + fname = stmt.target.id + field = self.add_node( + NodeType.SERIALIZER_FIELD, + fname, + f"{qname}.{fname}", + stmt.lineno, + {"app": self.app, "pydantic": True}, + ) + self.add_edge(model.id, field.id, EdgeType.HAS_FIELD) + + def _consumer(self, node: ast.ClassDef) -> None: + qname = f"{self.app}.{node.name}" + extra = {"app": self.app, "bases": _bases(node), "websocket": True} + consumer = self.add_node(NodeType.CONSUMER, node.name, qname, node.lineno, extra) + self._link_model_queries(consumer.id, node) + + def _link_model_queries(self, owner_id: str, node: ast.AST) -> None: + seen: set[str] = set() + for child in ast.walk(node): + if not isinstance(child, ast.Attribute) or child.attr != "objects": + continue + model = _name(child.value) + if not model: + continue + short = model.split(".")[-1] + if not short[:1].isupper(): + continue + app = self.app + head = model.split(".")[0] + target = self.from_imports.get(head) or self.imports.get(head) or "" + if "models" in target.split("."): + parts = target.split(".") + if "models" in parts: + idx = parts.index("models") + if idx > 0 and parts[idx - 1] not in {"django", "db"}: + app = parts[idx - 1] + key = f"{app}.{short}" + if key in seen: + continue + seen.add(key) + self.add_edge( + owner_id, + node_id(NodeType.MODEL, key), + EdgeType.QUERIES_MODEL, + confidence=0.8, + ) + + def _looks_like_cache(self, fname: str) -> bool: + low = fname.lower() + return "cache" in low or low.startswith("caches[") + + def _looks_like_flag(self, fname: str) -> bool: + low = fname.lower() + if fname.split(".")[-1] not in FLAG_FUNCS | {"is_active", "is_enabled"}: + return False + return any(tok in low for tok in ("flag", "waffle", "feature", "unleash", "flags")) + + def _cache_call(self, node: ast.Call, fname: str, method: str) -> None: + key = _const_str(node.args[0]) if node.args else None + if not key: + return + qname = f"cache:{key}" + cache = self.add_node( + NodeType.CACHE_KEY, + key, + qname, + node.lineno, + {"app": self.app, "method": method}, + ) + owner_type, owner_q = self._owner_id() + etype = EdgeType.INVALIDATES_CACHE if method in {"set", "delete", "add"} else EdgeType.CALLS + self.add_edge(node_id(owner_type, owner_q), cache.id, etype, extra={"call": fname, "line": node.lineno}) + + def _flag_call(self, node: ast.Call, fname: str) -> None: + name = None + for arg in node.args: + name = _const_str(arg) + if name: + break + if not name: + name = _const_str(_kw(node, "name") or _kw(node, "flag") or _kw(node, "key")) + if not name: + return + flag = self.add_node( + NodeType.FEATURE_FLAG, + name, + f"flag:{name}", + node.lineno, + {"app": self.app, "call": fname}, + ) + owner_type, owner_q = self._owner_id() + self.add_edge(node_id(owner_type, owner_q), flag.id, EdgeType.CHECKS_FLAG, extra={"line": node.lineno}) + + def _side_effect_on_commit(self, node: ast.Call) -> None: + self.graph.residuals.append( + f"transaction.on_commit() at {self.rel_path}:{node.lineno} — async work may be hidden in a lambda" + ) + owner_type, owner_q = self._owner_id() + effect = self.add_node( + NodeType.SIDE_EFFECT, + "on_commit", + f"{owner_q}:on_commit:{node.lineno}", + node.lineno, + {"app": self.app, "kind": "on_commit"}, + ) + self.add_edge(node_id(owner_type, owner_q), effect.id, EdgeType.ON_COMMIT, extra={"line": node.lineno}) + self._enqueue_from_on_commit(node) + def _maybe_receiver(self, node: ast.FunctionDef) -> None: for dec in node.decorator_list: dname = _name(dec.func if isinstance(dec, ast.Call) else dec) or "" @@ -916,19 +1225,24 @@ def _url_path(self, node: ast.Call) -> None: if route is None: return view_name = None + asgi = False if len(node.args) > 1: view_expr = node.args[1] - if isinstance(view_expr, ast.Call) and _name(view_expr.func) and "as_view" in (_name(view_expr.func) or ""): - view_name = (_name(view_expr.func) or "").replace(".as_view", "") - # mapping dict for viewsets + func_name = _name(view_expr.func) if isinstance(view_expr, ast.Call) else _name(view_expr) + func_name = func_name or "" + if isinstance(view_expr, ast.Call) and "as_view" in func_name: + view_name = func_name.replace(".as_view", "") if view_expr.args and isinstance(view_expr.args[0], ast.Dict): for k, v in zip(view_expr.args[0].keys, view_expr.args[0].values, strict=True): method = _const_str(k) action = _name(v) if method and action: pass + elif isinstance(view_expr, ast.Call) and "as_asgi" in func_name: + view_name = func_name.replace(".as_asgi", "") + asgi = True else: - view_name = _name(view_expr) + view_name = func_name or _name(view_expr) name = _const_str(_kw(node, "name")) include_mod = None if len(node.args) > 1: @@ -938,21 +1252,25 @@ def _url_path(self, node: ast.Call) -> None: if fn.split(".")[-1] == "include": include_mod = self._include_target(view_expr) view_name = None + websocket = asgi or (route or "").lstrip("/").startswith("ws") extra = { "app": self.app, "route": route, "url_name": name, "view": view_name, "include": include_mod, + "websocket": websocket, } display, qname = self._route_identity(route, include_mod, name, node.lineno) - route_node = self.add_node(NodeType.ROUTE, display, qname, node.lineno, extra) + ntype = NodeType.WEBSOCKET_ROUTE if websocket else NodeType.ROUTE + route_node = self.add_node(ntype, display, qname, node.lineno, extra) if name: un = self.add_node(NodeType.URL_NAME, name, name, node.lineno, extra) self.add_edge(route_node.id, un.id, EdgeType.BELONGS_TO) if view_name: - vq = f"{self.app}.{view_name.split('.')[-1]}" - self.add_edge(route_node.id, node_id(NodeType.VIEW, vq), EdgeType.PUBLISHES_ROUTE) + short = view_name.split(".")[-1] + target_type = NodeType.CONSUMER if websocket else NodeType.VIEW + self.add_edge(route_node.id, node_id(target_type, f"{self.app}.{short}"), EdgeType.PUBLISHES_ROUTE) def _router_register(self, node: ast.Call) -> None: if len(node.args) < 2: diff --git a/src/loadpath/extractors/react.py b/src/loadpath/extractors/react.py index 114009a..4c5af2b 100644 --- a/src/loadpath/extractors/react.py +++ b/src/loadpath/extractors/react.py @@ -66,6 +66,12 @@ BOUNDARY_RE = re.compile(r"""\b(ErrorBoundary|Suspense)\b""") RTK_RE = re.compile(r"""createApi\s*\(\s*\{""") FEATURE_FOLDER_RE = re.compile(r"""features/([^/]+)""") +GQL_DOC_RE = re.compile( + r"""(?:gql|graphql)\s*(?:<[^>]*>)?\s*`([^`]+)`""", + re.S, +) +GQL_OP_RE = re.compile(r"""\b(query|mutation|subscription)\s+([A-Za-z_]\w*)""") +GQL_SELECTION_RE = re.compile(r"""\{\s*([A-Za-z_]\w*)""") def _feature_from_path(rel: str) -> str | None: @@ -303,6 +309,32 @@ def edge(src: str, dst: str, etype: EdgeType, confidence: float = 1.0, extra: di rn = add(NodeType.REACT_ROUTE, rpath, f"react.route:{rpath}", line, {"element": page_name}) edge(rn.id, node_id(NodeType.PAGE, f"{feature or 'app'}.{page_name}"), EdgeType.PUBLISHES_ROUTE) + for m in GQL_DOC_RE.finditer(source): + body = m.group(1) + line = source[: m.start()].count("\n") + 1 + ops = GQL_OP_RE.findall(body) + if not ops: + ops = [("query", f"{stem}Query")] + selections = GQL_SELECTION_RE.findall(body) + for kind, op_name in ops: + extra = { + "kind": kind.lower(), + "feature": feature, + "client": True, + "selections": [s for s in selections if s not in {"query", "mutation", "subscription"}][:8], + } + op = add( + NodeType.GRAPHQL_OPERATION, + op_name, + f"graphql.{op_name}", + line, + extra, + ) + for owner in hooks or components: + edge(owner.id, op.id, EdgeType.CALLS) + if feature: + edge(node_id(NodeType.FEATURE_MODULE, f"features.{feature}"), op.id, EdgeType.CALLS) + for m in ZOD_RE.finditer(source): name, body = m.group(1), m.group(2) line = source[: m.start()].count("\n") + 1 diff --git a/src/loadpath/extractors/templates.py b/src/loadpath/extractors/templates.py new file mode 100644 index 0000000..a332647 --- /dev/null +++ b/src/loadpath/extractors/templates.py @@ -0,0 +1,106 @@ +"""Django templates and HTMX attributes as sinks on the load path.""" + +from __future__ import annotations + +import re +from pathlib import Path + +from loadpath.config import LoadpathConfig +from loadpath.types import Edge, EdgeType, ExtractedGraph, Node, NodeType, node_id + +HTMX_RE = re.compile( + r"""\bhx-(get|post|put|patch|delete)\s*=\s*["']([^"']+)["']""", + re.I, +) +URL_TAG_RE = re.compile(r"""\{\%\s*url\s+['"]([^'"]+)['"]""") +INCLUDE_RE = re.compile(r"""\{\%\s*include\s+['"]([^'"]+)['"]""") +EXTENDS_RE = re.compile(r"""\{\%\s*extends\s+['"]([^'"]+)['"]""") +BLOCK_RE = re.compile(r"""\{\%\s*block\s+(\w+)""") + + +def _app_from_template(rel: str) -> str: + parts = Path(rel).parts + if "templates" in parts: + idx = parts.index("templates") + if idx > 0: + return parts[idx - 1] + if idx + 1 < len(parts): + return parts[idx + 1] + if len(parts) >= 2: + return parts[-2] + return "unknown" + + +def template_qname(rel: str) -> str: + """Django template name: path after `templates/`, else the relative file path.""" + parts = Path(rel.replace("\\", "/")).parts + if "templates" in parts: + idx = parts.index("templates") + tail = "/".join(parts[idx + 1 :]) + if tail: + return tail + return rel.replace("\\", "/") + + +def extract_template_file(rel_path: str, source: str, config: LoadpathConfig) -> ExtractedGraph: + rel = rel_path.replace("\\", "/") + graph = ExtractedGraph() + app = _app_from_template(rel) + context = config.context_for_django_app(app) + name = Path(rel).name + qname = template_qname(rel) + extra = { + "app": app, + "blocks": BLOCK_RE.findall(source)[:12], + "htmx": bool(HTMX_RE.search(source)), + } + template = Node( + id=node_id(NodeType.TEMPLATE, qname), + type=NodeType.TEMPLATE, + name=name, + qualified_name=qname, + file_path=rel, + start_line=1, + context=context, + extra=extra, + ) + graph.nodes.append(template) + + for tag in URL_TAG_RE.findall(source): + graph.edges.append( + Edge( + src=template.id, + dst=node_id(NodeType.URL_NAME, tag), + type=EdgeType.CALLS, + confidence=0.8, + extra={"url_name": tag}, + ) + ) + + for other in INCLUDE_RE.findall(source) + EXTENDS_RE.findall(source): + graph.edges.append( + Edge( + src=template.id, + dst=node_id(NodeType.TEMPLATE, other), + type=EdgeType.RENDERS, + confidence=0.9, + extra={"include": other}, + ) + ) + + for match in HTMX_RE.finditer(source): + method, url = match.group(1).upper(), match.group(2) + call_name = f"{method} {url}" + call = Node( + id=node_id(NodeType.HTMX_CALL, f"{rel}:{call_name}"), + type=NodeType.HTMX_CALL, + name=call_name, + qualified_name=f"{rel}:{call_name}", + file_path=rel, + start_line=source[: match.start()].count("\n") + 1, + context=context, + extra={"app": app, "method": method, "url": url}, + ) + graph.nodes.append(call) + graph.edges.append(Edge(src=template.id, dst=call.id, type=EdgeType.HTMX_CALLS)) + return graph diff --git a/src/loadpath/graph/store.py b/src/loadpath/graph/store.py index de2cd58..589e4bf 100644 --- a/src/loadpath/graph/store.py +++ b/src/loadpath/graph/store.py @@ -300,11 +300,25 @@ def get_review(self, review_id: str) -> dict[str, Any] | None: "payload": json.loads(row["payload"]), } - def list_reviews(self) -> list[dict[str, Any]]: - rows = self.conn.execute( - "SELECT id, created_at, repo_root, base_ref, head_ref FROM reviews ORDER BY created_at DESC" - ).fetchall() - return [dict(r) for r in rows] + def list_reviews(self, *, include_payload: bool = False, limit: int = 40) -> list[dict[str, Any]]: + sql = "SELECT id, created_at, repo_root, base_ref, head_ref" + if include_payload: + sql += ", payload" + sql += " FROM reviews ORDER BY created_at DESC LIMIT ?" + rows = self.conn.execute(sql, (max(1, min(limit, 200)),)).fetchall() + out: list[dict[str, Any]] = [] + for row in rows: + item = { + "id": row["id"], + "created_at": row["created_at"], + "repo_root": row["repo_root"], + "base_ref": row["base_ref"], + "head_ref": row["head_ref"], + } + if include_payload: + item["payload"] = json.loads(row["payload"]) + out.append(item) + return out def counts(self) -> dict[str, int]: n = self.conn.execute("SELECT COUNT(*) AS c FROM nodes").fetchone()["c"] diff --git a/src/loadpath/index.py b/src/loadpath/index.py index 1e7abc3..5f6cee1 100644 --- a/src/loadpath/index.py +++ b/src/loadpath/index.py @@ -7,15 +7,16 @@ from loadpath.config import LoadpathConfig, load_config from loadpath.extractors.django import extract_django_file from loadpath.extractors.react import extract_react_file +from loadpath.extractors.templates import extract_template_file from loadpath.extractors.django_boot import try_boot_models from loadpath.graph.store import GraphStore from loadpath.stitch.openapi import stitch from loadpath.types import GENERATED_PATH_MARKERS, ExtractedGraph, Node, NodeType, node_id PY_SKIP = {"migrations"} # still extract migrations, just not skip -INDEX_EXTENSIONS = {".py", ".ts", ".tsx", ".js", ".jsx"} +INDEX_EXTENSIONS = {".py", ".ts", ".tsx", ".js", ".jsx", ".html", ".htm"} # Bump when extractor/stitch node identity changes so incremental indexes rebuild. -INDEX_REVISION = "8" +INDEX_REVISION = "10" def default_db_path(repo_root: Path) -> Path: @@ -68,6 +69,8 @@ def file_hash(path: Path) -> str: def language_for(path: Path) -> str: if path.suffix == ".py": return "python" + if path.suffix in {".html", ".htm"}: + return "html" if path.suffix in {".ts", ".tsx"}: return "typescript" return "javascript" @@ -177,7 +180,9 @@ def index_repo( continue store.delete_file_nodes(rel, drop_incoming=False) source = path.read_text(encoding="utf-8", errors="replace") - if path.suffix == ".py": + if path.suffix in {".html", ".htm"}: + graph = extract_template_file(rel, source, config) + elif path.suffix == ".py": graph = extract_django_file(rel, source, config) else: graph = extract_react_file(rel, source, config) @@ -234,7 +239,7 @@ def _assign_contexts(graph: ExtractedGraph, config: LoadpathConfig, rel: str) -> for node in graph.nodes: if node.context: continue - if node.type.value.startswith("django.") or node.type.value.startswith("react."): + if node.type.value.startswith(("django.", "react.", "fastapi.", "graphql.")): if rel.endswith(".py"): app = (node.extra or {}).get("app") if app: diff --git a/src/loadpath/mcp/compact.py b/src/loadpath/mcp/compact.py index 00f9b24..5df0bcf 100644 --- a/src/loadpath/mcp/compact.py +++ b/src/loadpath/mcp/compact.py @@ -42,6 +42,10 @@ def compact_review(review: dict[str, Any]) -> dict[str, Any]: "depth_note": review.get("depth_note"), "residuals": (review.get("residuals") or [])[:12], "low_risk": review.get("low_risk"), + "contract_break": review.get("contract_break"), + "auth": review.get("auth"), + "suggested_tests": (review.get("suggested_tests") or [])[:6], + "trend": review.get("trend"), "index": review.get("index"), "workspace": review.get("workspace"), } diff --git a/src/loadpath/mcp/server.py b/src/loadpath/mcp/server.py index abdd217..5546cac 100644 --- a/src/loadpath/mcp/server.py +++ b/src/loadpath/mcp/server.py @@ -65,16 +65,24 @@ def _register_tools(mcp: MCPServer) -> None: )(tools.detect_repo) mcp.tool( name="list_pull_requests", - description="List GitHub or Bitbucket pull requests using tokens stored in Loadpath settings.", + description="List GitHub, GitLab, or Bitbucket pull requests using tokens stored in Loadpath settings.", )(tools.list_pull_requests) mcp.tool( name="list_remote_repositories", - description="List GitHub or Bitbucket repositories the signed-in account can access.", + description="List GitHub, GitLab, or Bitbucket repositories the signed-in account can access.", )(tools.list_remote_repositories) mcp.tool( name="post_review_comment", description="Upsert the single Loadpath markdown brief on a pull request (updated in place).", )(tools.post_review_comment) + mcp.tool( + name="what_if", + description="Simulate a change from one indexed node and list sinks, auth, and suggested tests. No git range.", + )(tools.what_if) + mcp.tool( + name="review_pull_request", + description="Fetch a GitHub/GitLab/Bitbucket PR into a local clone and review the three-dot range.", + )(tools.review_pull_request) def create_mcp_server( diff --git a/src/loadpath/mcp/tools.py b/src/loadpath/mcp/tools.py index 4357bca..8104dc9 100644 --- a/src/loadpath/mcp/tools.py +++ b/src/loadpath/mcp/tools.py @@ -20,12 +20,22 @@ def _with_scm(provider: str, fn: Callable[[Any], _T]) -> _T | dict[str, str]: settings = AppSettings.load() - token = settings.github_token if provider == "github" else settings.bitbucket_token - username = settings.bitbucket_username + token = "" + username = "" + host = "" + if provider == "github": + token = settings.github_token + host = settings.github_host + elif provider == "gitlab": + token = settings.gitlab_token + host = settings.gitlab_host + else: + token = settings.bitbucket_token + username = settings.bitbucket_username if not token: return {"error": f"No {provider} token configured in Loadpath settings"} try: - return fn(provider_for(provider, token, username=username)) + return fn(provider_for(provider, token, username=username, host=host)) except httpx.HTTPStatusError as exc: if ( provider == "bitbucket" @@ -120,6 +130,7 @@ def review_range( reindex: bool = True, incremental: bool = True, three_dot: bool = True, + dirty: bool = False, ) -> dict[str, Any]: """Review a git range as a load path: sinks, confidence, reviewers. Not hunk comments.""" root = _repo(repo_path) @@ -133,6 +144,7 @@ def review_range( reindex=reindex, incremental=incremental, three_dot=three_dot, + dirty=dirty, ) except FileNotFoundError as exc: return {"error": str(exc)} @@ -156,7 +168,7 @@ def list_pull_requests( repo: str, state: str = "open", ) -> dict[str, Any]: - """List pull requests from GitHub or Bitbucket using tokens in ~/.loadpath/settings.json.""" + """List pull requests from GitHub, GitLab, or Bitbucket using tokens in ~/.loadpath/settings.json.""" result = _with_scm(provider, lambda scm: scm.list_pull_requests(repo, state=state)) if isinstance(result, dict) and result.get("error"): return result @@ -164,7 +176,7 @@ def list_pull_requests( def list_remote_repositories(provider: str) -> dict[str, Any]: - """List GitHub or Bitbucket repositories the saved token can access.""" + """List GitHub, GitLab, or Bitbucket repositories the saved token can access.""" settings = AppSettings.load() result = _with_scm(provider, lambda scm: (scm.list_repositories(), scm.current_user())) if isinstance(result, dict) and result.get("error"): @@ -188,3 +200,47 @@ def post_review_comment( lambda scm: scm.upsert_pull_request_comment(repo, number, markdown), ) return result + + +def what_if(repo_path: str, node_id: str) -> dict[str, Any]: + """Walk sinks from one indexed node without a git range.""" + root = _repo(repo_path) + if isinstance(root, dict): + return root + from loadpath.review.whatif import simulate_node + + try: + payload = simulate_node(root, node_id) + except (FileNotFoundError, KeyError) as exc: + return {"error": str(exc)} + payload.pop("nodes", None) + payload.pop("edges", None) + return payload + + +def review_pull_request( + provider: str, + repo: str, + number: int, + repo_path: str | None = None, +) -> dict[str, Any]: + """Fetch a PR/MR into a local clone and review the three-dot range.""" + from loadpath.providers.pr_fetch import prepare_pull_request + + try: + prepared = prepare_pull_request(provider, repo, number, repo_path=repo_path) + review = run_review( + Path(prepared["repo_path"]), + base=prepared["base"], + head=prepared["head"], + reindex=True, + incremental=True, + three_dot=True, + ) + except Exception as exc: # noqa: BLE001 + return {"error": str(exc)} + review["markdown"] = render_markdown(review) + register_workspace(Path(prepared["repo_path"])) + compact = compact_review(review) + compact["pull_request"] = prepared + return compact diff --git a/src/loadpath/providers/oauth.py b/src/loadpath/providers/oauth.py index 9107a93..69cb59d 100644 --- a/src/loadpath/providers/oauth.py +++ b/src/loadpath/providers/oauth.py @@ -21,6 +21,7 @@ BITBUCKET_AUTHORIZE_URL = "https://bitbucket.org/site/oauth2/authorize" BITBUCKET_TOKEN_URL = "https://bitbucket.org/site/oauth2/access_token" BITBUCKET_SCOPES = "account repository pullrequest" +GITLAB_SCOPES = "api read_user read_repository" LOOPBACK_HOSTS = frozenset({"127.0.0.1", "localhost", "::1", "testserver", "testclient"}) GITHUB_DEVICE_HOSTS = frozenset({"github.com", "www.github.com"}) MAX_PENDING = 8 @@ -44,25 +45,30 @@ def is_loopback_request(host_header: str, origin: str = "") -> bool: return _hostname(host_header) in LOOPBACK_HOSTS -def _is_github_device_url(url: str) -> bool: +def _is_github_device_url(url: str, host: str = "github.com") -> bool: try: parsed = urlparse(url) except ValueError: return False if parsed.scheme != "https" or parsed.username or parsed.password: return False - if (parsed.hostname or "").lower() not in GITHUB_DEVICE_HOSTS: + hostname = (parsed.hostname or "").lower() + allowed = {host.lower(), f"www.{host.lower()}"} + if host.lower() in {"github.com", "www.github.com"}: + allowed |= GITHUB_DEVICE_HOSTS + if hostname not in allowed: return False return parsed.path.rstrip("/") == "/login/device" -def github_device_urls(data: dict[str, Any], user_code: str) -> tuple[str, str]: - verification = data.get("verification_uri") or "https://github.com/login/device" - if not _is_github_device_url(verification): +def github_device_urls(data: dict[str, Any], user_code: str, host: str = "github.com") -> tuple[str, str]: + origin = f"https://{host}" + verification = data.get("verification_uri") or f"{origin}/login/device" + if not _is_github_device_url(verification, host): raise ValueError("GitHub returned an unexpected verification URL") complete = data.get("verification_uri_complete") or "" - if not _is_github_device_url(complete): - complete = f"https://github.com/login/device?user_code={user_code}" + if not _is_github_device_url(complete, host): + complete = f"{origin}/login/device?user_code={user_code}" return verification, complete @@ -78,6 +84,22 @@ def _remember_pending(flow_id: str, row: dict[str, Any]) -> None: _pending[flow_id] = row +def github_web_host(settings: AppSettings | None = None) -> str: + settings = settings or AppSettings.load() + host = (os.environ.get("LOADPATH_GITHUB_HOST") or settings.github_host or "github.com").strip() + host = host.removeprefix("https://").removeprefix("http://").strip("/") + if host in {"", "api.github.com", "www.github.com"}: + return "github.com" + return host + + +def gitlab_web_host(settings: AppSettings | None = None) -> str: + settings = settings or AppSettings.load() + host = (os.environ.get("LOADPATH_GITLAB_HOST") or settings.gitlab_host or "gitlab.com").strip() + host = host.removeprefix("https://").removeprefix("http://").strip("/") + return host or "gitlab.com" + + def github_client_id(settings: AppSettings | None = None) -> str: settings = settings or AppSettings.load() return (os.environ.get("LOADPATH_GITHUB_CLIENT_ID") or settings.github_oauth_client_id or "").strip() @@ -92,15 +114,33 @@ def bitbucket_oauth_client(settings: AppSettings | None = None) -> tuple[str, st return client_id, secret +def gitlab_oauth_client(settings: AppSettings | None = None) -> tuple[str, str]: + settings = settings or AppSettings.load() + client_id = (os.environ.get("LOADPATH_GITLAB_CLIENT_ID") or settings.gitlab_oauth_client_id or "").strip() + secret = ( + os.environ.get("LOADPATH_GITLAB_CLIENT_SECRET") or settings.gitlab_oauth_client_secret or "" + ).strip() + return client_id, secret + + def oauth_status(settings: AppSettings | None = None) -> dict[str, Any]: settings = settings or AppSettings.load() bb_id, bb_secret = bitbucket_oauth_client(settings) + gl_id, gl_secret = gitlab_oauth_client(settings) return { "github": { "connected": bool(settings.github_token), "user": settings.github_user, "token_set": bool(settings.github_token), "oauth_ready": bool(github_client_id(settings)), + "host": github_web_host(settings), + }, + "gitlab": { + "connected": bool(settings.gitlab_token), + "user": settings.gitlab_user, + "token_set": bool(settings.gitlab_token), + "oauth_ready": bool(gl_id and gl_secret), + "host": gitlab_web_host(settings), }, "bitbucket": { "connected": bool(settings.bitbucket_token), @@ -124,8 +164,10 @@ def start_github_device(client: httpx.Client | None = None) -> dict[str, Any]: "or paste a GitHub OAuth App client ID in Settings (enable Device Flow on the app)." ) http = _client(client) + host = github_web_host(settings) + device_url = f"https://{host}/login/device/code" response = http.post( - GITHUB_DEVICE_CODE_URL, + device_url, data={"client_id": client_id, "scope": GITHUB_SCOPES}, headers={"Accept": "application/json"}, ) @@ -135,7 +177,7 @@ def start_github_device(client: httpx.Client | None = None) -> dict[str, Any]: user_code = data.get("user_code") or "" if not device_code or not user_code: raise ValueError("GitHub did not return a device code") - verification, complete = github_device_urls(data, user_code) + verification, complete = github_device_urls(data, user_code, host=host) flow_id = secrets.token_urlsafe(16) interval = int(data.get("interval") or 5) expires_in = int(data.get("expires_in") or 900) @@ -145,6 +187,7 @@ def start_github_device(client: httpx.Client | None = None) -> dict[str, Any]: "provider": "github", "device_code": device_code, "client_id": client_id, + "host": host, "interval": interval, "expires_at": time.time() + expires_in, }, @@ -169,8 +212,10 @@ def poll_github_device(flow_id: str, client: httpx.Client | None = None) -> dict _pending.pop(flow_id, None) return {"status": "expired"} http = _client(client) + host = pending.get("host") or "github.com" + token_url = f"https://{host}/login/oauth/access_token" response = http.post( - GITHUB_TOKEN_URL, + token_url, data={ "client_id": pending["client_id"], "device_code": pending["device_code"], @@ -203,7 +248,7 @@ def poll_github_device(flow_id: str, client: httpx.Client | None = None) -> dict raise ValueError("GitHub did not return an access token") with _lock: _pending.pop(flow_id, None) - settings = _store_login("github", token, client=http) + settings = _store_login("github", token, client=http, host=host) return {"status": "complete", **oauth_status(settings)["github"]} @@ -274,6 +319,78 @@ def finish_bitbucket_authorize( ) +def start_gitlab_authorize(redirect_uri: str) -> dict[str, Any]: + settings = AppSettings.load() + client_id, secret = gitlab_oauth_client(settings) + if not client_id or not secret: + raise ValueError( + "GitLab OAuth application is not configured. Set LOADPATH_GITLAB_CLIENT_ID and " + "LOADPATH_GITLAB_CLIENT_SECRET, or paste the application id and secret in Settings. " + f"Callback URL must be {redirect_uri}." + ) + host = gitlab_web_host(settings) + flow_id = secrets.token_urlsafe(16) + _remember_pending( + flow_id, + { + "provider": "gitlab", + "redirect_uri": redirect_uri, + "host": host, + "expires_at": time.time() + 600, + }, + ) + query = urlencode( + { + "client_id": client_id, + "response_type": "code", + "scope": GITLAB_SCOPES, + "state": flow_id, + "redirect_uri": redirect_uri, + } + ) + return {"flow_id": flow_id, "authorize_url": f"https://{host}/oauth/authorize?{query}"} + + +def finish_gitlab_authorize( + code: str, + state: str, + client: httpx.Client | None = None, +) -> AppSettings: + with _lock: + pending = _pending.pop(state, None) + if not pending or pending.get("provider") != "gitlab": + raise ValueError("Unknown or expired GitLab sign-in") + if pending["expires_at"] < time.time(): + raise ValueError("GitLab sign-in expired. Start again from Settings.") + settings = AppSettings.load() + client_id, secret = gitlab_oauth_client(settings) + host = pending.get("host") or gitlab_web_host(settings) + http = _client(client) + response = http.post( + f"https://{host}/oauth/token", + data={ + "grant_type": "authorization_code", + "code": code, + "redirect_uri": pending["redirect_uri"], + "client_id": client_id, + "client_secret": secret, + }, + headers={"Accept": "application/json"}, + ) + response.raise_for_status() + data = response.json() + token = data.get("access_token") or "" + if not token: + raise ValueError(data.get("error_description") or "GitLab did not return an access token") + return _store_login( + "gitlab", + token, + refresh_token=data.get("refresh_token") or "", + client=http, + host=host, + ) + + def refresh_bitbucket_access_token( settings: AppSettings | None = None, client: httpx.Client | None = None, @@ -311,6 +428,10 @@ def disconnect_scm(provider: str) -> AppSettings: settings.bitbucket_token = "" settings.bitbucket_user = "" settings.bitbucket_refresh_token = "" + elif provider == "gitlab": + settings.gitlab_token = "" + settings.gitlab_user = "" + settings.gitlab_refresh_token = "" else: raise ValueError(f"Unknown SCM provider: {provider}") settings.save() @@ -323,22 +444,33 @@ def _store_login( *, refresh_token: str = "", client: httpx.Client | None = None, + host: str = "", ) -> AppSettings: settings = AppSettings.load() username = "" if provider == "github": settings.github_token = token + if host: + settings.github_host = host if host != "github.com" else settings.github_host + elif provider == "gitlab": + settings.gitlab_token = token + if host: + settings.gitlab_host = host if host != "gitlab.com" else settings.gitlab_host + if refresh_token: + settings.gitlab_refresh_token = refresh_token else: settings.bitbucket_token = token settings.bitbucket_username = "" if refresh_token: settings.bitbucket_refresh_token = refresh_token try: - scm = provider_for(provider, token, username=username, client=client) + scm = provider_for(provider, token, username=username, client=client, host=host) profile = scm.current_user() login = profile.get("login") or "" if provider == "github": settings.github_user = login + elif provider == "gitlab": + settings.gitlab_user = login else: settings.bitbucket_user = login except httpx.HTTPError: diff --git a/src/loadpath/providers/pr_fetch.py b/src/loadpath/providers/pr_fetch.py new file mode 100644 index 0000000..7b9a520 --- /dev/null +++ b/src/loadpath/providers/pr_fetch.py @@ -0,0 +1,173 @@ +"""Fetch a PR/MR into a local clone so review can walk it without a pre-synced checkout.""" + +from __future__ import annotations + +import os +import subprocess +from pathlib import Path +from typing import Any +from urllib.parse import quote + +from loadpath.providers.scm import PullRequest, provider_for +from loadpath.settings import AppSettings, register_workspace + +_GIT_TIMEOUT = 120 +FETCH_SPEC = { + "github": "pull/{n}/head", + "gitlab": "merge-requests/{n}/head", + "bitbucket": "pull-requests/{n}/from", +} + + +def clones_root() -> Path: + return Path.home() / ".loadpath" / "clones" + + +def fetch_spec(provider: str, number: int) -> str: + template = FETCH_SPEC.get(provider) + if not template: + raise ValueError(f"Cannot fetch pull requests from {provider}") + return template.format(n=int(number)) + + +def local_pr_ref(number: int) -> str: + return f"refs/loadpath/pr-{int(number)}" + + +def _git(repo: Path, *args: str, env: dict[str, str] | None = None) -> str: + return subprocess.check_output( + ["git", "-C", str(repo), *args], + text=True, + stderr=subprocess.PIPE, + timeout=_GIT_TIMEOUT, + env=env, + ) + + +def _token_for(settings: AppSettings, provider: str) -> tuple[str, str]: + if provider == "github": + token = settings.github_token or os.environ.get("GITHUB_TOKEN") or os.environ.get("LOADPATH_GITHUB_TOKEN") or "" + return token, settings.github_host or "" + if provider == "gitlab": + token = settings.gitlab_token or os.environ.get("GITLAB_TOKEN") or os.environ.get("LOADPATH_GITLAB_TOKEN") or "" + return token, settings.gitlab_host or "" + if provider == "bitbucket": + return settings.bitbucket_token, "" + return "", "" + + +def clone_url(provider: str, slug: str, token: str, host: str = "") -> str: + if provider == "github": + web = host.strip() or "github.com" + if web in {"github.com", "www.github.com", "api.github.com"}: + web = "github.com" + if token: + return f"https://x-access-token:{quote(token, safe='')}@{web}/{slug}.git" + return f"https://{web}/{slug}.git" + if provider == "gitlab": + web = host.strip() or "gitlab.com" + if token: + return f"https://oauth2:{quote(token, safe='')}@{web}/{slug}.git" + return f"https://{web}/{slug}.git" + if provider == "bitbucket": + if token: + return f"https://x-token-auth:{quote(token, safe='')}@bitbucket.org/{slug}.git" + return f"https://bitbucket.org/{slug}.git" + raise ValueError(f"Unknown provider {provider}") + + +def ensure_clone(provider: str, slug: str, *, token: str = "", host: str = "") -> Path: + dest = clones_root() / provider / slug.replace("/", "__") + dest.parent.mkdir(parents=True, exist_ok=True) + env = os.environ.copy() + env.setdefault("GIT_TERMINAL_PROMPT", "0") + if dest.is_dir() and (dest / ".git").exists(): + try: + _git(dest, "fetch", "--all", "--prune", env=env) + except subprocess.CalledProcessError: + pass + return dest + url = clone_url(provider, slug, token, host) + subprocess.check_call( + ["git", "clone", "--filter=blob:none", url, str(dest)], + env=env, + timeout=_GIT_TIMEOUT, + stdout=subprocess.DEVNULL, + stderr=subprocess.PIPE, + ) + return dest + + +def fetch_pull_ref(repo_root: Path, provider: str, number: int) -> str: + repo_root = repo_root.resolve() + spec = fetch_spec(provider, number) + local = local_pr_ref(number) + try: + _git(repo_root, "fetch", "origin", f"{spec}:{local}", "--force") + except subprocess.CalledProcessError as exc: + raise RuntimeError( + f"Could not fetch {provider} #{number} ({spec}). " + "Need a remote named origin that advertises pull/merge-request refs." + ) from exc + return local + + +def prepare_pull_request( + provider: str, + repo: str, + number: int, + *, + repo_path: str | None = None, +) -> dict[str, Any]: + """Return local path + git refs for reviewing a remote PR/MR.""" + settings = AppSettings.load() + token, host = _token_for(settings, provider) + scm = provider_for(provider, token, username=settings.bitbucket_username, host=host) if token else None + pr: PullRequest | None = None + if scm: + pr = scm.get_pull_request(repo, number) + root: Path | None = None + if repo_path: + candidate = Path(repo_path).expanduser().resolve() + if candidate.is_dir(): + root = candidate + if root is None: + from loadpath.providers.scm import attach_local_paths, RemoteRepo + + listed = [ + RemoteRepo(provider=provider, slug=repo, name=repo.split("/")[-1], owner=repo.split("/")[0], url="") + ] + attach_local_paths(listed, [w.path for w in settings.workspaces]) + if listed[0].local_path: + root = Path(listed[0].local_path) + cloned = False + if root is None: + if not token: + raise RuntimeError( + f"No local clone for {repo} and no {provider} token to clone it. " + "Sign in under Settings or pass a local repo path." + ) + root = ensure_clone(provider, repo, token=token, host=host) + cloned = True + register_workspace(root, name=repo.split("/")[-1]) + local_ref = fetch_pull_ref(root, provider, number) + base_ref = (pr.target_branch if pr else None) or "origin/HEAD" + if pr and pr.target_branch: + try: + _git(root, "fetch", "origin", pr.target_branch) + base_ref = f"origin/{pr.target_branch}" + except subprocess.CalledProcessError: + base_ref = pr.target_branch + return { + "repo_path": str(root), + "provider": provider, + "repo": repo, + "number": number, + "base": base_ref, + "head": local_ref, + "cloned": cloned, + "title": pr.title if pr else f"{provider} #{number}", + "source_branch": pr.source_branch if pr else "", + "target_branch": pr.target_branch if pr else "", + "url": pr.url if pr else "", + } \ No newline at end of file diff --git a/src/loadpath/providers/scm.py b/src/loadpath/providers/scm.py index 23fa7f1..5575aa6 100644 --- a/src/loadpath/providers/scm.py +++ b/src/loadpath/providers/scm.py @@ -11,7 +11,7 @@ REPO_SLUG = re.compile(r"^[\w.-]+/[\w.-]+$") LOADPATH_COMMENT_MARKER = "" REMOTE_HOST = re.compile( - r"(github\.com|bitbucket\.org)[:/](?P[\w.-]+/[\w.-]+?)(?:\.git)?/?$", + r"(?Pgithub\.com|bitbucket\.org|gitlab\.com|(?:[\w.-]+\.)?(?:github|gitlab)[\w.-]*)[:/](?P[\w.-]+(?:/[\w.-]+)+?)(?:\.git)?/?$", re.IGNORECASE, ) REPO_LIST_LIMIT = 500 @@ -33,16 +33,24 @@ def require_repo_slug(repo: str) -> str: def parse_remote_url(url: str) -> tuple[str, str] | None: - """Return (provider, owner/name) for a GitHub or Bitbucket remote URL.""" + """Return (provider, owner/name) for GitHub, GitLab, or Bitbucket remotes.""" raw = (url or "").strip() match = REMOTE_HOST.search(raw) if not match: return None slug = match.group("slug").strip("/") + parts = slug.split("/") + if len(parts) >= 2: + slug = "/".join(parts[:2]) if not REPO_SLUG.match(slug): return None - host = match.group(1).lower() - provider = "github" if host == "github.com" else "bitbucket" + host = match.group("host").lower() + if "bitbucket" in host: + provider = "bitbucket" + elif "gitlab" in host: + provider = "gitlab" + else: + provider = "github" return provider, slug @@ -132,10 +140,15 @@ def upsert_pull_request_comment(self, repo: str, number: int, markdown: str) -> class GitHubProvider: name = "github" - def __init__(self, token: str, client: httpx.Client | None = None) -> None: + def __init__(self, token: str, client: httpx.Client | None = None, *, host: str = "") -> None: self.token = token self.client = client or httpx.Client(timeout=30.0) - self.base = "https://api.github.com" + self.host = _normalize_host(host) or "github.com" + if self.host in {"github.com", "www.github.com", "api.github.com"}: + self.host = "github.com" + self.base = "https://api.github.com" + else: + self.base = f"https://{self.host}/api/v3" def _headers(self) -> dict[str, str]: return { @@ -489,9 +502,182 @@ def upsert_pull_request_comment(self, repo: str, number: int, markdown: str) -> return {"id": str(data.get("id")), "url": url, "updated": False} -def provider_for(name: str, token: str, username: str = "", client: httpx.Client | None = None) -> SCMProvider: +def _normalize_host(host: str) -> str: + raw = (host or "").strip() + if raw.startswith("https://") or raw.startswith("http://"): + raw = raw.split("://", 1)[1] + return raw.strip("/").lower() + + +class GitLabProvider: + name = "gitlab" + + def __init__(self, token: str, client: httpx.Client | None = None, *, host: str = "") -> None: + self.token = token + self.client = client or httpx.Client(timeout=30.0) + self.host = _normalize_host(host) or "gitlab.com" + self.base = f"https://{self.host}/api/v4" + + def _headers(self) -> dict[str, str]: + return {"PRIVATE-TOKEN": self.token, "Accept": "application/json"} + + def _project(self, repo: str) -> str: + return require_repo_slug(repo).replace("/", "%2F") + + def current_user(self) -> dict[str, str]: + r = self.client.get(f"{self.base}/user", headers=self._headers()) + r.raise_for_status() + item = r.json() + login = item.get("username") or "" + return { + "login": login, + "name": item.get("name") or login, + "url": item.get("web_url") or "", + } + + def list_repositories(self, limit: int = REPO_LIST_LIMIT) -> list[RemoteRepo]: + cap = max(1, min(limit, REPO_LIST_LIMIT)) + out: list[RemoteRepo] = [] + page = 1 + while len(out) < cap: + per_page = min(100, cap - len(out)) + r = self.client.get( + f"{self.base}/projects", + params={ + "membership": "true", + "simple": "true", + "order_by": "last_activity_at", + "per_page": per_page, + "page": page, + }, + headers=self._headers(), + ) + r.raise_for_status() + batch = r.json() or [] + if not batch: + break + for item in batch: + slug = item.get("path_with_namespace") or "" + owner, _, name = slug.partition("/") + out.append( + RemoteRepo( + provider="gitlab", + slug=slug, + name=name or slug, + owner=owner, + url=item.get("web_url") or "", + private=item.get("visibility") != "public", + default_branch=item.get("default_branch") or "", + updated_at=item.get("last_activity_at") or "", + description=item.get("description") or "", + ) + ) + if len(batch) < per_page: + break + page += 1 + return out[:cap] + + def list_pull_requests(self, repo: str, state: str = "open") -> list[PullRequest]: + repo = require_repo_slug(repo) + gl_state = "opened" if state == "open" else state + r = self.client.get( + f"{self.base}/projects/{self._project(repo)}/merge_requests", + params={"state": gl_state, "per_page": 50, "order_by": "updated_at"}, + headers=self._headers(), + ) + r.raise_for_status() + out = [] + for item in r.json() or []: + out.append(self._mr(repo, item)) + return out + + def get_pull_request(self, repo: str, number: int) -> PullRequest: + repo = require_repo_slug(repo) + r = self.client.get( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}", + headers=self._headers(), + ) + r.raise_for_status() + return self._mr(repo, r.json()) + + def get_diff(self, repo: str, number: int) -> str: + repo = require_repo_slug(repo) + r = self.client.get( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}/diffs", + headers={**self._headers(), "Accept": "text/plain"}, + ) + if r.status_code == 406: + r = self.client.get( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}.diff", + headers=self._headers(), + ) + r.raise_for_status() + return r.text + + def upsert_pull_request_comment(self, repo: str, number: int, markdown: str) -> dict[str, Any]: + repo = require_repo_slug(repo) + body = _marked_comment(markdown) + listed = self.client.get( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}/notes", + params={"per_page": 100}, + headers=self._headers(), + ) + listed.raise_for_status() + existing_id = None + for item in listed.json() or []: + if LOADPATH_COMMENT_MARKER in (item.get("body") or ""): + existing_id = item.get("id") + break + if existing_id: + r = self.client.put( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}/notes/{existing_id}", + headers=self._headers(), + json={"body": body}, + ) + r.raise_for_status() + data = r.json() + return {"id": str(data.get("id")), "url": "", "updated": True} + r = self.client.post( + f"{self.base}/projects/{self._project(repo)}/merge_requests/{number}/notes", + headers=self._headers(), + json={"body": body}, + ) + r.raise_for_status() + data = r.json() + return {"id": str(data.get("id")), "url": "", "updated": False} + + def _mr(self, repo: str, item: dict[str, Any]) -> PullRequest: + refs = item.get("diff_refs") or {} + return PullRequest( + provider="gitlab", + id=str(item.get("id") or item.get("iid")), + number=int(item.get("iid") or 0), + title=item.get("title") or "", + url=item.get("web_url") or "", + author=((item.get("author") or {}).get("username")) or "", + source_branch=item.get("source_branch") or "", + target_branch=item.get("target_branch") or "", + repo=repo, + state="open" if item.get("state") == "opened" else (item.get("state") or ""), + updated_at=item.get("updated_at") or "", + draft=bool(item.get("draft") or item.get("work_in_progress")), + head_sha=item.get("sha") or refs.get("head_sha") or "", + base_sha=refs.get("base_sha") or refs.get("start_sha") or "", + ) + + +def provider_for( + name: str, + token: str, + username: str = "", + client: httpx.Client | None = None, + *, + host: str = "", +) -> SCMProvider: if name == "github": - return GitHubProvider(token, client=client) + return GitHubProvider(token, client=client, host=host) if name == "bitbucket": return BitbucketProvider(token, username=username, client=client) + if name == "gitlab": + return GitLabProvider(token, client=client, host=host) raise ValueError(f"Unknown SCM provider: {name}") diff --git a/src/loadpath/review/auth.py b/src/loadpath/review/auth.py new file mode 100644 index 0000000..80b3297 --- /dev/null +++ b/src/loadpath/review/auth.py @@ -0,0 +1,93 @@ +"""Auth as a first-class load path: who can hit the sinks after this change.""" + +from __future__ import annotations + +from loadpath.graph.store import GraphStore +from loadpath.types import EdgeType, NodeType + +ANONYMOUS_OK = {"AllowAny", "IsAuthenticatedOrReadOnly"} +AUTHED = {"IsAuthenticated", "IsAdminUser", "IsOwner", "DjangoModelPermissions", "TokenHasReadWriteScope"} + + +def auth_path(store: GraphStore, impact_nodes: list[dict], impact_edges: list[dict]) -> dict: + views = [n for n in impact_nodes if n["type"] in {NodeType.VIEW.value, NodeType.VIEWSET_ACTION.value}] + routes = [ + n + for n in impact_nodes + if n["type"] + in { + NodeType.ROUTE.value, + NodeType.FASTAPI_ROUTE.value, + NodeType.WEBSOCKET_ROUTE.value, + NodeType.GRAPHQL_OPERATION.value, + } + ] + perms_by_view: dict[str, list[str]] = {} + for n in views: + extra = n.get("extra") or {} + perms_by_view[n["id"]] = list(extra.get("permissions") or extra.get("authentication") or []) + + for e in impact_edges: + if e["type"] != EdgeType.HAS_PERMISSION.value: + continue + dst = next((n for n in impact_nodes if n["id"] == e["dst"]), None) + if dst and dst["type"] == NodeType.PERMISSION.value: + perms_by_view.setdefault(e["src"], []) + if dst["name"] not in perms_by_view[e["src"]]: + perms_by_view[e["src"]].append(dst["name"]) + + sinks: list[dict] = [] + missing: list[dict] = [] + object_scope: list[dict] = [] + for view in views: + extra = view.get("extra") or {} + perms = perms_by_view.get(view["id"]) or [] + item = { + "id": view["id"], + "name": view["name"], + "file_path": view.get("file_path"), + "permissions": perms, + "authentication": extra.get("authentication") or [], + "get_queryset": bool(extra.get("get_queryset")), + } + sinks.append(item) + if not perms and not extra.get("fastapi") and not extra.get("ninja"): + missing.append(item) + if extra.get("get_queryset"): + object_scope.append(item) + + for route in routes: + extra = route.get("extra") or {} + if extra.get("websocket") and not extra.get("permissions"): + missing.append( + { + "id": route["id"], + "name": route["name"], + "file_path": route.get("file_path"), + "permissions": [], + "authentication": [], + "get_queryset": False, + } + ) + + note = _note(sinks, missing, object_scope) + return { + "sinks": sinks[:24], + "missing_permissions": missing[:12], + "object_scope": object_scope[:12], + "note": note, + } + + +def _note(sinks: list[dict], missing: list[dict], object_scope: list[dict]) -> str: + if not sinks: + return "No view/route auth surface on this path" + if missing: + names = ", ".join(m["name"] for m in missing[:3]) + return f"No permission_classes on {names}" + declared = sorted({p for s in sinks for p in s.get("permissions") or []}) + bit = ", ".join(declared[:4]) if declared else "undeclared" + extra = "" + if object_scope: + extra = f"; {len(object_scope)} view(s) use get_queryset for object scope" + return f"Sinks gated by {bit}{extra}" diff --git a/src/loadpath/review/cluster.py b/src/loadpath/review/cluster.py index 005a798..ddd8630 100644 --- a/src/loadpath/review/cluster.py +++ b/src/loadpath/review/cluster.py @@ -20,6 +20,12 @@ NodeType.FORM_SCHEMA, NodeType.HOOK, NodeType.COMPONENT, + NodeType.GRAPHQL_TYPE, + NodeType.GRAPHQL_OPERATION, + NodeType.FASTAPI_ROUTE, + NodeType.CONSUMER, + NodeType.TEMPLATE, + NodeType.PYDANTIC_MODEL, ] # Shared hubs that connect unrelated contexts if traversed. @@ -53,6 +59,12 @@ "destructive_migration", "changes_permission", "crosses_context", + "serves_template", + "htmx_calls", + "invalidates_cache", + "checks_flag", + "on_commit", + "publishes_graphql", } BACKWARD_TYPES = { @@ -71,6 +83,12 @@ "uses_query_key", "belongs_to", "destructive_migration", + "serves_template", + "htmx_calls", + "on_commit", + "publishes_graphql", + "invalidates_cache", + "checks_flag", } diff --git a/src/loadpath/review/contract.py b/src/loadpath/review/contract.py new file mode 100644 index 0000000..586d745 --- /dev/null +++ b/src/loadpath/review/contract.py @@ -0,0 +1,131 @@ +"""Classify serializer/OpenAPI/Zod/GraphQL diffs as additive, breaking, or drift.""" + +from __future__ import annotations + +import re + +from loadpath.review.diff import DiffSet +from loadpath.types import CONTRACT_TYPES, ContractBreakKind, NodeType + +REQUIRED_RE = re.compile( + r"""extra_kwargs\s*=\s*\{[^}]*['"](\w+)['"]\s*:\s*\{[^}]*required['"]?\s*:\s*True""", + re.S, +) +FIELD_ASSIGN_RE = re.compile(r"""^\s*(\w+)\s*=\s*\w*(Field|Serializer)\b""", re.M) +REMOVED_FIELD_RE = re.compile(r"""^\-\s*['"](\w+)['"]\s*,?\s*$""", re.M) +ADDED_FIELD_RE = re.compile(r"""^\+\s*['"](\w+)['"]\s*,?\s*$""", re.M) +ZOD_REQUIRED_RE = re.compile(r"""^\+\s*(\w+)\s*:\s*z\.""", re.M) +ZOD_OPTIONAL_RE = re.compile(r"""\.optional\(\)|\.nullish\(\)|nullish\(""") + + +def _touched(node: dict, changed_files: set[str]) -> bool: + if not changed_files: + return True + return (node.get("file_path") or "") in changed_files + + +def classify_contract_break(impact_nodes: list[dict], diff: DiffSet | None) -> dict: + kinds: set[str] = set() + reasons: list[str] = [] + fields: list[str] = [] + contract_nodes = [n for n in impact_nodes if n.get("type") in {t.value for t in CONTRACT_TYPES}] + if not contract_nodes: + return { + "kind": ContractBreakKind.NONE.value, + "reasons": [], + "fields": [], + } + + patch = "\n".join(f.patch or "" for f in (diff.files if diff else [])) + changed_files = {f.path for f in (diff.files if diff else []) if not f.skip} + required = {m.group(1) for m in REQUIRED_RE.finditer(patch) if "+" in patch[max(0, m.start() - 80) : m.start() + 1] or True} + # extra_kwargs required=True in added lines + added_required: list[str] = [] + for line in patch.splitlines(): + if line.startswith("+") and "required" in line and "True" in line: + names = re.findall(r"""['"](\w+)['"]""", line) + added_required.extend(names) + if line.startswith("+") and "required=True" in line.replace(" ", ""): + added_required.extend(re.findall(r"""['"](\w+)['"]""", line)) + + removed = REMOVED_FIELD_RE.findall(patch) + added = ADDED_FIELD_RE.findall(patch) + zod_added = ZOD_REQUIRED_RE.findall(patch) + + serializer_changed = any( + n["type"] in {NodeType.SERIALIZER.value, NodeType.SERIALIZER_FIELD.value, NodeType.PYDANTIC_MODEL.value} + and _touched(n, changed_files) + for n in contract_nodes + ) + graphql_changed = any( + n["type"].startswith("graphql.") and _touched(n, changed_files) for n in contract_nodes + ) + openapi_changed = any( + n["type"] == NodeType.OPENAPI_PATH.value and _touched(n, changed_files) for n in contract_nodes + ) + zod_changed = any( + n["type"] == NodeType.FORM_SCHEMA.value and _touched(n, changed_files) for n in contract_nodes + ) + + if added_required or required: + names = sorted({n for n in added_required if n not in {"extra_kwargs", "required"}} or required) + if names: + kinds.add(ContractBreakKind.BREAKING.value) + fields.extend(names) + reasons.append("Required contract field(s): " + ", ".join(f"`{n}`" for n in names[:6])) + + if removed and serializer_changed: + kinds.add(ContractBreakKind.BREAKING.value) + fields.extend(removed) + reasons.append("Removed published field(s): " + ", ".join(f"`{n}`" for n in removed[:6])) + + if added and serializer_changed and ContractBreakKind.BREAKING.value not in kinds: + kinds.add(ContractBreakKind.ADDITIVE.value) + fields.extend(added) + reasons.append("Added published field(s): " + ", ".join(f"`{n}`" for n in added[:6])) + + if graphql_changed: + kinds.add(ContractBreakKind.BREAKING.value if serializer_changed else ContractBreakKind.ADDITIVE.value) + reasons.append("GraphQL operation or type is on the impact path") + + if openapi_changed and serializer_changed: + kinds.add(ContractBreakKind.DRIFT.value) + reasons.append("OpenAPI path moved with the serializer — confirm generated clients") + + if zod_changed and serializer_changed: + ser_names = { + n["name"] + for n in impact_nodes + if n["type"] in {NodeType.SERIALIZER_FIELD.value, NodeType.FIELD.value} + } + schema_fields: set[str] = set() + for n in impact_nodes: + extra = n.get("extra") or {} + if n["type"] == NodeType.FORM_SCHEMA.value: + schema_fields.update(extra.get("fields") or []) + missing = sorted(ser_names - schema_fields - {"id", "pk"}) + if missing: + kinds.add(ContractBreakKind.DRIFT.value) + fields.extend(missing) + reasons.append("Zod/form schema does not include " + ", ".join(f"`{f}`" for f in missing[:6])) + elif zod_added: + kinds.add(ContractBreakKind.ADDITIVE.value) + + if not kinds and contract_nodes: + kinds.add(ContractBreakKind.ADDITIVE.value) + reasons.append("Public contract nodes changed without a detected field removal or required=True") + + order = [ + ContractBreakKind.BREAKING.value, + ContractBreakKind.DRIFT.value, + ContractBreakKind.ADDITIVE.value, + ContractBreakKind.NONE.value, + ] + kind = next((k for k in order if k in kinds), ContractBreakKind.NONE.value) + seen: set[str] = set() + uniq_fields = [] + for f in fields: + if f not in seen and f not in {"extra_kwargs", "required", "True", "False"}: + seen.add(f) + uniq_fields.append(f) + return {"kind": kind, "reasons": reasons[:4], "fields": uniq_fields[:12]} diff --git a/src/loadpath/review/diff.py b/src/loadpath/review/diff.py index bbfe6f1..afa06f3 100644 --- a/src/loadpath/review/diff.py +++ b/src/loadpath/review/diff.py @@ -49,6 +49,24 @@ def git_diff( head: str | None = None, *, three_dot: bool = True, + dirty: bool = False, +) -> DiffSet: + committed = _git_range_diff(repo_root, base, head, three_dot=three_dot) + if not dirty: + return committed + worktree = git_worktree_diff(repo_root) + merged = _merge_diffsets(committed, worktree) + merged.base = committed.base + merged.head = "WORKTREE" + return merged + + +def _git_range_diff( + repo_root: Path, + base: str, + head: str | None, + *, + three_dot: bool, ) -> DiffSet: repo_root = repo_root.resolve() specs: list[list[str]] = [] @@ -123,6 +141,60 @@ def git_diff( return DiffSet(files=files, base=base, head=head or "WORKTREE") +def git_worktree_diff(repo_root: Path) -> DiffSet: + """Uncommitted tracked changes plus untracked source files vs HEAD.""" + repo_root = repo_root.resolve() + tracked = _git_range_diff(repo_root, "HEAD", None, three_dot=False) + tracked.head = "WORKTREE" + files = {f.path: f for f in tracked.files} + try: + raw = subprocess.check_output( + ["git", "-C", str(repo_root), "ls-files", "--others", "--exclude-standard"], + text=True, + stderr=subprocess.DEVNULL, + ) + except (subprocess.CalledProcessError, FileNotFoundError): + raw = "" + for rel in raw.splitlines(): + path = rel.strip() + if not path or path in files: + continue + abs_path = repo_root / path + try: + text = abs_path.read_text(encoding="utf-8", errors="replace") + except OSError: + continue + added = text.count("\n") + (1 if text and not text.endswith("\n") else 0) + files[path] = FileDiff( + path=path, + status="A", + added=added, + deleted=0, + patch=f"diff --git a/{path} b/{path}\n--- /dev/null\n+++ b/{path}\n" + + "".join(f"+{line}\n" for line in text.splitlines()), + skip=is_skippable(path), + ) + return DiffSet(files=list(files.values()), base="HEAD", head="WORKTREE") + + +def _merge_diffsets(committed: DiffSet, worktree: DiffSet) -> DiffSet: + by_path = {f.path: f for f in committed.files} + for item in worktree.files: + existing = by_path.get(item.path) + if existing is None: + by_path[item.path] = item + continue + by_path[item.path] = FileDiff( + path=item.path, + status=item.status or existing.status, + added=existing.added + item.added, + deleted=existing.deleted + item.deleted, + patch=(existing.patch or "") + ("\n" if existing.patch and item.patch else "") + (item.patch or ""), + skip=existing.skip or item.skip, + ) + return DiffSet(files=list(by_path.values()), base=committed.base, head=worktree.head) + + def _split_patches(patch: str) -> dict[str, str]: out: dict[str, str] = {} current: list[str] = [] diff --git a/src/loadpath/review/engine.py b/src/loadpath/review/engine.py index 707a138..1ef52ed 100644 --- a/src/loadpath/review/engine.py +++ b/src/loadpath/review/engine.py @@ -12,8 +12,12 @@ from loadpath.index import default_db_path, index_drift, index_repo from loadpath.review.cluster import cluster_diff from loadpath.review.confidence import score_confidence +from loadpath.review.auth import auth_path +from loadpath.review.contract import classify_contract_break from loadpath.review.diff import DiffSet, git_diff from loadpath.review.evolution import analyze_evolution +from loadpath.review.suggested_tests import suggested_tests as sketches_for +from loadpath.review.trend import confidence_trend from loadpath.stitch.openapi import published_route from loadpath.workspace import git_dirty_paths, resolve_review_range from loadpath.types import ( @@ -46,6 +50,18 @@ NodeType.COMPONENT, NodeType.TEST, NodeType.REACT_TEST, + NodeType.GRAPHQL_TYPE, + NodeType.GRAPHQL_FIELD, + NodeType.GRAPHQL_OPERATION, + NodeType.FASTAPI_ROUTE, + NodeType.PYDANTIC_MODEL, + NodeType.CONSUMER, + NodeType.WEBSOCKET_ROUTE, + NodeType.TEMPLATE, + NodeType.HTMX_CALL, + NodeType.CACHE_KEY, + NodeType.FEATURE_FLAG, + NodeType.SIDE_EFFECT, ] @@ -60,6 +76,11 @@ def classify_change(impact_nodes: list[dict], findings: list, seeds: list[dict] or NodeType.OPENAPI_PATH.value in seed_types or NodeType.FORM_SCHEMA.value in seed_types or NodeType.ROUTE.value in seed_types + or NodeType.GRAPHQL_TYPE.value in seed_types + or NodeType.GRAPHQL_FIELD.value in seed_types + or NodeType.GRAPHQL_OPERATION.value in seed_types + or NodeType.FASTAPI_ROUTE.value in seed_types + or NodeType.PYDANTIC_MODEL.value in seed_types ): kinds.add(ChangeKind.PUBLIC_CONTRACT.value) if ( @@ -348,6 +369,7 @@ def run_review( *, three_dot: bool = True, draft_config: bool = False, + dirty: bool = False, ) -> dict: repo_root = repo_root.resolve() config = config or load_config(repo_root) @@ -368,8 +390,8 @@ def run_review( store = GraphStore(graph_db) range_info = resolve_review_range(repo_root, base, head, three_dot=three_dot) - diff = diff or git_diff(repo_root, base, head, three_dot=three_dot) - dirty = git_dirty_paths(repo_root) + diff = diff or git_diff(repo_root, base, head, three_dot=three_dot, dirty=dirty) + dirty_paths = git_dirty_paths(repo_root) clusters, impact_nodes, impact_edges = cluster_diff(store, diff) impact_edges = linked_edges(impact_nodes, impact_edges) seed_ids = {n["id"] for n in store.nodes_in_files(diff.paths)} @@ -400,10 +422,17 @@ def run_review( detail = store.get_meta("django_boot_detail") or "django.setup() failed" confidence["reasons"] = [detail, *reasons][:3] kinds = classify_change(impact_nodes, scoped, seeds=store.nodes_in_files(diff.paths)) + contract = classify_contract_break(impact_nodes, diff) + auth = auth_path(store, impact_nodes, impact_edges) + if auth.get("missing_permissions") and ChangeKind.AUTH.value not in kinds: + kinds.append(ChangeKind.AUTH.value) + kinds.sort() read, skip = read_order_files(diff, impact_nodes) reviewers = suggested_reviewers(config, impact_nodes) knowledge = _knowledge_owners(evolution) low_risk = is_low_risk(kinds, confidence, scoped) + if contract["kind"] == "breaking": + low_risk = False labels = ["loadpath:" + confidence["level"]] if low_risk: labels.append("loadpath:low-risk") @@ -411,6 +440,10 @@ def run_review( labels.append("loadpath:cross-context") if ChangeKind.PUBLIC_CONTRACT.value in kinds: labels.append("loadpath:contract") + if contract["kind"] and contract["kind"] != "none": + labels.append("loadpath:contract-" + contract["kind"]) + if ChangeKind.AUTH.value in kinds: + labels.append("loadpath:auth") title = _title(clusters, kinds) sinks = _sink_summaries(impact_nodes, store) @@ -418,8 +451,9 @@ def run_review( arch_note = _arch_note(scoped, kinds, impact_nodes) depth_note = _depth_note(scoped) deepening = deepening_candidates(scoped) + sketches = sketches_for(confidence.get("untested_sinks") or [], impact_nodes) drift = index_drift(store, repo_root, config) - dirty_set = set(dirty) + dirty_set = set(dirty_paths) overlap = [p for p in diff.paths if p in dirty_set] payload = { @@ -446,6 +480,9 @@ def run_review( "depth_note": depth_note, "deepening": deepening, "evolution": evolution, + "contract_break": contract, + "auth": auth, + "suggested_tests": sketches, "nodes": impact_nodes, "edges": impact_edges, "counts": store.counts(), @@ -463,20 +500,32 @@ def run_review( "django_boot_detail": store.get_meta("django_boot_detail") or "", }, "workspace": { - "dirty": dirty[:40], - "dirty_count": len(dirty), + "dirty": dirty_paths[:40], + "dirty_count": len(dirty_paths), "dirty_overlaps_review": bool(overlap), "dirty_overlap": overlap[:20], + "dirty_included": dirty, "merge_base": range_info.get("merge_base"), "three_dot": three_dot, "base_sha": range_info.get("base_sha"), "head_sha": range_info.get("head_sha"), }, "headline": _headline( - confidence, title, sinks, tests_note, arch_note, residuals, reviewers, evolution, depth_note + confidence, + title, + sinks, + tests_note, + arch_note, + residuals, + reviewers, + evolution, + depth_note, + contract=contract, + auth=auth, ), } store.save_review(payload["id"], payload["created_at"], str(repo_root), diff.base, diff.head, payload) + payload["trend"] = confidence_trend(store, base=diff.base, head=diff.head) store.close() return payload @@ -500,6 +549,14 @@ def _sink_summaries(nodes: list[dict], store: GraphStore) -> list[dict]: NodeType.PERMISSION.value, NodeType.MIGRATION_OP.value, NodeType.RECEIVER.value, + NodeType.CONSUMER.value, + NodeType.WEBSOCKET_ROUTE.value, + NodeType.TEMPLATE.value, + NodeType.GRAPHQL_OPERATION.value, + NodeType.FASTAPI_ROUTE.value, + NodeType.CACHE_KEY.value, + NodeType.FEATURE_FLAG.value, + NodeType.SIDE_EFFECT.value, } out = [] for n in nodes: @@ -549,10 +606,22 @@ def _depth_note(findings: list) -> str: def _headline( - confidence, title, sinks, tests_note, arch_note, residuals, reviewers, evolution=None, depth_note="" + confidence, + title, + sinks, + tests_note, + arch_note, + residuals, + reviewers, + evolution=None, + depth_note="", + contract=None, + auth=None, ) -> str: sink_bits = [] routes = [s["name"] for s in sinks if s["type"] == NodeType.ROUTE.value] + fastapi_routes = [s["name"] for s in sinks if s["type"] == NodeType.FASTAPI_ROUTE.value] + gql = [s["name"] for s in sinks if s["type"] == NodeType.GRAPHQL_OPERATION.value] celery_tasks = [s["name"] for s in sinks if s["type"] == NodeType.TASK.value and s.get("broker") == "celery"] dramatiq_tasks = [s["name"] for s in sinks if s["type"] == NodeType.TASK.value and s.get("broker") == "dramatiq"] other_tasks = [ @@ -561,8 +630,14 @@ def _headline( if s["type"] == NodeType.TASK.value and s.get("broker") not in {"celery", "dramatiq"} ] pages = [s["name"] for s in sinks if s["type"] in {NodeType.PAGE.value, NodeType.FORM_SCHEMA.value}] + templates = [s["name"] for s in sinks if s["type"] == NodeType.TEMPLATE.value] + sockets = [s["name"] for s in sinks if s["type"] in {NodeType.CONSUMER.value, NodeType.WEBSOCKET_ROUTE.value}] if routes: sink_bits.append(", ".join(routes[:4])) + if fastapi_routes: + sink_bits.append("FastAPI " + ", ".join(fastapi_routes[:3])) + if gql: + sink_bits.append("GraphQL " + ", ".join(gql[:3])) if celery_tasks: sink_bits.append("Celery " + ", ".join(celery_tasks[:3])) if dramatiq_tasks: @@ -571,13 +646,21 @@ def _headline( sink_bits.append("async " + ", ".join(other_tasks[:3])) if pages: sink_bits.append("React " + ", ".join(pages[:4])) + if templates: + sink_bits.append("templates " + ", ".join(templates[:3])) + if sockets: + sink_bits.append("WS " + ", ".join(sockets[:3])) residual = residuals[0] if residuals else "none" owners = ", ".join(reviewers) if reviewers else "context owners" pressure = (evolution or {}).get("notes") or [] churn = pressure[0] if pressure else "none" + contract_bit = (contract or {}).get("kind") or "none" + auth_bit = (auth or {}).get("note") or "n/a" return ( f"Loadpath: {confidence['level'].upper()} — {title}\n" f"Sinks: {'; '.join(sink_bits) or 'none typed'}\n" + f"Contract: {contract_bit}\n" + f"Auth: {auth_bit}\n" f"Tests: {tests_note}\n" f"Architecture: {arch_note}\n" f"Depth: {depth_note or 'published seams hold'}\n" diff --git a/src/loadpath/review/gate.py b/src/loadpath/review/gate.py new file mode 100644 index 0000000..0da9b35 --- /dev/null +++ b/src/loadpath/review/gate.py @@ -0,0 +1,58 @@ +"""CI merge-gate: map a review to a process exit code.""" + +from __future__ import annotations + +FAIL_ON_CHOICES = ("never", "blocker", "low", "medium") + + +def gate_result(review: dict, fail_on: str = "blocker") -> dict: + fail_on = (fail_on or "blocker").lower() + if fail_on not in FAIL_ON_CHOICES: + fail_on = "blocker" + findings = [f for f in (review.get("findings") or []) if not f.get("waived")] + blockers = [f for f in findings if f.get("severity") == "blocker"] + level = (review.get("confidence") or {}).get("level") or "medium" + contract = (review.get("contract_break") or {}).get("kind") + reasons: list[str] = [] + code = 0 + if fail_on != "never" and blockers: + code = 2 + reasons.append(f"{len(blockers)} architecture blocker(s)") + if fail_on in {"low", "medium"} and level == "low" and code == 0: + code = 3 + reasons.append("confidence is low") + if fail_on == "medium" and level == "medium" and code == 0: + code = 3 + reasons.append("confidence is medium") + if fail_on in {"low", "medium"} and contract == "breaking" and code == 0: + code = 4 + reasons.append("breaking public contract") + passed = code == 0 + summary = "pass" if passed else "fail" + title = (review.get("title") or "change").strip() + return { + "passed": passed, + "exit_code": code, + "fail_on": fail_on, + "summary": summary, + "level": level, + "contract_break": contract, + "blockers": len(blockers), + "reasons": reasons, + "annotation": f"Loadpath {level.upper()} — {title}" + + (f" ({'; '.join(reasons)})" if reasons else ""), + } + + +def write_github_output(path: str, gate: dict, review: dict) -> None: + conf = review.get("confidence") or {} + lines = [ + f"level={gate.get('level') or ''}", + f"passed={str(gate['passed']).lower()}", + f"title={review.get('title') or ''}", + f"contract_break={gate.get('contract_break') or 'none'}", + f"sinks={conf.get('sinks') or 0}", + f"annotation={gate.get('annotation') or ''}", + ] + with open(path, "a", encoding="utf-8") as handle: + handle.write("\n".join(lines) + "\n") diff --git a/src/loadpath/review/render.py b/src/loadpath/review/render.py index e7e2ab8..33d6c41 100644 --- a/src/loadpath/review/render.py +++ b/src/loadpath/review/render.py @@ -52,6 +52,28 @@ def render_markdown(review: dict) -> str: lines += ["", "### Residual uncertainty (AI-eligible)"] for r in review["residuals"][:12]: lines.append(f"- {r}") + contract = review.get("contract_break") or {} + if contract.get("kind") and contract["kind"] != "none": + lines += ["", "### Contract", f"**{contract['kind']}**"] + for reason in contract.get("reasons") or []: + lines.append(f"- {reason}") + auth = review.get("auth") or {} + if auth.get("note"): + lines += ["", "### Auth", auth["note"]] + for item in (auth.get("missing_permissions") or [])[:6]: + lines.append(f"- missing permission_classes on `{item.get('name')}`") + sketches = review.get("suggested_tests") or [] + if sketches: + lines += ["", "### Suggested tests"] + for sketch in sketches[:6]: + lines.append(f"- **{sketch['title']}** ({sketch['kind']})") + lines.append("") + lines.append("```") + lines.append((sketch.get("body") or "").rstrip()) + lines.append("```") + trend = review.get("trend") or {} + if trend.get("note"): + lines += ["", "### Confidence trend", trend["note"]] if review["low_risk"]: lines += ["", "_Fast-track: `loadpath:low-risk`. Human review can be a glance._"] evolution = review.get("evolution") or {} @@ -99,6 +121,8 @@ def render_markdown(review: dict) -> str: "Uncommitted files overlap this review: " + ", ".join(f"`{p}`" for p in (workspace.get("dirty_overlap") or [])[:8]), ] + elif workspace.get("dirty_included"): + lines += ["", "### Working tree", "Uncommitted files are included in this review."] elif workspace.get("dirty_count"): lines += [ "", diff --git a/src/loadpath/review/suggested_tests.py b/src/loadpath/review/suggested_tests.py new file mode 100644 index 0000000..31c328c --- /dev/null +++ b/src/loadpath/review/suggested_tests.py @@ -0,0 +1,170 @@ +"""Turn untested seams into pytest / RTL / GraphQL / HTMX sketches.""" + +from __future__ import annotations + +from loadpath.stitch.openapi import published_route +from loadpath.types import NodeType + + +def suggested_tests(untested_sinks: list[dict], impact_nodes: list[dict]) -> list[dict]: + by_id = {n["id"]: n for n in impact_nodes} + out: list[dict] = [] + seen: set[str] = set() + for sink in untested_sinks: + node = by_id.get(sink.get("id") or "") or sink + ntype = node.get("type") or "" + name = node.get("name") or sink.get("name") or "sink" + key = f"{ntype}:{name}" + if key in seen: + continue + seen.add(key) + sketch = _sketch(ntype, name, node) + if not sketch: + continue + out.append(sketch) + return out[:8] + + +def _sketch(ntype: str, name: str, node: dict) -> dict | None: + extra = node.get("extra") or {} + file_path = node.get("file_path") or "" + if ntype == NodeType.ROUTE.value: + route = published_route(node) if "extra" in node or "name" in node else name + method = (extra.get("method") or "GET").upper() + call = "get" if method in {"GET", "HEAD"} else method.lower() + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"Hit {route} through the published route", + "body": ( + f"def test_{_ident(name)}_via_route(client):\n" + f" response = client.{call}({route!r})\n" + f" assert response.status_code in {{200, 201, 204}}\n" + ), + } + if ntype == NodeType.FASTAPI_ROUTE.value: + route = extra.get("route") or name + method = (extra.get("method") or "GET").lower() + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"Hit FastAPI {name}", + "body": ( + f"def test_{_ident(name)}_fastapi(client):\n" + f" response = client.{method}({route!r})\n" + f" assert response.status_code < 500\n" + ), + } + if ntype in {NodeType.PAGE.value, NodeType.FORM_SCHEMA.value}: + component = name if ntype == NodeType.PAGE.value else name.replace("Schema", "Form") + return { + "sink": name, + "type": ntype, + "kind": "rtl", + "title": f"Render {component} at the page seam", + "body": ( + f"import {{ render, screen }} from '@testing-library/react'\n" + f"import {{ {component} }} from './{component}'\n\n" + f"it('renders {component}', () => {{\n" + f" render(<{component} />)\n" + f" expect(screen.getByRole('form', {{ hidden: true }}) || document.body).toBeTruthy()\n" + f"}})\n" + ), + } + if ntype == NodeType.GRAPHQL_OPERATION.value: + kind = extra.get("kind") or "query" + return { + "sink": name, + "type": ntype, + "kind": "graphql", + "title": f"Exercise GraphQL {kind} {name}", + "body": ( + f"def test_{_ident(name)}_graphql(client):\n" + f" response = client.post('/graphql', {{'query': '{kind} {{ {name} {{ __typename }} }}'}})\n" + f" assert response.status_code == 200\n" + f" assert 'errors' not in response.json()\n" + ), + } + if ntype in {NodeType.CONSUMER.value, NodeType.WEBSOCKET_ROUTE.value}: + return { + "sink": name, + "type": ntype, + "kind": "channels", + "title": f"Connect to {name}", + "body": ( + f"async def test_{_ident(name)}_ws(communicator):\n" + f" connected, _ = await communicator.connect()\n" + f" assert connected\n" + f" await communicator.disconnect()\n" + ), + } + if ntype == NodeType.TEMPLATE.value: + return { + "sink": name, + "type": ntype, + "kind": "django", + "title": f"Render template {name}", + "body": ( + f"def test_{_ident(name)}_template(client):\n" + f" response = client.get('/') # route that serves {file_path or name}\n" + f" assert response.status_code == 200\n" + ), + } + if ntype == NodeType.CACHE_KEY.value: + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"Assert cache key {name} after the write", + "body": ( + f"def test_{_ident(name)}_cache(client):\n" + f" # exercise the view that writes `{name}`\n" + f" client.get('/')\n" + f" assert cache.get({name!r}) is not None\n" + ), + } + if ntype == NodeType.FEATURE_FLAG.value: + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"Both sides of flag {name}", + "body": ( + f"@pytest.mark.parametrize('on', [True, False])\n" + f"def test_{_ident(name)}_flag(client, on, monkeypatch):\n" + f" monkeypatch.setattr('waffle.flag_is_active', lambda *a, **k: on)\n" + f" response = client.get('/')\n" + f" assert response.status_code < 500\n" + ), + } + if ntype == NodeType.SIDE_EFFECT.value: + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"on_commit side effect from {name}", + "body": ( + f"def test_{_ident(name)}_on_commit(django_capture_on_commit_callbacks):\n" + f" with django_capture_on_commit_callbacks(execute=True):\n" + f" ... # the write that schedules {name}\n" + ), + } + if ntype == NodeType.TASK.value: + return { + "sink": name, + "type": ntype, + "kind": "pytest", + "title": f"Call task {name} with a pk", + "body": ( + f"def test_{_ident(name)}_task():\n" + f" {name}(1) # pass a model pk, not a deserialized object\n" + ), + } + return None + + +def _ident(name: str) -> str: + cleaned = "".join(ch if ch.isalnum() else "_" for ch in name) + return cleaned.strip("_").lower() or "sink" diff --git a/src/loadpath/review/trend.py b/src/loadpath/review/trend.py new file mode 100644 index 0000000..ab62ccc --- /dev/null +++ b/src/loadpath/review/trend.py @@ -0,0 +1,73 @@ +"""Confidence history for the same repo / PR range.""" + +from __future__ import annotations + +from loadpath.graph.store import GraphStore + +_LEVEL_RANK = {"high": 2, "medium": 1, "low": 0} + + +def confidence_trend( + store: GraphStore, + *, + base: str | None = None, + head: str | None = None, + current: dict | None = None, + limit: int = 12, +) -> dict: + rows = store.list_reviews(include_payload=True, limit=40) + points: list[dict] = [] + for row in rows: + payload = row.get("payload") or {} + conf = payload.get("confidence") or {} + points.append( + { + "id": row["id"], + "created_at": row["created_at"], + "base": row.get("base_ref"), + "head": row.get("head_ref"), + "level": conf.get("level"), + "sinks": conf.get("sinks"), + "covered_sinks": conf.get("covered_sinks"), + "title": payload.get("title"), + "contract_break": (payload.get("contract_break") or {}).get("kind"), + } + ) + same_range = [p for p in points if (not base or p["base"] == base) and (not head or p["head"] == head)] + series = same_range or points + series = series[:limit] + if current: + current_point = { + "id": current.get("id"), + "created_at": current.get("created_at"), + "base": current.get("base"), + "head": current.get("head"), + "level": (current.get("confidence") or {}).get("level"), + "sinks": (current.get("confidence") or {}).get("sinks"), + "covered_sinks": (current.get("confidence") or {}).get("covered_sinks"), + "title": current.get("title"), + "contract_break": (current.get("contract_break") or {}).get("kind"), + "current": True, + } + if not series or series[0].get("id") != current_point.get("id"): + series = [current_point, *series] + note = _note(series) + return {"points": series[:limit], "note": note} + + +def _note(series: list[dict]) -> str: + levels = [p.get("level") for p in series if p.get("level")] + if len(levels) < 2: + return "First review stored for this range" + newest, previous = levels[0], levels[1] + if _LEVEL_RANK.get(newest, 1) < _LEVEL_RANK.get(previous, 1): + return f"Confidence dropped {previous} → {newest}" + if _LEVEL_RANK.get(newest, 1) > _LEVEL_RANK.get(previous, 1): + return f"Confidence rose {previous} → {newest}" + sinks_now = series[0].get("sinks") + sinks_prev = series[1].get("sinks") + if isinstance(sinks_now, int) and isinstance(sinks_prev, int) and sinks_now != sinks_prev: + delta = sinks_now - sinks_prev + sign = "+" if delta > 0 else "" + return f"Confidence stayed {newest}; sinks {sign}{delta}" + return f"Confidence unchanged at {newest}" diff --git a/src/loadpath/review/whatif.py b/src/loadpath/review/whatif.py new file mode 100644 index 0000000..22b11ce --- /dev/null +++ b/src/loadpath/review/whatif.py @@ -0,0 +1,104 @@ +"""Simulate a change from a node without a git range.""" + +from __future__ import annotations + +from pathlib import Path + +from loadpath.architecture.rules import evaluate +from loadpath.config import load_config +from loadpath.graph.store import GraphStore, linked_edges +from loadpath.index import default_db_path +from loadpath.review.auth import auth_path +from loadpath.review.cluster import impact_walk +from loadpath.review.confidence import score_confidence +from loadpath.review.contract import classify_contract_break +from loadpath.review.suggested_tests import suggested_tests as sketches_for +from loadpath.review.engine import ( + READ_ORDER, + _arch_note, + _depth_note, + _sink_summaries, + _tests_note, + classify_change, + collect_residuals, + suggested_reviewers, +) + + +def simulate_node(repo_root: Path, node_id: str, *, hops: int = 8) -> dict: + repo_root = repo_root.resolve() + config = load_config(repo_root) + db = default_db_path(repo_root) + if not db.is_file(): + raise FileNotFoundError(f"No index at {db}. Run `loadpath index` first.") + store = GraphStore(db) + seed = store.get_node(node_id) + if not seed: + store.close() + raise KeyError(f"Unknown node: {node_id}") + nodes, edges = impact_walk(store, {node_id}, hops=hops) + edges = linked_edges(nodes, edges) + findings = evaluate(store, config, changed_ids={node_id}) + impact_ids = {n["id"] for n in nodes} + scoped = [ + f + for f in findings + if (f.node_id and f.node_id in impact_ids) or f.node_id == node_id or not impact_ids + ] + residuals = collect_residuals(store, nodes, None) + confidence = score_confidence(store, nodes, edges, scoped, residuals) + auth = auth_path(store, nodes, edges) + sinks = _sink_summaries(nodes, store) + sketches = sketches_for(confidence.get("untested_sinks") or [], nodes) + kinds = classify_change(nodes, scoped, seeds=[seed]) + contract = classify_contract_break(nodes, None) + read_order = _read_order(nodes) + payload = { + "ok": True, + "what_if": True, + "id": f"whatif:{node_id}", + "node": seed, + "title": f"What if {seed.get('name')} changes", + "headline": f"What if {seed.get('name')} changes — {confidence.get('level')}", + "confidence": confidence, + "change_kinds": kinds, + "labels": [], + "low_risk": False, + "clusters": [], + "read_order": read_order, + "skip": [], + "sinks": sinks, + "nodes": nodes, + "edges": edges, + "findings": [f.to_dict() for f in scoped], + "residuals": residuals, + "auth": auth, + "contract_break": contract, + "suggested_tests": sketches, + "suggested_reviewers": suggested_reviewers(config, nodes), + "tests_note": _tests_note(confidence, nodes), + "architecture_note": _arch_note(scoped, kinds, nodes), + "depth_note": _depth_note(scoped), + "seed_type": seed.get("type"), + "counts": {"nodes": len(nodes), "edges": len(edges)}, + } + store.close() + return payload + + +def _read_order(nodes: list[dict]) -> list[dict]: + rank = {t.value: i for i, t in enumerate(READ_ORDER)} + by_file: dict[str, list[dict]] = {} + for n in nodes: + path = n.get("file_path") + if path: + by_file.setdefault(path, []).append(n) + out = [] + for path, group in by_file.items(): + why = ", ".join(sorted({n["type"].split(".")[-1] for n in group})[:4]) + file_rank = min(rank.get(n["type"], 40) for n in group) + out.append({"path": path, "why": why, "status": "M", "rank": file_rank}) + out.sort(key=lambda r: (r["rank"], r["path"])) + for item in out: + item.pop("rank", None) + return out diff --git a/src/loadpath/server/app.py b/src/loadpath/server/app.py index 8f16bf9..935065e 100644 --- a/src/loadpath/server/app.py +++ b/src/loadpath/server/app.py @@ -33,11 +33,13 @@ callback_html, disconnect_scm, finish_bitbucket_authorize, + finish_gitlab_authorize, is_loopback_request, oauth_status, poll_github_device, start_bitbucket_authorize, start_github_device, + start_gitlab_authorize, ) from loadpath.providers.scm import attach_local_paths, provider_for from loadpath.review.engine import run_review @@ -58,6 +60,7 @@ class ReviewRequest(BaseModel): reindex: bool = True incremental: bool = True three_dot: bool = True + dirty: bool = False class InitRequest(BaseModel): @@ -77,6 +80,11 @@ class PRCommentRequest(BaseModel): class SettingsUpdate(BaseModel): github_token: str | None = None github_oauth_client_id: str | None = None + github_host: str | None = None + gitlab_token: str | None = None + gitlab_host: str | None = None + gitlab_oauth_client_id: str | None = None + gitlab_oauth_client_secret: str | None = None bitbucket_token: str | None = None bitbucket_username: str | None = None bitbucket_workspace: str | None = None @@ -109,6 +117,20 @@ class OAuthDisconnect(BaseModel): provider: str +class WhatIfRequest(BaseModel): + repo_path: str + node_id: str + + +class PRReviewRequest(BaseModel): + provider: str + repo: str + number: int + repo_path: str | None = None + reindex: bool = True + incremental: bool = True + + def require_repo_path(path: str | None) -> Path: if not (path or "").strip(): raise HTTPException(400, "repo_path is required") @@ -118,11 +140,13 @@ def require_repo_path(path: str | None) -> Path: return root -def _scm_credentials(settings: AppSettings, provider: str) -> tuple[str, str]: +def _scm_credentials(settings: AppSettings, provider: str) -> tuple[str, str, str]: if provider == "github": - return settings.github_token, "" + return settings.github_token, "", settings.github_host + if provider == "gitlab": + return settings.gitlab_token, "", settings.gitlab_host if provider == "bitbucket": - return settings.bitbucket_token, settings.bitbucket_username + return settings.bitbucket_token, settings.bitbucket_username, "" raise HTTPException(400, f"Unknown SCM provider: {provider}") @@ -130,11 +154,11 @@ def _call_scm(provider: str, fn): from loadpath.providers.oauth import refresh_bitbucket_access_token settings = AppSettings.load() - token, username = _scm_credentials(settings, provider) + token, username, host = _scm_credentials(settings, provider) if not token: raise HTTPException(400, f"No {provider} token configured") try: - return fn(provider_for(provider, token, username=username)) + return fn(provider_for(provider, token, username=username, host=host)) except httpx.HTTPStatusError as exc: if ( provider == "bitbucket" @@ -146,8 +170,8 @@ def _call_scm(provider: str, fn): settings = refresh_bitbucket_access_token(settings) except Exception as refresh_exc: # noqa: BLE001 raise HTTPException(502, str(refresh_exc)) from refresh_exc - token, username = _scm_credentials(settings, provider) - return fn(provider_for(provider, token, username=username)) + token, username, host = _scm_credentials(settings, provider) + return fn(provider_for(provider, token, username=username, host=host)) raise HTTPException(502, str(exc)) from exc @@ -232,6 +256,16 @@ def put_settings(body: SettingsUpdate) -> dict[str, Any]: current.github_token = body.github_token or "" if body.github_oauth_client_id is not None: current.github_oauth_client_id = body.github_oauth_client_id.strip() + if body.github_host is not None: + current.github_host = body.github_host.strip() + if _should_update_secret(body.gitlab_token, current.gitlab_token): + current.gitlab_token = body.gitlab_token or "" + if body.gitlab_host is not None: + current.gitlab_host = body.gitlab_host.strip() + if body.gitlab_oauth_client_id is not None: + current.gitlab_oauth_client_id = body.gitlab_oauth_client_id.strip() + if _should_update_secret(body.gitlab_oauth_client_secret, current.gitlab_oauth_client_secret): + current.gitlab_oauth_client_secret = body.gitlab_oauth_client_secret or "" if _should_update_secret(body.bitbucket_token, current.bitbucket_token): current.bitbucket_token = body.bitbucket_token or "" if body.bitbucket_username is not None: @@ -321,6 +355,7 @@ def api_review(body: ReviewRequest) -> dict[str, Any]: reindex=body.reindex, incremental=body.incremental, three_dot=body.three_dot, + dirty=body.dirty, ) except FileNotFoundError as exc: raise HTTPException(409, str(exc)) from exc @@ -389,7 +424,8 @@ def api_prs(body: PRListRequest) -> dict[str, Any]: username = body.username or settings.bitbucket_username if token: try: - scm = provider_for(body.provider, token, username=username) + _, _, host = _scm_credentials(settings, body.provider) + scm = provider_for(body.provider, token, username=username, host=host) prs = scm.list_pull_requests(body.repo, state=body.state) except ValueError as exc: raise HTTPException(400, str(exc)) from exc @@ -427,7 +463,8 @@ def api_pr_comment(body: PRCommentRequest) -> dict[str, Any]: raise HTTPException(400, "markdown is empty") if token: try: - scm = provider_for(body.provider, token, username=username) + _, _, host = _scm_credentials(settings, body.provider) + scm = provider_for(body.provider, token, username=username, host=host) return scm.upsert_pull_request_comment(body.repo, body.number, body.markdown) except ValueError as exc: raise HTTPException(400, str(exc)) from exc @@ -468,6 +505,9 @@ def _load(scm): if provider == "github" and current.github_user != login: current.github_user = login current.save() + elif provider == "gitlab" and current.gitlab_user != login: + current.gitlab_user = login + current.save() elif provider == "bitbucket" and current.bitbucket_user != login: current.bitbucket_user = login current.save() @@ -548,6 +588,48 @@ def api_bitbucket_oauth_callback(code: str = "", state: str = "", error: str = " ) ) + @app.get("/api/oauth/gitlab/start") + def api_gitlab_oauth_start(request: Request) -> dict[str, Any]: + require_loopback(request) + redirect_uri = f"{base.rstrip('/')}/api/oauth/gitlab/callback" + try: + return start_gitlab_authorize(redirect_uri) + except ValueError as exc: + raise HTTPException(400, str(exc)) from exc + + @app.get("/api/oauth/gitlab/callback") + def api_gitlab_oauth_callback(code: str = "", state: str = "", error: str = "") -> HTMLResponse: + if error: + return HTMLResponse( + callback_html(ok=False, title="GitLab sign-in cancelled", body=error.replace("_", " ")), + status_code=400, + ) + if not code or not state: + return HTMLResponse( + callback_html(ok=False, title="GitLab sign-in failed", body="Missing code or state."), + status_code=400, + ) + try: + settings = finish_gitlab_authorize(code, state) + except ValueError as exc: + return HTMLResponse( + callback_html(ok=False, title="GitLab sign-in failed", body=str(exc)), + status_code=400, + ) + except httpx.HTTPError as exc: + return HTMLResponse( + callback_html(ok=False, title="GitLab sign-in failed", body=str(exc)), + status_code=502, + ) + user = settings.gitlab_user or "your account" + return HTMLResponse( + callback_html( + ok=True, + title="Connected to GitLab", + body=f"Signed in as {user}. Return to Loadpath — your repositories are available on the Pull requests tab.", + ) + ) + @app.post("/api/oauth/disconnect") def api_oauth_disconnect(request: Request, body: OAuthDisconnect) -> dict[str, Any]: require_loopback(request) @@ -574,6 +656,48 @@ def api_residual(body: ResidualRequest) -> dict[str, Any]: raise HTTPException(502, str(exc)) from exc return {"note": text} + @app.post("/api/whatif") + def api_whatif(body: WhatIfRequest) -> dict[str, Any]: + root = require_repo_path(body.repo_path) + from loadpath.review.whatif import simulate_node + + try: + return simulate_node(root, body.node_id) + except FileNotFoundError as exc: + raise HTTPException(409, str(exc)) from exc + except KeyError as exc: + raise HTTPException(404, str(exc)) from exc + + @app.post("/api/prs/review") + def api_pr_review(request: Request, body: PRReviewRequest) -> dict[str, Any]: + require_loopback(request) + from loadpath.providers.pr_fetch import prepare_pull_request + + try: + prepared = prepare_pull_request( + body.provider, body.repo, body.number, repo_path=body.repo_path + ) + except Exception as exc: # noqa: BLE001 + raise HTTPException(400, str(exc)) from exc + root = Path(prepared["repo_path"]) + try: + review = run_review( + root, + base=prepared["base"], + head=prepared["head"], + reindex=body.reindex, + incremental=body.incremental, + three_dot=True, + ) + except FileNotFoundError as exc: + raise HTTPException(409, str(exc)) from exc + except Exception as exc: # noqa: BLE001 + raise HTTPException(400, str(exc)) from exc + review["markdown"] = render_markdown(review) + review["pull_request"] = prepared + register_workspace(root) + return review + copy_mcp_routes(app, mcp_http) static_dir = package_dir() / "static" diff --git a/src/loadpath/settings.py b/src/loadpath/settings.py index c65c99c..545c1bd 100644 --- a/src/loadpath/settings.py +++ b/src/loadpath/settings.py @@ -40,6 +40,13 @@ class AppSettings(BaseModel): github_token: str = "" github_user: str = "" github_oauth_client_id: str = "" + github_host: str = "" + gitlab_token: str = "" + gitlab_user: str = "" + gitlab_host: str = "" + gitlab_oauth_client_id: str = "" + gitlab_oauth_client_secret: str = "" + gitlab_refresh_token: str = "" bitbucket_token: str = "" bitbucket_username: str = "" bitbucket_workspace: str = "" @@ -108,15 +115,24 @@ def register_workspace(path: Path, name: str | None = None) -> AppSettings: def public_settings(settings: AppSettings) -> dict[str, Any]: data = settings.model_dump() data["github_token"] = mask_secret(settings.github_token) + data["gitlab_token"] = mask_secret(settings.gitlab_token) + data["gitlab_refresh_token"] = mask_secret(settings.gitlab_refresh_token) + data["gitlab_oauth_client_secret"] = mask_secret(settings.gitlab_oauth_client_secret) data["bitbucket_token"] = mask_secret(settings.bitbucket_token) data["bitbucket_refresh_token"] = mask_secret(settings.bitbucket_refresh_token) data["bitbucket_oauth_client_secret"] = mask_secret(settings.bitbucket_oauth_client_secret) data["github_token_set"] = bool(settings.github_token) + data["gitlab_token_set"] = bool(settings.gitlab_token) + data["gitlab_oauth_client_secret_set"] = bool(settings.gitlab_oauth_client_secret) data["bitbucket_token_set"] = bool(settings.bitbucket_token) data["bitbucket_oauth_client_secret_set"] = bool(settings.bitbucket_oauth_client_secret) data["github_oauth_ready"] = bool( (os.environ.get("LOADPATH_GITHUB_CLIENT_ID") or settings.github_oauth_client_id or "").strip() ) + data["gitlab_oauth_ready"] = bool( + (os.environ.get("LOADPATH_GITLAB_CLIENT_ID") or settings.gitlab_oauth_client_id or "").strip() + and (os.environ.get("LOADPATH_GITLAB_CLIENT_SECRET") or settings.gitlab_oauth_client_secret or "").strip() + ) data["bitbucket_oauth_ready"] = bool( (os.environ.get("LOADPATH_BITBUCKET_CLIENT_ID") or settings.bitbucket_oauth_client_id or "").strip() and (os.environ.get("LOADPATH_BITBUCKET_CLIENT_SECRET") or settings.bitbucket_oauth_client_secret or "").strip() diff --git a/src/loadpath/stitch/openapi.py b/src/loadpath/stitch/openapi.py index 9a9136c..252ed19 100644 --- a/src/loadpath/stitch/openapi.py +++ b/src/loadpath/stitch/openapi.py @@ -180,7 +180,7 @@ def stitch(store: GraphStore, config: LoadpathConfig, repo_root: Path) -> list[s ) ) - routes = [n for n in store.nodes([NodeType.ROUTE])] + routes = [n for n in store.nodes([NodeType.ROUTE, NodeType.FASTAPI_ROUTE, NodeType.WEBSOCKET_ROUTE])] clients = [n for n in store.nodes([NodeType.API_CLIENT])] serializers = [n for n in store.nodes([NodeType.SERIALIZER])] ser_fields = [n for n in store.nodes([NodeType.SERIALIZER_FIELD])] @@ -336,10 +336,84 @@ def stitch(store: GraphStore, config: LoadpathConfig, repo_root: Path) -> list[s ) ) + residuals.extend(_stitch_graphql(store)) + residuals.extend(_stitch_htmx(store)) store.conn.commit() return residuals +def _stitch_graphql(store: GraphStore) -> list[str]: + residuals: list[str] = [] + ops = store.nodes([NodeType.GRAPHQL_OPERATION]) + server = [n for n in ops if not (n.get("extra") or {}).get("client")] + clients = [n for n in ops if (n.get("extra") or {}).get("client")] + by_name = {n["name"].lower(): n for n in server} + + def match_server(name: str) -> dict | None: + return by_name.get((name or "").lower()) + + for client in clients: + extra = client.get("extra") or {} + match = match_server(client["name"]) + if not match: + for sel in extra.get("selections") or []: + match = match_server(str(sel)) + if match: + break + if not match: + residuals.append( + f"GraphQL client operation {client['name']} has no matching server field " + f"({client.get('file_path')})" + ) + continue + store.upsert_edge( + Edge( + src=match["id"], + dst=client["id"], + type=EdgeType.CONSUMED_BY_CLIENT, + confidence=0.92, + extra={"via": "graphql", "operation": client["name"], "server": match["name"]}, + ) + ) + return residuals + + +def _stitch_htmx(store: GraphStore) -> list[str]: + residuals: list[str] = [] + calls = store.nodes([NodeType.HTMX_CALL]) + if not calls: + return residuals + routes = [ + n + for n in store.nodes([NodeType.ROUTE, NodeType.FASTAPI_ROUTE]) + if not (n.get("extra") or {}).get("include") + ] + for call in calls: + url = str((call.get("extra") or {}).get("url") or "") + if not url or url.startswith("{%"): + continue + tmpl = django_route_to_template(url) + matched = False + for route in routes: + rtmpl = django_route_to_template(str(published_route(route))) + if not _paths_match(tmpl, rtmpl) and not (tmpl.endswith(rtmpl) or rtmpl.endswith(tmpl)): + continue + store.upsert_edge( + Edge( + src=route["id"], + dst=call["id"], + type=EdgeType.CONSUMED_BY_CLIENT, + confidence=0.8, + extra={"via": "htmx", "htmx": True, "django": rtmpl, "htmx_url": tmpl}, + ) + ) + matched = True + break + if not matched: + residuals.append(f"HTMX {tmpl} has no matching Django route ({call.get('file_path')})") + return residuals + + def _paths_match(a: str, b: str) -> bool: a = normalize_url_template(a) b = django_route_to_template(b) diff --git a/src/loadpath/types.py b/src/loadpath/types.py index 4aa148c..1eb7dcc 100644 --- a/src/loadpath/types.py +++ b/src/loadpath/types.py @@ -38,6 +38,18 @@ class NodeType(StrEnum): ADMIN = "django.admin" MANAGEMENT_COMMAND = "django.management_command" TEST = "django.test" + CONSUMER = "django.consumer" + WEBSOCKET_ROUTE = "django.websocket_route" + TEMPLATE = "django.template" + HTMX_CALL = "django.htmx" + CACHE_KEY = "django.cache_key" + FEATURE_FLAG = "django.feature_flag" + SIDE_EFFECT = "django.side_effect" + GRAPHQL_TYPE = "graphql.type" + GRAPHQL_FIELD = "graphql.field" + GRAPHQL_OPERATION = "graphql.operation" + FASTAPI_ROUTE = "fastapi.route" + PYDANTIC_MODEL = "fastapi.model" # React REACT_ROUTE = "react.route" PAGE = "react.page" @@ -76,6 +88,12 @@ class EdgeType(StrEnum): HAS_PERMISSION = "has_permission" SERVES = "serves" RELATES_TO = "relates_to" + SERVES_TEMPLATE = "serves_template" + HTMX_CALLS = "htmx_calls" + INVALIDATES_CACHE = "invalidates_cache" + CHECKS_FLAG = "checks_flag" + ON_COMMIT = "on_commit" + PUBLISHES_GRAPHQL = "publishes_graphql" class EdgeWeight(StrEnum): @@ -93,6 +111,8 @@ class EdgeWeight(StrEnum): EdgeType.SERVES, EdgeType.USES_QUERY_KEY, EdgeType.RELATES_TO, + EdgeType.SERVES_TEMPLATE, + EdgeType.CHECKS_FLAG, } EXPENSIVE_EDGES = { EdgeType.SERIALIZES, @@ -104,6 +124,10 @@ class EdgeWeight(StrEnum): EdgeType.HAS_PERMISSION, EdgeType.TESTED_BY, EdgeType.MATCHES_SCHEMA, + EdgeType.HTMX_CALLS, + EdgeType.INVALIDATES_CACHE, + EdgeType.ON_COMMIT, + EdgeType.PUBLISHES_GRAPHQL, } CRITICAL_EDGES = { EdgeType.PUBLISHES_ROUTE, @@ -124,6 +148,14 @@ class EdgeWeight(StrEnum): NodeType.ADMIN, NodeType.MANAGEMENT_COMMAND, NodeType.OPENAPI_PATH, + NodeType.CONSUMER, + NodeType.WEBSOCKET_ROUTE, + NodeType.TEMPLATE, + NodeType.CACHE_KEY, + NodeType.FEATURE_FLAG, + NodeType.SIDE_EFFECT, + NodeType.GRAPHQL_OPERATION, + NodeType.FASTAPI_ROUTE, } CONTRACT_TYPES = { @@ -133,6 +165,11 @@ class EdgeWeight(StrEnum): NodeType.OPENAPI_PATH, NodeType.FORM_SCHEMA, NodeType.ROUTE, + NodeType.GRAPHQL_TYPE, + NodeType.GRAPHQL_FIELD, + NodeType.GRAPHQL_OPERATION, + NodeType.PYDANTIC_MODEL, + NodeType.FASTAPI_ROUTE, } GENERATED_PATH_MARKERS = ( @@ -158,6 +195,13 @@ class ChangeKind(StrEnum): MIXED = "mixed" +class ContractBreakKind(StrEnum): + NONE = "none" + ADDITIVE = "additive" + BREAKING = "breaking" + DRIFT = "drift" + + class ConfidenceLevel(StrEnum): HIGH = "high" MEDIUM = "medium" diff --git a/tests/e2e/test_api_flow.py b/tests/e2e/test_api_flow.py index f743cea..416dbf7 100644 --- a/tests/e2e/test_api_flow.py +++ b/tests/e2e/test_api_flow.py @@ -174,6 +174,63 @@ def test_api_lists_github_and_bitbucket_prs(tmp_path, monkeypatch): assert bb.json()["pull_requests"][0]["provider"] == "bitbucket" +def test_api_whatif_and_gitlab_mrs(tmp_path, monkeypatch): + monkeypatch.setenv("HOME", str(tmp_path / "home")) + (tmp_path / "home").mkdir() + repo = prepare_review_repo(tmp_path) + client = TestClient(create_app()) + indexed = client.post("/api/index", json={"repo_path": str(repo), "incremental": False}) + assert indexed.status_code == 200, indexed.text + walked = client.post( + "/api/whatif", + json={"repo_path": str(repo), "node_id": "django.field:billing.Invoice.total"}, + ) + assert walked.status_code == 200, walked.text + body = walked.json() + assert body["what_if"] is True + assert body["nodes"] + assert body["sinks"] + dirty = client.post( + "/api/review", + json={"repo_path": str(repo), "base": "HEAD~1", "head": "HEAD", "reindex": False, "dirty": True}, + ) + assert dirty.status_code == 200, dirty.text + assert dirty.json()["workspace"]["dirty_included"] is True + assert dirty.json()["contract_break"]["kind"] in {"breaking", "additive", "drift", "none"} + + +@respx.mock +def test_api_lists_gitlab_merge_requests(tmp_path, monkeypatch): + monkeypatch.setenv("HOME", str(tmp_path / "home")) + (tmp_path / "home").mkdir() + client = TestClient(create_app()) + client.put("/api/settings", json={"gitlab_token": "glpat_test", "gitlab_host": "gitlab.com"}) + respx.get("https://gitlab.com/api/v4/projects/acme%2Fdemo/merge_requests").mock( + return_value=httpx.Response( + 200, + json=[ + { + "id": 9, + "iid": 4, + "title": "Invoice total", + "web_url": "https://gitlab.com/acme/demo/-/merge_requests/4", + "author": {"username": "ada"}, + "source_branch": "feat/total", + "target_branch": "main", + "state": "opened", + "updated_at": "2026-08-14T00:00:00Z", + "draft": False, + "sha": "abc", + } + ], + ) + ) + gl = client.post("/api/prs", json={"provider": "gitlab", "repo": "acme/demo"}) + assert gl.status_code == 200, gl.text + assert gl.json()["pull_requests"][0]["number"] == 4 + assert gl.json()["pull_requests"][0]["provider"] == "gitlab" + + def test_blank_and_missing_repo_path_rejected(tmp_path, monkeypatch): monkeypatch.setenv("HOME", str(tmp_path / "home")) (tmp_path / "home").mkdir() diff --git a/tests/e2e/test_cli_review.py b/tests/e2e/test_cli_review.py index c021e23..b7d058f 100644 --- a/tests/e2e/test_cli_review.py +++ b/tests/e2e/test_cli_review.py @@ -72,6 +72,7 @@ def test_cli_help(): assert "architecture" in result.output assert "init" in result.output assert "mcp" in result.output + assert "whatif" in result.output def test_cli_serve_help(): @@ -103,3 +104,46 @@ def test_cli_mcp_help(): result = runner.invoke(app, ["mcp", "--help"]) assert result.exit_code == 0 assert "stdio" in result.output.lower() + + +def test_cli_whatif_dirty_and_gate(tmp_path, monkeypatch): + monkeypatch.setenv("HOME", str(tmp_path / "home")) + (tmp_path / "home").mkdir() + repo = prepare_review_repo(tmp_path) + indexed = runner.invoke(app, ["index", str(repo)]) + assert indexed.exit_code == 0, indexed.output + walked = runner.invoke(app, ["whatif", str(repo), "django.field:billing.Invoice.total"]) + assert walked.exit_code == 0, walked.output + assert "What if" in walked.output + gh_out = tmp_path / "github_output" + gated = runner.invoke( + app, + [ + "review", + str(repo), + "--base", + "HEAD~1", + "--head", + "HEAD", + "--no-reindex", + "--fail-on", + "never", + "--github-output", + str(gh_out), + "--format", + "json", + "--out", + str(tmp_path / "review.json"), + ], + ) + assert gated.exit_code == 0, gated.output + assert "level=" in gh_out.read_text() + (repo / "backend/billing/serializers.py").write_text( + (repo / "backend/billing/serializers.py").read_text() + "\n# uncommitted\n" + ) + dirty = runner.invoke( + app, + ["review", str(repo), "--dirty", "--no-reindex", "--format", "json", "--out", str(tmp_path / "dirty.json")], + ) + assert dirty.exit_code == 0, dirty.output + assert "dirty_included" in (tmp_path / "dirty.json").read_text() diff --git a/tests/unit/test_overlays.py b/tests/unit/test_overlays.py new file mode 100644 index 0000000..156a6a0 --- /dev/null +++ b/tests/unit/test_overlays.py @@ -0,0 +1,123 @@ +from __future__ import annotations + +from loadpath.config import load_config +from loadpath.extractors.django import extract_django_file +from loadpath.extractors.react import extract_react_file +from loadpath.extractors.templates import extract_template_file +from loadpath.index import index_repo +from loadpath.types import EdgeType, NodeType + +from tests.conftest import FIXTURE_ROOT as FIXTURE + + +def _cfg(): + return load_config(FIXTURE) + + +def test_extracts_strawberry_and_graphene(): + source = (FIXTURE / "backend/billing/schema.py").read_text() + g = extract_django_file("backend/billing/schema.py", source, _cfg()) + types = {n.name: n for n in g.nodes if n.type is NodeType.GRAPHQL_TYPE} + assert "InvoiceType" in types + assert "Query" in types + assert "CreditInvoice" in types + ops = {n.name for n in g.nodes if n.type is NodeType.GRAPHQL_OPERATION} + assert "invoice" in ops + assert "credit_invoice" in ops + assert any(n.type is NodeType.GRAPHQL_FIELD and n.name == "total" for n in g.nodes) + assert any(e.type is EdgeType.PUBLISHES_GRAPHQL for e in g.edges) + assert any(e.type is EdgeType.QUERIES_MODEL and "Invoice" in e.dst for e in g.edges) + + +def test_extracts_channels_consumer_and_websocket_route(): + consumer = extract_django_file( + "backend/billing/consumers.py", + (FIXTURE / "backend/billing/consumers.py").read_text(), + _cfg(), + ) + assert any(n.type is NodeType.CONSUMER and n.name == "InvoiceConsumer" for n in consumer.nodes) + routing = extract_django_file( + "backend/billing/routing.py", + (FIXTURE / "backend/billing/routing.py").read_text(), + _cfg(), + ) + ws = [n for n in routing.nodes if n.type is NodeType.WEBSOCKET_ROUTE] + assert ws + assert any("ws/invoices" in n.name for n in ws) + assert any(e.type is EdgeType.PUBLISHES_ROUTE and "InvoiceConsumer" in e.dst for e in routing.edges) + + +def test_extracts_fastapi_next_to_django_not_ninja(): + gateway = extract_django_file( + "backend/billing/gateway.py", + (FIXTURE / "backend/billing/gateway.py").read_text(), + _cfg(), + ) + assert any(n.type is NodeType.FASTAPI_ROUTE and "/internal/invoices" in n.name for n in gateway.nodes) + assert any(n.type is NodeType.PYDANTIC_MODEL and n.name == "InvoiceOut" for n in gateway.nodes) + assert any(e.type is EdgeType.USES_SERIALIZER for e in gateway.edges) + ninja = extract_django_file( + "backend/billing/api.py", + (FIXTURE / "backend/billing/api.py").read_text(), + _cfg(), + ) + assert not any(n.type is NodeType.FASTAPI_ROUTE for n in ninja.nodes) + assert any(n.type is NodeType.ROUTE and n.extra.get("ninja") for n in ninja.nodes) + + +def test_extracts_templates_htmx_and_url_tags(): + rel = "backend/billing/templates/billing/invoice_board.html" + g = extract_template_file(rel, (FIXTURE / rel).read_text(), _cfg()) + templates = [n for n in g.nodes if n.type is NodeType.TEMPLATE] + assert templates[0].qualified_name == "billing/invoice_board.html" + assert any(n.type is NodeType.HTMX_CALL and "/api/invoices/totals/" in n.name for n in g.nodes) + assert any(e.type is EdgeType.HTMX_CALLS for e in g.edges) + assert any(e.extra.get("url_name") == "invoice-board" for e in g.edges) + + +def test_view_serves_template_and_cache_flag_on_commit(): + source = (FIXTURE / "backend/billing/views.py").read_text() + g = extract_django_file("backend/billing/views.py", source, _cfg()) + assert any(n.type is NodeType.TEMPLATE and n.qualified_name == "billing/invoice_board.html" for n in g.nodes) + assert any(e.type is EdgeType.SERVES_TEMPLATE for e in g.edges) + assert any(n.type is NodeType.CACHE_KEY and n.name == "invoice:list" for n in g.nodes) + assert any(n.type is NodeType.FEATURE_FLAG and n.name == "async_ledger" for n in g.nodes) + assert any(n.type is NodeType.SIDE_EFFECT for n in g.nodes) + assert any(e.type is EdgeType.ON_COMMIT for e in g.edges) + assert any(e.type is EdgeType.INVALIDATES_CACHE for e in g.edges) + assert any(e.type is EdgeType.CHECKS_FLAG for e in g.edges) + + +def test_react_gql_document_is_a_client_operation(): + source = (FIXTURE / "frontend/src/features/billing/InvoicePage.tsx").read_text() + g = extract_react_file("frontend/src/features/billing/InvoicePage.tsx", source, _cfg()) + ops = [n for n in g.nodes if n.type is NodeType.GRAPHQL_OPERATION] + assert any(n.name == "Invoice" and n.extra.get("client") for n in ops) + assert any("invoice" in (n.extra.get("selections") or []) for n in ops) + + +def test_index_stitches_graphql_htmx_and_fastapi(tmp_path): + store = index_repo(FIXTURE, db_path=tmp_path / "g.sqlite3", incremental=False) + types = store.type_counts() + assert types.get("graphql.operation", 0) >= 2 + assert types.get("fastapi.route", 0) >= 1 + assert types.get("django.template", 0) >= 1 + assert types.get("django.consumer", 0) >= 1 + gql_edges = [ + e + for e in store.edges() + if e["type"] == "consumed_by_client" and (e.get("extra") or {}).get("via") == "graphql" + ] + assert gql_edges, "client Invoice query should stitch to server invoice field" + htmx_edges = [ + e for e in store.edges() if e["type"] == "consumed_by_client" and (e.get("extra") or {}).get("htmx") + ] + assert htmx_edges, "HTMX totals call should stitch to the Django totals route" + fastapi = next(n for n in store.nodes() if n["type"] == "fastapi.route") + openapi = [ + e + for e in store.edges() + if e["src"] == fastapi["id"] and e["type"] == "publishes_route" and "openapi" in (e.get("extra") or {}).get("via", "") + ] + assert openapi, "FastAPI /internal/invoices/{id} should stitch to OpenAPI" + store.close() diff --git a/tests/unit/test_providers_and_api.py b/tests/unit/test_providers_and_api.py index 4900c8a..7885ce1 100644 --- a/tests/unit/test_providers_and_api.py +++ b/tests/unit/test_providers_and_api.py @@ -4,7 +4,7 @@ from fastapi.testclient import TestClient -from loadpath.providers.scm import BitbucketProvider, GitHubProvider +from loadpath.providers.scm import BitbucketProvider, GitHubProvider, GitLabProvider from loadpath.server.app import create_app from loadpath.settings import AppSettings @@ -115,7 +115,9 @@ def test_parse_remote_url_github_and_bitbucket(): assert parse_remote_url("https://x-access-token:tok@github.com/acme/demo.git") == ("github", "acme/demo") assert parse_remote_url("https://bitbucket.org/acme/demo.git") == ("bitbucket", "acme/demo") assert parse_remote_url("git@bitbucket.org:acme/demo.git") == ("bitbucket", "acme/demo") - assert parse_remote_url("https://gitlab.com/acme/demo.git") is None + assert parse_remote_url("https://gitlab.com/acme/demo.git") == ("gitlab", "acme/demo") + assert parse_remote_url("git@gitlab.com:acme/demo.git") == ("gitlab", "acme/demo") + assert parse_remote_url("https://gitlab.example.com/acme/demo.git") == ("gitlab", "acme/demo") def test_github_lists_repositories_across_pages(): @@ -218,3 +220,60 @@ def handler(request: httpx.Request) -> httpx.Response: assert bb.current_user()["login"] == "bob" repos = bb.list_repositories() assert [r.slug for r in repos] == ["acme/demo", "acme/ledger"] + + +def test_github_enterprise_uses_api_v3(): + gh = GitHubProvider("tok", host="github.example.com") + assert gh.base == "https://github.example.com/api/v3" + cloud = GitHubProvider("tok", host="github.com") + assert cloud.base == "https://api.github.com" + + +def test_gitlab_lists_merge_requests(): + import httpx + + def handler(request: httpx.Request) -> httpx.Response: + if request.url.path.endswith("/user"): + return httpx.Response(200, json={"username": "ada", "name": "Ada", "web_url": "https://gitlab.com/ada"}) + return httpx.Response( + 200, + json=[ + { + "id": 90, + "iid": 4, + "title": "Invoice total", + "web_url": "https://gitlab.com/acme/demo/-/merge_requests/4", + "author": {"username": "ada"}, + "source_branch": "feat/total", + "target_branch": "main", + "state": "opened", + "updated_at": "2026-08-14T00:00:00Z", + "draft": False, + "sha": "abc", + "diff_refs": {"base_sha": "def", "head_sha": "abc"}, + } + ], + ) + + client = httpx.Client(transport=httpx.MockTransport(handler)) + gl = GitLabProvider("tok", client=client) + assert gl.current_user()["login"] == "ada" + mrs = gl.list_pull_requests("acme/demo") + assert mrs[0].number == 4 + assert mrs[0].provider == "gitlab" + assert mrs[0].source_branch == "feat/total" + + +def test_clone_url_and_fetch_spec(): + from loadpath.providers.pr_fetch import clone_url, fetch_spec, local_pr_ref + + gh = clone_url("github", "acme/demo", "tok") + assert "x-access-token:tok@" in gh + assert gh.endswith("github.com/acme/demo.git") + gl = clone_url("gitlab", "acme/demo", "glpat", "gitlab.example.com") + assert "oauth2:glpat@" in gl + assert "gitlab.example.com/acme/demo.git" in gl + assert fetch_spec("github", 12) == "pull/12/head" + assert fetch_spec("gitlab", 4) == "merge-requests/4/head" + assert fetch_spec("bitbucket", 3) == "pull-requests/3/from" + assert local_pr_ref(12) == "refs/loadpath/pr-12" diff --git a/tests/unit/test_review_features.py b/tests/unit/test_review_features.py new file mode 100644 index 0000000..690fd1e --- /dev/null +++ b/tests/unit/test_review_features.py @@ -0,0 +1,196 @@ +from __future__ import annotations + +from loadpath.review.auth import auth_path +from loadpath.review.contract import classify_contract_break +from loadpath.review.diff import DiffSet, FileDiff, git_diff +from loadpath.review.engine import run_review +from loadpath.review.gate import FAIL_ON_CHOICES, gate_result, write_github_output +from loadpath.review.suggested_tests import suggested_tests +from loadpath.review.trend import confidence_trend +from loadpath.review.whatif import simulate_node +from loadpath.types import ContractBreakKind + +from tests.conftest import copy_fixture, git_init_with_main, prepare_review_repo + + +def test_contract_break_required_field_is_breaking(): + diff = DiffSet( + files=[ + FileDiff( + path="backend/billing/serializers.py", + status="M", + patch='+ extra_kwargs = {"total": {"required": True}}\n', + ) + ] + ) + nodes = [ + { + "type": "django.serializer", + "name": "InvoiceSerializer", + "file_path": "backend/billing/serializers.py", + } + ] + result = classify_contract_break(nodes, diff) + assert result["kind"] == ContractBreakKind.BREAKING.value + assert "total" in result["fields"] + + +def test_contract_break_ignores_untouched_graphql(): + diff = DiffSet( + files=[ + FileDiff( + path="backend/billing/serializers.py", + status="M", + patch="+ extra_kwargs = {\"total\": {\"required\": True}}\n", + ) + ] + ) + nodes = [ + { + "type": "django.serializer", + "name": "InvoiceSerializer", + "file_path": "backend/billing/serializers.py", + }, + { + "type": "graphql.operation", + "name": "invoice", + "file_path": "backend/billing/schema.py", + }, + ] + result = classify_contract_break(nodes, diff) + assert result["kind"] == ContractBreakKind.BREAKING.value + assert not any("GraphQL" in r for r in result["reasons"]) + + +def test_auth_path_flags_missing_permissions(): + views = [ + { + "id": "django.view:billing.OpenView", + "type": "django.view", + "name": "OpenView", + "extra": {}, + }, + { + "id": "django.view:billing.InvoiceViewSet", + "type": "django.view", + "name": "InvoiceViewSet", + "extra": {"permissions": ["IsAuthenticated"], "get_queryset": True}, + }, + ] + routes = [ + { + "id": "django.websocket_route:billing:ws/invoices/", + "type": "django.websocket_route", + "name": "ws/invoices/", + "extra": {"websocket": True}, + } + ] + class _Store: + def nodes(self, types=None): + return [] + + result = auth_path(_Store(), views + routes, []) + names = {m["name"] for m in result["missing_permissions"]} + assert "OpenView" in names + assert "ws/invoices/" in names + assert result["object_scope"] + + +def test_suggested_tests_cover_new_sinks(): + sketches = suggested_tests( + [ + {"id": "fastapi.route:x", "name": "GET /internal/invoices/{id}", "type": "fastapi.route"}, + {"id": "graphql.operation:invoice", "name": "invoice", "type": "graphql.operation"}, + {"id": "django.consumer:c", "name": "InvoiceConsumer", "type": "django.consumer"}, + {"id": "django.template:t", "name": "invoice_board.html", "type": "django.template"}, + ], + [ + { + "id": "fastapi.route:x", + "name": "GET /internal/invoices/{id}", + "type": "fastapi.route", + "extra": {"route": "/internal/invoices/{id}", "method": "GET"}, + }, + {"id": "graphql.operation:invoice", "name": "invoice", "type": "graphql.operation", "extra": {"kind": "query"}}, + {"id": "django.consumer:c", "name": "InvoiceConsumer", "type": "django.consumer", "extra": {}}, + {"id": "django.template:t", "name": "invoice_board.html", "type": "django.template", "extra": {}}, + ], + ) + kinds = {s["kind"] for s in sketches} + assert {"pytest", "graphql", "channels", "django"} <= kinds + + +def test_gate_fail_on_blocker_and_breaking_contract(tmp_path): + assert "blocker" in FAIL_ON_CHOICES + review = { + "title": "Invoice.total", + "confidence": {"level": "medium", "sinks": 4}, + "findings": [{"severity": "blocker", "waived": False}], + "contract_break": {"kind": "breaking"}, + } + blocked = gate_result(review, "blocker") + assert blocked["passed"] is False + assert blocked["exit_code"] == 2 + never = gate_result(review, "never") + assert never["passed"] is True + medium = gate_result( + { + "title": "x", + "confidence": {"level": "medium", "sinks": 1}, + "findings": [], + "contract_break": {"kind": "breaking"}, + }, + "medium", + ) + assert medium["exit_code"] == 4 + out = tmp_path / "github_output" + write_github_output(str(out), blocked, review) + text = out.read_text() + assert "passed=false" in text + assert "contract_break=breaking" in text + + +def test_dirty_diff_includes_uncommitted_and_untracked(tmp_path): + repo = copy_fixture(tmp_path) + git_init_with_main(repo) + (repo / "backend/billing/serializers.py").write_text( + (repo / "backend/billing/serializers.py").read_text() + "\n# dirty\n" + ) + (repo / "backend/billing/scratch.py").write_text("VALUE = 1\n") + committed = git_diff(repo, "HEAD", "HEAD", dirty=False) + dirty = git_diff(repo, "HEAD", "HEAD", dirty=True) + assert "backend/billing/serializers.py" not in committed.paths or committed.paths == [] + assert "backend/billing/serializers.py" in dirty.paths + assert "backend/billing/scratch.py" in dirty.paths + review = run_review(repo, base="HEAD", head="HEAD", dirty=True) + assert review["workspace"]["dirty_included"] is True + assert review["workspace"]["dirty_count"] >= 1 + + +def test_whatif_walks_from_invoice_total(tmp_path): + repo = prepare_review_repo(tmp_path) + run_review(repo, base="HEAD~1", head="HEAD") + payload = simulate_node(repo, "django.field:billing.Invoice.total") + assert payload["ok"] is True + assert payload["what_if"] is True + names = {n["name"] for n in payload["nodes"]} + assert "InvoiceSerializer" in names or "total" in names + assert payload["sinks"] + assert payload["read_order"] + assert payload["auth"]["note"] + + +def test_confidence_trend_compares_same_range(tmp_path): + repo = prepare_review_repo(tmp_path) + first = run_review(repo, base="HEAD~1", head="HEAD") + second = run_review(repo, base="HEAD~1", head="HEAD", reindex=False) + trend = second["trend"] + assert trend["points"] + assert "Confidence" in trend["note"] or "First review" in trend["note"] + from loadpath.graph.store import GraphStore + from loadpath.index import default_db_path + + store = GraphStore(default_db_path(repo)) + note = confidence_trend(store, base=first["base"] if "base" in first else None, head=None) + store.close() + assert note["note"] diff --git a/ui/src/App.tsx b/ui/src/App.tsx index c087e15..6d74b18 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -51,6 +51,8 @@ export function App() { const [scmRepo, setScmRepo] = useState(localStorage.getItem("loadpath.scmRepo") || ""); const [provider, setProvider] = useState(localStorage.getItem("loadpath.provider") || "github"); const [prNumber, setPrNumber] = useState(localStorage.getItem("loadpath.prNumber") || ""); + const [dirty, setDirty] = useState(localStorage.getItem("loadpath.dirty") === "1"); + const [tourIndex, setTourIndex] = useState(0); const [aiNote, setAiNote] = useState(""); const [theme, setTheme] = useState(readTheme); const [settingsReady, setSettingsReady] = useState(false); @@ -63,6 +65,7 @@ export function App() { interval: number; } | null>(null); const [bitbucketWaiting, setBitbucketWaiting] = useState(false); + const [gitlabWaiting, setGitlabWaiting] = useState(false); const repoRef = useRef(repo); repoRef.current = repo; const explorerOpenRef = useRef(false); @@ -157,7 +160,11 @@ export function App() { }; const tokenSetFor = (name: string) => - name === "github" ? Boolean(settings.github_token_set) : Boolean(settings.bitbucket_token_set); + name === "github" + ? Boolean(settings.github_token_set) + : name === "gitlab" + ? Boolean(settings.gitlab_token_set) + : Boolean(settings.bitbucket_token_set); const loadRemoteRepos = useCallback(async (name = provider) => { try { @@ -166,7 +173,11 @@ export function App() { if (listed.user?.login) { setSettings((current) => ({ ...current, - ...(name === "github" ? { github_user: listed.user.login } : { bitbucket_user: listed.user.login }), + ...(name === "github" + ? { github_user: listed.user.login } + : name === "gitlab" + ? { gitlab_user: listed.user.login } + : { bitbucket_user: listed.user.login }), })); } } catch { @@ -258,6 +269,42 @@ export function App() { }; }, [bitbucketWaiting, loadRemoteRepos]); + useEffect(() => { + if (!gitlabWaiting) return; + let cancelled = false; + let timer = 0; + const started = Date.now(); + const tick = async () => { + try { + const status = await api.oauthStatus(); + if (cancelled) return; + if (status.gitlab.connected) { + setGitlabWaiting(false); + const next = await api.settings(); + setSettings(next); + setCopied(status.gitlab.user ? `Signed in to GitLab as ${status.gitlab.user}` : "Signed in to GitLab"); + void loadRemoteRepos("gitlab"); + return; + } + if (Date.now() - started > 180_000) { + setGitlabWaiting(false); + setError("GitLab sign-in timed out. Finish in the browser, or try again."); + return; + } + timer = window.setTimeout(tick, 1500); + } catch (e) { + if (cancelled) return; + setGitlabWaiting(false); + setError(e instanceof Error ? e.message : String(e)); + } + }; + timer = window.setTimeout(tick, 1500); + return () => { + cancelled = true; + window.clearTimeout(timer); + }; + }, [gitlabWaiting, loadRemoteRepos]); + const loadArchitecture = async (path = repo) => { if (!path.trim()) return null; const report = await api.architecture(path); @@ -274,8 +321,9 @@ export function App() { persistRepo(repo); persistRefs(base, head); try { - const r = await api.review(repo, base, head, true); + const r = await api.review(repo, base, head, true, dirty); setReview(r); + setTourIndex(0); setGraphMode("review"); setTab("review"); await api.repos().then((x) => setRepos(x.repos)).catch(() => undefined); @@ -393,6 +441,65 @@ export function App() { } }; + const startGitlabLogin = async () => { + setError(""); + try { + const flow = await api.gitlabOAuthStart(); + setGitlabWaiting(true); + openOAuthUrl(flow.authorize_url, new URL(flow.authorize_url).hostname, "/oauth/authorize"); + } catch (e) { + setGitlabWaiting(false); + setError(e instanceof Error ? e.message : String(e)); + } + }; + + const runWhatIf = async (nodeId: string) => { + if (busyRef.current || !repo.trim()) return; + setError(""); + markBusy("Walking what-if path…"); + try { + const result = await api.whatIf(repo, nodeId); + setCopied(`${result.title} — ${result.confidence.level} · ${(result.sinks || []).length} sinks`); + setReview({ + ...result, + markdown: result.markdown || "", + index: result.index || review?.index, + workspace: result.workspace || review?.workspace, + }); + setTourIndex(0); + setGraphMode("review"); + setTab("review"); + } catch (e) { + setError(e instanceof Error ? e.message : String(e)); + } finally { + markBusy(""); + } + }; + + const reviewRemotePr = async (item: PullRequest) => { + if (busyRef.current) return; + persistPr(item.provider, item.repo, String(item.number)); + const match = remoteRepos.find((r) => r.slug.toLowerCase() === item.repo.toLowerCase()); + if (match?.local_path) persistRepo(match.local_path); + setError(""); + markBusy(`Fetching ${item.provider} #${item.number}…`); + try { + const r = await api.reviewPr(item.provider, item.repo, item.number, match?.local_path || repo || undefined); + setReview(r); + setTourIndex(0); + if (r.pull_request && typeof r.pull_request.repo_path === "string") persistRepo(r.pull_request.repo_path); + persistRefs(String(r.base || item.target_branch), String(r.head || item.source_branch)); + setGraphMode("review"); + setTab("review"); + } catch (e) { + persistRefs(item.base_sha || item.target_branch, item.head_sha || item.source_branch); + setTab("review"); + setError(e instanceof Error ? e.message : String(e)); + } finally { + markBusy(""); + } + }; + const disconnectProvider = async (name: string) => { setError(""); try { @@ -410,6 +517,11 @@ export function App() { const body = { github_token: String(fd.get("github_token") || ""), github_oauth_client_id: String(fd.get("github_oauth_client_id") || ""), + github_host: String(fd.get("github_host") || ""), + gitlab_token: String(fd.get("gitlab_token") || ""), + gitlab_host: String(fd.get("gitlab_host") || ""), + gitlab_oauth_client_id: String(fd.get("gitlab_oauth_client_id") || ""), + gitlab_oauth_client_secret: String(fd.get("gitlab_oauth_client_secret") || ""), bitbucket_token: String(fd.get("bitbucket_token") || ""), bitbucket_username: String(fd.get("bitbucket_username") || ""), bitbucket_oauth_client_id: String(fd.get("bitbucket_oauth_client_id") || ""), @@ -633,6 +745,22 @@ export function App() { onNeedRefs={loadGitRefs} /> +
)} @@ -734,7 +871,7 @@ export function App() {
{architecture?.indexed ? ( - + ) : null}
@@ -779,7 +916,7 @@ export function App() { {graphNodes.length ? ( - + ) : (

Index the repo or run a review first. Click a node to inspect it. @@ -799,6 +936,7 @@ export function App() { onChange={(e) => persistPr(e.target.value, scmRepo, prNumber)} > + @@ -840,6 +978,7 @@ export function App() {

{remoteRepos.length} {provider} repositor{remoteRepos.length === 1 ? "y" : "ies"} {provider === "github" && settings.github_user ? ` · @${String(settings.github_user)}` : ""} + {provider === "gitlab" && settings.gitlab_user ? ` · @${String(settings.gitlab_user)}` : ""} {provider === "bitbucket" && settings.bitbucket_user ? ` · ${String(settings.bitbucket_user)}` : ""}

) : null} @@ -872,15 +1011,9 @@ export function App() { type="button" className="btn primary" data-testid={`pr-review-${p.number}`} - onClick={() => { - persistRefs(p.base_sha || p.target_branch, p.head_sha || p.source_branch); - persistPr(p.provider, p.repo, String(p.number)); - const match = remoteRepos.find((item) => item.slug.toLowerCase() === p.repo.toLowerCase()); - if (match?.local_path) persistRepo(match.local_path); - setTab("review"); - }} + onClick={() => void reviewRemotePr(p)} > - Review this range + Review this PR @@ -975,6 +1108,65 @@ export function App() { /> + + +
+
+ GitLab +

+ {settings.gitlab_token_set + ? settings.gitlab_user + ? `Signed in as @${String(settings.gitlab_user)}` + : "Token saved on this machine" + : "Not connected"} +

+
+
+ {settings.gitlab_token_set ? ( + + ) : ( + + )} +
+
+ + + + + + + +
Bitbucket @@ -1100,6 +1292,8 @@ function ReviewBrief({ findings, aiNote, busy, + tourIndex, + onTour, onAskAi, onCopy, onPost, @@ -1108,6 +1302,8 @@ function ReviewBrief({ findings: Review["findings"]; aiNote: string; busy: boolean; + tourIndex: number; + onTour: (index: number) => void; onAskAi: () => void; onCopy: () => void; onPost: () => void; @@ -1132,6 +1328,11 @@ function ReviewBrief({ {kindLabel(k)} ))} + {review.contract_break?.kind && review.contract_break.kind !== "none" ? ( + + contract {review.contract_break.kind} + + ) : null}
@@ -1174,13 +1375,38 @@ function ReviewBrief({ Read this {review.read_order.length} {review.read_order.map((f, i) => ( -
+
{i + 1}. {f.path}
{f.why}
))} + {review.read_order.length > 0 ? ( +
+ + + + {tourIndex + 1}/{review.read_order.length} + +
+ ) : null}
@@ -1208,6 +1434,55 @@ function ReviewBrief({ )}
+ {review.contract_break?.reasons?.length ? ( +
+ + Contract {review.contract_break.kind} + + {review.contract_break.reasons.map((reason) => ( +
+ {reason} +
+ ))} +
+ ) : null} + {review.auth?.note ? ( +
+ Auth +
{review.auth.note}
+ {(review.auth.missing_permissions || []).map((item) => ( +
+ missing + {item.name} +
+ ))} +
+ ) : null} + {(review.suggested_tests || []).length ? ( +
+ + Suggested tests {review.suggested_tests?.length} + + {(review.suggested_tests || []).map((sketch) => ( +
+ {sketch.title} +
{sketch.body}
+
+ ))} +
+ ) : null} + {review.trend?.note ? ( +
+ Confidence trend +
{review.trend.note}
+ {(review.trend.points || []).slice(0, 6).map((point) => ( +
+ {point.level} · {formatWhen(point.created_at)} + {point.sinks != null ? ` · ${point.sinks} sinks` : ""} +
+ ))} +
+ ) : null}
Residual {review.residuals.length} diff --git a/ui/src/ImpactGraph.tsx b/ui/src/ImpactGraph.tsx index e5f89b5..f217e1a 100644 --- a/ui/src/ImpactGraph.tsx +++ b/ui/src/ImpactGraph.tsx @@ -106,11 +106,13 @@ function GraphInspector({ nodes, edges, onClose, + onWhatIf, }: { node: GraphNode; nodes: GraphNode[]; edges: GraphEdge[]; onClose: () => void; + onWhatIf?: (id: string) => void; }) { const info = inspectNode(node, nodes, edges); useEffect(() => { @@ -173,6 +175,11 @@ function GraphInspector({ extra={info.extraOutputs} empty="This node does not point at anything in this graph." /> + {onWhatIf ? ( + + ) : null} ); } @@ -219,7 +226,17 @@ function InspectorLinks({ ); } -export function ImpactGraph({ nodes, edges }: { nodes: GraphNode[]; edges: GraphEdge[] }) { +export function ImpactGraph({ + nodes, + edges, + onWhatIf, + focusPath, +}: { + nodes: GraphNode[]; + edges: GraphEdge[]; + onWhatIf?: (id: string) => void; + focusPath?: string; +}) { const [selectedId, setSelectedId] = useState(null); const [projection, setProjection] = useState(null); const [detail, setDetail] = useState(null); @@ -254,6 +271,12 @@ export function ImpactGraph({ nodes, edges }: { nodes: GraphNode[]; edges: Graph if (selectedId && !byId.has(selectedId)) setSelectedId(null); }, [byId, selectedId]); + useEffect(() => { + if (!focusPath) return; + const match = nodes.find((n) => n.file_path === focusPath); + if (match) setSelectedId(match.id); + }, [focusPath, nodes]); + const onNodeClick: NodeMouseHandler = (_evt, node) => { setSelectedId(node.id); }; @@ -379,7 +402,7 @@ export function ImpactGraph({ nodes, edges }: { nodes: GraphNode[]; edges: Graph /> {selected ? ( - + ) : null}
) : ( @@ -417,7 +440,7 @@ export function ImpactGraph({ nodes, edges }: { nodes: GraphNode[]; edges: Graph {selected ? ( - + ) : null} )} diff --git a/ui/src/api.ts b/ui/src/api.ts index 3ca16fc..7677ffe 100644 --- a/ui/src/api.ts +++ b/ui/src/api.ts @@ -1,4 +1,4 @@ -import type { ArchitectureReport, FsListing, GitRefs, IndexedRepo, PullRequest, RemoteRepo, Review } from "./types"; +import type { ArchitectureReport, FsListing, GitRefs, GraphNode, IndexedRepo, PullRequest, RemoteRepo, Review } from "./types"; export function formatApiError(text: string, fallback = "Request failed"): string { const trimmed = (text || "").trim(); @@ -39,6 +39,8 @@ async function req(path: string, init?: RequestInit): Promise { const BLANK_SETTINGS_KEYS = [ "github_token", + "gitlab_token", + "gitlab_oauth_client_secret", "bitbucket_token", "bitbucket_oauth_client_secret", "ai_api_key", @@ -70,10 +72,31 @@ export const api = { req(`/api/index?repo_path=${encodeURIComponent(repo_path)}`), architecture: (repo_path: string) => req(`/api/architecture?repo_path=${encodeURIComponent(repo_path)}`), - review: (repo_path: string, base: string, head?: string, reindex = true) => + review: (repo_path: string, base: string, head?: string, reindex = true, dirty = false) => req("/api/review", { method: "POST", - body: JSON.stringify({ repo_path, base, head: head || null, reindex, incremental: true, three_dot: true }), + body: JSON.stringify({ + repo_path, + base, + head: head || null, + reindex, + incremental: true, + three_dot: true, + dirty, + }), + }), + whatIf: (repo_path: string, node_id: string) => + req< + Review & { + ok: boolean; + node: GraphNode; + what_if?: boolean; + } + >("/api/whatif", { method: "POST", body: JSON.stringify({ repo_path, node_id }) }), + reviewPr: (provider: string, repo: string, number: number, repo_path?: string) => + req }>("/api/prs/review", { + method: "POST", + body: JSON.stringify({ provider, repo, number, repo_path: repo_path || null }), }), init: (repo_path: string, overwrite = false) => req<{ wrote: boolean; message: string; django_root: string; react_root: string; has_config: boolean }>( @@ -100,7 +123,8 @@ export const api = { ), oauthStatus: () => req<{ - github: { connected: boolean; user: string; token_set: boolean; oauth_ready: boolean }; + github: { connected: boolean; user: string; token_set: boolean; oauth_ready: boolean; host?: string }; + gitlab: { connected: boolean; user: string; token_set: boolean; oauth_ready: boolean; host?: string }; bitbucket: { connected: boolean; user: string; token_set: boolean; oauth_ready: boolean }; }>("/api/oauth/status"), githubOAuthStart: () => @@ -119,6 +143,8 @@ export const api = { }), bitbucketOAuthStart: () => req<{ flow_id: string; authorize_url: string }>("/api/oauth/bitbucket/start"), + gitlabOAuthStart: () => + req<{ flow_id: string; authorize_url: string }>("/api/oauth/gitlab/start"), oauthDisconnect: (provider: string) => req>("/api/oauth/disconnect", { method: "POST", diff --git a/ui/src/graphView.test.ts b/ui/src/graphView.test.ts index a792c02..69675ec 100644 --- a/ui/src/graphView.test.ts +++ b/ui/src/graphView.test.ts @@ -5,6 +5,7 @@ import { LAYER_LABELS, defaultDetail, defaultProjection, + familyFor, layoutNodes3d, neighborIds, visibleGraph, @@ -78,6 +79,12 @@ describe("defaults", () => { expect(defaultDetail(LARGE_GRAPH)).toBe("overview"); }); + it("places GraphQL and FastAPI with the stitch family", () => { + expect(familyFor("graphql.operation")).toBe("stitch"); + expect(familyFor("fastapi.route")).toBe("stitch"); + expect(familyFor("django.template")).toBe("django"); + }); + it("names every architecture layer used in 2d layout", () => { for (const layer of new Set(Object.values(LAYER_ORDER))) { expect(LAYER_LABELS[layer]).toBeTruthy(); diff --git a/ui/src/graphView.ts b/ui/src/graphView.ts index a011e7a..f7dc2e7 100644 --- a/ui/src/graphView.ts +++ b/ui/src/graphView.ts @@ -13,6 +13,7 @@ export const OVERVIEW_HIDDEN_TYPES = new Set([ "django.relation", "django.test", "react.test", + "graphql.field", "django.url_name", "django.throttle", ]); @@ -36,6 +37,17 @@ export const TYPE_COLOR: Record = { "django.test": "#6c757d", "django.admin": "#adb5bd", "django.migration_op": "#9d4edd", + "django.consumer": "#e76f51", + "django.websocket_route": "#4cc9f0", + "django.template": "#c77dff", + "django.htmx": "#ff6b6b", + "django.cache_key": "#6c757d", + "django.feature_flag": "#f4a261", + "django.side_effect": "#e85d04", + "graphql.type": "#00bbf9", + "graphql.operation": "#00bbf9", + "fastapi.route": "#4cc9f0", + "fastapi.model": "#f4a261", "openapi.path": "#00bbf9", "react.api_client": "#ff6b6b", "react.query_key": "#adb5bd", @@ -71,7 +83,7 @@ export const LAYER_LABELS: Record = { export function familyFor(type: string): GraphFamily { if (type.startsWith("react.")) return "react"; - if (type.startsWith("openapi.")) return "stitch"; + if (type.startsWith("openapi.") || type.startsWith("graphql.") || type.startsWith("fastapi.")) return "stitch"; if (type.startsWith("arch.")) return "arch"; return "django"; } diff --git a/ui/src/nodeInspector.test.ts b/ui/src/nodeInspector.test.ts index 2aae8e3..7994826 100644 --- a/ui/src/nodeInspector.test.ts +++ b/ui/src/nodeInspector.test.ts @@ -13,6 +13,9 @@ describe("typePurpose", () => { it("explains known types and falls back by family", () => { expect(typePurpose("django.field")).toMatch(/column/i); expect(typePurpose("react.form_schema")).toMatch(/typed/i); + expect(typePurpose("graphql.operation")).toMatch(/GraphQL/i); + expect(typePurpose("fastapi.route")).toMatch(/FastAPI/i); + expect(typePurpose("django.template")).toMatch(/template/i); expect(typePurpose("django.mystery")).toMatch(/Django/); }); }); diff --git a/ui/src/nodeInspector.ts b/ui/src/nodeInspector.ts index 9c42ed0..8bca27e 100644 --- a/ui/src/nodeInspector.ts +++ b/ui/src/nodeInspector.ts @@ -16,6 +16,14 @@ export const SINK_TYPES = new Set([ "django.admin", "django.management_command", "openapi.path", + "django.consumer", + "django.websocket_route", + "django.template", + "django.cache_key", + "django.feature_flag", + "django.side_effect", + "graphql.operation", + "fastapi.route", ]); export const CONTRACT_TYPES = new Set([ @@ -25,6 +33,11 @@ export const CONTRACT_TYPES = new Set([ "openapi.path", "react.form_schema", "django.route", + "graphql.type", + "graphql.field", + "graphql.operation", + "fastapi.model", + "fastapi.route", ]); const TYPE_PURPOSE: Record = { @@ -50,6 +63,18 @@ const TYPE_PURPOSE: Record = { "django.admin": "Django admin class for a model.", "django.migration_op": "Schema migration operation (CreateModel, AlterField, …).", "django.management_command": "manage.py command — an operational sink.", + "django.consumer": "Django Channels WebSocket/HTTP consumer. A sink once a client connects.", + "django.websocket_route": "ASGI WebSocket URL. A sink: this is where a change becomes a live connection.", + "django.template": "Django template. HTML (and HTMX) the server renders.", + "django.htmx": "HTMX call from a template to a URL — another published seam.", + "django.cache_key": "Cache get/set key. Invalidation is part of the load path.", + "django.feature_flag": "Feature flag checked on this path. The change may be dark-launched.", + "django.side_effect": "transaction.on_commit (or similar) side effect that runs after the request commits.", + "graphql.type": "GraphQL object/input type — a published contract.", + "graphql.field": "One field on a GraphQL type.", + "graphql.operation": "GraphQL query, mutation, or subscription. A published contract and a sink.", + "fastapi.route": "FastAPI path operation sitting next to Django in this repo.", + "fastapi.model": "Pydantic response/request model — the FastAPI contract.", "openapi.path": "Generated OpenAPI operation. The typed HTTP contract between stacks.", "react.api_client": "Frontend fetch or generated client call to an API path.", "react.query_key": "React Query cache key. Invalidation and reads share this name.", diff --git a/ui/src/styles.css b/ui/src/styles.css index a377e9f..95c4779 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -1329,7 +1329,12 @@ h2 { font-size: 13px; margin: 0; font-weight: 600; } border-bottom: 1px solid color-mix(in srgb, var(--line) 70%, transparent); } .read-item:last-child, .finding:last-child { border-bottom: 0; } -.read-item .why { color: var(--muted); font-size: 12px; margin-top: 2px; } +.read-item.tour-current { + background: color-mix(in srgb, var(--accent) 12%, var(--surface)); + border-color: var(--accent); +} +.tour-row { margin-top: 8px; align-items: center; } +.field.dirty .chip-btn { height: 32px; } .muted { color: var(--muted); font-size: 13px; line-height: 1.45; } .error { color: var(--low); diff --git a/ui/src/types.ts b/ui/src/types.ts index b2a30e1..54599b4 100644 --- a/ui/src/types.ts +++ b/ui/src/types.ts @@ -70,6 +70,15 @@ export type Review = { architecture_note: string; depth_note?: string; deepening?: DeepeningCandidate[]; + contract_break?: { kind: string; reasons: string[]; fields: string[] }; + auth?: { + note: string; + sinks: { id: string; name: string; permissions: string[] }[]; + missing_permissions: { id: string; name: string }[]; + }; + suggested_tests?: { sink: string; type: string; kind: string; title: string; body: string }[]; + trend?: { note: string; points: { id: string; created_at: string; level: string; sinks?: number }[] }; + what_if?: boolean; evolution?: { hotspots: { path: string; commits: number; bus_factor: number; complexity?: number }[]; change_coupling: { a: string; b: string; together: number; cross_context?: boolean }[]; @@ -96,6 +105,7 @@ export type Review = { dirty_count: number; dirty_overlaps_review: boolean; dirty_overlap: string[]; + dirty_included?: boolean; merge_base?: string | null; three_dot?: boolean; base_sha?: string | null; @@ -240,6 +250,19 @@ export const LAYER_ORDER: Record = { "django.test": 7, "django.migration_op": 7, "django.admin": 7, + "django.management_command": 7, + "django.consumer": 7, + "django.websocket_route": 1, + "django.template": 11, + "django.htmx": 9, + "django.cache_key": 7, + "django.feature_flag": 7, + "django.side_effect": 7, + "graphql.type": 3, + "graphql.field": 4, + "graphql.operation": 8, + "fastapi.route": 1, + "fastapi.model": 3, "openapi.path": 8, "react.api_client": 9, "react.query_key": 10, From af566f9d3fe2761c6663e598f3fb3d6467d42b2d Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 15 Aug 2026 13:24:35 +0000 Subject: [PATCH 2/4] Fix remote .git stripping and prefer breaking-contract CI gates. parse_remote_url treated '.git' as part of the slug because the host regex allows dots. Gate checks for a breaking contract before medium confidence so --fail-on medium fails on a public-contract break. Co-authored-by: zord.lack.net --- src/loadpath/providers/scm.py | 2 ++ src/loadpath/review/gate.py | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/loadpath/providers/scm.py b/src/loadpath/providers/scm.py index 5575aa6..ccd67c4 100644 --- a/src/loadpath/providers/scm.py +++ b/src/loadpath/providers/scm.py @@ -39,6 +39,8 @@ def parse_remote_url(url: str) -> tuple[str, str] | None: if not match: return None slug = match.group("slug").strip("/") + if slug.endswith(".git"): + slug = slug[:-4] parts = slug.split("/") if len(parts) >= 2: slug = "/".join(parts[:2]) diff --git a/src/loadpath/review/gate.py b/src/loadpath/review/gate.py index 0da9b35..cabdf1d 100644 --- a/src/loadpath/review/gate.py +++ b/src/loadpath/review/gate.py @@ -18,15 +18,15 @@ def gate_result(review: dict, fail_on: str = "blocker") -> dict: if fail_on != "never" and blockers: code = 2 reasons.append(f"{len(blockers)} architecture blocker(s)") + if fail_on in {"low", "medium"} and contract == "breaking" and code == 0: + code = 4 + reasons.append("breaking public contract") if fail_on in {"low", "medium"} and level == "low" and code == 0: code = 3 reasons.append("confidence is low") if fail_on == "medium" and level == "medium" and code == 0: code = 3 reasons.append("confidence is medium") - if fail_on in {"low", "medium"} and contract == "breaking" and code == 0: - code = 4 - reasons.append("breaking public contract") passed = code == 0 summary = "pass" if passed else "fail" title = (review.get("title") or "change").strip() From d12ea7af64355b8420fcc2f19413bcb374994e02 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 15 Aug 2026 14:14:50 +0000 Subject: [PATCH 3/4] Add granular index progress and parallel extract. Indexing now reports scan/extract/boot/stitch phases with per-file counts, hashes each source once, extracts CPU-bound ASTs in a process pool, and keeps SQLite upserts on one thread with WAL and batched commits. The CLI shows a live bar, the API exposes GET /api/index/progress, and the UI polls that endpoint so a long index is distinguishable from a hang. Co-authored-by: zord.lack.net --- src/loadpath/cli.py | 98 ++++- src/loadpath/graph/store.py | 7 +- src/loadpath/index.py | 393 ++++++++++++++++-- src/loadpath/progress.py | 44 ++ src/loadpath/review/engine.py | 4 + src/loadpath/server/app.py | 19 +- ...mUQO6wms.js => LayeredGraph3D-CNVAazxv.js} | 2 +- src/loadpath/static/assets/index-CEZTl1rC.js | 62 --- src/loadpath/static/assets/index-D9L1hiqG.js | 62 +++ ...{index-B5eCWnJO.css => index-p-RF8Le9.css} | 2 +- src/loadpath/static/index.html | 4 +- tests/unit/test_index_progress.py | 91 ++++ ui/src/App.tsx | 44 +- ui/src/api.ts | 4 +- ui/src/styles.css | 7 + ui/src/types.ts | 15 + 16 files changed, 747 insertions(+), 111 deletions(-) create mode 100644 src/loadpath/progress.py rename src/loadpath/static/assets/{LayeredGraph3D-mUQO6wms.js => LayeredGraph3D-CNVAazxv.js} (99%) delete mode 100644 src/loadpath/static/assets/index-CEZTl1rC.js create mode 100644 src/loadpath/static/assets/index-D9L1hiqG.js rename src/loadpath/static/assets/{index-B5eCWnJO.css => index-p-RF8Le9.css} (65%) create mode 100644 tests/unit/test_index_progress.py diff --git a/src/loadpath/cli.py b/src/loadpath/cli.py index 07e327f..1dfb79f 100644 --- a/src/loadpath/cli.py +++ b/src/loadpath/cli.py @@ -1,11 +1,13 @@ from __future__ import annotations +from contextlib import contextmanager from pathlib import Path -from typing import Optional +from typing import Any, Iterator, Optional import typer from rich.console import Console from rich.markdown import Markdown +from rich.progress import BarColumn, MofNCompleteColumn, Progress, SpinnerColumn, TextColumn, TimeElapsedColumn from loadpath import __version__ from loadpath.architecture.snapshot import architecture_report @@ -18,6 +20,50 @@ console = Console() +@contextmanager +def _index_progress() -> Iterator[Any]: + """Live CLI bar so a long extract is distinguishable from a hang.""" + if not console.is_terminal: + def _plain(event: dict[str, Any]) -> None: + msg = event.get("message") or event.get("phase") + if not msg: + return + phase = event.get("phase") + if phase == "extract" and event.get("current") and str(msg).startswith("Extracting "): + return + if phase in {"scan", "extract", "boot", "stitch", "done", "skipped"}: + console.print(f"[dim]{msg}[/dim]") + + yield _plain + return + + bar = Progress( + SpinnerColumn(), + TextColumn("[progress.description]{task.description}"), + BarColumn(), + MofNCompleteColumn(), + TimeElapsedColumn(), + console=console, + transient=False, + ) + task_id: Any = None + with bar: + def _cb(event: dict[str, Any]) -> None: + nonlocal task_id + desc = str(event.get("message") or event.get("phase") or "Indexing") + total = int(event.get("total") or 0) + done = int(event.get("done") or 0) + if task_id is None: + task_id = bar.add_task(desc, total=total if total else None) + return + kwargs: dict[str, Any] = {"description": desc, "completed": done} + if total: + kwargs["total"] = total + bar.update(task_id, **kwargs) + + yield _cb + + @app.callback() def _version(version: bool = typer.Option(False, "--version", help="Show version")) -> None: if version: @@ -43,24 +89,41 @@ def init( def index( repo: Path = typer.Argument(Path("."), exists=True, file_okay=False), full: bool = typer.Option(False, "--full", help="Re-extract every file"), + jobs: Optional[int] = typer.Option( + None, + "--jobs", + "-j", + help="Parallel extract workers (default: CPU count, 1 if few files). LOADPATH_INDEX_JOBS also works.", + ), ) -> None: """Index a Django + React monorepo into a SQLite graph.""" from loadpath.architecture.snapshot import summarize_index from loadpath.config import load_config from loadpath.settings import register_workspace - store = index_repo(repo, incremental=not full, draft_config=True) + with _index_progress() as on_progress: + store = index_repo( + repo, + incremental=not full, + draft_config=True, + progress=on_progress, + workers=jobs, + ) register_workspace(repo) summary = summarize_index(store, load_config(repo)) counts = summary["counts"] extracted = summary.get("files_extracted") or 0 skipped = summary.get("reindex_skipped") + workers = store.get_meta("index_workers") + elapsed = store.get_meta("index_elapsed_ms") + timing = f" in {elapsed}ms" if elapsed else "" + jobs_note = f" · {workers} extract workers" if workers and workers not in {"0", "1"} else "" if skipped: - console.print(f"Index already current ({counts['nodes']} nodes / {counts['edges']} edges) → {default_db_path(repo)}") + console.print(f"Index already current ({counts['nodes']} nodes / {counts['edges']} edges){timing} → {default_db_path(repo)}") else: console.print( f"Indexed {counts['nodes']} nodes / {counts['edges']} edges" - f" (extracted {extracted} files) → {default_db_path(repo)}" + f" (extracted {extracted} files){timing}{jobs_note} → {default_db_path(repo)}" ) contexts = ", ".join(summary["contexts"]) or "none" console.print(f"Contexts: {contexts}") @@ -99,6 +162,12 @@ def review( scm_repo: Optional[str] = typer.Option(None, "--repo", help="owner/name for --comment / --pr fetch"), fetch_pr: bool = typer.Option(False, "--fetch-pr", help="Fetch --pr refs into this clone before reviewing"), github_output: Optional[Path] = typer.Option(None, "--github-output", help="Append gate fields for GitHub Actions"), + jobs: Optional[int] = typer.Option( + None, + "--jobs", + "-j", + help="Parallel extract workers when reindexing (default: CPU count). LOADPATH_INDEX_JOBS also works.", + ), ) -> None: """Review a git range as clustered load paths + confidence brief.""" import os @@ -116,15 +185,18 @@ def review( head = prepared["head"] console.print(f"Fetched {provider} #{pr} → {head} (base {base})") - payload = run_review( - repo_path, - base=base, - head=head, - reindex=reindex, - incremental=not full, - three_dot=three_dot, - dirty=dirty, - ) + with _index_progress() as on_progress: + payload = run_review( + repo_path, + base=base, + head=head, + reindex=reindex, + incremental=not full, + three_dot=three_dot, + dirty=dirty, + progress=on_progress if reindex else None, + workers=jobs, + ) if format == "json": import json diff --git a/src/loadpath/graph/store.py b/src/loadpath/graph/store.py index 589e4bf..174585b 100644 --- a/src/loadpath/graph/store.py +++ b/src/loadpath/graph/store.py @@ -72,6 +72,8 @@ def __init__(self, db_path: Path) -> None: self.conn = sqlite3.connect(str(self.db_path)) self.conn.row_factory = sqlite3.Row self.conn.execute("PRAGMA foreign_keys = ON") + self.conn.execute("PRAGMA journal_mode = WAL") + self.conn.execute("PRAGMA synchronous = NORMAL") self.conn.executescript(SCHEMA) self.conn.commit() @@ -131,12 +133,13 @@ def prune_dangling_edges(self) -> None: "DELETE FROM edges WHERE src NOT IN (SELECT id FROM nodes) OR dst NOT IN (SELECT id FROM nodes)" ) - def upsert_graph(self, graph: ExtractedGraph) -> None: + def upsert_graph(self, graph: ExtractedGraph, *, commit: bool = True) -> None: for node in graph.nodes: self.upsert_node(node) for edge in graph.edges: self.upsert_edge(edge) - self.conn.commit() + if commit: + self.conn.commit() def upsert_node(self, node: Node) -> None: existing = self.get_node(node.id) diff --git a/src/loadpath/index.py b/src/loadpath/index.py index 5f6cee1..135a6ce 100644 --- a/src/loadpath/index.py +++ b/src/loadpath/index.py @@ -1,8 +1,15 @@ from __future__ import annotations import hashlib +import multiprocessing +import os +import sys +import time +from concurrent.futures import ProcessPoolExecutor, ThreadPoolExecutor, as_completed +from concurrent.futures.process import BrokenProcessPool from datetime import datetime, timezone from pathlib import Path +from typing import Any, Callable from loadpath.config import LoadpathConfig, load_config from loadpath.extractors.django import extract_django_file @@ -17,6 +24,18 @@ INDEX_EXTENSIONS = {".py", ".ts", ".tsx", ".js", ".jsx", ".html", ".htm"} # Bump when extractor/stitch node identity changes so incremental indexes rebuild. INDEX_REVISION = "10" +_UPSERT_BATCH = 25 + +ProgressCallback = Callable[[dict[str, Any]], None] + + +class SourceFile: + __slots__ = ("path", "rel", "digest") + + def __init__(self, path: Path, rel: str, digest: str) -> None: + self.path = path + self.rel = rel + self.digest = digest def default_db_path(repo_root: Path) -> Path: @@ -66,6 +85,10 @@ def file_hash(path: Path) -> str: return hashlib.sha256(path.read_bytes()).hexdigest() +def _hash_job(path: str) -> str: + return file_hash(Path(path)) + + def language_for(path: Path) -> str: if path.suffix == ".py": return "python" @@ -99,15 +122,107 @@ def _sidecar_digest(repo_root: Path, config: LoadpathConfig) -> str: return digest.hexdigest() -def index_drift(store: GraphStore, repo_root: Path, config: LoadpathConfig) -> dict: - files = iter_source_files(repo_root, config) - present = {path.relative_to(repo_root).as_posix() for path in files} +def _emit(progress: ProgressCallback | None, event: dict[str, Any]) -> None: + if progress is None: + return + progress(event) + + +def _elapsed_ms(started: float) -> int: + return int((time.monotonic() - started) * 1000) + + +def default_workers(n_files: int) -> int: + env = os.environ.get("LOADPATH_INDEX_JOBS", "").strip() + if env.isdigit(): + return max(1, int(env)) + if getattr(sys, "frozen", False): + return 1 + if n_files < 6: + return 1 + cpu = os.cpu_count() or 2 + return max(1, min(8, cpu, n_files)) + + +def list_source_files( + repo_root: Path, + config: LoadpathConfig, + *, + hash_workers: int | None = None, + progress: ProgressCallback | None = None, + started: float | None = None, +) -> list[SourceFile]: + """Scan once and hash each source file. Hashing is I/O-bound, so threads help.""" + started = time.monotonic() if started is None else started + paths = iter_source_files(repo_root, config) + _emit( + progress, + { + "phase": "scan", + "done": 0, + "total": len(paths), + "elapsed_ms": _elapsed_ms(started), + "message": f"Scanning {len(paths)} source files", + }, + ) + if not paths: + return [] + workers = hash_workers if hash_workers is not None else (1 if len(paths) < 8 else min(8, len(paths))) + out: list[SourceFile] = [] + if workers <= 1: + for i, path in enumerate(paths, start=1): + rel = path.relative_to(repo_root).as_posix() + out.append(SourceFile(path, rel, file_hash(path))) + if i == 1 or i == len(paths) or i % 25 == 0: + _emit( + progress, + { + "phase": "scan", + "done": i, + "total": len(paths), + "current": rel, + "elapsed_ms": _elapsed_ms(started), + "message": f"Hashed {i}/{len(paths)} files", + }, + ) + return out + with ThreadPoolExecutor(max_workers=workers) as pool: + futs = {pool.submit(_hash_job, str(path)): path for path in paths} + done = 0 + for fut in as_completed(futs): + path = futs[fut] + rel = path.relative_to(repo_root).as_posix() + out.append(SourceFile(path, rel, fut.result())) + done += 1 + if done == 1 or done == len(paths) or done % 25 == 0: + _emit( + progress, + { + "phase": "scan", + "done": done, + "total": len(paths), + "current": rel, + "elapsed_ms": _elapsed_ms(started), + "message": f"Hashed {done}/{len(paths)} files", + }, + ) + by_path = {src.path: src for src in out} + return [by_path[path] for path in paths] + + +def index_drift( + store: GraphStore, + repo_root: Path, + config: LoadpathConfig, + files: list[SourceFile] | None = None, +) -> dict: + files = files if files is not None else list_source_files(repo_root, config) + present = {src.rel for src in files} indexed = set(store.indexed_paths()) changed: list[str] = [] - for path in files: - rel = path.relative_to(repo_root).as_posix() - if store.file_hash(rel) != file_hash(path): - changed.append(rel) + for src in files: + if store.file_hash(src.rel) != src.digest: + changed.append(src.rel) added = sorted(present - indexed) deleted = sorted(indexed - present) config_changed = _sidecar_digest(repo_root, config) != (store.get_meta("sidecar_hash") or "") @@ -136,6 +251,120 @@ def _boot_status(residuals: list[str], enabled: bool) -> tuple[str, str]: return "skipped", "django.setup() did not run" +def _extract_one(rel: str, path: Path, config: LoadpathConfig) -> ExtractedGraph: + source = path.read_text(encoding="utf-8", errors="replace") + if path.suffix in {".html", ".htm"}: + graph = extract_template_file(rel, source, config) + elif path.suffix == ".py": + graph = extract_django_file(rel, source, config) + else: + graph = extract_react_file(rel, source, config) + _assign_contexts(graph, config, rel) + return graph + + +def _extract_job(payload: tuple[str, str, LoadpathConfig]) -> tuple[str, ExtractedGraph | None, str | None]: + """Picklable worker: extract one file. Must stay at module level for spawn.""" + rel, path, config = payload + try: + return rel, _extract_one(rel, Path(path), config), None + except Exception as exc: # pragma: no cover - surfaced as residual + return rel, None, f"{type(exc).__name__}: {exc}" + + +def _extract_sequential( + files: list[SourceFile], + config: LoadpathConfig, + *, + started: float, + progress: ProgressCallback | None, + workers: int = 1, +) -> list[tuple[SourceFile, ExtractedGraph | None, str | None]]: + results: list[tuple[SourceFile, ExtractedGraph | None, str | None]] = [] + total = len(files) + for i, src in enumerate(files, start=1): + _emit( + progress, + { + "phase": "extract", + "done": i - 1, + "total": total, + "current": src.rel, + "workers": workers, + "elapsed_ms": _elapsed_ms(started), + "message": f"Extracting {src.rel} ({i}/{total})", + }, + ) + try: + results.append((src, _extract_one(src.rel, src.path, config), None)) + except Exception as exc: + results.append((src, None, f"{type(exc).__name__}: {exc}")) + _emit( + progress, + { + "phase": "extract", + "done": i, + "total": total, + "current": src.rel, + "workers": workers, + "elapsed_ms": _elapsed_ms(started), + "message": f"Extracted {src.rel} ({i}/{total})", + }, + ) + return results + + +def _extract_parallel( + files: list[SourceFile], + config: LoadpathConfig, + *, + workers: int, + started: float, + progress: ProgressCallback | None, +) -> list[tuple[SourceFile, ExtractedGraph | None, str | None]]: + by_rel = {src.rel: src for src in files} + total = len(files) + found: dict[str, tuple[ExtractedGraph | None, str | None]] = {} + ctx = multiprocessing.get_context("spawn") + _emit( + progress, + { + "phase": "extract", + "done": 0, + "total": total, + "workers": workers, + "elapsed_ms": _elapsed_ms(started), + "message": f"Extracting {total} files with {workers} workers", + }, + ) + with ProcessPoolExecutor(max_workers=workers, mp_context=ctx) as pool: + futs = { + pool.submit(_extract_job, (src.rel, str(src.path), config)): src.rel for src in files + } + done = 0 + for fut in as_completed(futs): + rel = futs[fut] + try: + _, graph, err = fut.result() + except Exception as exc: + graph, err = None, f"{type(exc).__name__}: {exc}" + found[rel] = (graph, err) + done += 1 + _emit( + progress, + { + "phase": "extract", + "done": done, + "total": total, + "current": rel, + "workers": workers, + "elapsed_ms": _elapsed_ms(started), + "message": f"Extracted {rel} ({done}/{total})", + }, + ) + return [(src, found[src.rel][0], found[src.rel][1]) for src in files] + + def index_repo( repo_root: Path, db_path: Path | None = None, @@ -143,8 +372,11 @@ def index_repo( incremental: bool = True, *, draft_config: bool = False, + progress: ProgressCallback | None = None, + workers: int | None = None, ) -> GraphStore: repo_root = repo_root.resolve() + started = time.monotonic() if draft_config: from loadpath.detect import write_draft_config @@ -155,43 +387,124 @@ def index_repo( store = GraphStore(db_path) store.set_meta("repo_root", str(repo_root)) - drift = index_drift(store, repo_root, config) + _emit( + progress, + { + "phase": "scan", + "done": 0, + "total": 0, + "elapsed_ms": 0, + "message": "Scanning source files", + }, + ) + files = list_source_files(repo_root, config, progress=progress, started=started) + n_cpu = workers if workers is not None else default_workers(len(files)) + drift = index_drift(store, repo_root, config, files=files) revision_changed = (store.get_meta("index_revision") or "") != INDEX_REVISION if incremental and store.file_count() > 0 and not drift["stale"] and not revision_changed: store.set_meta("reindex_skipped", "1") store.set_meta("files_extracted", "0") store.set_meta("files_skipped", str(drift["indexed_count"])) + store.set_meta("index_workers", "0") + store.set_meta("index_elapsed_ms", str(_elapsed_ms(started))) store.conn.commit() + _emit( + progress, + { + "phase": "skipped", + "done": drift["indexed_count"], + "total": drift["indexed_count"], + "skipped": drift["indexed_count"], + "workers": 0, + "elapsed_ms": _elapsed_ms(started), + "message": f"Index already current ({drift['indexed_count']} files unchanged)", + }, + ) return store residuals: list[str] = [] skipped: set[str] = set() - files = iter_source_files(repo_root, config) - present = {path.relative_to(repo_root).as_posix() for path in files} + present = {src.rel for src in files} extracted = 0 + used_workers = 1 for stale in store.indexed_paths(): if stale not in present: store.delete_file_nodes(stale) - for path in files: - rel = path.relative_to(repo_root).as_posix() - digest = file_hash(path) - if incremental and not revision_changed and store.file_hash(rel) == digest: - skipped.add(rel) + + to_extract: list[SourceFile] = [] + for src in files: + if incremental and not revision_changed and store.file_hash(src.rel) == src.digest: + skipped.add(src.rel) continue - store.delete_file_nodes(rel, drop_incoming=False) - source = path.read_text(encoding="utf-8", errors="replace") - if path.suffix in {".html", ".htm"}: - graph = extract_template_file(rel, source, config) - elif path.suffix == ".py": - graph = extract_django_file(rel, source, config) + to_extract.append(src) + + _emit( + progress, + { + "phase": "extract", + "done": 0, + "total": len(to_extract), + "workers": n_cpu, + "skipped": len(skipped), + "elapsed_ms": _elapsed_ms(started), + "message": ( + f"Extracting {len(to_extract)} of {len(files)} files" + if to_extract + else f"Nothing to extract ({len(skipped)} unchanged)" + ), + }, + ) + + results: list[tuple[SourceFile, ExtractedGraph | None, str | None]] = [] + if to_extract: + if n_cpu > 1 and len(to_extract) > 1: + try: + results = _extract_parallel( + to_extract, + config, + workers=n_cpu, + started=started, + progress=progress, + ) + used_workers = n_cpu + except (BrokenProcessPool, OSError, PermissionError): + results = _extract_sequential( + to_extract, config, started=started, progress=progress, workers=1 + ) + used_workers = 1 else: - graph = extract_react_file(rel, source, config) - _assign_contexts(graph, config, rel) - store.upsert_file(rel, digest, language_for(path)) - store.upsert_graph(graph) + results = _extract_sequential( + to_extract, config, started=started, progress=progress, workers=1 + ) + used_workers = 1 + + pending = 0 + for src, graph, err in results: + if err or graph is None: + residuals.append(f"Failed to extract {src.rel}: {err or 'unknown error'}") + continue + store.delete_file_nodes(src.rel, drop_incoming=False) + store.upsert_file(src.rel, src.digest, language_for(src.path)) + store.upsert_graph(graph, commit=False) residuals.extend(graph.residuals) extracted += 1 + pending += 1 + if pending >= _UPSERT_BATCH: + store.conn.commit() + pending = 0 + if pending: + store.conn.commit() + _emit( + progress, + { + "phase": "boot", + "done": 0, + "total": 1, + "elapsed_ms": _elapsed_ms(started), + "message": "Booting Django models (optional)", + }, + ) boot = ExtractedGraph() if config.boot_django: boot = try_boot_models(repo_root, config) @@ -199,6 +512,16 @@ def index_repo( residuals.extend(boot.residuals) boot_state, boot_detail = _boot_status(boot.residuals, config.boot_django) + _emit( + progress, + { + "phase": "stitch", + "done": 0, + "total": 1, + "elapsed_ms": _elapsed_ms(started), + "message": "Stitching contracts (OpenAPI, GraphQL, HTMX)", + }, + ) _ensure_context_nodes(store, config) stitch_residuals = stitch(store, config, repo_root) store.prune_dangling_edges() @@ -220,6 +543,7 @@ def index_repo( residuals = deduped else: residuals.extend(stitch_residuals) + elapsed = _elapsed_ms(started) store.set_meta("residuals", "\n".join(residuals)) store.set_meta("indexed_at", datetime.now(timezone.utc).isoformat()) store.set_meta("incremental", "1" if incremental else "0") @@ -231,7 +555,26 @@ def index_repo( store.set_meta("config_hash", _config_digest(repo_root)) store.set_meta("sidecar_hash", _sidecar_digest(repo_root, config)) store.set_meta("index_revision", INDEX_REVISION) + store.set_meta("index_workers", str(used_workers)) + store.set_meta("index_elapsed_ms", str(elapsed)) store.conn.commit() + _emit( + progress, + { + "phase": "done", + "done": extracted, + "total": len(files), + "skipped": len(skipped), + "workers": used_workers, + "elapsed_ms": elapsed, + "errors": sum(1 for line in residuals if line.startswith("Failed to extract ")), + "message": ( + f"Indexed {extracted} files ({len(skipped)} unchanged) in {elapsed}ms" + if extracted + else f"Indexed 0 files ({len(skipped)} unchanged) in {elapsed}ms" + ), + }, + ) return store diff --git a/src/loadpath/progress.py b/src/loadpath/progress.py new file mode 100644 index 0000000..7c3a78f --- /dev/null +++ b/src/loadpath/progress.py @@ -0,0 +1,44 @@ +"""In-memory index progress for the local API/UI (and tests).""" + +from __future__ import annotations + +import threading +import time +from pathlib import Path +from typing import Any, Callable + +_lock = threading.Lock() +_STATE: dict[str, dict[str, Any]] = {} + + +def progress_key(repo_root: Path | str) -> str: + return str(Path(repo_root).expanduser().resolve()) + + +def record_progress(repo_root: Path | str, event: dict[str, Any]) -> None: + key = progress_key(repo_root) + payload = {**event, "repo_path": key, "updated_at": time.time()} + with _lock: + _STATE[key] = payload + + +def read_progress(repo_root: Path | str) -> dict[str, Any]: + key = progress_key(repo_root) + with _lock: + current = _STATE.get(key) + if current is None: + return { + "phase": "idle", + "done": 0, + "total": 0, + "message": "No index in progress", + "repo_path": key, + } + return dict(current) + + +def progress_callback(repo_root: Path | str) -> Callable[[dict[str, Any]], None]: + def _cb(event: dict[str, Any]) -> None: + record_progress(repo_root, event) + + return _cb diff --git a/src/loadpath/review/engine.py b/src/loadpath/review/engine.py index 1ef52ed..b45754a 100644 --- a/src/loadpath/review/engine.py +++ b/src/loadpath/review/engine.py @@ -370,6 +370,8 @@ def run_review( three_dot: bool = True, draft_config: bool = False, dirty: bool = False, + progress: object | None = None, + workers: int | None = None, ) -> dict: repo_root = repo_root.resolve() config = config or load_config(repo_root) @@ -381,6 +383,8 @@ def run_review( config=config, incremental=incremental, draft_config=draft_config, + progress=progress, + workers=workers, ) else: if not graph_db.is_file(): diff --git a/src/loadpath/server/app.py b/src/loadpath/server/app.py index 935065e..8d972c4 100644 --- a/src/loadpath/server/app.py +++ b/src/loadpath/server/app.py @@ -29,6 +29,7 @@ from loadpath.detect import detect_layout, write_draft_config from loadpath.graph.store import GraphStore from loadpath.index import default_db_path, index_repo +from loadpath.progress import progress_callback, read_progress from loadpath.providers.oauth import ( callback_html, disconnect_scm, @@ -51,6 +52,7 @@ class IndexRequest(BaseModel): repo_path: str incremental: bool = True + jobs: int | None = None class ReviewRequest(BaseModel): @@ -61,6 +63,7 @@ class ReviewRequest(BaseModel): incremental: bool = True three_dot: bool = True dirty: bool = False + jobs: int | None = None class InitRequest(BaseModel): @@ -294,12 +297,23 @@ def put_settings(body: SettingsUpdate) -> dict[str, Any]: @app.post("/api/index") def api_index(body: IndexRequest) -> dict[str, Any]: root = require_repo_path(body.repo_path) - store = index_repo(root, incremental=body.incremental, draft_config=True) + store = index_repo( + root, + incremental=body.incremental, + draft_config=True, + progress=progress_callback(root), + workers=body.jobs, + ) register_workspace(root) summary = summarize_index(store, load_config(root)) store.close() return summary + @app.get("/api/index/progress") + def api_index_progress(repo_path: str) -> dict[str, Any]: + root = require_repo_path(repo_path) + return read_progress(root) + @app.get("/api/index") def api_index_status(repo_path: str) -> dict[str, Any]: root = require_repo_path(repo_path) @@ -356,6 +370,8 @@ def api_review(body: ReviewRequest) -> dict[str, Any]: incremental=body.incremental, three_dot=body.three_dot, dirty=body.dirty, + progress=progress_callback(root) if body.reindex else None, + workers=body.jobs, ) except FileNotFoundError as exc: raise HTTPException(409, str(exc)) from exc @@ -688,6 +704,7 @@ def api_pr_review(request: Request, body: PRReviewRequest) -> dict[str, Any]: reindex=body.reindex, incremental=body.incremental, three_dot=True, + progress=progress_callback(root) if body.reindex else None, ) except FileNotFoundError as exc: raise HTTPException(409, str(exc)) from exc diff --git a/src/loadpath/static/assets/LayeredGraph3D-mUQO6wms.js b/src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js similarity index 99% rename from src/loadpath/static/assets/LayeredGraph3D-mUQO6wms.js rename to src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js index ba45ac8..08abd43 100644 --- a/src/loadpath/static/assets/LayeredGraph3D-mUQO6wms.js +++ b/src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js @@ -1,4 +1,4 @@ -import{r as bn,l as tc,c as nc,a as ic,L as sc,j as jn,t as rc}from"./index-CEZTl1rC.js";/** +import{r as bn,l as tc,c as nc,a as ic,L as sc,j as jn,t as rc}from"./index-D9L1hiqG.js";/** * @license * Copyright 2010-2026 Three.js Authors * SPDX-License-Identifier: MIT diff --git a/src/loadpath/static/assets/index-CEZTl1rC.js b/src/loadpath/static/assets/index-CEZTl1rC.js deleted file mode 100644 index 029e199..0000000 --- a/src/loadpath/static/assets/index-CEZTl1rC.js +++ /dev/null @@ -1,62 +0,0 @@ -(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))l(a);new MutationObserver(a=>{for(const u of a)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function o(a){const u={};return a.integrity&&(u.integrity=a.integrity),a.referrerPolicy&&(u.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?u.credentials="include":a.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(a){if(a.ep)return;a.ep=!0;const u=o(a);fetch(a.href,u)}})();function xp(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var wu={exports:{}},uo={},_u={exports:{}},Ie={};/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Hf;function Qy(){if(Hf)return Ie;Hf=1;var t=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),u=Symbol.for("react.provider"),d=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),x=Symbol.iterator;function v(M){return M===null||typeof M!="object"?null:(M=x&&M[x]||M["@@iterator"],typeof M=="function"?M:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},S=Object.assign,C={};function E(M,L,ne){this.props=M,this.context=L,this.refs=C,this.updater=ne||_}E.prototype.isReactComponent={},E.prototype.setState=function(M,L){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,L,"setState")},E.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function N(){}N.prototype=E.prototype;function I(M,L,ne){this.props=M,this.context=L,this.refs=C,this.updater=ne||_}var k=I.prototype=new N;k.constructor=I,S(k,E.prototype),k.isPureReactComponent=!0;var j=Array.isArray,R=Object.prototype.hasOwnProperty,T={current:null},B={key:!0,ref:!0,__self:!0,__source:!0};function G(M,L,ne){var re,ce={},fe=null,de=null;if(L!=null)for(re in L.ref!==void 0&&(de=L.ref),L.key!==void 0&&(fe=""+L.key),L)R.call(L,re)&&!B.hasOwnProperty(re)&&(ce[re]=L[re]);var K=arguments.length-2;if(K===1)ce.children=ne;else if(1>>1,L=D[M];if(0>>1;Ma(ce,H))fea(de,ce)?(D[M]=de,D[fe]=H,M=fe):(D[M]=ce,D[re]=H,M=re);else if(fea(de,H))D[M]=de,D[fe]=H,M=fe;else break e}}return A}function a(D,A){var H=D.sortIndex-A.sortIndex;return H!==0?H:D.id-A.id}if(typeof performance=="object"&&typeof performance.now=="function"){var u=performance;t.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();t.unstable_now=function(){return d.now()-f}}var g=[],y=[],m=1,x=null,v=3,_=!1,S=!1,C=!1,E=typeof setTimeout=="function"?setTimeout:null,N=typeof clearTimeout=="function"?clearTimeout:null,I=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function k(D){for(var A=o(y);A!==null;){if(A.callback===null)l(y);else if(A.startTime<=D)l(y),A.sortIndex=A.expirationTime,r(g,A);else break;A=o(y)}}function j(D){if(C=!1,k(D),!S)if(o(g)!==null)S=!0,V(R);else{var A=o(y);A!==null&&W(j,A.startTime-D)}}function R(D,A){S=!1,C&&(C=!1,N(G),G=-1),_=!0;var H=v;try{for(k(A),x=o(g);x!==null&&(!(x.expirationTime>A)||D&&!q());){var M=x.callback;if(typeof M=="function"){x.callback=null,v=x.priorityLevel;var L=M(x.expirationTime<=A);A=t.unstable_now(),typeof L=="function"?x.callback=L:x===o(g)&&l(g),k(A)}else l(g);x=o(g)}if(x!==null)var ne=!0;else{var re=o(y);re!==null&&W(j,re.startTime-A),ne=!1}return ne}finally{x=null,v=H,_=!1}}var T=!1,B=null,G=-1,U=5,ee=-1;function q(){return!(t.unstable_now()-eeD||125M?(D.sortIndex=H,r(y,D),o(g)===null&&D===o(y)&&(C?(N(G),G=-1):C=!0,W(j,H-M))):(D.sortIndex=L,r(g,D),S||_||(S=!0,V(R))),D},t.unstable_shouldYield=q,t.unstable_wrapCallback=function(D){var A=v;return function(){var H=v;v=A;try{return D.apply(this,arguments)}finally{v=H}}}})(Eu)),Eu}var Yf;function e0(){return Yf||(Yf=1,ku.exports=Jy()),ku.exports}/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Xf;function t0(){if(Xf)return Ct;Xf=1;var t=bo(),r=e0();function o(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,i=1;i"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),g=Object.prototype.hasOwnProperty,y=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,m={},x={};function v(e){return g.call(x,e)?!0:g.call(m,e)?!1:y.test(e)?x[e]=!0:(m[e]=!0,!1)}function _(e,n,i,s){if(i!==null&&i.type===0)return!1;switch(typeof n){case"function":case"symbol":return!0;case"boolean":return s?!1:i!==null?!i.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function S(e,n,i,s){if(n===null||typeof n>"u"||_(e,n,i,s))return!0;if(s)return!1;if(i!==null)switch(i.type){case 3:return!n;case 4:return n===!1;case 5:return isNaN(n);case 6:return isNaN(n)||1>n}return!1}function C(e,n,i,s,c,h,w){this.acceptsBooleans=n===2||n===3||n===4,this.attributeName=s,this.attributeNamespace=c,this.mustUseProperty=i,this.propertyName=e,this.type=n,this.sanitizeURL=h,this.removeEmptyString=w}var E={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){E[e]=new C(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var n=e[0];E[n]=new C(n,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){E[e]=new C(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){E[e]=new C(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){E[e]=new C(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){E[e]=new C(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){E[e]=new C(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){E[e]=new C(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){E[e]=new C(e,5,!1,e.toLowerCase(),null,!1,!1)});var N=/[\-:]([a-z])/g;function I(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var n=e.replace(N,I);E[n]=new C(n,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var n=e.replace(N,I);E[n]=new C(n,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var n=e.replace(N,I);E[n]=new C(n,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){E[e]=new C(e,1,!1,e.toLowerCase(),null,!1,!1)}),E.xlinkHref=new C("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){E[e]=new C(e,1,!1,e.toLowerCase(),null,!0,!0)});function k(e,n,i,s){var c=E.hasOwnProperty(n)?E[n]:null;(c!==null?c.type!==0:s||!(2P||c[w]!==h[P]){var z=` -`+c[w].replace(" at new "," at ");return e.displayName&&z.includes("")&&(z=z.replace("",e.displayName)),z}while(1<=w&&0<=P);break}}}finally{ne=!1,Error.prepareStackTrace=i}return(e=e?e.displayName||e.name:"")?L(e):""}function ce(e){switch(e.tag){case 5:return L(e.type);case 16:return L("Lazy");case 13:return L("Suspense");case 19:return L("SuspenseList");case 0:case 2:case 15:return e=re(e.type,!1),e;case 11:return e=re(e.type.render,!1),e;case 1:return e=re(e.type,!0),e;default:return""}}function fe(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case B:return"Fragment";case T:return"Portal";case U:return"Profiler";case G:return"StrictMode";case J:return"Suspense";case b:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case q:return(e.displayName||"Context")+".Consumer";case ee:return(e._context.displayName||"Context")+".Provider";case te:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Y:return n=e.displayName||null,n!==null?n:fe(e.type)||"Memo";case V:n=e._payload,e=e._init;try{return fe(e(n))}catch{}}return null}function de(e){var n=e.type;switch(e.tag){case 24:return"Cache";case 9:return(n.displayName||"Context")+".Consumer";case 10:return(n._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=n.render,e=e.displayName||e.name||"",n.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return n;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return fe(n);case 8:return n===G?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n}return null}function K(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function se(e){var n=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function pe(e){var n=se(e)?"checked":"value",i=Object.getOwnPropertyDescriptor(e.constructor.prototype,n),s=""+e[n];if(!e.hasOwnProperty(n)&&typeof i<"u"&&typeof i.get=="function"&&typeof i.set=="function"){var c=i.get,h=i.set;return Object.defineProperty(e,n,{configurable:!0,get:function(){return c.call(this)},set:function(w){s=""+w,h.call(this,w)}}),Object.defineProperty(e,n,{enumerable:i.enumerable}),{getValue:function(){return s},setValue:function(w){s=""+w},stopTracking:function(){e._valueTracker=null,delete e[n]}}}}function _e(e){e._valueTracker||(e._valueTracker=pe(e))}function me(e){if(!e)return!1;var n=e._valueTracker;if(!n)return!0;var i=n.getValue(),s="";return e&&(s=se(e)?e.checked?"true":"false":e.value),e=s,e!==i?(n.setValue(e),!0):!1}function ye(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Ne(e,n){var i=n.checked;return H({},n,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:i??e._wrapperState.initialChecked})}function Pe(e,n){var i=n.defaultValue==null?"":n.defaultValue,s=n.checked!=null?n.checked:n.defaultChecked;i=K(n.value!=null?n.value:i),e._wrapperState={initialChecked:s,initialValue:i,controlled:n.type==="checkbox"||n.type==="radio"?n.checked!=null:n.value!=null}}function je(e,n){n=n.checked,n!=null&&k(e,"checked",n,!1)}function Me(e,n){je(e,n);var i=K(n.value),s=n.type;if(i!=null)s==="number"?(i===0&&e.value===""||e.value!=i)&&(e.value=""+i):e.value!==""+i&&(e.value=""+i);else if(s==="submit"||s==="reset"){e.removeAttribute("value");return}n.hasOwnProperty("value")?Ge(e,n.type,i):n.hasOwnProperty("defaultValue")&&Ge(e,n.type,K(n.defaultValue)),n.checked==null&&n.defaultChecked!=null&&(e.defaultChecked=!!n.defaultChecked)}function tt(e,n,i){if(n.hasOwnProperty("value")||n.hasOwnProperty("defaultValue")){var s=n.type;if(!(s!=="submit"&&s!=="reset"||n.value!==void 0&&n.value!==null))return;n=""+e._wrapperState.initialValue,i||n===e.value||(e.value=n),e.defaultValue=n}i=e.name,i!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,i!==""&&(e.name=i)}function Ge(e,n,i){(n!=="number"||ye(e.ownerDocument)!==e)&&(i==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+i&&(e.defaultValue=""+i))}var nt=Array.isArray;function Ke(e,n,i,s){if(e=e.options,n){n={};for(var c=0;c"+n.valueOf().toString()+"",n=wt.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;n.firstChild;)e.appendChild(n.firstChild)}});function Ut(e,n){if(n){var i=e.firstChild;if(i&&i===e.lastChild&&i.nodeType===3){i.nodeValue=n;return}}e.textContent=n}var gn={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},Ni=["Webkit","ms","Moz","O"];Object.keys(gn).forEach(function(e){Ni.forEach(function(n){n=n+e.charAt(0).toUpperCase()+e.substring(1),gn[n]=gn[e]})});function $r(e,n,i){return n==null||typeof n=="boolean"||n===""?"":i||typeof n!="number"||n===0||gn.hasOwnProperty(e)&&gn[e]?(""+n).trim():n+"px"}function ir(e,n){e=e.style;for(var i in n)if(n.hasOwnProperty(i)){var s=i.indexOf("--")===0,c=$r(i,n[i],s);i==="float"&&(i="cssFloat"),s?e.setProperty(i,c):e[i]=c}}var Ci=H({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function or(e,n){if(n){if(Ci[e]&&(n.children!=null||n.dangerouslySetInnerHTML!=null))throw Error(o(137,e));if(n.dangerouslySetInnerHTML!=null){if(n.children!=null)throw Error(o(60));if(typeof n.dangerouslySetInnerHTML!="object"||!("__html"in n.dangerouslySetInnerHTML))throw Error(o(61))}if(n.style!=null&&typeof n.style!="object")throw Error(o(62))}}function Pn(e,n){if(e.indexOf("-")===-1)return typeof n.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var mn=null;function In(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var sr=null,on=null,sn=null;function lr(e){if(e=Gi(e)){if(typeof sr!="function")throw Error(o(280));var n=e.stateNode;n&&(n=os(n),sr(e.stateNode,e.type,n))}}function ar(e){on?sn?sn.push(e):sn=[e]:on=e}function ur(){if(on){var e=on,n=sn;if(sn=on=null,lr(e),n)for(e=0;e>>=0,e===0?32:31-(Ol(e)/Fl|0)|0}var Br=64,Vr=4194304;function hr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function yn(e,n){var i=e.pendingLanes;if(i===0)return 0;var s=0,c=e.suspendedLanes,h=e.pingedLanes,w=i&268435455;if(w!==0){var P=w&~c;P!==0?s=hr(P):(h&=w,h!==0&&(s=hr(h)))}else w=i&~c,w!==0?s=hr(w):h!==0&&(s=hr(h));if(s===0)return 0;if(n!==0&&n!==s&&(n&c)===0&&(c=s&-s,h=n&-n,c>=h||c===16&&(h&4194240)!==0))return n;if((s&4)!==0&&(s|=i&16),n=e.entangledLanes,n!==0)for(e=e.entanglements,n&=s;0i;i++)n.push(e);return n}function gr(e,n,i){e.pendingLanes|=n,n!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,n=31-Pt(n),e[n]=i}function Vl(e,n){var i=e.pendingLanes&~n;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=n,e.mutableReadLanes&=n,e.entangledLanes&=n,n=e.entanglements;var s=e.eventTimes;for(e=e.expirationTimes;0=Oi),Rc=" ",Lc=!1;function zc(e,n){switch(e){case"keyup":return Um.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Ac(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var Xr=!1;function Ym(e,n){switch(e){case"compositionend":return Ac(n);case"keypress":return n.which!==32?null:(Lc=!0,Rc);case"textInput":return e=n.data,e===Rc&&Lc?null:e;default:return null}}function Xm(e,n){if(Xr)return e==="compositionend"||!ea&&zc(e,n)?(e=jc(),Go=Gl=$n=null,Xr=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:i,offset:n-e};e=s}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=Vc(i)}}function Wc(e,n){return e&&n?e===n?!0:e&&e.nodeType===3?!1:n&&n.nodeType===3?Wc(e,n.parentNode):"contains"in e?e.contains(n):e.compareDocumentPosition?!!(e.compareDocumentPosition(n)&16):!1:!1}function Yc(){for(var e=window,n=ye();n instanceof e.HTMLIFrameElement;){try{var i=typeof n.contentWindow.location.href=="string"}catch{i=!1}if(i)e=n.contentWindow;else break;n=ye(e.document)}return n}function ra(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n&&(n==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||n==="textarea"||e.contentEditable==="true")}function ny(e){var n=Yc(),i=e.focusedElem,s=e.selectionRange;if(n!==i&&i&&i.ownerDocument&&Wc(i.ownerDocument.documentElement,i)){if(s!==null&&ra(i)){if(n=s.start,e=s.end,e===void 0&&(e=n),"selectionStart"in i)i.selectionStart=n,i.selectionEnd=Math.min(e,i.value.length);else if(e=(n=i.ownerDocument||document)&&n.defaultView||window,e.getSelection){e=e.getSelection();var c=i.textContent.length,h=Math.min(s.start,c);s=s.end===void 0?h:Math.min(s.end,c),!e.extend&&h>s&&(c=s,s=h,h=c),c=Uc(i,h);var w=Uc(i,s);c&&w&&(e.rangeCount!==1||e.anchorNode!==c.node||e.anchorOffset!==c.offset||e.focusNode!==w.node||e.focusOffset!==w.offset)&&(n=n.createRange(),n.setStart(c.node,c.offset),e.removeAllRanges(),h>s?(e.addRange(n),e.extend(w.node,w.offset)):(n.setEnd(w.node,w.offset),e.addRange(n)))}}for(n=[],e=i;e=e.parentNode;)e.nodeType===1&&n.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof i.focus=="function"&&i.focus(),i=0;i=document.documentMode,Gr=null,ia=null,Vi=null,oa=!1;function Xc(e,n,i){var s=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;oa||Gr==null||Gr!==ye(s)||(s=Gr,"selectionStart"in s&&ra(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),Vi&&Bi(Vi,s)||(Vi=s,s=ns(ia,"onSelect"),0Jr||(e.current=ya[Jr],ya[Jr]=null,Jr--)}function De(e,n){Jr++,ya[Jr]=e.current,e.current=n}var Bn={},pt=Hn(Bn),_t=Hn(!1),yr=Bn;function ei(e,n){var i=e.type.contextTypes;if(!i)return Bn;var s=e.stateNode;if(s&&s.__reactInternalMemoizedUnmaskedChildContext===n)return s.__reactInternalMemoizedMaskedChildContext;var c={},h;for(h in i)c[h]=n[h];return s&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=n,e.__reactInternalMemoizedMaskedChildContext=c),c}function St(e){return e=e.childContextTypes,e!=null}function ss(){Fe(_t),Fe(pt)}function ad(e,n,i){if(pt.current!==Bn)throw Error(o(168));De(pt,n),De(_t,i)}function ud(e,n,i){var s=e.stateNode;if(n=n.childContextTypes,typeof s.getChildContext!="function")return i;s=s.getChildContext();for(var c in s)if(!(c in n))throw Error(o(108,de(e)||"Unknown",c));return H({},i,s)}function ls(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Bn,yr=pt.current,De(pt,e),De(_t,_t.current),!0}function cd(e,n,i){var s=e.stateNode;if(!s)throw Error(o(169));i?(e=ud(e,n,yr),s.__reactInternalMemoizedMergedChildContext=e,Fe(_t),Fe(pt),De(pt,e)):Fe(_t),De(_t,i)}var xn=null,as=!1,va=!1;function dd(e){xn===null?xn=[e]:xn.push(e)}function py(e){as=!0,dd(e)}function Vn(){if(!va&&xn!==null){va=!0;var e=0,n=ze;try{var i=xn;for(ze=1;e>=w,c-=w,wn=1<<32-Pt(n)+c|i<Ce?(at=Ee,Ee=null):at=Ee.sibling;var Le=ie(X,Ee,Q[Ce],ue);if(Le===null){Ee===null&&(Ee=at);break}e&&Ee&&Le.alternate===null&&n(X,Ee),O=h(Le,O,Ce),ke===null?we=Le:ke.sibling=Le,ke=Le,Ee=at}if(Ce===Q.length)return i(X,Ee),Be&&xr(X,Ce),we;if(Ee===null){for(;CeCe?(at=Ee,Ee=null):at=Ee.sibling;var Zn=ie(X,Ee,Le.value,ue);if(Zn===null){Ee===null&&(Ee=at);break}e&&Ee&&Zn.alternate===null&&n(X,Ee),O=h(Zn,O,Ce),ke===null?we=Zn:ke.sibling=Zn,ke=Zn,Ee=at}if(Le.done)return i(X,Ee),Be&&xr(X,Ce),we;if(Ee===null){for(;!Le.done;Ce++,Le=Q.next())Le=le(X,Le.value,ue),Le!==null&&(O=h(Le,O,Ce),ke===null?we=Le:ke.sibling=Le,ke=Le);return Be&&xr(X,Ce),we}for(Ee=s(X,Ee);!Le.done;Ce++,Le=Q.next())Le=he(Ee,X,Ce,Le.value,ue),Le!==null&&(e&&Le.alternate!==null&&Ee.delete(Le.key===null?Ce:Le.key),O=h(Le,O,Ce),ke===null?we=Le:ke.sibling=Le,ke=Le);return e&&Ee.forEach(function(Gy){return n(X,Gy)}),Be&&xr(X,Ce),we}function qe(X,O,Q,ue){if(typeof Q=="object"&&Q!==null&&Q.type===B&&Q.key===null&&(Q=Q.props.children),typeof Q=="object"&&Q!==null){switch(Q.$$typeof){case R:e:{for(var we=Q.key,ke=O;ke!==null;){if(ke.key===we){if(we=Q.type,we===B){if(ke.tag===7){i(X,ke.sibling),O=c(ke,Q.props.children),O.return=X,X=O;break e}}else if(ke.elementType===we||typeof we=="object"&&we!==null&&we.$$typeof===V&&yd(we)===ke.type){i(X,ke.sibling),O=c(ke,Q.props),O.ref=Qi(X,ke,Q),O.return=X,X=O;break e}i(X,ke);break}else n(X,ke);ke=ke.sibling}Q.type===B?(O=jr(Q.props.children,X.mode,ue,Q.key),O.return=X,X=O):(ue=As(Q.type,Q.key,Q.props,null,X.mode,ue),ue.ref=Qi(X,O,Q),ue.return=X,X=ue)}return w(X);case T:e:{for(ke=Q.key;O!==null;){if(O.key===ke)if(O.tag===4&&O.stateNode.containerInfo===Q.containerInfo&&O.stateNode.implementation===Q.implementation){i(X,O.sibling),O=c(O,Q.children||[]),O.return=X,X=O;break e}else{i(X,O);break}else n(X,O);O=O.sibling}O=gu(Q,X.mode,ue),O.return=X,X=O}return w(X);case V:return ke=Q._init,qe(X,O,ke(Q._payload),ue)}if(nt(Q))return ve(X,O,Q,ue);if(A(Q))return xe(X,O,Q,ue);fs(X,Q)}return typeof Q=="string"&&Q!==""||typeof Q=="number"?(Q=""+Q,O!==null&&O.tag===6?(i(X,O.sibling),O=c(O,Q),O.return=X,X=O):(i(X,O),O=pu(Q,X.mode,ue),O.return=X,X=O),w(X)):i(X,O)}return qe}var ii=vd(!0),xd=vd(!1),hs=Hn(null),ps=null,oi=null,Ea=null;function Na(){Ea=oi=ps=null}function Ca(e){var n=hs.current;Fe(hs),e._currentValue=n}function ja(e,n,i){for(;e!==null;){var s=e.alternate;if((e.childLanes&n)!==n?(e.childLanes|=n,s!==null&&(s.childLanes|=n)):s!==null&&(s.childLanes&n)!==n&&(s.childLanes|=n),e===i)break;e=e.return}}function si(e,n){ps=e,Ea=oi=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&n)!==0&&(kt=!0),e.firstContext=null)}function Ft(e){var n=e._currentValue;if(Ea!==e)if(e={context:e,memoizedValue:n,next:null},oi===null){if(ps===null)throw Error(o(308));oi=e,ps.dependencies={lanes:0,firstContext:e}}else oi=oi.next=e;return n}var wr=null;function ba(e){wr===null?wr=[e]:wr.push(e)}function wd(e,n,i,s){var c=n.interleaved;return c===null?(i.next=i,ba(n)):(i.next=c.next,c.next=i),n.interleaved=i,Sn(e,s)}function Sn(e,n){e.lanes|=n;var i=e.alternate;for(i!==null&&(i.lanes|=n),i=e,e=e.return;e!==null;)e.childLanes|=n,i=e.alternate,i!==null&&(i.childLanes|=n),i=e,e=e.return;return i.tag===3?i.stateNode:null}var Un=!1;function Ma(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function _d(e,n){e=e.updateQueue,n.updateQueue===e&&(n.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function kn(e,n){return{eventTime:e,lane:n,tag:0,payload:null,callback:null,next:null}}function Wn(e,n,i){var s=e.updateQueue;if(s===null)return null;if(s=s.shared,(Te&2)!==0){var c=s.pending;return c===null?n.next=n:(n.next=c.next,c.next=n),s.pending=n,Sn(e,i)}return c=s.interleaved,c===null?(n.next=n,ba(s)):(n.next=c.next,c.next=n),s.interleaved=n,Sn(e,i)}function gs(e,n,i){if(n=n.updateQueue,n!==null&&(n=n.shared,(i&4194240)!==0)){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,Ur(e,i)}}function Sd(e,n){var i=e.updateQueue,s=e.alternate;if(s!==null&&(s=s.updateQueue,i===s)){var c=null,h=null;if(i=i.firstBaseUpdate,i!==null){do{var w={eventTime:i.eventTime,lane:i.lane,tag:i.tag,payload:i.payload,callback:i.callback,next:null};h===null?c=h=w:h=h.next=w,i=i.next}while(i!==null);h===null?c=h=n:h=h.next=n}else c=h=n;i={baseState:s.baseState,firstBaseUpdate:c,lastBaseUpdate:h,shared:s.shared,effects:s.effects},e.updateQueue=i;return}e=i.lastBaseUpdate,e===null?i.firstBaseUpdate=n:e.next=n,i.lastBaseUpdate=n}function ms(e,n,i,s){var c=e.updateQueue;Un=!1;var h=c.firstBaseUpdate,w=c.lastBaseUpdate,P=c.shared.pending;if(P!==null){c.shared.pending=null;var z=P,Z=z.next;z.next=null,w===null?h=Z:w.next=Z,w=z;var oe=e.alternate;oe!==null&&(oe=oe.updateQueue,P=oe.lastBaseUpdate,P!==w&&(P===null?oe.firstBaseUpdate=Z:P.next=Z,oe.lastBaseUpdate=z))}if(h!==null){var le=c.baseState;w=0,oe=Z=z=null,P=h;do{var ie=P.lane,he=P.eventTime;if((s&ie)===ie){oe!==null&&(oe=oe.next={eventTime:he,lane:0,tag:P.tag,payload:P.payload,callback:P.callback,next:null});e:{var ve=e,xe=P;switch(ie=n,he=i,xe.tag){case 1:if(ve=xe.payload,typeof ve=="function"){le=ve.call(he,le,ie);break e}le=ve;break e;case 3:ve.flags=ve.flags&-65537|128;case 0:if(ve=xe.payload,ie=typeof ve=="function"?ve.call(he,le,ie):ve,ie==null)break e;le=H({},le,ie);break e;case 2:Un=!0}}P.callback!==null&&P.lane!==0&&(e.flags|=64,ie=c.effects,ie===null?c.effects=[P]:ie.push(P))}else he={eventTime:he,lane:ie,tag:P.tag,payload:P.payload,callback:P.callback,next:null},oe===null?(Z=oe=he,z=le):oe=oe.next=he,w|=ie;if(P=P.next,P===null){if(P=c.shared.pending,P===null)break;ie=P,P=ie.next,ie.next=null,c.lastBaseUpdate=ie,c.shared.pending=null}}while(!0);if(oe===null&&(z=le),c.baseState=z,c.firstBaseUpdate=Z,c.lastBaseUpdate=oe,n=c.shared.interleaved,n!==null){c=n;do w|=c.lane,c=c.next;while(c!==n)}else h===null&&(c.shared.lanes=0);kr|=w,e.lanes=w,e.memoizedState=le}}function kd(e,n,i){if(e=n.effects,n.effects=null,e!==null)for(n=0;ni?i:4,e(!0);var s=La.transition;La.transition={};try{e(!1),n()}finally{ze=i,La.transition=s}}function Bd(){return Ht().memoizedState}function vy(e,n,i){var s=Qn(e);if(i={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null},Vd(e))Ud(n,i);else if(i=wd(e,n,i,s),i!==null){var c=xt();Kt(i,e,s,c),Wd(i,n,s)}}function xy(e,n,i){var s=Qn(e),c={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null};if(Vd(e))Ud(n,c);else{var h=e.alternate;if(e.lanes===0&&(h===null||h.lanes===0)&&(h=n.lastRenderedReducer,h!==null))try{var w=n.lastRenderedState,P=h(w,i);if(c.hasEagerState=!0,c.eagerState=P,Wt(P,w)){var z=n.interleaved;z===null?(c.next=c,ba(n)):(c.next=z.next,z.next=c),n.interleaved=c;return}}catch{}finally{}i=wd(e,n,c,s),i!==null&&(c=xt(),Kt(i,e,s,c),Wd(i,n,s))}}function Vd(e){var n=e.alternate;return e===Ye||n!==null&&n===Ye}function Ud(e,n){Ji=xs=!0;var i=e.pending;i===null?n.next=n:(n.next=i.next,i.next=n),e.pending=n}function Wd(e,n,i){if((i&4194240)!==0){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,Ur(e,i)}}var Ss={readContext:Ft,useCallback:gt,useContext:gt,useEffect:gt,useImperativeHandle:gt,useInsertionEffect:gt,useLayoutEffect:gt,useMemo:gt,useReducer:gt,useRef:gt,useState:gt,useDebugValue:gt,useDeferredValue:gt,useTransition:gt,useMutableSource:gt,useSyncExternalStore:gt,useId:gt,unstable_isNewReconciler:!1},wy={readContext:Ft,useCallback:function(e,n){return cn().memoizedState=[e,n===void 0?null:n],e},useContext:Ft,useEffect:Ld,useImperativeHandle:function(e,n,i){return i=i!=null?i.concat([e]):null,ws(4194308,4,Dd.bind(null,n,e),i)},useLayoutEffect:function(e,n){return ws(4194308,4,e,n)},useInsertionEffect:function(e,n){return ws(4,2,e,n)},useMemo:function(e,n){var i=cn();return n=n===void 0?null:n,e=e(),i.memoizedState=[e,n],e},useReducer:function(e,n,i){var s=cn();return n=i!==void 0?i(n):n,s.memoizedState=s.baseState=n,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},s.queue=e,e=e.dispatch=vy.bind(null,Ye,e),[s.memoizedState,e]},useRef:function(e){var n=cn();return e={current:e},n.memoizedState=e},useState:Td,useDebugValue:Ha,useDeferredValue:function(e){return cn().memoizedState=e},useTransition:function(){var e=Td(!1),n=e[0];return e=yy.bind(null,e[1]),cn().memoizedState=e,[n,e]},useMutableSource:function(){},useSyncExternalStore:function(e,n,i){var s=Ye,c=cn();if(Be){if(i===void 0)throw Error(o(407));i=i()}else{if(i=n(),lt===null)throw Error(o(349));(Sr&30)!==0||jd(s,n,i)}c.memoizedState=i;var h={value:i,getSnapshot:n};return c.queue=h,Ld(Md.bind(null,s,h,e),[e]),s.flags|=2048,no(9,bd.bind(null,s,h,i,n),void 0,null),i},useId:function(){var e=cn(),n=lt.identifierPrefix;if(Be){var i=_n,s=wn;i=(s&~(1<<32-Pt(s)-1)).toString(32)+i,n=":"+n+"R"+i,i=eo++,0<\/script>",e=e.removeChild(e.firstChild)):typeof s.is=="string"?e=w.createElement(i,{is:s.is}):(e=w.createElement(i),i==="select"&&(w=e,s.multiple?w.multiple=!0:s.size&&(w.size=s.size))):e=w.createElementNS(e,i),e[an]=n,e[Xi]=s,ff(e,n,!1,!1),n.stateNode=e;e:{switch(w=Pn(i,s),i){case"dialog":Oe("cancel",e),Oe("close",e),c=s;break;case"iframe":case"object":case"embed":Oe("load",e),c=s;break;case"video":case"audio":for(c=0;cdi&&(n.flags|=128,s=!0,ro(h,!1),n.lanes=4194304)}else{if(!s)if(e=ys(w),e!==null){if(n.flags|=128,s=!0,i=e.updateQueue,i!==null&&(n.updateQueue=i,n.flags|=4),ro(h,!0),h.tail===null&&h.tailMode==="hidden"&&!w.alternate&&!Be)return mt(n),null}else 2*Ue()-h.renderingStartTime>di&&i!==1073741824&&(n.flags|=128,s=!0,ro(h,!1),n.lanes=4194304);h.isBackwards?(w.sibling=n.child,n.child=w):(i=h.last,i!==null?i.sibling=w:n.child=w,h.last=w)}return h.tail!==null?(n=h.tail,h.rendering=n,h.tail=n.sibling,h.renderingStartTime=Ue(),n.sibling=null,i=We.current,De(We,s?i&1|2:i&1),n):(mt(n),null);case 22:case 23:return du(),s=n.memoizedState!==null,e!==null&&e.memoizedState!==null!==s&&(n.flags|=8192),s&&(n.mode&1)!==0?(Lt&1073741824)!==0&&(mt(n),n.subtreeFlags&6&&(n.flags|=8192)):mt(n),null;case 24:return null;case 25:return null}throw Error(o(156,n.tag))}function by(e,n){switch(wa(n),n.tag){case 1:return St(n.type)&&ss(),e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 3:return li(),Fe(_t),Fe(pt),Ra(),e=n.flags,(e&65536)!==0&&(e&128)===0?(n.flags=e&-65537|128,n):null;case 5:return Ia(n),null;case 13:if(Fe(We),e=n.memoizedState,e!==null&&e.dehydrated!==null){if(n.alternate===null)throw Error(o(340));ri()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 19:return Fe(We),null;case 4:return li(),null;case 10:return Ca(n.type._context),null;case 22:case 23:return du(),null;case 24:return null;default:return null}}var Cs=!1,yt=!1,My=typeof WeakSet=="function"?WeakSet:Set,ge=null;function ui(e,n){var i=e.ref;if(i!==null)if(typeof i=="function")try{i(null)}catch(s){Qe(e,n,s)}else i.current=null}function Ja(e,n,i){try{i()}catch(s){Qe(e,n,s)}}var gf=!1;function Py(e,n){if(da=Yo,e=Yc(),ra(e)){if("selectionStart"in e)var i={start:e.selectionStart,end:e.selectionEnd};else e:{i=(i=e.ownerDocument)&&i.defaultView||window;var s=i.getSelection&&i.getSelection();if(s&&s.rangeCount!==0){i=s.anchorNode;var c=s.anchorOffset,h=s.focusNode;s=s.focusOffset;try{i.nodeType,h.nodeType}catch{i=null;break e}var w=0,P=-1,z=-1,Z=0,oe=0,le=e,ie=null;t:for(;;){for(var he;le!==i||c!==0&&le.nodeType!==3||(P=w+c),le!==h||s!==0&&le.nodeType!==3||(z=w+s),le.nodeType===3&&(w+=le.nodeValue.length),(he=le.firstChild)!==null;)ie=le,le=he;for(;;){if(le===e)break t;if(ie===i&&++Z===c&&(P=w),ie===h&&++oe===s&&(z=w),(he=le.nextSibling)!==null)break;le=ie,ie=le.parentNode}le=he}i=P===-1||z===-1?null:{start:P,end:z}}else i=null}i=i||{start:0,end:0}}else i=null;for(fa={focusedElem:e,selectionRange:i},Yo=!1,ge=n;ge!==null;)if(n=ge,e=n.child,(n.subtreeFlags&1028)!==0&&e!==null)e.return=n,ge=e;else for(;ge!==null;){n=ge;try{var ve=n.alternate;if((n.flags&1024)!==0)switch(n.tag){case 0:case 11:case 15:break;case 1:if(ve!==null){var xe=ve.memoizedProps,qe=ve.memoizedState,X=n.stateNode,O=X.getSnapshotBeforeUpdate(n.elementType===n.type?xe:Xt(n.type,xe),qe);X.__reactInternalSnapshotBeforeUpdate=O}break;case 3:var Q=n.stateNode.containerInfo;Q.nodeType===1?Q.textContent="":Q.nodeType===9&&Q.documentElement&&Q.removeChild(Q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(ue){Qe(n,n.return,ue)}if(e=n.sibling,e!==null){e.return=n.return,ge=e;break}ge=n.return}return ve=gf,gf=!1,ve}function io(e,n,i){var s=n.updateQueue;if(s=s!==null?s.lastEffect:null,s!==null){var c=s=s.next;do{if((c.tag&e)===e){var h=c.destroy;c.destroy=void 0,h!==void 0&&Ja(n,i,h)}c=c.next}while(c!==s)}}function js(e,n){if(n=n.updateQueue,n=n!==null?n.lastEffect:null,n!==null){var i=n=n.next;do{if((i.tag&e)===e){var s=i.create;i.destroy=s()}i=i.next}while(i!==n)}}function eu(e){var n=e.ref;if(n!==null){var i=e.stateNode;switch(e.tag){case 5:e=i;break;default:e=i}typeof n=="function"?n(e):n.current=e}}function mf(e){var n=e.alternate;n!==null&&(e.alternate=null,mf(n)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(n=e.stateNode,n!==null&&(delete n[an],delete n[Xi],delete n[ma],delete n[fy],delete n[hy])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function yf(e){return e.tag===5||e.tag===3||e.tag===4}function vf(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||yf(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.nodeType===8?i.parentNode.insertBefore(e,n):i.insertBefore(e,n):(i.nodeType===8?(n=i.parentNode,n.insertBefore(e,i)):(n=i,n.appendChild(e)),i=i._reactRootContainer,i!=null||n.onclick!==null||(n.onclick=is));else if(s!==4&&(e=e.child,e!==null))for(tu(e,n,i),e=e.sibling;e!==null;)tu(e,n,i),e=e.sibling}function nu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.insertBefore(e,n):i.appendChild(e);else if(s!==4&&(e=e.child,e!==null))for(nu(e,n,i),e=e.sibling;e!==null;)nu(e,n,i),e=e.sibling}var dt=null,Gt=!1;function Yn(e,n,i){for(i=i.child;i!==null;)xf(e,n,i),i=i.sibling}function xf(e,n,i){if(Mt&&typeof Mt.onCommitFiberUnmount=="function")try{Mt.onCommitFiberUnmount(Hr,i)}catch{}switch(i.tag){case 5:yt||ui(i,n);case 6:var s=dt,c=Gt;dt=null,Yn(e,n,i),dt=s,Gt=c,dt!==null&&(Gt?(e=dt,i=i.stateNode,e.nodeType===8?e.parentNode.removeChild(i):e.removeChild(i)):dt.removeChild(i.stateNode));break;case 18:dt!==null&&(Gt?(e=dt,i=i.stateNode,e.nodeType===8?ga(e.parentNode,i):e.nodeType===1&&ga(e,i),Ai(e)):ga(dt,i.stateNode));break;case 4:s=dt,c=Gt,dt=i.stateNode.containerInfo,Gt=!0,Yn(e,n,i),dt=s,Gt=c;break;case 0:case 11:case 14:case 15:if(!yt&&(s=i.updateQueue,s!==null&&(s=s.lastEffect,s!==null))){c=s=s.next;do{var h=c,w=h.destroy;h=h.tag,w!==void 0&&((h&2)!==0||(h&4)!==0)&&Ja(i,n,w),c=c.next}while(c!==s)}Yn(e,n,i);break;case 1:if(!yt&&(ui(i,n),s=i.stateNode,typeof s.componentWillUnmount=="function"))try{s.props=i.memoizedProps,s.state=i.memoizedState,s.componentWillUnmount()}catch(P){Qe(i,n,P)}Yn(e,n,i);break;case 21:Yn(e,n,i);break;case 22:i.mode&1?(yt=(s=yt)||i.memoizedState!==null,Yn(e,n,i),yt=s):Yn(e,n,i);break;default:Yn(e,n,i)}}function wf(e){var n=e.updateQueue;if(n!==null){e.updateQueue=null;var i=e.stateNode;i===null&&(i=e.stateNode=new My),n.forEach(function(s){var c=Oy.bind(null,e,s);i.has(s)||(i.add(s),s.then(c,c))})}}function Qt(e,n){var i=n.deletions;if(i!==null)for(var s=0;sc&&(c=w),s&=~h}if(s=c,s=Ue()-s,s=(120>s?120:480>s?480:1080>s?1080:1920>s?1920:3e3>s?3e3:4320>s?4320:1960*Ty(s/1960))-s,10e?16:e,Gn===null)var s=!1;else{if(e=Gn,Gn=null,Ts=0,(Te&6)!==0)throw Error(o(331));var c=Te;for(Te|=4,ge=e.current;ge!==null;){var h=ge,w=h.child;if((ge.flags&16)!==0){var P=h.deletions;if(P!==null){for(var z=0;zUe()-ou?Nr(e,0):iu|=i),Nt(e,n)}function Rf(e,n){n===0&&((e.mode&1)===0?n=1:(n=Vr,Vr<<=1,(Vr&130023424)===0&&(Vr=4194304)));var i=xt();e=Sn(e,n),e!==null&&(gr(e,n,i),Nt(e,i))}function $y(e){var n=e.memoizedState,i=0;n!==null&&(i=n.retryLane),Rf(e,i)}function Oy(e,n){var i=0;switch(e.tag){case 13:var s=e.stateNode,c=e.memoizedState;c!==null&&(i=c.retryLane);break;case 19:s=e.stateNode;break;default:throw Error(o(314))}s!==null&&s.delete(n),Rf(e,i)}var Lf;Lf=function(e,n,i){if(e!==null)if(e.memoizedProps!==n.pendingProps||_t.current)kt=!0;else{if((e.lanes&i)===0&&(n.flags&128)===0)return kt=!1,Cy(e,n,i);kt=(e.flags&131072)!==0}else kt=!1,Be&&(n.flags&1048576)!==0&&fd(n,cs,n.index);switch(n.lanes=0,n.tag){case 2:var s=n.type;Ns(e,n),e=n.pendingProps;var c=ei(n,pt.current);si(n,i),c=Aa(null,n,s,e,c,i);var h=Da();return n.flags|=1,typeof c=="object"&&c!==null&&typeof c.render=="function"&&c.$$typeof===void 0?(n.tag=1,n.memoizedState=null,n.updateQueue=null,St(s)?(h=!0,ls(n)):h=!1,n.memoizedState=c.state!==null&&c.state!==void 0?c.state:null,Ma(n),c.updater=ks,n.stateNode=c,c._reactInternals=n,Va(n,s,e,i),n=Xa(null,n,s,!0,h,i)):(n.tag=0,Be&&h&&xa(n),vt(null,n,c,i),n=n.child),n;case 16:s=n.elementType;e:{switch(Ns(e,n),e=n.pendingProps,c=s._init,s=c(s._payload),n.type=s,c=n.tag=Hy(s),e=Xt(s,e),c){case 0:n=Ya(null,n,s,e,i);break e;case 1:n=sf(null,n,s,e,i);break e;case 11:n=ef(null,n,s,e,i);break e;case 14:n=tf(null,n,s,Xt(s.type,e),i);break e}throw Error(o(306,s,""))}return n;case 0:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Xt(s,c),Ya(e,n,s,c,i);case 1:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Xt(s,c),sf(e,n,s,c,i);case 3:e:{if(lf(n),e===null)throw Error(o(387));s=n.pendingProps,h=n.memoizedState,c=h.element,_d(e,n),ms(n,s,null,i);var w=n.memoizedState;if(s=w.element,h.isDehydrated)if(h={element:s,isDehydrated:!1,cache:w.cache,pendingSuspenseBoundaries:w.pendingSuspenseBoundaries,transitions:w.transitions},n.updateQueue.baseState=h,n.memoizedState=h,n.flags&256){c=ai(Error(o(423)),n),n=af(e,n,s,i,c);break e}else if(s!==c){c=ai(Error(o(424)),n),n=af(e,n,s,i,c);break e}else for(Rt=Fn(n.stateNode.containerInfo.firstChild),Tt=n,Be=!0,Yt=null,i=xd(n,null,s,i),n.child=i;i;)i.flags=i.flags&-3|4096,i=i.sibling;else{if(ri(),s===c){n=En(e,n,i);break e}vt(e,n,s,i)}n=n.child}return n;case 5:return Ed(n),e===null&&Sa(n),s=n.type,c=n.pendingProps,h=e!==null?e.memoizedProps:null,w=c.children,ha(s,c)?w=null:h!==null&&ha(s,h)&&(n.flags|=32),of(e,n),vt(e,n,w,i),n.child;case 6:return e===null&&Sa(n),null;case 13:return uf(e,n,i);case 4:return Pa(n,n.stateNode.containerInfo),s=n.pendingProps,e===null?n.child=ii(n,null,s,i):vt(e,n,s,i),n.child;case 11:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Xt(s,c),ef(e,n,s,c,i);case 7:return vt(e,n,n.pendingProps,i),n.child;case 8:return vt(e,n,n.pendingProps.children,i),n.child;case 12:return vt(e,n,n.pendingProps.children,i),n.child;case 10:e:{if(s=n.type._context,c=n.pendingProps,h=n.memoizedProps,w=c.value,De(hs,s._currentValue),s._currentValue=w,h!==null)if(Wt(h.value,w)){if(h.children===c.children&&!_t.current){n=En(e,n,i);break e}}else for(h=n.child,h!==null&&(h.return=n);h!==null;){var P=h.dependencies;if(P!==null){w=h.child;for(var z=P.firstContext;z!==null;){if(z.context===s){if(h.tag===1){z=kn(-1,i&-i),z.tag=2;var Z=h.updateQueue;if(Z!==null){Z=Z.shared;var oe=Z.pending;oe===null?z.next=z:(z.next=oe.next,oe.next=z),Z.pending=z}}h.lanes|=i,z=h.alternate,z!==null&&(z.lanes|=i),ja(h.return,i,n),P.lanes|=i;break}z=z.next}}else if(h.tag===10)w=h.type===n.type?null:h.child;else if(h.tag===18){if(w=h.return,w===null)throw Error(o(341));w.lanes|=i,P=w.alternate,P!==null&&(P.lanes|=i),ja(w,i,n),w=h.sibling}else w=h.child;if(w!==null)w.return=h;else for(w=h;w!==null;){if(w===n){w=null;break}if(h=w.sibling,h!==null){h.return=w.return,w=h;break}w=w.return}h=w}vt(e,n,c.children,i),n=n.child}return n;case 9:return c=n.type,s=n.pendingProps.children,si(n,i),c=Ft(c),s=s(c),n.flags|=1,vt(e,n,s,i),n.child;case 14:return s=n.type,c=Xt(s,n.pendingProps),c=Xt(s.type,c),tf(e,n,s,c,i);case 15:return nf(e,n,n.type,n.pendingProps,i);case 17:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Xt(s,c),Ns(e,n),n.tag=1,St(s)?(e=!0,ls(n)):e=!1,si(n,i),Xd(n,s,c),Va(n,s,c,i),Xa(null,n,s,!0,e,i);case 19:return df(e,n,i);case 22:return rf(e,n,i)}throw Error(o(156,n.tag))};function zf(e,n){return Do(e,n)}function Fy(e,n,i,s){this.tag=e,this.key=i,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=s,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Vt(e,n,i,s){return new Fy(e,n,i,s)}function hu(e){return e=e.prototype,!(!e||!e.isReactComponent)}function Hy(e){if(typeof e=="function")return hu(e)?1:0;if(e!=null){if(e=e.$$typeof,e===te)return 11;if(e===Y)return 14}return 2}function qn(e,n){var i=e.alternate;return i===null?(i=Vt(e.tag,n,e.key,e.mode),i.elementType=e.elementType,i.type=e.type,i.stateNode=e.stateNode,i.alternate=e,e.alternate=i):(i.pendingProps=n,i.type=e.type,i.flags=0,i.subtreeFlags=0,i.deletions=null),i.flags=e.flags&14680064,i.childLanes=e.childLanes,i.lanes=e.lanes,i.child=e.child,i.memoizedProps=e.memoizedProps,i.memoizedState=e.memoizedState,i.updateQueue=e.updateQueue,n=e.dependencies,i.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext},i.sibling=e.sibling,i.index=e.index,i.ref=e.ref,i}function As(e,n,i,s,c,h){var w=2;if(s=e,typeof e=="function")hu(e)&&(w=1);else if(typeof e=="string")w=5;else e:switch(e){case B:return jr(i.children,c,h,n);case G:w=8,c|=8;break;case U:return e=Vt(12,i,n,c|2),e.elementType=U,e.lanes=h,e;case J:return e=Vt(13,i,n,c),e.elementType=J,e.lanes=h,e;case b:return e=Vt(19,i,n,c),e.elementType=b,e.lanes=h,e;case W:return Ds(i,c,h,n);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case ee:w=10;break e;case q:w=9;break e;case te:w=11;break e;case Y:w=14;break e;case V:w=16,s=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return n=Vt(w,i,n,c),n.elementType=e,n.type=s,n.lanes=h,n}function jr(e,n,i,s){return e=Vt(7,e,s,n),e.lanes=i,e}function Ds(e,n,i,s){return e=Vt(22,e,s,n),e.elementType=W,e.lanes=i,e.stateNode={isHidden:!1},e}function pu(e,n,i){return e=Vt(6,e,null,n),e.lanes=i,e}function gu(e,n,i){return n=Vt(4,e.children!==null?e.children:[],e.key,n),n.lanes=i,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}function By(e,n,i,s,c){this.tag=n,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=pr(0),this.expirationTimes=pr(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=pr(0),this.identifierPrefix=s,this.onRecoverableError=c,this.mutableSourceEagerHydrationData=null}function mu(e,n,i,s,c,h,w,P,z){return e=new By(e,n,i,P,z),n===1?(n=1,h===!0&&(n|=8)):n=0,h=Vt(3,null,null,n),e.current=h,h.stateNode=e,h.memoizedState={element:s,isDehydrated:i,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(h),e}function Vy(e,n,i){var s=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Su.exports=t0(),Su.exports}var Qf;function n0(){if(Qf)return Us;Qf=1;var t=wp();return Us.createRoot=t.createRoot,Us.hydrateRoot=t.hydrateRoot,Us}var r0=n0();function i0(t,r="Request failed"){const o=(t||"").trim();if(!o)return r;try{const a=JSON.parse(o).detail;if(typeof a=="string"&&a.trim())return a;if(Array.isArray(a)){const u=a.map(d=>typeof d=="string"?d:d&&typeof d=="object"&&"msg"in d?String(d.msg):"").filter(Boolean);if(u.length)return u.join("; ")}}catch{}return o}async function Ze(t,r){const o=await fetch(t,{...r,headers:{"Content-Type":"application/json",...(r==null?void 0:r.headers)||{}}});if(!o.ok){const l=await o.text();throw new Error(i0(l,o.statusText||"Request failed"))}return o.json()}const o0=["github_token","bitbucket_token","bitbucket_oauth_client_secret","ai_api_key","ai_model","ai_base_url"],Ve={health:()=>Ze("/api/health"),settings:()=>Ze("/api/settings"),saveSettings:t=>{const r={...t};for(const o of o0)r[o]===""&&delete r[o];return Ze("/api/settings",{method:"PUT",body:JSON.stringify(r)})},repos:()=>Ze("/api/repos"),browse:t=>Ze(`/api/fs${t?`?path=${encodeURIComponent(t)}`:""}`),gitRefs:(t,r=50)=>Ze(`/api/git/refs?repo_path=${encodeURIComponent(t)}&limit=${r}`),index:(t,r=!0)=>Ze("/api/index",{method:"POST",body:JSON.stringify({repo_path:t,incremental:r})}),indexStatus:t=>Ze(`/api/index?repo_path=${encodeURIComponent(t)}`),architecture:t=>Ze(`/api/architecture?repo_path=${encodeURIComponent(t)}`),review:(t,r,o,l=!0)=>Ze("/api/review",{method:"POST",body:JSON.stringify({repo_path:t,base:r,head:o||null,reindex:l,incremental:!0,three_dot:!0})}),init:(t,r=!1)=>Ze("/api/init",{method:"POST",body:JSON.stringify({repo_path:t,overwrite:r})}),postComment:(t,r,o,l)=>Ze("/api/prs/comment",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,markdown:l})}),graph:(t,r="full")=>Ze(`/api/graph?repo_path=${encodeURIComponent(t)}&scope=${r}`),prs:(t,r,o="open")=>Ze("/api/prs",{method:"POST",body:JSON.stringify({provider:t,repo:r,state:o})}),scmRepos:t=>Ze(`/api/scm/repos?provider=${encodeURIComponent(t)}`),oauthStatus:()=>Ze("/api/oauth/status"),githubOAuthStart:()=>Ze("/api/oauth/github/start",{method:"POST",body:"{}"}),githubOAuthPoll:t=>Ze("/api/oauth/github/poll",{method:"POST",body:JSON.stringify({flow_id:t})}),bitbucketOAuthStart:()=>Ze("/api/oauth/bitbucket/start"),oauthDisconnect:t=>Ze("/api/oauth/disconnect",{method:"POST",body:JSON.stringify({provider:t})}),residual:t=>Ze("/api/ai/residual",{method:"POST",body:JSON.stringify({review:t})})};function yo(t){return t.replaceAll("_"," ")}function s0(t){return t.replaceAll("_"," ")}function yl(t){return t.split(".").pop()||t}function l0(t){if(!t)return"";const r=new Date(t);return Number.isNaN(r.getTime())?t:r.toLocaleString()}function pi(t){return t.replace(/([/\\._:@-])/g,"$1​")}function Dr({className:t,children:r}){return p.jsx("svg",{className:t,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:r})}function a0({className:t}){return p.jsxs(Dr,{className:t,children:[p.jsx("path",{d:"M3 3.5h6.5L13 7v5.5H3z"}),p.jsx("path",{d:"M9.5 3.5V7H13"}),p.jsx("path",{d:"M5.5 9.5h5M5.5 11.5h3.5"})]})}function u0({className:t}){return p.jsxs(Dr,{className:t,children:[p.jsx("rect",{x:"2.5",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"2.5",y:"9",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"9",width:"4.5",height:"4.5",rx:"0.8"})]})}function c0({className:t}){return p.jsxs(Dr,{className:t,children:[p.jsx("circle",{cx:"4",cy:"8",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"4",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"12",r:"1.6"}),p.jsx("path",{d:"M5.5 7.2 10.4 4.8M5.5 8.8 10.4 11.2"})]})}function d0({className:t}){return p.jsxs(Dr,{className:t,children:[p.jsx("circle",{cx:"4.5",cy:"4",r:"1.4"}),p.jsx("circle",{cx:"4.5",cy:"12",r:"1.4"}),p.jsx("circle",{cx:"11.5",cy:"12",r:"1.4"}),p.jsx("path",{d:"M4.5 5.5v5M4.5 8h4.2a3 3 0 0 1 3 3"})]})}function f0({className:t}){return p.jsxs(Dr,{className:t,children:[p.jsx("circle",{cx:"8",cy:"8",r:"2.1"}),p.jsx("path",{d:"M8 2.5v1.6M8 11.9v1.6M2.5 8h1.6M11.9 8h1.6M4.1 4.1l1.1 1.1M10.8 10.8l1.1 1.1M11.9 4.1l-1.1 1.1M5.2 10.8l-1.1 1.1"})]})}function _p({className:t}){return p.jsx(Dr,{className:t,children:p.jsx("path",{d:"M2.5 4.5h4L8 6h5.5v6.5h-11z"})})}function h0({className:t}){return p.jsx(Dr,{className:t,children:p.jsx("path",{d:"M4 6.5 8 10.5 12 6.5"})})}const p0="modulepreload",g0=function(t,r){return new URL(t,r).href},Kf={},m0=function(r,o,l){let a=Promise.resolve();if(o&&o.length>0){let d=function(m){return Promise.all(m.map(x=>Promise.resolve(x).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};const f=document.getElementsByTagName("link"),g=document.querySelector("meta[property=csp-nonce]"),y=(g==null?void 0:g.nonce)||(g==null?void 0:g.getAttribute("nonce"));a=d(o.map(m=>{if(m=g0(m,l),m in Kf)return;Kf[m]=!0;const x=m.endsWith(".css"),v=x?'[rel="stylesheet"]':"";if(!!l)for(let C=f.length-1;C>=0;C--){const E=f[C];if(E.href===m&&(!x||E.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${m}"]${v}`))return;const S=document.createElement("link");if(S.rel=x?"stylesheet":p0,x||(S.as="script"),S.crossOrigin="",S.href=m,y&&S.setAttribute("nonce",y),document.head.appendChild(S),x)return new Promise((C,E)=>{S.addEventListener("load",C),S.addEventListener("error",()=>E(new Error(`Unable to preload CSS for ${m}`)))})}))}function u(d){const f=new Event("vite:preloadError",{cancelable:!0});if(f.payload=d,window.dispatchEvent(f),!f.defaultPrevented)throw d}return a.then(d=>{for(const f of d||[])f.status==="rejected"&&u(f.reason);return r().catch(u)})};function et(t){if(typeof t=="string"||typeof t=="number")return""+t;let r="";if(Array.isArray(t))for(let o=0,l;o{}};function vl(){for(var t=0,r=arguments.length,o={},l;t=0&&(l=o.slice(a+1),o=o.slice(0,a)),o&&!r.hasOwnProperty(o))throw new Error("unknown type: "+o);return{type:o,name:l}})}tl.prototype=vl.prototype={constructor:tl,on:function(t,r){var o=this._,l=v0(t+"",o),a,u=-1,d=l.length;if(arguments.length<2){for(;++u0)for(var o=new Array(a),l=0,a,u;l=0&&(r=t.slice(0,o))!=="xmlns"&&(t=t.slice(o+1)),Zf.hasOwnProperty(r)?{space:Zf[r],local:t}:t}function w0(t){return function(){var r=this.ownerDocument,o=this.namespaceURI;return o===Ou&&r.documentElement.namespaceURI===Ou?r.createElement(t):r.createElementNS(o,t)}}function _0(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function Sp(t){var r=xl(t);return(r.local?_0:w0)(r)}function S0(){}function Ju(t){return t==null?S0:function(){return this.querySelector(t)}}function k0(t){typeof t!="function"&&(t=Ju(t));for(var r=this._groups,o=r.length,l=new Array(o),a=0;a=k&&(k=I+1);!(R=E[k])&&++k=0;)(d=l[a])&&(u&&d.compareDocumentPosition(u)^4&&u.parentNode.insertBefore(d,u),u=d);return this}function G0(t){t||(t=Q0);function r(x,v){return x&&v?t(x.__data__,v.__data__):!x-!v}for(var o=this._groups,l=o.length,a=new Array(l),u=0;ur?1:t>=r?0:NaN}function K0(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function q0(){return Array.from(this)}function Z0(){for(var t=this._groups,r=0,o=t.length;r1?this.each((r==null?uv:typeof r=="function"?dv:cv)(t,r,o??"")):vi(this.node(),t)}function vi(t,r){return t.style.getPropertyValue(r)||jp(t).getComputedStyle(t,null).getPropertyValue(r)}function hv(t){return function(){delete this[t]}}function pv(t,r){return function(){this[t]=r}}function gv(t,r){return function(){var o=r.apply(this,arguments);o==null?delete this[t]:this[t]=o}}function mv(t,r){return arguments.length>1?this.each((r==null?hv:typeof r=="function"?gv:pv)(t,r)):this.node()[t]}function bp(t){return t.trim().split(/^|\s+/)}function ec(t){return t.classList||new Mp(t)}function Mp(t){this._node=t,this._names=bp(t.getAttribute("class")||"")}Mp.prototype={add:function(t){var r=this._names.indexOf(t);r<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var r=this._names.indexOf(t);r>=0&&(this._names.splice(r,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Pp(t,r){for(var o=ec(t),l=-1,a=r.length;++l=0&&(o=r.slice(l+1),r=r.slice(0,l)),{type:r,name:o}})}function Uv(t){return function(){var r=this.__on;if(r){for(var o=0,l=-1,a=r.length,u;o()=>t;function Fu(t,{sourceEvent:r,subject:o,target:l,identifier:a,active:u,x:d,y:f,dx:g,dy:y,dispatch:m}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},subject:{value:o,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},identifier:{value:a,enumerable:!0,configurable:!0},active:{value:u,enumerable:!0,configurable:!0},x:{value:d,enumerable:!0,configurable:!0},y:{value:f,enumerable:!0,configurable:!0},dx:{value:g,enumerable:!0,configurable:!0},dy:{value:y,enumerable:!0,configurable:!0},_:{value:m}})}Fu.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};function ex(t){return!t.ctrlKey&&!t.button}function tx(){return this.parentNode}function nx(t,r){return r??{x:t.x,y:t.y}}function rx(){return navigator.maxTouchPoints||"ontouchstart"in this}function Ap(){var t=ex,r=tx,o=nx,l=rx,a={},u=vl("start","drag","end"),d=0,f,g,y,m,x=0;function v(j){j.on("mousedown.drag",_).filter(l).on("touchstart.drag",E).on("touchmove.drag",N,Jv).on("touchend.drag touchcancel.drag",I).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(j,R){if(!(m||!t.call(this,j,R))){var T=k(this,r.call(this,j,R),j,R,"mouse");T&&(zt(j.view).on("mousemove.drag",S,vo).on("mouseup.drag",C,vo),Lp(j.view),Nu(j),y=!1,f=j.clientX,g=j.clientY,T("start",j))}}function S(j){if(mi(j),!y){var R=j.clientX-f,T=j.clientY-g;y=R*R+T*T>x}a.mouse("drag",j)}function C(j){zt(j.view).on("mousemove.drag mouseup.drag",null),zp(j.view,y),mi(j),a.mouse("end",j)}function E(j,R){if(t.call(this,j,R)){var T=j.changedTouches,B=r.call(this,j,R),G=T.length,U,ee;for(U=0;U>8&15|r>>4&240,r>>4&15|r&240,(r&15)<<4|r&15,1):o===8?Ys(r>>24&255,r>>16&255,r>>8&255,(r&255)/255):o===4?Ys(r>>12&15|r>>8&240,r>>8&15|r>>4&240,r>>4&15|r&240,((r&15)<<4|r&15)/255):null):(r=ox.exec(t))?new jt(r[1],r[2],r[3],1):(r=sx.exec(t))?new jt(r[1]*255/100,r[2]*255/100,r[3]*255/100,1):(r=lx.exec(t))?Ys(r[1],r[2],r[3],r[4]):(r=ax.exec(t))?Ys(r[1]*255/100,r[2]*255/100,r[3]*255/100,r[4]):(r=ux.exec(t))?oh(r[1],r[2]/100,r[3]/100,1):(r=cx.exec(t))?oh(r[1],r[2]/100,r[3]/100,r[4]):Jf.hasOwnProperty(t)?nh(Jf[t]):t==="transparent"?new jt(NaN,NaN,NaN,0):null}function nh(t){return new jt(t>>16&255,t>>8&255,t&255,1)}function Ys(t,r,o,l){return l<=0&&(t=r=o=NaN),new jt(t,r,o,l)}function hx(t){return t instanceof Po||(t=Tr(t)),t?(t=t.rgb(),new jt(t.r,t.g,t.b,t.opacity)):new jt}function Hu(t,r,o,l){return arguments.length===1?hx(t):new jt(t,r,o,l??1)}function jt(t,r,o,l){this.r=+t,this.g=+r,this.b=+o,this.opacity=+l}tc(jt,Hu,Dp(Po,{brighter(t){return t=t==null?ll:Math.pow(ll,t),new jt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?xo:Math.pow(xo,t),new jt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new jt(Pr(this.r),Pr(this.g),Pr(this.b),al(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:rh,formatHex:rh,formatHex8:px,formatRgb:ih,toString:ih}));function rh(){return`#${Mr(this.r)}${Mr(this.g)}${Mr(this.b)}`}function px(){return`#${Mr(this.r)}${Mr(this.g)}${Mr(this.b)}${Mr((isNaN(this.opacity)?1:this.opacity)*255)}`}function ih(){const t=al(this.opacity);return`${t===1?"rgb(":"rgba("}${Pr(this.r)}, ${Pr(this.g)}, ${Pr(this.b)}${t===1?")":`, ${t})`}`}function al(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Pr(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function Mr(t){return t=Pr(t),(t<16?"0":"")+t.toString(16)}function oh(t,r,o,l){return l<=0?t=r=o=NaN:o<=0||o>=1?t=r=NaN:r<=0&&(t=NaN),new Zt(t,r,o,l)}function $p(t){if(t instanceof Zt)return new Zt(t.h,t.s,t.l,t.opacity);if(t instanceof Po||(t=Tr(t)),!t)return new Zt;if(t instanceof Zt)return t;t=t.rgb();var r=t.r/255,o=t.g/255,l=t.b/255,a=Math.min(r,o,l),u=Math.max(r,o,l),d=NaN,f=u-a,g=(u+a)/2;return f?(r===u?d=(o-l)/f+(o0&&g<1?0:d,new Zt(d,f,g,t.opacity)}function gx(t,r,o,l){return arguments.length===1?$p(t):new Zt(t,r,o,l??1)}function Zt(t,r,o,l){this.h=+t,this.s=+r,this.l=+o,this.opacity=+l}tc(Zt,gx,Dp(Po,{brighter(t){return t=t==null?ll:Math.pow(ll,t),new Zt(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?xo:Math.pow(xo,t),new Zt(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,r=isNaN(t)||isNaN(this.s)?0:this.s,o=this.l,l=o+(o<.5?o:1-o)*r,a=2*o-l;return new jt(Cu(t>=240?t-240:t+120,a,l),Cu(t,a,l),Cu(t<120?t+240:t-120,a,l),this.opacity)},clamp(){return new Zt(sh(this.h),Xs(this.s),Xs(this.l),al(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=al(this.opacity);return`${t===1?"hsl(":"hsla("}${sh(this.h)}, ${Xs(this.s)*100}%, ${Xs(this.l)*100}%${t===1?")":`, ${t})`}`}}));function sh(t){return t=(t||0)%360,t<0?t+360:t}function Xs(t){return Math.max(0,Math.min(1,t||0))}function Cu(t,r,o){return(t<60?r+(o-r)*t/60:t<180?o:t<240?r+(o-r)*(240-t)/60:r)*255}const nc=t=>()=>t;function mx(t,r){return function(o){return t+o*r}}function yx(t,r,o){return t=Math.pow(t,o),r=Math.pow(r,o)-t,o=1/o,function(l){return Math.pow(t+l*r,o)}}function vx(t){return(t=+t)==1?Op:function(r,o){return o-r?yx(r,o,t):nc(isNaN(r)?o:r)}}function Op(t,r){var o=r-t;return o?mx(t,o):nc(isNaN(t)?r:t)}const ul=(function t(r){var o=vx(r);function l(a,u){var d=o((a=Hu(a)).r,(u=Hu(u)).r),f=o(a.g,u.g),g=o(a.b,u.b),y=Op(a.opacity,u.opacity);return function(m){return a.r=d(m),a.g=f(m),a.b=g(m),a.opacity=y(m),a+""}}return l.gamma=t,l})(1);function xx(t,r){r||(r=[]);var o=t?Math.min(r.length,t.length):0,l=r.slice(),a;return function(u){for(a=0;ao&&(u=r.slice(o,u),f[d]?f[d]+=u:f[++d]=u),(l=l[0])===(a=a[0])?f[d]?f[d]+=a:f[++d]=a:(f[++d]=null,g.push({i:d,x:fn(l,a)})),o=ju.lastIndex;return o180?m+=360:m-y>180&&(y+=360),v.push({i:x.push(a(x)+"rotate(",null,l)-2,x:fn(y,m)})):m&&x.push(a(x)+"rotate("+m+l)}function f(y,m,x,v){y!==m?v.push({i:x.push(a(x)+"skewX(",null,l)-2,x:fn(y,m)}):m&&x.push(a(x)+"skewX("+m+l)}function g(y,m,x,v,_,S){if(y!==x||m!==v){var C=_.push(a(_)+"scale(",null,",",null,")");S.push({i:C-4,x:fn(y,x)},{i:C-2,x:fn(m,v)})}else(x!==1||v!==1)&&_.push(a(_)+"scale("+x+","+v+")")}return function(y,m){var x=[],v=[];return y=t(y),m=t(m),u(y.translateX,y.translateY,m.translateX,m.translateY,x,v),d(y.rotate,m.rotate,x,v),f(y.skewX,m.skewX,x,v),g(y.scaleX,y.scaleY,m.scaleX,m.scaleY,x,v),y=m=null,function(_){for(var S=-1,C=v.length,E;++S=0&&t._call.call(void 0,r),t=t._next;--xi}function uh(){Rr=(dl=_o.now())+wl,xi=ho=0;try{Lx()}finally{xi=0,Ax(),Rr=0}}function zx(){var t=_o.now(),r=t-dl;r>Vp&&(wl-=r,dl=t)}function Ax(){for(var t,r=cl,o,l=1/0;r;)r._call?(l>r._time&&(l=r._time),t=r,r=r._next):(o=r._next,r._next=null,r=t?t._next=o:cl=o);po=t,Uu(l)}function Uu(t){if(!xi){ho&&(ho=clearTimeout(ho));var r=t-Rr;r>24?(t<1/0&&(ho=setTimeout(uh,t-_o.now()-wl)),co&&(co=clearInterval(co))):(co||(dl=_o.now(),co=setInterval(zx,Vp)),xi=1,Up(uh))}}function ch(t,r,o){var l=new fl;return r=r==null?0:+r,l.restart(a=>{l.stop(),t(a+r)},r,o),l}var Dx=vl("start","end","cancel","interrupt"),$x=[],Yp=0,dh=1,Wu=2,rl=3,fh=4,Yu=5,il=6;function _l(t,r,o,l,a,u){var d=t.__transition;if(!d)t.__transition={};else if(o in d)return;Ox(t,o,{name:r,index:l,group:a,on:Dx,tween:$x,time:u.time,delay:u.delay,duration:u.duration,ease:u.ease,timer:null,state:Yp})}function ic(t,r){var o=nn(t,r);if(o.state>Yp)throw new Error("too late; already scheduled");return o}function pn(t,r){var o=nn(t,r);if(o.state>rl)throw new Error("too late; already running");return o}function nn(t,r){var o=t.__transition;if(!o||!(o=o[r]))throw new Error("transition not found");return o}function Ox(t,r,o){var l=t.__transition,a;l[r]=o,o.timer=Wp(u,0,o.time);function u(y){o.state=dh,o.timer.restart(d,o.delay,o.time),o.delay<=y&&d(y-o.delay)}function d(y){var m,x,v,_;if(o.state!==dh)return g();for(m in l)if(_=l[m],_.name===o.name){if(_.state===rl)return ch(d);_.state===fh?(_.state=il,_.timer.stop(),_.on.call("interrupt",t,t.__data__,_.index,_.group),delete l[m]):+mWu&&l.state=0&&(r=r.slice(0,o)),!r||r==="start"})}function gw(t,r,o){var l,a,u=pw(r)?ic:pn;return function(){var d=u(this,t),f=d.on;f!==l&&(a=(l=f).copy()).on(r,o),d.on=a}}function mw(t,r){var o=this._id;return arguments.length<2?nn(this.node(),o).on.on(t):this.each(gw(o,t,r))}function yw(t){return function(){var r=this.parentNode;for(var o in this.__transition)if(+o!==t)return;r&&r.removeChild(this)}}function vw(){return this.on("end.remove",yw(this._id))}function xw(t){var r=this._name,o=this._id;typeof t!="function"&&(t=Ju(t));for(var l=this._groups,a=l.length,u=new Array(a),d=0;d()=>t;function Uw(t,{sourceEvent:r,target:o,transform:l,dispatch:a}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},transform:{value:l,enumerable:!0,configurable:!0},_:{value:a}})}function jn(t,r,o){this.k=t,this.x=r,this.y=o}jn.prototype={constructor:jn,scale:function(t){return t===1?this:new jn(this.k*t,this.x,this.y)},translate:function(t,r){return t===0&r===0?this:new jn(this.k,this.x+this.k*t,this.y+this.k*r)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var Sl=new jn(1,0,0);Kp.prototype=jn.prototype;function Kp(t){for(;!t.__zoom;)if(!(t=t.parentNode))return Sl;return t.__zoom}function bu(t){t.stopImmediatePropagation()}function fo(t){t.preventDefault(),t.stopImmediatePropagation()}function Ww(t){return(!t.ctrlKey||t.type==="wheel")&&!t.button}function Yw(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t,t.hasAttribute("viewBox")?(t=t.viewBox.baseVal,[[t.x,t.y],[t.x+t.width,t.y+t.height]]):[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]):[[0,0],[t.clientWidth,t.clientHeight]]}function hh(){return this.__zoom||Sl}function Xw(t){return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Gw(){return navigator.maxTouchPoints||"ontouchstart"in this}function Qw(t,r,o){var l=t.invertX(r[0][0])-o[0][0],a=t.invertX(r[1][0])-o[1][0],u=t.invertY(r[0][1])-o[0][1],d=t.invertY(r[1][1])-o[1][1];return t.translate(a>l?(l+a)/2:Math.min(0,l)||Math.max(0,a),d>u?(u+d)/2:Math.min(0,u)||Math.max(0,d))}function qp(){var t=Ww,r=Yw,o=Qw,l=Xw,a=Gw,u=[0,1/0],d=[[-1/0,-1/0],[1/0,1/0]],f=250,g=nl,y=vl("start","zoom","end"),m,x,v,_=500,S=150,C=0,E=10;function N(b){b.property("__zoom",hh).on("wheel.zoom",G,{passive:!1}).on("mousedown.zoom",U).on("dblclick.zoom",ee).filter(a).on("touchstart.zoom",q).on("touchmove.zoom",te).on("touchend.zoom touchcancel.zoom",J).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}N.transform=function(b,Y,V,W){var D=b.selection?b.selection():b;D.property("__zoom",hh),b!==D?R(b,Y,V,W):D.interrupt().each(function(){T(this,arguments).event(W).start().zoom(null,typeof Y=="function"?Y.apply(this,arguments):Y).end()})},N.scaleBy=function(b,Y,V,W){N.scaleTo(b,function(){var D=this.__zoom.k,A=typeof Y=="function"?Y.apply(this,arguments):Y;return D*A},V,W)},N.scaleTo=function(b,Y,V,W){N.transform(b,function(){var D=r.apply(this,arguments),A=this.__zoom,H=V==null?j(D):typeof V=="function"?V.apply(this,arguments):V,M=A.invert(H),L=typeof Y=="function"?Y.apply(this,arguments):Y;return o(k(I(A,L),H,M),D,d)},V,W)},N.translateBy=function(b,Y,V,W){N.transform(b,function(){return o(this.__zoom.translate(typeof Y=="function"?Y.apply(this,arguments):Y,typeof V=="function"?V.apply(this,arguments):V),r.apply(this,arguments),d)},null,W)},N.translateTo=function(b,Y,V,W,D){N.transform(b,function(){var A=r.apply(this,arguments),H=this.__zoom,M=W==null?j(A):typeof W=="function"?W.apply(this,arguments):W;return o(Sl.translate(M[0],M[1]).scale(H.k).translate(typeof Y=="function"?-Y.apply(this,arguments):-Y,typeof V=="function"?-V.apply(this,arguments):-V),A,d)},W,D)};function I(b,Y){return Y=Math.max(u[0],Math.min(u[1],Y)),Y===b.k?b:new jn(Y,b.x,b.y)}function k(b,Y,V){var W=Y[0]-V[0]*b.k,D=Y[1]-V[1]*b.k;return W===b.x&&D===b.y?b:new jn(b.k,W,D)}function j(b){return[(+b[0][0]+ +b[1][0])/2,(+b[0][1]+ +b[1][1])/2]}function R(b,Y,V,W){b.on("start.zoom",function(){T(this,arguments).event(W).start()}).on("interrupt.zoom end.zoom",function(){T(this,arguments).event(W).end()}).tween("zoom",function(){var D=this,A=arguments,H=T(D,A).event(W),M=r.apply(D,A),L=V==null?j(M):typeof V=="function"?V.apply(D,A):V,ne=Math.max(M[1][0]-M[0][0],M[1][1]-M[0][1]),re=D.__zoom,ce=typeof Y=="function"?Y.apply(D,A):Y,fe=g(re.invert(L).concat(ne/re.k),ce.invert(L).concat(ne/ce.k));return function(de){if(de===1)de=ce;else{var K=fe(de),se=ne/K[2];de=new jn(se,L[0]-K[0]*se,L[1]-K[1]*se)}H.zoom(null,de)}})}function T(b,Y,V){return!V&&b.__zooming||new B(b,Y)}function B(b,Y){this.that=b,this.args=Y,this.active=0,this.sourceEvent=null,this.extent=r.apply(b,Y),this.taps=0}B.prototype={event:function(b){return b&&(this.sourceEvent=b),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(b,Y){return this.mouse&&b!=="mouse"&&(this.mouse[1]=Y.invert(this.mouse[0])),this.touch0&&b!=="touch"&&(this.touch0[1]=Y.invert(this.touch0[0])),this.touch1&&b!=="touch"&&(this.touch1[1]=Y.invert(this.touch1[0])),this.that.__zoom=Y,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(b){var Y=zt(this.that).datum();y.call(b,this.that,new Uw(b,{sourceEvent:this.sourceEvent,target:N,transform:this.that.__zoom,dispatch:y}),Y)}};function G(b,...Y){if(!t.apply(this,arguments))return;var V=T(this,Y).event(b),W=this.__zoom,D=Math.max(u[0],Math.min(u[1],W.k*Math.pow(2,l.apply(this,arguments)))),A=qt(b);if(V.wheel)(V.mouse[0][0]!==A[0]||V.mouse[0][1]!==A[1])&&(V.mouse[1]=W.invert(V.mouse[0]=A)),clearTimeout(V.wheel);else{if(W.k===D)return;V.mouse=[A,W.invert(A)],ol(this),V.start()}fo(b),V.wheel=setTimeout(H,S),V.zoom("mouse",o(k(I(W,D),V.mouse[0],V.mouse[1]),V.extent,d));function H(){V.wheel=null,V.end()}}function U(b,...Y){if(v||!t.apply(this,arguments))return;var V=b.currentTarget,W=T(this,Y,!0).event(b),D=zt(b.view).on("mousemove.zoom",L,!0).on("mouseup.zoom",ne,!0),A=qt(b,V),H=b.clientX,M=b.clientY;Lp(b.view),bu(b),W.mouse=[A,this.__zoom.invert(A)],ol(this),W.start();function L(re){if(fo(re),!W.moved){var ce=re.clientX-H,fe=re.clientY-M;W.moved=ce*ce+fe*fe>C}W.event(re).zoom("mouse",o(k(W.that.__zoom,W.mouse[0]=qt(re,V),W.mouse[1]),W.extent,d))}function ne(re){D.on("mousemove.zoom mouseup.zoom",null),zp(re.view,W.moved),fo(re),W.event(re).end()}}function ee(b,...Y){if(t.apply(this,arguments)){var V=this.__zoom,W=qt(b.changedTouches?b.changedTouches[0]:b,this),D=V.invert(W),A=V.k*(b.shiftKey?.5:2),H=o(k(I(V,A),W,D),r.apply(this,Y),d);fo(b),f>0?zt(this).transition().duration(f).call(R,H,W,b):zt(this).call(N.transform,H,W,b)}}function q(b,...Y){if(t.apply(this,arguments)){var V=b.touches,W=V.length,D=T(this,Y,b.changedTouches.length===W).event(b),A,H,M,L;for(bu(b),H=0;H`Seems like you have not used ${t==="svelte"?"SvelteFlowProvider":"ReactFlowProvider"} as an ancestor. Help: https://${t}flow.dev/error#001`,error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:t=>`Node type "${t}" not found. Using fallback type "default".`,error004:()=>"The parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:t=>`The old edge with id=${t} does not exist.`,error009:t=>`Marker type "${t}" doesn't exist.`,error008:(t,{id:r,sourceHandle:o,targetHandle:l})=>`Couldn't create edge for ${t} handle id: "${t==="source"?o:l}", edge id: ${r}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:t=>`Edge type "${t}" not found. Using fallback type "default".`,error012:t=>`Node with id "${t}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(t="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${t}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs.",error016:t=>`Edge with id "${t}" does not exist, it may have been removed. This can happen when an edge is deleted before the "onEdgeClick" handler is called.`},So=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Zp=["Enter"," ","Escape"],Jp={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:t,x:r,y:o})=>`Moved selected node ${t}. New position, x: ${r}, y: ${o}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"};var wi;(function(t){t.Strict="strict",t.Loose="loose"})(wi||(wi={}));var Ir;(function(t){t.Free="free",t.Vertical="vertical",t.Horizontal="horizontal"})(Ir||(Ir={}));var ko;(function(t){t.Partial="partial",t.Full="full"})(ko||(ko={}));const eg={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};var nr;(function(t){t.Bezier="default",t.Straight="straight",t.Step="step",t.SmoothStep="smoothstep",t.SimpleBezier="simplebezier"})(nr||(nr={}));var Eo;(function(t){t.Arrow="arrow",t.ArrowClosed="arrowclosed"})(Eo||(Eo={}));var Se;(function(t){t.Left="left",t.Top="top",t.Right="right",t.Bottom="bottom"})(Se||(Se={}));const ph={[Se.Left]:Se.Right,[Se.Right]:Se.Left,[Se.Top]:Se.Bottom,[Se.Bottom]:Se.Top};function tg(t){return t===null?null:t?"valid":"invalid"}const ng=t=>!!t&&typeof t=="object"&&"id"in t&&"source"in t&&"target"in t,Kw=t=>!!t&&typeof t=="object"&&"id"in t&&"position"in t&&!("source"in t)&&!("target"in t),sc=t=>!!t&&typeof t=="object"&&"id"in t&&"internals"in t&&!("source"in t)&&!("target"in t),Io=(t,r=[0,0])=>{const{width:o,height:l}=rn(t),a=t.origin??r,u=o*a[0],d=l*a[1];return{x:t.position.x-u,y:t.position.y-d}},qw=(t,r={nodeOrigin:[0,0]})=>{if(t.length===0)return{x:0,y:0,width:0,height:0};let o=!1;const l=t.reduce((a,u)=>{const d=typeof u=="string";let f=!r.nodeLookup&&!d?u:void 0;return r.nodeLookup&&(f=d?r.nodeLookup.get(u):sc(u)?u:r.nodeLookup.get(u.id)),f?(o=!0,kl(a,hl(f,r.nodeOrigin))):a},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return o?El(l):{x:0,y:0,width:0,height:0}},To=(t,r={})=>{let o={x:1/0,y:1/0,x2:-1/0,y2:-1/0},l=!1;return t.forEach(a=>{(r.filter===void 0||r.filter(a))&&(o=kl(o,hl(a)),l=!0)}),l?El(o):{x:0,y:0,width:0,height:0}},lc=(t,r,[o,l,a]=[0,0,1],u=!1,d=!1)=>{const f=(r.x-o)/a,g=(r.y-l)/a,y=r.width/a,m=r.height/a,x=[];for(const v of t.values()){const{measured:_,selectable:S=!0,hidden:C=!1}=v;if(d&&!S||C)continue;const E=_.width??v.width??v.initialWidth??0,N=_.height??v.height??v.initialHeight??0,{x:I,y:k}=v.internals.positionAbsolute,j=sg(f,g,y,m,I,k,E,N),R=E*N,T=u&&j>0;(!v.internals.handleBounds||T||j>=R||v.dragging)&&x.push(v)}return x},Zw=(t,r)=>{const o=new Set;return t.forEach(l=>{o.add(l.id)}),r.filter(l=>o.has(l.source)||o.has(l.target))};function Jw(t,r){const o=new Map,l=r!=null&&r.nodes?new Set(r.nodes.map(a=>a.id)):null;return t.forEach(a=>{let u;if(r!=null&&r.includeHiddenNodes){const{width:d,height:f}=rn(a);u=d>0&&f>0}else u=!!(a.measured.width&&a.measured.height&&!a.hidden);u&&(!l||l.has(a.id))&&o.set(a.id,a)}),o}async function e1({nodes:t,width:r,height:o,panZoom:l,minZoom:a,maxZoom:u},d){if(t.size===0)return!0;const f=Jw(t,d),g=To(f),y=uc(g,r,o,(d==null?void 0:d.minZoom)??a,(d==null?void 0:d.maxZoom)??u,(d==null?void 0:d.padding)??.1);return await l.setViewport(y,{duration:d==null?void 0:d.duration,ease:d==null?void 0:d.ease,interpolate:d==null?void 0:d.interpolate}),!0}function rg({nodeId:t,nextPosition:r,nodeLookup:o,nodeOrigin:l=[0,0],nodeExtent:a,onError:u}){const d=o.get(t),f=d.parentId?o.get(d.parentId):void 0,{x:g,y}=f?f.internals.positionAbsolute:{x:0,y:0},m=d.origin??l;let x=d.extent||a;if(d.extent==="parent"&&!d.expandParent)if(!f)u==null||u("005",tn.error005());else{const{width:_,height:S}=rn(f);_&&S&&(x=[[g,y],[g+_,y+S]])}else f&&zr(d.extent)&&(x=[[d.extent[0][0]+g,d.extent[0][1]+y],[d.extent[1][0]+g,d.extent[1][1]+y]]);const v=zr(x)?Lr(r,x,d.measured):r;return(d.measured.width===void 0||d.measured.height===void 0)&&(u==null||u("015",tn.error015())),{position:{x:v.x-g+(d.measured.width??0)*m[0],y:v.y-y+(d.measured.height??0)*m[1]},positionAbsolute:v}}async function t1({nodesToRemove:t=[],edgesToRemove:r=[],nodes:o,edges:l,onBeforeDelete:a}){const u=new Set(t.map(v=>v.id)),d=[];for(const v of o){if(v.deletable===!1)continue;const _=u.has(v.id),S=!_&&v.parentId&&d.find(C=>C.id===v.parentId);(_||S)&&d.push(v)}const f=new Set(r.map(v=>v.id)),g=l.filter(v=>v.deletable!==!1),m=Zw(d,g);for(const v of g)f.has(v.id)&&!m.find(S=>S.id===v.id)&&m.push(v);if(!a)return{edges:m,nodes:d};const x=await a({nodes:d,edges:m});return typeof x=="boolean"?x?{edges:m,nodes:d}:{edges:[],nodes:[]}:x}const _i=(t,r=0,o=1)=>Math.min(Math.max(t,r),o),Lr=(t={x:0,y:0},r,o)=>({x:_i(t.x,r[0][0],r[1][0]-((o==null?void 0:o.width)??0)),y:_i(t.y,r[0][1],r[1][1]-((o==null?void 0:o.height)??0))});function ig(t,r,o){const{width:l,height:a}=rn(o),{x:u,y:d}=o.internals.positionAbsolute;return Lr(t,[[u,d],[u+l,d+a]],r)}const gh=(t,r,o)=>to?-_i(Math.abs(t-o),1,r)/r:0,ac=(t,r,o=15,l=40)=>{const a=gh(t.x,l,r.width-l)*o,u=gh(t.y,l,r.height-l)*o;return[a,u]},kl=(t,r)=>({x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),x2:Math.max(t.x2,r.x2),y2:Math.max(t.y2,r.y2)}),Xu=({x:t,y:r,width:o,height:l})=>({x:t,y:r,x2:t+o,y2:r+l}),El=({x:t,y:r,x2:o,y2:l})=>({x:t,y:r,width:o-t,height:l-r}),No=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=sc(t)?t.internals.positionAbsolute:Io(t,r);return{x:o,y:l,width:((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0,height:((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0}},hl=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=sc(t)?t.internals.positionAbsolute:Io(t,r);return{x:o,y:l,x2:o+(((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0),y2:l+(((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0)}},og=(t,r)=>El(kl(Xu(t),Xu(r))),sg=(t,r,o,l,a,u,d,f)=>{const g=Math.max(0,Math.min(t+o,a+d)-Math.max(t,a)),y=Math.max(0,Math.min(r+l,u+f)-Math.max(r,u));return Math.ceil(g*y)},pl=(t,r)=>sg(t.x,t.y,t.width,t.height,r.x,r.y,r.width,r.height),mh=t=>Jt(t.width)&&Jt(t.height)&&Jt(t.x)&&Jt(t.y),Jt=t=>!isNaN(t)&&isFinite(t),lg=(t,r)=>(o,l)=>{},Ro=(t,r=[1,1])=>({x:r[0]*Math.round(t.x/r[0]),y:r[1]*Math.round(t.y/r[1])}),Lo=({x:t,y:r},[o,l,a],u=!1,d=[1,1])=>{const f={x:(t-o)/a,y:(r-l)/a};return u?Ro(f,d):f},Si=({x:t,y:r},[o,l,a])=>({x:t*a+o,y:r*a+l});function hi(t,r){if(typeof t=="number")return Math.floor((r-r/(1+t))*.5);if(typeof t=="string"&&t.endsWith("px")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(o)}if(typeof t=="string"&&t.endsWith("%")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(r*o*.01)}return console.error(`The padding value "${t}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function n1(t,r,o){if(typeof t=="string"||typeof t=="number"){const l=hi(t,o),a=hi(t,r);return{top:l,right:a,bottom:l,left:a,x:a*2,y:l*2}}if(typeof t=="object"){const l=hi(t.top??t.y??0,o),a=hi(t.bottom??t.y??0,o),u=hi(t.left??t.x??0,r),d=hi(t.right??t.x??0,r);return{top:l,right:d,bottom:a,left:u,x:u+d,y:l+a}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function r1(t,r,o,l,a,u){const{x:d,y:f}=Si(t,[r,o,l]),{x:g,y}=Si({x:t.x+t.width,y:t.y+t.height},[r,o,l]),m=a-g,x=u-y;return{left:Math.floor(d),top:Math.floor(f),right:Math.floor(m),bottom:Math.floor(x)}}const uc=(t,r,o,l,a,u)=>{const d=n1(u,r,o),f=(r-d.x)/t.width,g=(o-d.y)/t.height,y=Math.min(f,g),m=_i(y,l,a),x=t.x+t.width/2,v=t.y+t.height/2,_=r/2-x*m,S=o/2-v*m,C=r1(t,_,S,m,r,o),E={left:Math.min(C.left-d.left,0),top:Math.min(C.top-d.top,0),right:Math.min(C.right-d.right,0),bottom:Math.min(C.bottom-d.bottom,0)};return{x:_-E.left+E.right,y:S-E.top+E.bottom,zoom:m}},Co=()=>{var t;return typeof navigator<"u"&&((t=navigator==null?void 0:navigator.userAgent)==null?void 0:t.indexOf("Mac"))>=0};function zr(t){return t!=null&&t!=="parent"}function rn(t){var r,o;return{width:((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth??0,height:((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight??0}}function ag(t){var r,o;return(((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth)!==void 0&&(((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight)!==void 0}function ug(t,r={width:0,height:0},o,l,a){const u={...t},d=l.get(o);if(d){const f=d.origin||a;u.x+=d.internals.positionAbsolute.x-(r.width??0)*f[0],u.y+=d.internals.positionAbsolute.y-(r.height??0)*f[1]}return u}function yh(t,r){if(t.size!==r.size)return!1;for(const o of t)if(!r.has(o))return!1;return!0}function i1(){let t,r;return{promise:new Promise((l,a)=>{t=l,r=a}),resolve:t,reject:r}}function o1(t){return{...Jp,...t||{}}}function mo(t,{snapGrid:r=[0,0],snapToGrid:o=!1,transform:l,containerBounds:a}){const{x:u,y:d}=en(t),f=Lo({x:u-((a==null?void 0:a.left)??0),y:d-((a==null?void 0:a.top)??0)},l),{x:g,y}=o?Ro(f,r):f;return{xSnapped:g,ySnapped:y,...f}}const cc=t=>({width:t.offsetWidth,height:t.offsetHeight}),cg=t=>{var r;return((r=t==null?void 0:t.getRootNode)==null?void 0:r.call(t))||(window==null?void 0:window.document)},s1=["INPUT","SELECT","TEXTAREA"];function dg(t){var l,a;const r=((a=(l=t.composedPath)==null?void 0:l.call(t))==null?void 0:a[0])||t.target;return(r==null?void 0:r.nodeType)!==1?!1:s1.includes(r.nodeName)||r.hasAttribute("contenteditable")||!!r.closest(".nokey")}const fg=t=>"clientX"in t,en=(t,r)=>{var u,d;const o=fg(t),l=o?t.clientX:(u=t.touches)==null?void 0:u[0].clientX,a=o?t.clientY:(d=t.touches)==null?void 0:d[0].clientY;return{x:l-((r==null?void 0:r.left)??0),y:a-((r==null?void 0:r.top)??0)}},vh=(t,r,o,l,a)=>{const u=r.querySelectorAll(`.${t}`);return!u||!u.length?null:Array.from(u).map(d=>{const f=d.getBoundingClientRect();return{id:d.getAttribute("data-handleid"),type:t,nodeId:a,position:d.getAttribute("data-handlepos"),x:(f.left-o.left)/l,y:(f.top-o.top)/l,...cc(d)}})};function hg({sourceX:t,sourceY:r,targetX:o,targetY:l,sourceControlX:a,sourceControlY:u,targetControlX:d,targetControlY:f}){const g=t*.125+a*.375+d*.375+o*.125,y=r*.125+u*.375+f*.375+l*.125,m=Math.abs(g-t),x=Math.abs(y-r);return[g,y,m,x]}function Ks(t,r){return t>=0?.5*t:r*25*Math.sqrt(-t)}function xh({pos:t,x1:r,y1:o,x2:l,y2:a,c:u}){switch(t){case Se.Left:return[r-Ks(r-l,u),o];case Se.Right:return[r+Ks(l-r,u),o];case Se.Top:return[r,o-Ks(o-a,u)];case Se.Bottom:return[r,o+Ks(a-o,u)]}}function pg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top,curvature:d=.25}){const[f,g]=xh({pos:o,x1:t,y1:r,x2:l,y2:a,c:d}),[y,m]=xh({pos:u,x1:l,y1:a,x2:t,y2:r,c:d}),[x,v,_,S]=hg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:f,sourceControlY:g,targetControlX:y,targetControlY:m});return[`M${t},${r} C${f},${g} ${y},${m} ${l},${a}`,x,v,_,S]}function gg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const a=Math.abs(o-t)/2,u=o0}const u1=({source:t,sourceHandle:r,target:o,targetHandle:l})=>`xy-edge__${t}${r||""}-${o}${l||""}`,c1=(t,r)=>r.some(o=>o.source===t.source&&o.target===t.target&&(o.sourceHandle===t.sourceHandle||!o.sourceHandle&&!t.sourceHandle)&&(o.targetHandle===t.targetHandle||!o.targetHandle&&!t.targetHandle)),d1=(t,r,o={})=>{var u;if(!t.source||!t.target)return(u=o.onError)==null||u.call(o,"006",tn.error006()),r;const l=o.getEdgeId||u1;let a;return ng(t)?a={...t}:a={...t,id:l(t)},c1(a,r)?r:(a.sourceHandle===null&&delete a.sourceHandle,a.targetHandle===null&&delete a.targetHandle,r.concat(a))};function mg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const[a,u,d,f]=gg({sourceX:t,sourceY:r,targetX:o,targetY:l});return[`M ${t},${r}L ${o},${l}`,a,u,d,f]}const wh={[Se.Left]:{x:-1,y:0},[Se.Right]:{x:1,y:0},[Se.Top]:{x:0,y:-1},[Se.Bottom]:{x:0,y:1}},f1=({source:t,sourcePosition:r=Se.Bottom,target:o})=>r===Se.Left||r===Se.Right?t.xMath.sqrt(Math.pow(r.x-t.x,2)+Math.pow(r.y-t.y,2));function h1({source:t,sourcePosition:r=Se.Bottom,target:o,targetPosition:l=Se.Top,center:a,offset:u,stepPosition:d}){const f=wh[r],g=wh[l],y={x:t.x+f.x*u,y:t.y+f.y*u},m={x:o.x+g.x*u,y:o.y+g.y*u},x=f1({source:y,sourcePosition:r,target:m}),v=x.x!==0?"x":"y",_=x[v];let S=[],C,E;const N={x:0,y:0},I={x:0,y:0},[,,k,j]=gg({sourceX:t.x,sourceY:t.y,targetX:o.x,targetY:o.y});if(f[v]*g[v]===-1){v==="x"?(C=a.x??y.x+(m.x-y.x)*d,E=a.y??(y.y+m.y)/2):(C=a.x??(y.x+m.x)/2,E=a.y??y.y+(m.y-y.y)*d);const G=[{x:C,y:y.y},{x:C,y:m.y}],U=[{x:y.x,y:E},{x:m.x,y:E}];f[v]===_?S=v==="x"?G:U:S=v==="x"?U:G}else{const G=[{x:y.x,y:m.y}],U=[{x:m.x,y:y.y}];if(v==="x"?S=f.x===_?U:G:S=f.y===_?G:U,r===l){const b=Math.abs(t[v]-o[v]);if(b<=u){const Y=Math.min(u-1,u-b);f[v]===_?N[v]=(y[v]>t[v]?-1:1)*Y:I[v]=(m[v]>o[v]?-1:1)*Y}}if(r!==l){const b=v==="x"?"y":"x",Y=f[v]===g[b],V=y[b]>m[b],W=y[b]=J?(C=(ee.x+q.x)/2,E=S[0].y):(C=S[0].x,E=(ee.y+q.y)/2)}const R={x:y.x+N.x,y:y.y+N.y},T={x:m.x+I.x,y:m.y+I.y};return[[t,...R.x!==S[0].x||R.y!==S[0].y?[R]:[],...S,...T.x!==S[S.length-1].x||T.y!==S[S.length-1].y?[T]:[],o],C,E,k,j]}function p1(t,r,o,l){const a=Math.min(_h(t,r)/2,_h(r,o)/2,l),{x:u,y:d}=r;if(t.x===u&&u===o.x||t.y===d&&d===o.y)return`L${u} ${d}`;if(t.y===d){const y=t.xo.id===r):t[0])||null}function Qu(t,r){return t?typeof t=="string"?t:`${r?`${r}__`:""}${Object.keys(t).sort().map(l=>`${l}=${t[l]}`).join("&")}`:""}function m1(t,{id:r,defaultColor:o,defaultMarkerStart:l,defaultMarkerEnd:a}){const u=new Set;return t.reduce((d,f)=>([f.markerStart||l,f.markerEnd||a].forEach(g=>{if(g&&typeof g=="object"){const y=Qu(g,r);u.has(y)||(d.push({id:y,color:g.color||o,...g}),u.add(y))}}),d),[]).sort((d,f)=>d.id.localeCompare(f.id))}const yg=1e3,y1=10,dc={nodeOrigin:[0,0],nodeExtent:So,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},v1={...dc,checkEquality:!0};function fc(t,r){const o={...t};for(const l in r)r[l]!==void 0&&(o[l]=r[l]);return o}function x1(t,r,o){const l=fc(dc,o);for(const a of t.values())if(a.parentId)pc(a,t,r,l);else{const u=Io(a,l.nodeOrigin),d=zr(a.extent)?a.extent:l.nodeExtent,f=Lr(u,d,rn(a));a.internals.positionAbsolute=f}}function w1(t,r){if(!t.handles)return t.measured?r==null?void 0:r.internals.handleBounds:void 0;const o=[],l=[];for(const a of t.handles){const u={id:a.id,width:a.width??1,height:a.height??1,nodeId:t.id,x:a.x,y:a.y,position:a.position,type:a.type};a.type==="source"?o.push(u):a.type==="target"&&l.push(u)}return{source:o,target:l}}function hc(t){return t==="manual"}function Ku(t,r,o,l={}){var m,x;const a=fc(v1,l),u={i:0},d=new Map(r),f=a!=null&&a.elevateNodesOnSelect&&!hc(a.zIndexMode)?yg:0;let g=t.length>0,y=!1;r.clear(),o.clear();for(const v of t){let _=d.get(v.id);if(a.checkEquality&&v===(_==null?void 0:_.internals.userNode))r.set(v.id,_);else{const S=Io(v,a.nodeOrigin),C=zr(v.extent)?v.extent:a.nodeExtent,E=Lr(S,C,rn(v));_={...a.defaults,...v,measured:{width:(m=v.measured)==null?void 0:m.width,height:(x=v.measured)==null?void 0:x.height},internals:{positionAbsolute:E,handleBounds:w1(v,_),z:vg(v,f,a.zIndexMode),userNode:v}},r.set(v.id,_)}(_.measured===void 0||_.measured.width===void 0||_.measured.height===void 0)&&!_.hidden&&(g=!1),v.parentId&&pc(_,r,o,l,u),y||(y=v.selected??!1)}return{nodesInitialized:g,hasSelectedNodes:y}}function _1(t,r){if(!t.parentId)return;const o=r.get(t.parentId);o?o.set(t.id,t):r.set(t.parentId,new Map([[t.id,t]]))}function pc(t,r,o,l,a){const{elevateNodesOnSelect:u,nodeOrigin:d,nodeExtent:f,zIndexMode:g}=fc(dc,l),y=t.parentId,m=r.get(y);if(!m){console.warn(`Parent node ${y} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}_1(t,o),a&&!m.parentId&&m.internals.rootParentIndex===void 0&&g==="auto"&&(m.internals.rootParentIndex=++a.i,m.internals.z=m.internals.z+a.i*y1),a&&m.internals.rootParentIndex!==void 0&&(a.i=m.internals.rootParentIndex);const x=u&&!hc(g)?yg:0,{x:v,y:_,z:S}=S1(t,m,d,f,x,g),{positionAbsolute:C}=t.internals,E=v!==C.x||_!==C.y;(E||S!==t.internals.z)&&r.set(t.id,{...t,internals:{...t.internals,positionAbsolute:E?{x:v,y:_}:C,z:S}})}function vg(t,r,o){const l=Jt(t.zIndex)?t.zIndex:0;return hc(o)?l:l+(t.selected?r:0)}function S1(t,r,o,l,a,u){const{x:d,y:f}=r.internals.positionAbsolute,g=rn(t),y=Io(t,o),m=zr(t.extent)?Lr(y,t.extent,g):y;let x=Lr({x:d+m.x,y:f+m.y},l,g);t.extent==="parent"&&(x=ig(x,g,r));const v=vg(t,a,u),_=r.internals.z??0;return{x:x.x,y:x.y,z:_>=v?_+1:v}}function gc(t,r,o,l=[0,0]){var d;const a=[],u=new Map;for(const f of t){const g=r.get(f.parentId);if(!g)continue;const y=((d=u.get(f.parentId))==null?void 0:d.expandedRect)??No(g),m=og(y,f.rect);u.set(f.parentId,{expandedRect:m,parent:g})}return u.size>0&&u.forEach(({expandedRect:f,parent:g},y)=>{var k;const m=g.internals.positionAbsolute,x=rn(g),v=g.origin??l,_=f.x0||S>0||N||I)&&(a.push({id:y,type:"position",position:{x:g.position.x-_+N,y:g.position.y-S+I}}),(k=o.get(y))==null||k.forEach(j=>{t.some(R=>R.id===j.id)||a.push({id:j.id,type:"position",position:{x:j.position.x+_,y:j.position.y+S}})})),(x.width0){const _=gc(v,r,o,a);y.push(..._)}return{changes:y,updatedInternals:g}}async function E1({delta:t,panZoom:r,transform:o,translateExtent:l,width:a,height:u}){if(!r||!t.x&&!t.y)return!1;const d=await r.setViewportConstrained({x:o[0]+t.x,y:o[1]+t.y,zoom:o[2]},[[0,0],[a,u]],l);return!!d&&(d.x!==o[0]||d.y!==o[1]||d.k!==o[2])}function Nh(t,r,o,l,a,u){let d=a;const f=l.get(d)||new Map;l.set(d,f.set(o,r)),d=`${a}-${t}`;const g=l.get(d)||new Map;if(l.set(d,g.set(o,r)),u){d=`${a}-${t}-${u}`;const y=l.get(d)||new Map;l.set(d,y.set(o,r))}}function xg(t,r,o){t.clear(),r.clear();for(const l of o){const{source:a,target:u,sourceHandle:d=null,targetHandle:f=null}=l,g={edgeId:l.id,source:a,target:u,sourceHandle:d,targetHandle:f},y=`${a}-${d}--${u}-${f}`,m=`${u}-${f}--${a}-${d}`;Nh("source",g,m,t,a,d),Nh("target",g,y,t,u,f),r.set(l.id,l)}}function wg(t,r){if(!t.parentId)return!1;const o=r.get(t.parentId);return o?o.selected?!0:wg(o,r):!1}function Ch(t,r,o){var a;let l=t;do{if((a=l==null?void 0:l.matches)!=null&&a.call(l,r))return!0;if(l===o)return!1;l=l==null?void 0:l.parentElement}while(l);return!1}function N1(t,r,o,l){const a=new Map;for(const[u,d]of t)if((d.selected||d.id===l)&&(!d.parentId||!wg(d,t))&&(d.draggable||r&&typeof d.draggable>"u")){const f=t.get(u);f&&a.set(u,{id:u,position:f.position||{x:0,y:0},distance:{x:o.x-f.internals.positionAbsolute.x,y:o.y-f.internals.positionAbsolute.y},extent:f.extent,parentId:f.parentId,origin:f.origin,expandParent:f.expandParent,internals:{positionAbsolute:f.internals.positionAbsolute||{x:0,y:0}},measured:{width:f.measured.width??0,height:f.measured.height??0}})}return a}function Mu({nodeId:t,dragItems:r,nodeLookup:o,dragging:l=!0}){var d,f,g;const a=[];for(const[y,m]of r){const x=(d=o.get(y))==null?void 0:d.internals.userNode;x&&a.push({...x,position:m.position,dragging:l})}if(!t)return[a[0],a];const u=(f=o.get(t))==null?void 0:f.internals.userNode;return[u?{...u,position:((g=r.get(t))==null?void 0:g.position)||u.position,dragging:l}:a[0],a]}function C1({dragItems:t,snapGrid:r,x:o,y:l}){const a=t.values().next().value;if(!a)return null;const u={x:o-a.distance.x,y:l-a.distance.y},d=Ro(u,r);return{x:d.x-u.x,y:d.y-u.y}}function j1({onNodeMouseDown:t,getStoreItems:r,onDragStart:o,onDrag:l,onDragStop:a}){let u={x:null,y:null},d=0,f=new Map,g=!1,y={x:0,y:0},m=null,x=!1,v=null,_=!1,S=!1,C=null;function E({noDragClassName:I,handleSelector:k,domNode:j,isSelectable:R,nodeId:T,nodeClickDistance:B=0}){v=zt(j);function G({x:te,y:J}){const{nodeLookup:b,nodeExtent:Y,snapGrid:V,snapToGrid:W,nodeOrigin:D,onNodeDrag:A,onSelectionDrag:H,onError:M,updateNodePositions:L}=r();u={x:te,y:J};let ne=!1;const re=f.size>1,ce=re&&Y?Xu(To(f)):null,fe=re&&W?C1({dragItems:f,snapGrid:V,x:te,y:J}):null;for(const[de,K]of f){if(!b.has(de))continue;let se={x:te-K.distance.x,y:J-K.distance.y};W&&(se=fe?{x:Math.round(se.x+fe.x),y:Math.round(se.y+fe.y)}:Ro(se,V));let pe=null;if(re&&Y&&!K.extent&&ce){const{positionAbsolute:ye}=K.internals,Ne=ye.x-ce.x+Y[0][0],Pe=ye.x+K.measured.width-ce.x2+Y[1][0],je=ye.y-ce.y+Y[0][1],Me=ye.y+K.measured.height-ce.y2+Y[1][1];pe=[[Ne,je],[Pe,Me]]}const{position:_e,positionAbsolute:me}=rg({nodeId:de,nextPosition:se,nodeLookup:b,nodeExtent:pe||Y,nodeOrigin:D,onError:M});ne=ne||K.position.x!==_e.x||K.position.y!==_e.y,K.position=_e,K.internals.positionAbsolute=me}if(S=S||ne,!!ne&&(L(f,!0),C&&(l||A||!T&&H))){const[de,K]=Mu({nodeId:T,dragItems:f,nodeLookup:b});l==null||l(C,f,de,K),A==null||A(C,de,K),T||H==null||H(C,K)}}async function U(){if(!m)return;const{transform:te,panBy:J,autoPanSpeed:b,autoPanOnNodeDrag:Y}=r();if(!Y){g=!1,cancelAnimationFrame(d);return}const[V,W]=ac(y,m,b);(V!==0||W!==0)&&(u.x=(u.x??0)-V/te[2],u.y=(u.y??0)-W/te[2],await J({x:V,y:W})&&G(u)),d=requestAnimationFrame(U)}function ee(te){var re;const{nodeLookup:J,multiSelectionActive:b,nodesDraggable:Y,transform:V,snapGrid:W,snapToGrid:D,selectNodesOnDrag:A,onNodeDragStart:H,onSelectionDragStart:M,unselectNodesAndEdges:L}=r();x=!0,(!A||!R)&&!b&&T&&((re=J.get(T))!=null&&re.selected||L()),R&&A&&T&&(t==null||t(T));const ne=mo(te.sourceEvent,{transform:V,snapGrid:W,snapToGrid:D,containerBounds:m});if(u=ne,f=N1(J,Y,ne,T),f.size>0&&(o||H||!T&&M)){const[ce,fe]=Mu({nodeId:T,dragItems:f,nodeLookup:J});o==null||o(te.sourceEvent,f,ce,fe),H==null||H(te.sourceEvent,ce,fe),T||M==null||M(te.sourceEvent,fe)}}const q=Ap().clickDistance(B).on("start",te=>{const{domNode:J,nodeDragThreshold:b,transform:Y,snapGrid:V,snapToGrid:W}=r();m=(J==null?void 0:J.getBoundingClientRect())||null,_=!1,S=!1,C=te.sourceEvent,b===0&&ee(te),u=mo(te.sourceEvent,{transform:Y,snapGrid:V,snapToGrid:W,containerBounds:m}),y=en(te.sourceEvent,m)}).on("drag",te=>{const{autoPanOnNodeDrag:J,transform:b,snapGrid:Y,snapToGrid:V,nodeDragThreshold:W,nodeLookup:D}=r(),A=mo(te.sourceEvent,{transform:b,snapGrid:Y,snapToGrid:V,containerBounds:m});if(C=te.sourceEvent,(te.sourceEvent.type==="touchmove"&&te.sourceEvent.touches.length>1||T&&!D.has(T))&&(_=!0),!_){if(!g&&J&&x&&(g=!0,U()),!x){const H=en(te.sourceEvent,m),M=H.x-y.x,L=H.y-y.y;Math.sqrt(M*M+L*L)>W&&ee(te)}(u.x!==A.xSnapped||u.y!==A.ySnapped)&&f&&x&&(y=en(te.sourceEvent,m),G(A))}}).on("end",te=>{if(!x||_){_&&f.size>0&&r().updateNodePositions(f,!1);return}if(g=!1,x=!1,cancelAnimationFrame(d),f.size>0){const{nodeLookup:J,updateNodePositions:b,onNodeDragStop:Y,onSelectionDragStop:V}=r();if(S&&(b(f,!1),S=!1),a||Y||!T&&V){const[W,D]=Mu({nodeId:T,dragItems:f,nodeLookup:J,dragging:!1});a==null||a(te.sourceEvent,f,W,D),Y==null||Y(te.sourceEvent,W,D),T||V==null||V(te.sourceEvent,D)}}}).filter(te=>{const J=te.target;return!te.button&&(!I||!Ch(J,`.${I}`,j))&&(!k||Ch(J,k,j))});v.call(q)}function N(){v==null||v.on(".drag",null)}return{update:E,destroy:N}}function b1(t,r,o){const l=[],a={x:t.x-o,y:t.y-o,width:o*2,height:o*2};for(const u of r.values())pl(a,No(u))>0&&l.push(u);return l}const M1=250;function P1(t,r,o,l){var f,g;let a=[],u=1/0;const d=b1(t,o,r+M1);for(const y of d){const m=[...((f=y.internals.handleBounds)==null?void 0:f.source)??[],...((g=y.internals.handleBounds)==null?void 0:g.target)??[]];for(const x of m){if(l.nodeId===x.nodeId&&l.type===x.type&&l.id===x.id)continue;const{x:v,y:_}=Ar(y,x,x.position,!0),S=Math.sqrt(Math.pow(v-t.x,2)+Math.pow(_-t.y,2));S>r||(S1){const y=l.type==="source"?"target":"source";return a.find(m=>m.type===y)??a[0]}return a[0]}function _g(t,r,o,l,a,u=!1){var y,m,x;const d=l.get(t);if(!d)return null;const f=a==="strict"?(y=d.internals.handleBounds)==null?void 0:y[r]:[...((m=d.internals.handleBounds)==null?void 0:m.source)??[],...((x=d.internals.handleBounds)==null?void 0:x.target)??[]],g=(o?f==null?void 0:f.find(v=>v.id===o):f==null?void 0:f[0])??null;return g&&u?{...g,...Ar(d,g,g.position,!0)}:g}function Sg(t,r){return t||(r!=null&&r.classList.contains("target")?"target":r!=null&&r.classList.contains("source")?"source":null)}function I1(t,r){let o=null;return r?o=!0:t&&!r&&(o=!1),o}const kg=()=>!0;function T1(t,{connectionMode:r,connectionRadius:o,handleId:l,nodeId:a,edgeUpdaterType:u,isTarget:d,domNode:f,nodeLookup:g,lib:y,autoPanOnConnect:m,flowId:x,panBy:v,cancelConnection:_,onConnectStart:S,onConnect:C,onConnectEnd:E,isValidConnection:N=kg,onReconnectEnd:I,updateConnection:k,getTransform:j,getFromHandle:R,autoPanSpeed:T,dragThreshold:B=1,handleDomNode:G}){const U=cg(t.target);let ee=0,q;const{x:te,y:J}=en(t),b=Sg(u,G),Y=f==null?void 0:f.getBoundingClientRect();let V=!1;if(!Y||!b)return;const W=_g(a,b,l,g,r);if(!W)return;let D=en(t,Y),A=!1,H=null,M=!1,L=null;function ne(){if(!m||!Y)return;const[_e,me]=ac(D,Y,T);v({x:_e,y:me}),ee=requestAnimationFrame(ne)}const re={...W,nodeId:a,type:b,position:W.position},ce=g.get(a);let de={inProgress:!0,isValid:null,from:Ar(ce,re,Se.Left,!0),fromHandle:re,fromPosition:re.position,fromNode:ce,to:D,toHandle:null,toPosition:ph[re.position],toNode:null,pointer:D};function K(){V=!0,k(de),S==null||S(t,{nodeId:a,handleId:l,handleType:b})}B===0&&K();function se(_e){if(!V){const{x:Me,y:tt}=en(_e),Ge=Me-te,nt=tt-J;if(!(Ge*Ge+nt*nt>B*B))return;K()}if(!R()||!re){pe(_e);return}const me=j();D=en(_e,Y),q=P1(Lo(D,me,!1,[1,1]),o,g,re),A||(ne(),A=!0);const ye=Eg(_e,{handle:q,connectionMode:r,fromNodeId:a,fromHandleId:l,fromType:d?"target":"source",isValidConnection:N,doc:U,lib:y,flowId:x,nodeLookup:g});L=ye.handleDomNode,H=ye.connection,M=I1(!!q,ye.isValid);const Ne=g.get(a),Pe=Ne?Ar(Ne,re,Se.Left,!0):de.from,je={...de,from:Pe,isValid:M,to:ye.toHandle&&M?Si({x:ye.toHandle.x,y:ye.toHandle.y},me):D,toHandle:ye.toHandle,toPosition:M&&ye.toHandle?ye.toHandle.position:ph[re.position],toNode:ye.toHandle?g.get(ye.toHandle.nodeId):null,pointer:D};k(je),de=je}function pe(_e){if(!("touches"in _e&&_e.touches.length>0)){if(V){(q||L)&&H&&M&&(C==null||C(H));const{inProgress:me,...ye}=de,Ne={...ye,toPosition:de.toHandle?de.toPosition:null};E==null||E(_e,Ne),u&&(I==null||I(_e,Ne))}_(),cancelAnimationFrame(ee),A=!1,M=!1,H=null,L=null,U.removeEventListener("mousemove",se),U.removeEventListener("mouseup",pe),U.removeEventListener("touchmove",se),U.removeEventListener("touchend",pe)}}U.addEventListener("mousemove",se),U.addEventListener("mouseup",pe),U.addEventListener("touchmove",se),U.addEventListener("touchend",pe)}function Eg(t,{handle:r,connectionMode:o,fromNodeId:l,fromHandleId:a,fromType:u,doc:d,lib:f,flowId:g,isValidConnection:y=kg,nodeLookup:m}){const x=u==="target",v=r?d.querySelector(`.${f}-flow__handle[data-id="${g}-${r==null?void 0:r.nodeId}-${r==null?void 0:r.id}-${r==null?void 0:r.type}"]`):null,{x:_,y:S}=en(t),C=d.elementFromPoint(_,S),E=C!=null&&C.classList.contains(`${f}-flow__handle`)?C:v,N={handleDomNode:E,isValid:!1,connection:null,toHandle:null};if(E){const I=Sg(void 0,E),k=E.getAttribute("data-nodeid"),j=E.getAttribute("data-handleid"),R=E.classList.contains("connectable"),T=E.classList.contains("connectableend");if(!k||!I)return N;const B={source:x?k:l,sourceHandle:x?j:a,target:x?l:k,targetHandle:x?a:j};N.connection=B;const U=R&&T&&(o===wi.Strict?x&&I==="source"||!x&&I==="target":k!==l||j!==a);N.isValid=U&&y(B),N.toHandle=_g(k,I,j,m,o,!0)}return N}const qu={onPointerDown:T1,isValid:Eg};function R1({domNode:t,panZoom:r,getTransform:o,getViewScale:l}){const a=zt(t);function u({translateExtent:f,width:g,height:y,zoomStep:m=1,pannable:x=!0,zoomable:v=!0,inversePan:_=!1}){const S=k=>{if(k.sourceEvent.type!=="wheel"||!r)return;const j=o(),R=k.sourceEvent.ctrlKey&&Co()?10:1,T=-k.sourceEvent.deltaY*(k.sourceEvent.deltaMode===1?.05:k.sourceEvent.deltaMode?1:.002)*m,B=j[2]*Math.pow(2,T*R);r.scaleTo(B)};let C=[0,0];const E=k=>{(k.sourceEvent.type==="mousedown"||k.sourceEvent.type==="touchstart")&&(C=[k.sourceEvent.clientX??k.sourceEvent.touches[0].clientX,k.sourceEvent.clientY??k.sourceEvent.touches[0].clientY])},N=k=>{const j=o();if(k.sourceEvent.type!=="mousemove"&&k.sourceEvent.type!=="touchmove"||!r)return;const R=[k.sourceEvent.clientX??k.sourceEvent.touches[0].clientX,k.sourceEvent.clientY??k.sourceEvent.touches[0].clientY],T=[R[0]-C[0],R[1]-C[1]];C=R;const B=l()*Math.max(j[2],Math.log(j[2]))*(_?-1:1),G={x:j[0]-T[0]*B,y:j[1]-T[1]*B},U=[[0,0],[g,y]];r.setViewportConstrained({x:G.x,y:G.y,zoom:j[2]},U,f)},I=qp().on("start",E).on("zoom",x?N:null).on("zoom.wheel",v?S:null);a.call(I,{})}function d(){a.on("zoom",null)}return{update:u,destroy:d,pointer:qt}}const Nl=t=>({x:t.x,y:t.y,zoom:t.k}),Pu=({x:t,y:r,zoom:o})=>Sl.translate(t,r).scale(o),tr=(t,r)=>t.target.closest(`.${r}`),Ng=(t,r)=>r===2&&Array.isArray(t)&&t.includes(2),L1=t=>((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2,Iu=(t,r=0,o=L1,l=()=>{})=>{const a=typeof r=="number"&&r>0;return a||l(),a?t.transition().duration(r).ease(o).on("end",l):t},Cg=t=>{const r=t.ctrlKey&&Co()?10:1;return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*r};function z1({zoomPanValues:t,noWheelClassName:r,d3Selection:o,d3Zoom:l,panOnScrollMode:a,panOnScrollSpeed:u,zoomOnPinch:d,onPanZoomStart:f,onPanZoom:g,onPanZoomEnd:y}){return m=>{if(tr(m,r))return m.ctrlKey&&m.preventDefault(),!1;m.preventDefault(),m.stopImmediatePropagation();const x=o.property("__zoom").k||1;if(m.ctrlKey&&d){const E=qt(m),N=Cg(m),I=x*Math.pow(2,N);l.scaleTo(o,I,E,m);return}const v=m.deltaMode===1?20:1;let _=a===Ir.Vertical?0:m.deltaX*v,S=a===Ir.Horizontal?0:m.deltaY*v;!Co()&&m.shiftKey&&a!==Ir.Vertical&&(_=m.deltaY*v,S=0),l.translateBy(o,-(_/x)*u,-(S/x)*u,{internal:!0});const C=Nl(o.property("__zoom"));clearTimeout(t.panScrollTimeout),t.isPanScrolling?g==null||g(m,C):(t.isPanScrolling=!0,f==null||f(m,C)),t.panScrollTimeout=setTimeout(()=>{y==null||y(m,C),t.isPanScrolling=!1},150)}}function A1({noWheelClassName:t,preventScrolling:r,d3ZoomHandler:o}){return function(l,a){const u=l.type==="wheel",d=!r&&u&&!l.ctrlKey,f=tr(l,t);if(l.ctrlKey&&u&&f&&l.preventDefault(),d||f)return null;l.preventDefault(),o.call(this,l,a)}}function D1({zoomPanValues:t,onDraggingChange:r,onPanZoomStart:o}){return l=>{var u,d,f;if((u=l.sourceEvent)!=null&&u.internal)return;const a=Nl(l.transform);t.mouseButton=((d=l.sourceEvent)==null?void 0:d.button)||0,t.isZoomingOrPanning=!0,t.prevViewport=a,((f=l.sourceEvent)==null?void 0:f.type)==="mousedown"&&r(!0),o&&(o==null||o(l.sourceEvent,a))}}function $1({zoomPanValues:t,panOnDrag:r,onPaneContextMenu:o,onTransformChange:l,onPanZoom:a}){return u=>{var d,f;t.usedRightMouseButton=!!(o&&Ng(r,t.mouseButton??0)),(d=u.sourceEvent)!=null&&d.sync||l([u.transform.x,u.transform.y,u.transform.k]),a&&!((f=u.sourceEvent)!=null&&f.internal)&&(a==null||a(u.sourceEvent,Nl(u.transform)))}}function O1({zoomPanValues:t,panOnDrag:r,panOnScroll:o,onDraggingChange:l,onPanZoomEnd:a,onPaneContextMenu:u}){return d=>{var f;if(!((f=d.sourceEvent)!=null&&f.internal)&&(t.isZoomingOrPanning=!1,u&&Ng(r,t.mouseButton??0)&&!t.usedRightMouseButton&&d.sourceEvent&&u(d.sourceEvent),t.usedRightMouseButton=!1,l(!1),a)){const g=Nl(d.transform);t.prevViewport=g,clearTimeout(t.timerId),t.timerId=setTimeout(()=>{a==null||a(d.sourceEvent,g)},o?150:0)}}}function F1({panActivationKeyPressed:t,zoomActivationKeyPressed:r,zoomOnScroll:o,zoomOnPinch:l,panOnDrag:a,panOnScroll:u,zoomOnDoubleClick:d,userSelectionActive:f,noWheelClassName:g,noPanClassName:y,lib:m,connectionInProgress:x}){return v=>{var N;const _=r||o,S=l&&v.ctrlKey,C=v.type==="wheel";if(v.button===1&&v.type==="mousedown"&&(tr(v,`${m}-flow__node`)||tr(v,`${m}-flow__edge`)||tr(v,`${m}-flow__selection`)||tr(v,`${m}-flow__nodesselection`)))return!0;if(!a&&!_&&!u&&!d&&!l||f||x&&!C||tr(v,g)&&C||tr(v,y)&&(!C||u&&C&&!r)||!l&&v.ctrlKey&&C)return!1;if(!l&&v.type==="touchstart"&&((N=v.touches)==null?void 0:N.length)>1)return v.preventDefault(),!1;if(!_&&!u&&!S&&C||!a&&(v.type==="mousedown"||v.type==="touchstart")||Array.isArray(a)&&!a.includes(v.button)&&v.type==="mousedown")return!1;const E=Array.isArray(a)&&a.includes(v.button)||!v.button||v.button<=1;return(!v.ctrlKey||C||t)&&E}}function H1({domNode:t,minZoom:r,maxZoom:o,translateExtent:l,viewport:a,onPanZoom:u,onPanZoomStart:d,onPanZoomEnd:f,onDraggingChange:g}){const y={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},m=t.getBoundingClientRect();let x=[[0,0],[m.width,m.height]];const v=typeof ResizeObserver<"u"?new ResizeObserver(J=>{const b=J[0];b&&(x=[[0,0],[b.contentRect.width,b.contentRect.height]])}):null;v==null||v.observe(t);const _=qp().extent(()=>x).scaleExtent([r,o]).translateExtent(l),S=zt(t).call(_);j({x:a.x,y:a.y,zoom:_i(a.zoom,r,o)},[[0,0],[m.width,m.height]],l);const C=S.on("wheel.zoom"),E=S.on("dblclick.zoom");_.wheelDelta(Cg);async function N(J,b){return S?new Promise(Y=>{_==null||_.interpolate((b==null?void 0:b.interpolate)==="linear"?go:nl).transform(Iu(S,b==null?void 0:b.duration,b==null?void 0:b.ease,()=>Y(!0)),J)}):!1}function I({noWheelClassName:J,noPanClassName:b,onPaneContextMenu:Y,userSelectionActive:V,panOnScroll:W,panOnDrag:D,panOnScrollMode:A,panOnScrollSpeed:H,preventScrolling:M,zoomOnPinch:L,zoomOnScroll:ne,zoomOnDoubleClick:re,panActivationKeyPressed:ce=!1,zoomActivationKeyPressed:fe,lib:de,onTransformChange:K,connectionInProgress:se,paneClickDistance:pe,selectionOnDrag:_e}){V&&!y.isZoomingOrPanning&&k();const me=W&&!fe&&!V;_.clickDistance(_e?1/0:!Jt(pe)||pe<0?0:pe);const ye=me?z1({zoomPanValues:y,noWheelClassName:J,d3Selection:S,d3Zoom:_,panOnScrollMode:A,panOnScrollSpeed:H,zoomOnPinch:L,onPanZoomStart:d,onPanZoom:u,onPanZoomEnd:f}):A1({noWheelClassName:J,preventScrolling:M,d3ZoomHandler:C});S.on("wheel.zoom",ye,{passive:!1});const Ne=D1({zoomPanValues:y,onDraggingChange:g,onPanZoomStart:d});_.on("start",Ne);const Pe=$1({zoomPanValues:y,panOnDrag:D,onPaneContextMenu:!!Y,onPanZoom:u,onTransformChange:K});_.on("zoom",Pe);const je=O1({zoomPanValues:y,panOnDrag:D,panOnScroll:W,onPaneContextMenu:Y,onPanZoomEnd:f,onDraggingChange:g});_.on("end",je);const Me=F1({panActivationKeyPressed:ce,zoomActivationKeyPressed:fe,panOnDrag:D,zoomOnScroll:ne,panOnScroll:W,zoomOnDoubleClick:re,zoomOnPinch:L,userSelectionActive:V,noPanClassName:b,noWheelClassName:J,lib:de,connectionInProgress:se});_.filter(Me),re?S.on("dblclick.zoom",E):S.on("dblclick.zoom",null)}function k(){_.on("zoom",null)}async function j(J,b,Y){const V=Pu(J),W=_==null?void 0:_.constrain()(V,b,Y);return W&&await N(W),W}async function R(J,b){const Y=Pu(J);return await N(Y,b),Y}function T(J){if(S){const b=Pu(J),Y=S.property("__zoom");(Y.k!==J.zoom||Y.x!==J.x||Y.y!==J.y)&&(_==null||_.transform(S,b,null,{sync:!0}))}}function B(){const J=S?Kp(S.node()):{x:0,y:0,k:1};return{x:J.x,y:J.y,zoom:J.k}}async function G(J,b){return S?new Promise(Y=>{_==null||_.interpolate((b==null?void 0:b.interpolate)==="linear"?go:nl).scaleTo(Iu(S,b==null?void 0:b.duration,b==null?void 0:b.ease,()=>Y(!0)),J)}):!1}async function U(J,b){return S?new Promise(Y=>{_==null||_.interpolate((b==null?void 0:b.interpolate)==="linear"?go:nl).scaleBy(Iu(S,b==null?void 0:b.duration,b==null?void 0:b.ease,()=>Y(!0)),J)}):!1}function ee(J){_==null||_.scaleExtent(J)}function q(J){_==null||_.translateExtent(J)}function te(J){const b=!Jt(J)||J<0?0:J;_==null||_.clickDistance(b)}return{update:I,destroy:k,setViewport:R,setViewportConstrained:j,getViewport:B,scaleTo:G,scaleBy:U,setScaleExtent:ee,setTranslateExtent:q,syncViewport:T,setClickDistance:te}}var ki;(function(t){t.Line="line",t.Handle="handle"})(ki||(ki={}));function B1({width:t,prevWidth:r,height:o,prevHeight:l,affectsX:a,affectsY:u}){const d=t-r,f=o-l,g=[d>0?1:d<0?-1:0,f>0?1:f<0?-1:0];return d&&a&&(g[0]=g[0]*-1),f&&u&&(g[1]=g[1]*-1),g}function jh(t){const r=t.includes("right")||t.includes("left"),o=t.includes("bottom")||t.includes("top"),l=t.includes("left"),a=t.includes("top");return{isHorizontal:r,isVertical:o,affectsX:l,affectsY:a}}function Jn(t,r){return Math.max(0,r-t)}function er(t,r){return Math.max(0,t-r)}function qs(t,r,o){return Math.max(0,r-t,t-o)}function bh(t,r){return t?!r:r}function V1(t,r,o,l,a,u,d,f){let{affectsX:g,affectsY:y}=r;const{isHorizontal:m,isVertical:x}=r,v=m&&x,{xSnapped:_,ySnapped:S}=o,{minWidth:C,maxWidth:E,minHeight:N,maxHeight:I}=l,{x:k,y:j,width:R,height:T,aspectRatio:B}=t;let G=Math.floor(m?_-t.pointerX:0),U=Math.floor(x?S-t.pointerY:0);const ee=R+(g?-G:G),q=T+(y?-U:U),te=-u[0]*R,J=-u[1]*T;let b=qs(ee,C,E),Y=qs(q,N,I);if(d){let D=0,A=0;g&&G<0?D=Jn(k+G+te,d[0][0]):!g&&G>0&&(D=er(k+ee+te,d[1][0])),y&&U<0?A=Jn(j+U+J,d[0][1]):!y&&U>0&&(A=er(j+q+J,d[1][1])),b=Math.max(b,D),Y=Math.max(Y,A)}if(f){let D=0,A=0;g&&G>0?D=er(k+G,f[0][0]):!g&&G<0&&(D=Jn(k+ee,f[1][0])),y&&U>0?A=er(j+U,f[0][1]):!y&&U<0&&(A=Jn(j+q,f[1][1])),b=Math.max(b,D),Y=Math.max(Y,A)}if(a){if(m){const D=qs(ee/B,N,I)*B;if(b=Math.max(b,D),d){let A=0;!g&&!y||g&&!y&&v?A=er(j+J+ee/B,d[1][1])*B:A=Jn(j+J+(g?G:-G)/B,d[0][1])*B,b=Math.max(b,A)}if(f){let A=0;!g&&!y||g&&!y&&v?A=Jn(j+ee/B,f[1][1])*B:A=er(j+(g?G:-G)/B,f[0][1])*B,b=Math.max(b,A)}}if(x){const D=qs(q*B,C,E)/B;if(Y=Math.max(Y,D),d){let A=0;!g&&!y||y&&!g&&v?A=er(k+q*B+te,d[1][0])/B:A=Jn(k+(y?U:-U)*B+te,d[0][0])/B,Y=Math.max(Y,A)}if(f){let A=0;!g&&!y||y&&!g&&v?A=Jn(k+q*B,f[1][0])/B:A=er(k+(y?U:-U)*B,f[0][0])/B,Y=Math.max(Y,A)}}}U=U+(U<0?Y:-Y),G=G+(G<0?b:-b),a&&(v?ee>q*B?U=(bh(g,y)?-G:G)/B:G=(bh(g,y)?-U:U)*B:m?(U=G/B,y=g):(G=U*B,g=y));const V=g?k+G:k,W=y?j+U:j;return{width:R+(g?-G:G),height:T+(y?-U:U),x:u[0]*G*(g?-1:1)+V,y:u[1]*U*(y?-1:1)+W}}const jg={width:0,height:0,x:0,y:0},U1={...jg,pointerX:0,pointerY:0,aspectRatio:1};function W1(t,r,o){const l=r.position.x+t.position.x,a=r.position.y+t.position.y,u=t.measured.width??0,d=t.measured.height??0,f=o[0]*u,g=o[1]*d;return[[l-f,a-g],[l+u-f,a+d-g]]}function Y1({domNode:t,nodeId:r,getStoreItems:o,onChange:l,onEnd:a}){const u=zt(t);let d={controlDirection:jh("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function f({controlPosition:y,boundaries:m,keepAspectRatio:x,resizeDirection:v,onResizeStart:_,onResize:S,onResizeEnd:C,shouldResize:E}){let N={...jg},I={...U1};d={boundaries:m,resizeDirection:v,keepAspectRatio:x,controlDirection:jh(y)};let k,j=null,R=[],T,B,G,U=!1;const ee=Ap().on("start",q=>{const{nodeLookup:te,transform:J,snapGrid:b,snapToGrid:Y,nodeOrigin:V,paneDomNode:W}=o();if(k=te.get(r),!k)return;j=(W==null?void 0:W.getBoundingClientRect())??null;const{xSnapped:D,ySnapped:A}=mo(q.sourceEvent,{transform:J,snapGrid:b,snapToGrid:Y,containerBounds:j});N={width:k.measured.width??0,height:k.measured.height??0,x:k.position.x??0,y:k.position.y??0},I={...N,pointerX:D,pointerY:A,aspectRatio:N.width/N.height},T=void 0,B=zr(k.extent)?k.extent:void 0,k.parentId&&(k.extent==="parent"||k.expandParent)&&(T=te.get(k.parentId)),T&&k.extent==="parent"&&(B=[[0,0],[T.measured.width,T.measured.height]]),R=[],G=void 0;for(const[H,M]of te)if(M.parentId===r&&(R.push({id:H,position:{...M.position},extent:M.extent}),M.extent==="parent"||M.expandParent)){const L=W1(M,k,M.origin??V);G?G=[[Math.min(L[0][0],G[0][0]),Math.min(L[0][1],G[0][1])],[Math.max(L[1][0],G[1][0]),Math.max(L[1][1],G[1][1])]]:G=L}_==null||_(q,{...N})}).on("drag",q=>{const{transform:te,snapGrid:J,snapToGrid:b,nodeOrigin:Y}=o(),V=mo(q.sourceEvent,{transform:te,snapGrid:J,snapToGrid:b,containerBounds:j}),W=[];if(!k)return;const{x:D,y:A,width:H,height:M}=N,L={},ne=k.origin??Y,{width:re,height:ce,x:fe,y:de}=V1(I,d.controlDirection,V,d.boundaries,d.keepAspectRatio,ne,B,G),K=re!==H,se=ce!==M,pe=fe!==D&&K,_e=de!==A&&se;if(!pe&&!_e&&!K&&!se)return;if((pe||_e||ne[0]===1||ne[1]===1)&&(L.x=pe?fe:N.x,L.y=_e?de:N.y,N.x=L.x,N.y=L.y,R.length>0)){const Pe=fe-D,je=de-A;for(const Me of R)Me.position={x:Me.position.x-Pe+ne[0]*(re-H),y:Me.position.y-je+ne[1]*(ce-M)},W.push(Me)}if((K||se)&&(L.width=K&&(!d.resizeDirection||d.resizeDirection==="horizontal")?re:N.width,L.height=se&&(!d.resizeDirection||d.resizeDirection==="vertical")?ce:N.height,N.width=L.width,N.height=L.height),T&&k.expandParent){const Pe=ne[0]*(L.width??0);L.x&&L.x{U&&(C==null||C(q,{...N}),a==null||a({...N}),U=!1)});u.call(ee)}function g(){u.on(".drag",null)}return{update:f,destroy:g}}var Tu={exports:{}},Ru={},Lu={exports:{}},zu={};/** - * @license React - * use-sync-external-store-shim.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Mh;function X1(){if(Mh)return zu;Mh=1;var t=bo();function r(x,v){return x===v&&(x!==0||1/x===1/v)||x!==x&&v!==v}var o=typeof Object.is=="function"?Object.is:r,l=t.useState,a=t.useEffect,u=t.useLayoutEffect,d=t.useDebugValue;function f(x,v){var _=v(),S=l({inst:{value:_,getSnapshot:v}}),C=S[0].inst,E=S[1];return u(function(){C.value=_,C.getSnapshot=v,g(C)&&E({inst:C})},[x,_,v]),a(function(){return g(C)&&E({inst:C}),x(function(){g(C)&&E({inst:C})})},[x]),d(_),_}function g(x){var v=x.getSnapshot;x=x.value;try{var _=v();return!o(x,_)}catch{return!0}}function y(x,v){return v()}var m=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?y:f;return zu.useSyncExternalStore=t.useSyncExternalStore!==void 0?t.useSyncExternalStore:m,zu}var Ph;function G1(){return Ph||(Ph=1,Lu.exports=X1()),Lu.exports}/** - * @license React - * use-sync-external-store-shim/with-selector.production.js - * - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var Ih;function Q1(){if(Ih)return Ru;Ih=1;var t=bo(),r=G1();function o(y,m){return y===m&&(y!==0||1/y===1/m)||y!==y&&m!==m}var l=typeof Object.is=="function"?Object.is:o,a=r.useSyncExternalStore,u=t.useRef,d=t.useEffect,f=t.useMemo,g=t.useDebugValue;return Ru.useSyncExternalStoreWithSelector=function(y,m,x,v,_){var S=u(null);if(S.current===null){var C={hasValue:!1,value:null};S.current=C}else C=S.current;S=f(function(){function N(T){if(!I){if(I=!0,k=T,T=v(T),_!==void 0&&C.hasValue){var B=C.value;if(_(B,T))return j=B}return j=T}if(B=j,l(k,T))return B;var G=v(T);return _!==void 0&&_(B,G)?(k=T,B):(k=T,j=G)}var I=!1,k,j,R=x===void 0?null:x;return[function(){return N(m())},R===null?void 0:function(){return N(R())}]},[m,x,v,_]);var E=a(y,S[0],S[1]);return d(function(){C.hasValue=!0,C.value=E},[E]),g(E),E},Ru}var Th;function K1(){return Th||(Th=1,Tu.exports=Q1()),Tu.exports}var q1=K1();const Z1=xp(q1),J1={},Rh=t=>{let r;const o=new Set,l=(m,x)=>{const v=typeof m=="function"?m(r):m;if(!Object.is(v,r)){const _=r;r=x??(typeof v!="object"||v===null)?v:Object.assign({},r,v),o.forEach(S=>S(r,_))}},a=()=>r,g={setState:l,getState:a,getInitialState:()=>y,subscribe:m=>(o.add(m),()=>o.delete(m)),destroy:()=>{(J1?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),o.clear()}},y=r=t(l,a,g);return g},e_=t=>t?Rh(t):Rh,{useDebugValue:t_}=Zy,{useSyncExternalStoreWithSelector:n_}=Z1,r_=t=>t;function bg(t,r=r_,o){const l=n_(t.subscribe,t.getState,t.getServerState||t.getInitialState,r,o);return t_(l),l}const Lh=(t,r)=>{const o=e_(t),l=(a,u=r)=>bg(o,a,u);return Object.assign(l,o),l},i_=(t,r)=>t?Lh(t,r):Lh;function Xe(t,r){if(Object.is(t,r))return!0;if(typeof t!="object"||t===null||typeof r!="object"||r===null)return!1;if(t instanceof Map&&r instanceof Map){if(t.size!==r.size)return!1;for(const[l,a]of t)if(!Object.is(a,r.get(l)))return!1;return!0}if(t instanceof Set&&r instanceof Set){if(t.size!==r.size)return!1;for(const l of t)if(!r.has(l))return!1;return!0}const o=Object.keys(t);if(o.length!==Object.keys(r).length)return!1;for(const l of o)if(!Object.prototype.hasOwnProperty.call(r,l)||!Object.is(t[l],r[l]))return!1;return!0}wp();const Cl=$.createContext(null),o_=Cl.Provider,Mg=tn.error001("react");function Re(t,r){const o=$.useContext(Cl);if(o===null)throw new Error(Mg);return bg(o,t,r)}function He(){const t=$.useContext(Cl);if(t===null)throw new Error(Mg);return $.useMemo(()=>({getState:t.getState,setState:t.setState,subscribe:t.subscribe}),[t])}const zh={display:"none"},s_={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},Pg="react-flow__node-desc",Ig="react-flow__edge-desc",l_="react-flow__aria-live",a_=t=>t.ariaLiveMessage,u_=t=>t.ariaLabelConfig;function c_({rfId:t}){const r=Re(a_);return p.jsx("div",{id:`${l_}-${t}`,"aria-live":"assertive","aria-atomic":"true",style:s_,children:r})}function d_({rfId:t,disableKeyboardA11y:r}){const o=Re(u_);return p.jsxs(p.Fragment,{children:[p.jsx("div",{id:`${Pg}-${t}`,style:zh,children:r?o["node.a11yDescription.default"]:o["node.a11yDescription.keyboardDisabled"]}),p.jsx("div",{id:`${Ig}-${t}`,style:zh,children:o["edge.a11yDescription.default"]}),!r&&p.jsx(c_,{rfId:t})]})}const jl=$.forwardRef(({position:t="top-left",children:r,className:o,style:l,...a},u)=>{const d=`${t}`.split("-");return p.jsx("div",{className:et(["react-flow__panel",o,...d]),style:l,ref:u,...a,children:r})});jl.displayName="Panel";const Ah="https://reactflow.dev?utm_source=attribution";function f_({proOptions:t,position:r="bottom-right"}){return t!=null&&t.hideAttribution?null:p.jsx(jl,{position:r,className:"react-flow__attribution","data-message":`Please only hide this attribution when you are subscribed to React Flow Pro: ${Ah}`,children:p.jsx("a",{href:Ah,target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}const h_=t=>{const r=[],o=[];for(const[,l]of t.nodeLookup)l.selected&&r.push(l.internals.userNode);for(const[,l]of t.edgeLookup)l.selected&&o.push(l);return{selectedNodes:r,selectedEdges:o}},Zs=t=>t.id;function p_(t,r){return Xe(t.selectedNodes.map(Zs),r.selectedNodes.map(Zs))&&Xe(t.selectedEdges.map(Zs),r.selectedEdges.map(Zs))}function g_({onSelectionChange:t}){const r=He(),{selectedNodes:o,selectedEdges:l}=Re(h_,p_);return $.useEffect(()=>{const a={nodes:o,edges:l};t==null||t(a),r.getState().onSelectionChangeHandlers.forEach(u=>u(a))},[o,l,t]),null}const m_=t=>!!t.onSelectionChangeHandlers;function y_({onSelectionChange:t}){const r=Re(m_);return t||r?p.jsx(g_,{onSelectionChange:t}):null}const Tg=[0,0],v_={x:0,y:0,zoom:1},x_=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","nodesFocusable","edgesFocusable","edgesReconnectable","elevateNodesOnSelect","elevateEdgesOnSelect","minZoom","maxZoom","nodeExtent","onNodesChange","onEdgesChange","elementsSelectable","connectionMode","snapGrid","snapToGrid","translateExtent","connectOnClick","defaultEdgeOptions","fitView","fitViewOptions","onNodesDelete","onEdgesDelete","onDelete","onNodeDrag","onNodeDragStart","onNodeDragStop","onSelectionDrag","onSelectionDragStart","onSelectionDragStop","onMoveStart","onMove","onMoveEnd","noPanClassName","nodeOrigin","autoPanOnConnect","autoPanOnNodeDrag","onError","connectionRadius","isValidConnection","selectNodesOnDrag","nodeDragThreshold","connectionDragThreshold","onBeforeDelete","debug","autoPanSpeed","ariaLabelConfig","zIndexMode"],Dh=[...x_,"rfId"],w_=t=>({setNodes:t.setNodes,setEdges:t.setEdges,setMinZoom:t.setMinZoom,setMaxZoom:t.setMaxZoom,setTranslateExtent:t.setTranslateExtent,setNodeExtent:t.setNodeExtent,reset:t.reset,setDefaultNodesAndEdges:t.setDefaultNodesAndEdges}),$h={translateExtent:So,nodeOrigin:Tg,minZoom:.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function __(t){const{setNodes:r,setEdges:o,setMinZoom:l,setMaxZoom:a,setTranslateExtent:u,setNodeExtent:d,reset:f,setDefaultNodesAndEdges:g}=Re(w_,Xe),y=He();$.useEffect(()=>(g(t.defaultNodes,t.defaultEdges),()=>{m.current=$h,f()}),[]);const m=$.useRef($h);return $.useEffect(()=>{for(const x of Dh){const v=t[x],_=m.current[x];v!==_&&(typeof t[x]>"u"||(x==="nodes"?r(v):x==="edges"?o(v):x==="minZoom"?l(v):x==="maxZoom"?a(v):x==="translateExtent"?u(v):x==="nodeExtent"?d(v):x==="ariaLabelConfig"?y.setState({ariaLabelConfig:o1(v)}):x==="fitView"?y.setState({fitViewQueued:v}):x==="fitViewOptions"?y.setState({fitViewOptions:v}):y.setState({[x]:v})))}m.current=t},Dh.map(x=>t[x])),null}function Oh(){return typeof window>"u"||!window.matchMedia?null:window.matchMedia("(prefers-color-scheme: dark)")}function S_(t){var l;const[r,o]=$.useState(t==="system"?null:t);return $.useEffect(()=>{if(t!=="system"){o(t);return}const a=Oh(),u=()=>o(a!=null&&a.matches?"dark":"light");return u(),a==null||a.addEventListener("change",u),()=>{a==null||a.removeEventListener("change",u)}},[t]),r!==null?r:(l=Oh())!=null&&l.matches?"dark":"light"}const Fh=typeof document<"u"?document:null;function jo(t=null,r={target:Fh,actInsideInputWithModifier:!0}){const[o,l]=$.useState(!1),a=$.useRef(!1),u=$.useRef(new Set([])),[d,f]=$.useMemo(()=>{if(t!==null){const y=(Array.isArray(t)?t:[t]).filter(x=>typeof x=="string").map(x=>x.replace(/\+/g,` -`).replace(` - -`,` -+`).split(` -`)),m=y.reduce((x,v)=>x.concat(...v),[]);return[y,m]}return[[],[]]},[t]);return $.useEffect(()=>{const g=(r==null?void 0:r.target)??Fh,y=(r==null?void 0:r.actInsideInputWithModifier)??!0;if(t!==null){const m=_=>{var E,N;if(a.current=_.ctrlKey||_.metaKey||_.shiftKey||_.altKey,(!a.current||a.current&&!y)&&dg(_))return!1;const C=Bh(_.code,f);if(u.current.add(_[C]),Hh(d,u.current,!1)){const I=((N=(E=_.composedPath)==null?void 0:E.call(_))==null?void 0:N[0])||_.target,k=(I==null?void 0:I.nodeName)==="BUTTON"||(I==null?void 0:I.nodeName)==="A";r.preventDefault!==!1&&(a.current||!k)&&_.preventDefault(),l(!0)}},x=_=>{const S=Bh(_.code,f);Hh(d,u.current,!0)?(l(!1),u.current.clear()):u.current.delete(_[S]),_.key==="Meta"&&u.current.clear(),a.current=!1},v=()=>{u.current.clear(),l(!1)};return g==null||g.addEventListener("keydown",m),g==null||g.addEventListener("keyup",x),window.addEventListener("blur",v),window.addEventListener("contextmenu",v),()=>{g==null||g.removeEventListener("keydown",m),g==null||g.removeEventListener("keyup",x),window.removeEventListener("blur",v),window.removeEventListener("contextmenu",v)}}},[t,l]),o}function Hh(t,r,o){return t.filter(l=>o||l.length===r.size).some(l=>l.every(a=>r.has(a)))}function Bh(t,r){return r.includes(t)?"code":"key"}const k_=()=>{const t=He();return $.useMemo(()=>({zoomIn:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1.2,r):!1},zoomOut:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1/1.2,r):!1},zoomTo:async(r,o)=>{const{panZoom:l}=t.getState();return l?l.scaleTo(r,o):!1},getZoom:()=>t.getState().transform[2],setViewport:async(r,o)=>{const{transform:[l,a,u],panZoom:d}=t.getState();return d?(await d.setViewport({x:r.x??l,y:r.y??a,zoom:r.zoom??u},o),!0):!1},getViewport:()=>{const[r,o,l]=t.getState().transform;return{x:r,y:o,zoom:l}},setCenter:async(r,o,l)=>t.getState().setCenter(r,o,l),fitBounds:async(r,o)=>{const{width:l,height:a,minZoom:u,maxZoom:d,panZoom:f}=t.getState(),g=uc(r,l,a,u,d,(o==null?void 0:o.padding)??.1);return f?(await f.setViewport(g,{duration:o==null?void 0:o.duration,ease:o==null?void 0:o.ease,interpolate:o==null?void 0:o.interpolate}),!0):!1},screenToFlowPosition:(r,o={})=>{const{transform:l,snapGrid:a,snapToGrid:u,domNode:d}=t.getState();if(!d)return r;const{x:f,y:g}=d.getBoundingClientRect(),y={x:r.x-f,y:r.y-g},m=o.snapGrid??a,x=o.snapToGrid??u;return Lo(y,l,x,m)},flowToScreenPosition:r=>{const{transform:o,domNode:l}=t.getState();if(!l)return r;const{x:a,y:u}=l.getBoundingClientRect(),d=Si(r,o);return{x:d.x+a,y:d.y+u}}}),[])};function Rg(t,r){const o=[],l=new Map,a=[];for(const u of t)if(u.type==="add"){a.push(u);continue}else if(u.type==="remove"||u.type==="replace")l.set(u.id,[u]);else{const d=l.get(u.id);d?d.push(u):l.set(u.id,[u])}for(const u of r){const d=l.get(u.id);if(!d){o.push(u);continue}if(d[0].type==="remove")continue;if(d[0].type==="replace"){o.push({...d[0].item});continue}const f={...u};for(const g of d)E_(g,f);o.push(f)}return a.length&&a.forEach(u=>{u.index!==void 0?o.splice(u.index,0,{...u.item}):o.push({...u.item})}),o}function E_(t,r){switch(t.type){case"select":{r.selected=t.selected;break}case"position":{typeof t.position<"u"&&(r.position=t.position),typeof t.dragging<"u"&&(r.dragging=t.dragging);break}case"dimensions":{typeof t.dimensions<"u"&&(r.measured={...t.dimensions},t.setAttributes&&((t.setAttributes===!0||t.setAttributes==="width")&&(r.width=t.dimensions.width),(t.setAttributes===!0||t.setAttributes==="height")&&(r.height=t.dimensions.height))),typeof t.resizing=="boolean"&&(r.resizing=t.resizing);break}}}function N_(t,r){return Rg(t,r)}function C_(t,r){return Rg(t,r)}function br(t,r){return{id:t,type:"select",selected:r}}function gi(t,r=new Set,o=!1){const l=[];for(const[a,u]of t){const d=r.has(a);!(u.selected===void 0&&!d)&&u.selected!==d&&(o&&(u.selected=d),l.push(br(u.id,d)))}return l}function Vh({items:t=[],lookup:r}){var a;const o=[],l=new Map(t.map(u=>[u.id,u]));for(const[u,d]of t.entries()){const f=r.get(d.id),g=((a=f==null?void 0:f.internals)==null?void 0:a.userNode)??f;g!==void 0&&g!==d&&o.push({id:d.id,item:d,type:"replace"}),g===void 0&&o.push({item:d,type:"add",index:u})}for(const[u]of r)l.get(u)===void 0&&o.push({id:u,type:"remove"});return o}function Uh(t){return{id:t.id,type:"remove"}}const j_=lg();function b_(t,r,o={}){return d1(t,r,{...o,onError:o.onError??j_})}const Wh=t=>Kw(t),M_=t=>ng(t);function Lg(t){return $.forwardRef(t)}const zg=typeof window<"u"?$.useLayoutEffect:$.useEffect;function Yh(t){const[r,o]=$.useState(BigInt(0)),[l]=$.useState(()=>P_(()=>o(a=>a+BigInt(1))));return zg(()=>{const a=l.get();a.length&&(t(a),l.reset())},[r]),l}function P_(t){let r=[];return{get:()=>r,reset:()=>{r=[]},push:o=>{r.push(o),t()}}}const Ag=$.createContext(null);function I_({children:t}){const r=He(),o=$.useCallback(f=>{const{nodes:g=[],setNodes:y,hasDefaultNodes:m,onNodesChange:x,nodeLookup:v,fitViewQueued:_,onNodesChangeMiddlewareMap:S}=r.getState();let C=g;for(const N of f)C=typeof N=="function"?N(C):N;let E=Vh({items:C,lookup:v});for(const N of S.values())E=N(E);m&&y(C),E.length>0?x==null||x(E):_&&window.requestAnimationFrame(()=>{const{fitViewQueued:N,nodes:I,setNodes:k}=r.getState();N&&k(I)})},[]),l=Yh(o),a=$.useCallback(f=>{const{edges:g=[],setEdges:y,hasDefaultEdges:m,onEdgesChange:x,edgeLookup:v}=r.getState();let _=g;for(const S of f)_=typeof S=="function"?S(_):S;m?y(_):x&&x(Vh({items:_,lookup:v}))},[]),u=Yh(a),d=$.useMemo(()=>({nodeQueue:l,edgeQueue:u}),[]);return p.jsx(Ag.Provider,{value:d,children:t})}function T_(){const t=$.useContext(Ag);if(!t)throw new Error("useBatchContext must be used within a BatchProvider");return t}const R_=t=>!!t.panZoom;function mc(){const t=k_(),r=He(),o=T_(),l=Re(R_),a=$.useMemo(()=>{const u=x=>r.getState().nodeLookup.get(x),d=x=>{o.nodeQueue.push(x)},f=x=>{o.edgeQueue.push(x)},g=x=>{var N,I;const{nodeLookup:v,nodeOrigin:_}=r.getState(),S=Wh(x)?x:v.get(x.id),C=S.parentId?ug(S.position,S.measured,S.parentId,v,_):S.position,E={...S,position:C,width:((N=S.measured)==null?void 0:N.width)??S.width,height:((I=S.measured)==null?void 0:I.height)??S.height};return No(E)},y=(x,v,_={replace:!1})=>{d(S=>S.map(C=>{if(C.id===x){const E=typeof v=="function"?v(C):v;return _.replace&&Wh(E)?E:{...C,...E}}return C}))},m=(x,v,_={replace:!1})=>{f(S=>S.map(C=>{if(C.id===x){const E=typeof v=="function"?v(C):v;return _.replace&&M_(E)?E:{...C,...E}}return C}))};return{getNodes:()=>r.getState().nodes.map(x=>({...x})),getNode:x=>{var v;return(v=u(x))==null?void 0:v.internals.userNode},getInternalNode:u,getEdges:()=>{const{edges:x=[]}=r.getState();return x.map(v=>({...v}))},getEdge:x=>r.getState().edgeLookup.get(x),setNodes:d,setEdges:f,addNodes:x=>{const v=Array.isArray(x)?x:[x];o.nodeQueue.push(_=>[..._,...v])},addEdges:x=>{const v=Array.isArray(x)?x:[x];o.edgeQueue.push(_=>[..._,...v])},toObject:()=>{const{nodes:x=[],edges:v=[],transform:_}=r.getState(),[S,C,E]=_;return{nodes:x.map(N=>({...N})),edges:v.map(N=>({...N})),viewport:{x:S,y:C,zoom:E}}},deleteElements:async({nodes:x=[],edges:v=[]})=>{const{nodes:_,edges:S,onNodesDelete:C,onEdgesDelete:E,triggerNodeChanges:N,triggerEdgeChanges:I,onDelete:k,onBeforeDelete:j}=r.getState(),{nodes:R,edges:T}=await t1({nodesToRemove:x,edgesToRemove:v,nodes:_,edges:S,onBeforeDelete:j}),B=T.length>0,G=R.length>0;if(B){const U=T.map(Uh);E==null||E(T),I(U)}if(G){const U=R.map(Uh);C==null||C(R),N(U)}return(G||B)&&(k==null||k({nodes:R,edges:T})),{deletedNodes:R,deletedEdges:T}},getIntersectingNodes:(x,v=!0,_)=>{const S=mh(x),C=S?x:g(x),E=_!==void 0;return C?(_||r.getState().nodes).filter(N=>{const I=r.getState().nodeLookup.get(N.id);if(I&&!S&&(N.id===x.id||!I.internals.positionAbsolute))return!1;const k=No(E?N:I),j=pl(k,C);return v&&j>0||j>=k.width*k.height||j>=C.width*C.height}):[]},isNodeIntersecting:(x,v,_=!0)=>{const C=mh(x)?x:g(x);if(!C)return!1;const E=pl(C,v);return _&&E>0||E>=v.width*v.height||E>=C.width*C.height},updateNode:y,updateNodeData:(x,v,_={replace:!1})=>{y(x,S=>{const C=typeof v=="function"?v(S):v;return _.replace?{...S,data:C}:{...S,data:{...S.data,...C}}},_)},updateEdge:m,updateEdgeData:(x,v,_={replace:!1})=>{m(x,S=>{const C=typeof v=="function"?v(S):v;return _.replace?{...S,data:C}:{...S,data:{...S.data,...C}}},_)},getNodesBounds:x=>{const{nodeLookup:v,nodeOrigin:_}=r.getState();return qw(x,{nodeLookup:v,nodeOrigin:_})},getHandleConnections:({type:x,id:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}-${x}${v?`-${v}`:""}`))==null?void 0:S.values())??[])},getNodeConnections:({type:x,handleId:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}${x?v?`-${x}-${v}`:`-${x}`:""}`))==null?void 0:S.values())??[])},fitView:async x=>{const v=r.getState().fitViewResolver??i1();return r.setState({fitViewQueued:!0,fitViewOptions:x,fitViewResolver:v}),o.nodeQueue.push(_=>[..._]),v.promise}}},[]);return $.useMemo(()=>({...a,...t,viewportInitialized:l}),[l])}const Xh=t=>t.selected,L_=typeof window<"u"?window:void 0;function z_({deleteKeyCode:t,multiSelectionKeyCode:r}){const o=He(),{deleteElements:l}=mc(),a=jo(t,{actInsideInputWithModifier:!1}),u=jo(r,{target:L_});$.useEffect(()=>{if(a){const{edges:d,nodes:f}=o.getState();l({nodes:f.filter(Xh),edges:d.filter(Xh)}),o.setState({nodesSelectionActive:!1})}},[a]),$.useEffect(()=>{o.setState({multiSelectionActive:u})},[u])}function A_(t){const r=He();$.useEffect(()=>{const o=()=>{var a,u,d,f;if(!t.current||!(((u=(a=t.current).checkVisibility)==null?void 0:u.call(a))??!0))return!1;const l=cc(t.current);(l.height===0||l.width===0)&&((f=(d=r.getState()).onError)==null||f.call(d,"004",tn.error004())),r.setState({width:l.width||500,height:l.height||500})};if(t.current){o(),window.addEventListener("resize",o);const l=new ResizeObserver(()=>o());return l.observe(t.current),()=>{window.removeEventListener("resize",o),l&&t.current&&l.unobserve(t.current)}}},[])}const bl={position:"absolute",width:"100%",height:"100%",top:0,left:0},D_=t=>({userSelectionActive:t.userSelectionActive,lib:t.lib,connectionInProgress:t.connection.inProgress});function $_({onPaneContextMenu:t,zoomOnScroll:r=!0,zoomOnPinch:o=!0,panOnScroll:l=!1,panActivationKeyPressed:a,panOnScrollSpeed:u=.5,panOnScrollMode:d=Ir.Free,zoomOnDoubleClick:f=!0,panOnDrag:g=!0,defaultViewport:y,translateExtent:m,minZoom:x,maxZoom:v,zoomActivationKeyCode:_,preventScrolling:S=!0,children:C,noWheelClassName:E,noPanClassName:N,onViewportChange:I,isControlledViewport:k,paneClickDistance:j,selectionOnDrag:R}){const T=He(),B=$.useRef(null),{userSelectionActive:G,lib:U,connectionInProgress:ee}=Re(D_,Xe),q=jo(_),te=$.useRef();A_(B);const J=$.useCallback(b=>{I==null||I({x:b[0],y:b[1],zoom:b[2]}),k||T.setState({transform:b})},[I,k]);return $.useEffect(()=>{if(B.current){te.current=H1({domNode:B.current,minZoom:x,maxZoom:v,translateExtent:m,viewport:y,onDraggingChange:W=>T.setState(D=>D.paneDragging===W?D:{paneDragging:W}),onPanZoomStart:(W,D)=>{const{onViewportChangeStart:A,onMoveStart:H}=T.getState();H==null||H(W,D),A==null||A(D)},onPanZoom:(W,D)=>{const{onViewportChange:A,onMove:H}=T.getState();H==null||H(W,D),A==null||A(D)},onPanZoomEnd:(W,D)=>{const{onViewportChangeEnd:A,onMoveEnd:H}=T.getState();H==null||H(W,D),A==null||A(D)}});const{x:b,y:Y,zoom:V}=te.current.getViewport();return T.setState({panZoom:te.current,transform:[b,Y,V],domNode:B.current.closest(".react-flow")}),()=>{var W;(W=te.current)==null||W.destroy()}}},[]),$.useEffect(()=>{var b;(b=te.current)==null||b.update({onPaneContextMenu:t,zoomOnScroll:r,zoomOnPinch:o,panOnScroll:l,panActivationKeyPressed:a,panOnScrollSpeed:u,panOnScrollMode:d,zoomOnDoubleClick:f,panOnDrag:g,zoomActivationKeyPressed:q,preventScrolling:S,noPanClassName:N,userSelectionActive:G,noWheelClassName:E,lib:U,onTransformChange:J,connectionInProgress:ee,selectionOnDrag:R,paneClickDistance:j})},[t,r,o,l,a,u,d,f,g,q,S,N,G,E,U,J,ee,R,j]),p.jsx("div",{className:"react-flow__renderer",ref:B,style:bl,children:C})}const O_=t=>({userSelectionActive:t.userSelectionActive,userSelectionRect:t.userSelectionRect});function F_(){const{userSelectionActive:t,userSelectionRect:r}=Re(O_,Xe);return t&&r?p.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:r.width,height:r.height,transform:`translate(${r.x}px, ${r.y}px)`}}):null}const Au=(t,r)=>o=>{o.target===r.current&&(t==null||t(o))},H_=t=>({userSelectionActive:t.userSelectionActive,elementsSelectable:t.elementsSelectable,dragging:t.paneDragging,panBy:t.panBy,autoPanSpeed:t.autoPanSpeed});function B_({isSelecting:t,selectionKeyPressed:r,selectionMode:o=ko.Full,panOnDrag:l,autoPanOnSelection:a,paneClickDistance:u,selectionOnDrag:d,onSelectionStart:f,onSelectionEnd:g,onPaneClick:y,onPaneContextMenu:m,onPaneScroll:x,onPaneMouseEnter:v,onPaneMouseMove:_,onPaneMouseLeave:S,children:C}){const E=$.useRef(0),N=He(),{userSelectionActive:I,elementsSelectable:k,dragging:j,panBy:R,autoPanSpeed:T}=Re(H_,Xe),B=k&&(t||I),G=$.useRef(null),U=$.useRef(),ee=$.useRef(new Set),q=$.useRef(new Set),te=$.useRef(!1),J=$.useRef(!1),b=$.useRef({x:0,y:0}),Y=$.useRef(!1),V=K=>{if(J.current||te.current||N.getState().connection.inProgress){J.current=!1,te.current=!1;return}y==null||y(K),N.getState().resetSelectedElements(),N.setState({nodesSelectionActive:!1})},W=K=>{if(Array.isArray(l)&&(l!=null&&l.includes(2))){K.preventDefault();return}m==null||m(K)},D=x?K=>x(K):void 0,A=K=>{J.current&&(K.stopPropagation(),J.current=!1)},H=K=>{var Me,tt;if(K.pointerType==="touch"&&l!==!1&&!r)return;const{domNode:se,transform:pe}=N.getState();if(U.current=se==null?void 0:se.getBoundingClientRect(),!U.current)return;const _e=K.target===G.current;if(!_e&&!!K.target.closest(".nokey")||!t||!(d&&_e||r)||K.button!==0||!K.isPrimary)return;(tt=(Me=K.target)==null?void 0:Me.setPointerCapture)==null||tt.call(Me,K.pointerId),J.current=!1;const{x:Ne,y:Pe}=en(K.nativeEvent,U.current),je=Lo({x:Ne,y:Pe},pe);N.setState({userSelectionRect:{width:0,height:0,startX:je.x,startY:je.y,x:Ne,y:Pe}}),_e||(K.stopPropagation(),K.preventDefault())};function M(K,se){const{userSelectionRect:pe}=N.getState();if(!pe)return;const{transform:_e,nodeLookup:me,edgeLookup:ye,connectionLookup:Ne,triggerNodeChanges:Pe,triggerEdgeChanges:je,defaultEdgeOptions:Me}=N.getState(),tt={x:pe.startX,y:pe.startY},{x:Ge,y:nt}=Si(tt,_e),Ke={startX:tt.x,startY:tt.y,x:Kut.id)),q.current=new Set;const ot=(Me==null?void 0:Me.selectable)??!0;for(const ut of ee.current){const ct=Ne.get(ut);if(ct)for(const{edgeId:ht}of ct.values()){const wt=ye.get(ht);wt&&(wt.selectable??ot)&&q.current.add(ht)}}if(!yh(bt,ee.current)){const ut=gi(me,ee.current,!0);Pe(ut)}if(!yh(Dt,q.current)){const ut=gi(ye,q.current);je(ut)}N.setState({userSelectionRect:Ke,userSelectionActive:!0,nodesSelectionActive:!1})}function L(){if(!a||!U.current)return;const[K,se]=ac(b.current,U.current,T);R({x:K,y:se}).then(pe=>{if(!J.current||!pe){E.current=requestAnimationFrame(L);return}const{x:_e,y:me}=b.current;M(_e,me),E.current=requestAnimationFrame(L)})}const ne=()=>{cancelAnimationFrame(E.current),E.current=0,Y.current=!1};$.useEffect(()=>()=>ne(),[]);const re=K=>{const{userSelectionRect:se,transform:pe,resetSelectedElements:_e}=N.getState();if(!U.current||!se)return;const{x:me,y:ye}=en(K.nativeEvent,U.current);b.current={x:me,y:ye};const Ne=Si({x:se.startX,y:se.startY},pe);if(!J.current){const Pe=r?0:u;if(Math.hypot(me-Ne.x,ye-Ne.y)<=Pe)return;_e(),f==null||f(K)}J.current=!0,Y.current||(L(),Y.current=!0),M(me,ye)},ce=K=>{var se,pe;if(!B){K.target===G.current&&N.getState().connection.inProgress&&(te.current=!0);return}K.button===0&&((pe=(se=K.target)==null?void 0:se.releasePointerCapture)==null||pe.call(se,K.pointerId),!I&&K.target===G.current&&N.getState().userSelectionRect&&(V==null||V(K)),N.setState({userSelectionActive:!1,userSelectionRect:null}),J.current&&(g==null||g(K),N.setState({nodesSelectionActive:ee.current.size>0})),ne())},fe=K=>{var se,pe;(pe=(se=K.target)==null?void 0:se.releasePointerCapture)==null||pe.call(se,K.pointerId),ne()},de=l===!0||Array.isArray(l)&&l.includes(0);return p.jsxs("div",{className:et(["react-flow__pane",{draggable:de,dragging:j,selection:t}]),onClick:B?void 0:Au(V,G),onContextMenu:Au(W,G),onWheel:Au(D,G),onPointerEnter:B?void 0:v,onPointerMove:B?re:_,onPointerUp:ce,onPointerCancel:B?fe:void 0,onPointerDownCapture:B?H:void 0,onClickCapture:B?A:void 0,onPointerLeave:S,ref:G,style:bl,children:[C,p.jsx(F_,{})]})}function Zu({id:t,store:r,unselect:o=!1,nodeRef:l}){const{addSelectedNodes:a,unselectNodesAndEdges:u,multiSelectionActive:d,nodeLookup:f,onError:g}=r.getState(),y=f.get(t);if(!y){g==null||g("012",tn.error012(t));return}r.setState({nodesSelectionActive:!1}),y.selected?(o||y.selected&&d)&&(u({nodes:[y],edges:[]}),requestAnimationFrame(()=>{var m;return(m=l==null?void 0:l.current)==null?void 0:m.blur()})):a([t])}function Dg({nodeRef:t,disabled:r=!1,noDragClassName:o,handleSelector:l,nodeId:a,isSelectable:u,nodeClickDistance:d}){const f=He(),[g,y]=$.useState(!1),m=$.useRef();return $.useEffect(()=>{if(!r)return m.current=j1({getStoreItems:()=>f.getState(),onNodeMouseDown:x=>{Zu({id:x,store:f,nodeRef:t})},onDragStart:()=>{y(!0)},onDragStop:()=>{y(!1)}}),()=>{var x;(x=m.current)==null||x.destroy(),m.current=void 0}},[r,f,t]),$.useEffect(()=>{r||!t.current||!m.current||m.current.update({noDragClassName:o,handleSelector:l,domNode:t.current,isSelectable:u,nodeId:a,nodeClickDistance:d})},[o,l,r,u,t,a,d]),g}const V_=t=>r=>r.selected&&(r.draggable||t&&typeof r.draggable>"u");function $g(){const t=He();return $.useCallback(o=>{const{nodeExtent:l,snapToGrid:a,snapGrid:u,nodesDraggable:d,onError:f,updateNodePositions:g,nodeLookup:y,nodeOrigin:m}=t.getState(),x=new Map,v=V_(d),_=a?u[0]:5,S=a?u[1]:5,C=o.direction.x*_*o.factor,E=o.direction.y*S*o.factor;for(const[,N]of y){if(!v(N))continue;let I={x:N.internals.positionAbsolute.x+C,y:N.internals.positionAbsolute.y+E};a&&(I=Ro(I,u));const{position:k,positionAbsolute:j}=rg({nodeId:N.id,nextPosition:I,nodeLookup:y,nodeExtent:l,nodeOrigin:m,onError:f});N.position=k,N.internals.positionAbsolute=j,x.set(N.id,N)}g(x)},[])}const yc=$.createContext(null),U_=yc.Provider;yc.Consumer;const Og=()=>$.useContext(yc),W_=t=>({connectOnClick:t.connectOnClick,noPanClassName:t.noPanClassName,rfId:t.rfId}),Fg=$.createContext(null);function Y_({children:t}){const r=Re(W_,Xe);return p.jsx(Fg.Provider,{value:r,children:t})}function X_(){const t=$.useContext(Fg);if(!t)throw new Error("useHandleConfig must be used within a HandleConfigProvider");return t}const G_={connectingFrom:!1,connectingTo:!1,clickConnecting:!1,isPossibleEndHandle:!0,connectionInProcess:!1,clickConnectionInProcess:!1,valid:!1},Q_=(t,r,o)=>l=>{const{connectionClickStartHandle:a,connectionMode:u,connection:d}=l,{fromHandle:f,toHandle:g,isValid:y}=d;if(!f&&!a)return G_;const m=(g==null?void 0:g.nodeId)===t&&(g==null?void 0:g.id)===r&&(g==null?void 0:g.type)===o;return{connectingFrom:(f==null?void 0:f.nodeId)===t&&(f==null?void 0:f.id)===r&&(f==null?void 0:f.type)===o,connectingTo:m,clickConnecting:(a==null?void 0:a.nodeId)===t&&(a==null?void 0:a.id)===r&&(a==null?void 0:a.type)===o,isPossibleEndHandle:u===wi.Strict?(f==null?void 0:f.type)!==o:t!==(f==null?void 0:f.nodeId)||r!==(f==null?void 0:f.id),connectionInProcess:!!f,clickConnectionInProcess:!!a,valid:m&&y}};function K_({type:t="source",position:r=Se.Top,isValidConnection:o,isConnectable:l=!0,isConnectableStart:a=!0,isConnectableEnd:u=!0,id:d,onConnect:f,children:g,className:y,onMouseDown:m,onTouchStart:x,...v},_){var Y,V;const S=d||null,C=t==="target",E=He(),N=Og(),{connectOnClick:I,noPanClassName:k,rfId:j}=X_(),{connectingFrom:R,connectingTo:T,clickConnecting:B,isPossibleEndHandle:G,connectionInProcess:U,clickConnectionInProcess:ee,valid:q}=Re(Q_(N,S,t),Xe);N||(V=(Y=E.getState()).onError)==null||V.call(Y,"010",tn.error010());const te=W=>{const{defaultEdgeOptions:D,onConnect:A,hasDefaultEdges:H}=E.getState(),M={...D,...W};if(H){const{edges:L,setEdges:ne,onError:re}=E.getState();ne(b_(M,L,{onError:re}))}A==null||A(M),f==null||f(M)},J=W=>{if(!N)return;const D=fg(W.nativeEvent);if(a&&(D&&W.button===0||!D)){const A=E.getState();qu.onPointerDown(W.nativeEvent,{handleDomNode:W.currentTarget,autoPanOnConnect:A.autoPanOnConnect,connectionMode:A.connectionMode,connectionRadius:A.connectionRadius,domNode:A.domNode,nodeLookup:A.nodeLookup,lib:A.lib,isTarget:C,handleId:S,nodeId:N,flowId:A.rfId,panBy:A.panBy,cancelConnection:A.cancelConnection,onConnectStart:A.onConnectStart,onConnectEnd:(...H)=>{var M,L;return(L=(M=E.getState()).onConnectEnd)==null?void 0:L.call(M,...H)},updateConnection:A.updateConnection,onConnect:te,isValidConnection:o||((...H)=>{var M,L;return((L=(M=E.getState()).isValidConnection)==null?void 0:L.call(M,...H))??!0}),getTransform:()=>E.getState().transform,getFromHandle:()=>E.getState().connection.fromHandle,autoPanSpeed:A.autoPanSpeed,dragThreshold:A.connectionDragThreshold})}D?m==null||m(W):x==null||x(W)},b=W=>{const{onClickConnectStart:D,onClickConnectEnd:A,connectionClickStartHandle:H,connectionMode:M,isValidConnection:L,lib:ne,rfId:re,nodeLookup:ce,connection:fe}=E.getState();if(!N||!H&&!a)return;if(!H){D==null||D(W.nativeEvent,{nodeId:N,handleId:S,handleType:t}),E.setState({connectionClickStartHandle:{nodeId:N,type:t,id:S}});return}const de=cg(W.target),K=o||L,{connection:se,isValid:pe}=qu.isValid(W.nativeEvent,{handle:{nodeId:N,id:S,type:t},connectionMode:M,fromNodeId:H.nodeId,fromHandleId:H.id||null,fromType:H.type,isValidConnection:K,flowId:re,doc:de,lib:ne,nodeLookup:ce});pe&&se&&te(se);const _e=structuredClone(fe);delete _e.inProgress,_e.toPosition=_e.toHandle?_e.toHandle.position:null,A==null||A(W,_e),E.setState({connectionClickStartHandle:null})};return p.jsx("div",{"data-handleid":S,"data-nodeid":N,"data-handlepos":r,"data-id":`${j}-${N}-${S}-${t}`,className:et(["react-flow__handle",`react-flow__handle-${r}`,"nodrag",k,y,{source:!C,target:C,connectable:l,connectablestart:a,connectableend:u,clickconnecting:B,connectingfrom:R,connectingto:T,valid:q,connectionindicator:l&&(!U||G)&&(U||ee?u:a)}]),onMouseDown:J,onTouchStart:J,onClick:I?b:void 0,ref:_,...v,children:g})}const Ei=$.memo(Lg(K_));function q_({data:t,isConnectable:r,sourcePosition:o=Se.Bottom}){return p.jsxs(p.Fragment,{children:[t==null?void 0:t.label,p.jsx(Ei,{type:"source",position:o,isConnectable:r})]})}function Z_({data:t,isConnectable:r,targetPosition:o=Se.Top,sourcePosition:l=Se.Bottom}){return p.jsxs(p.Fragment,{children:[p.jsx(Ei,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label,p.jsx(Ei,{type:"source",position:l,isConnectable:r})]})}function J_(){return null}function eS({data:t,isConnectable:r,targetPosition:o=Se.Top}){return p.jsxs(p.Fragment,{children:[p.jsx(Ei,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label]})}const gl={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},Gh={input:q_,default:Z_,output:eS,group:J_};function tS(t){var r,o,l,a;return t.internals.handleBounds===void 0?{width:t.width??t.initialWidth??((r=t.style)==null?void 0:r.width),height:t.height??t.initialHeight??((o=t.style)==null?void 0:o.height)}:{width:t.width??((l=t.style)==null?void 0:l.width),height:t.height??((a=t.style)==null?void 0:a.height)}}const nS=t=>{const{width:r,height:o,x:l,y:a}=To(t.nodeLookup,{filter:u=>!!u.selected});return{width:Jt(r)?r:null,height:Jt(o)?o:null,userSelectionActive:t.userSelectionActive,transformString:`translate(${t.transform[0]}px,${t.transform[1]}px) scale(${t.transform[2]}) translate(${l}px,${a}px)`}};function rS({onSelectionContextMenu:t,noPanClassName:r,disableKeyboardA11y:o}){const l=He(),{width:a,height:u,transformString:d,userSelectionActive:f}=Re(nS,Xe),g=$g(),y=$.useRef(null);$.useEffect(()=>{var _;o||(_=y.current)==null||_.focus({preventScroll:!0})},[o]);const m=!f&&a!==null&&u!==null;if(Dg({nodeRef:y,disabled:!m}),!m)return null;const x=t?_=>{const S=l.getState().nodes.filter(C=>C.selected);t(_,S)}:void 0,v=_=>{Object.prototype.hasOwnProperty.call(gl,_.key)&&(_.preventDefault(),g({direction:gl[_.key],factor:_.shiftKey?4:1}))};return p.jsx("div",{className:et(["react-flow__nodesselection","react-flow__container",r]),style:{transform:d},children:p.jsx("div",{ref:y,className:"react-flow__nodesselection-rect",onContextMenu:x,tabIndex:o?void 0:-1,onKeyDown:o?void 0:v,style:{width:a,height:u}})})}const Qh=typeof window<"u"?window:void 0,iS=t=>({nodesSelectionActive:t.nodesSelectionActive,userSelectionActive:t.userSelectionActive});function Hg({children:t,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,paneClickDistance:f,deleteKeyCode:g,selectionKeyCode:y,selectionOnDrag:m,selectionMode:x,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:S,panActivationKeyCode:C,zoomActivationKeyCode:E,elementsSelectable:N,zoomOnScroll:I,zoomOnPinch:k,panOnScroll:j,panOnScrollSpeed:R,panOnScrollMode:T,zoomOnDoubleClick:B,panOnDrag:G,autoPanOnSelection:U,defaultViewport:ee,translateExtent:q,minZoom:te,maxZoom:J,preventScrolling:b,onSelectionContextMenu:Y,noWheelClassName:V,noPanClassName:W,disableKeyboardA11y:D,onViewportChange:A,isControlledViewport:H}){const{nodesSelectionActive:M,userSelectionActive:L}=Re(iS,Xe),ne=jo(y,{target:Qh}),re=jo(C,{target:Qh}),ce=re||G,fe=re||j,de=m&&ce!==!0,K=ne||L||de;return z_({deleteKeyCode:g,multiSelectionKeyCode:S}),p.jsx($_,{onPaneContextMenu:u,elementsSelectable:N,zoomOnScroll:I,zoomOnPinch:k,panOnScroll:fe,panActivationKeyPressed:re,panOnScrollSpeed:R,panOnScrollMode:T,zoomOnDoubleClick:B,panOnDrag:!ne&&ce,defaultViewport:ee,translateExtent:q,minZoom:te,maxZoom:J,zoomActivationKeyCode:E,preventScrolling:b,noWheelClassName:V,noPanClassName:W,onViewportChange:A,isControlledViewport:H,paneClickDistance:f,selectionOnDrag:de,children:p.jsxs(B_,{onSelectionStart:v,onSelectionEnd:_,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,panOnDrag:ce,autoPanOnSelection:U,isSelecting:!!K,selectionMode:x,selectionKeyPressed:ne,paneClickDistance:f,selectionOnDrag:de,children:[t,M&&p.jsx(rS,{onSelectionContextMenu:Y,noPanClassName:W,disableKeyboardA11y:D})]})})}Hg.displayName="FlowRenderer";const oS=$.memo(Hg),sS=t=>r=>t?lc(r.nodeLookup,{x:0,y:0,width:r.width,height:r.height},r.transform,!0).map(o=>o.id):Array.from(r.nodeLookup.keys());function lS(t){return Re($.useCallback(sS(t),[t]),Xe)}const aS=t=>t.updateNodeInternals;function uS(){const t=Re(aS),[r]=$.useState(()=>typeof ResizeObserver>"u"?null:new ResizeObserver(o=>{const l=new Map;o.forEach(a=>{const u=a.target.getAttribute("data-id");l.set(u,{id:u,nodeElement:a.target,force:!0})}),t(l)}));return $.useEffect(()=>()=>{r==null||r.disconnect()},[r]),r}function cS({node:t,nodeType:r,hasDimensions:o,resizeObserver:l}){const a=He(),u=$.useRef(null),d=$.useRef(null),f=$.useRef(t.sourcePosition),g=$.useRef(t.targetPosition),y=$.useRef(r),m=o&&!!t.internals.handleBounds;return $.useEffect(()=>{u.current&&!t.hidden&&(!m||d.current!==u.current)&&(d.current&&(l==null||l.unobserve(d.current)),l==null||l.observe(u.current),d.current=u.current)},[m,t.hidden]),$.useEffect(()=>()=>{d.current&&(l==null||l.unobserve(d.current),d.current=null)},[]),$.useEffect(()=>{if(u.current){const x=y.current!==r,v=f.current!==t.sourcePosition,_=g.current!==t.targetPosition;(x||v||_)&&(y.current=r,f.current=t.sourcePosition,g.current=t.targetPosition,a.getState().updateNodeInternals(new Map([[t.id,{id:t.id,nodeElement:u.current,force:!0}]])))}},[t.id,r,t.sourcePosition,t.targetPosition]),u}function dS({id:t,onClick:r,onMouseEnter:o,onMouseMove:l,onMouseLeave:a,onContextMenu:u,onDoubleClick:d,nodesDraggable:f,elementsSelectable:g,nodesConnectable:y,nodesFocusable:m,resizeObserver:x,noDragClassName:v,noPanClassName:_,disableKeyboardA11y:S,rfId:C,nodeTypes:E,nodeClickDistance:N,onError:I}){const{node:k,internals:j,isParent:R}=Re(K=>{const se=K.nodeLookup.get(t),pe=K.parentLookup.has(t);return{node:se,internals:se.internals,isParent:pe}},Xe);let T=k.type||"default",B=(E==null?void 0:E[T])||Gh[T];B===void 0&&(I==null||I("003",tn.error003(T)),T="default",B=(E==null?void 0:E.default)||Gh.default);const G=!!(k.draggable||f&&typeof k.draggable>"u"),U=!!(k.selectable||g&&typeof k.selectable>"u"),ee=!!(k.connectable||y&&typeof k.connectable>"u"),q=!!(k.focusable||m&&typeof k.focusable>"u"),te=He(),J=ag(k),b=cS({node:k,nodeType:T,hasDimensions:J,resizeObserver:x}),Y=Dg({nodeRef:b,disabled:k.hidden||!G,noDragClassName:v,handleSelector:k.dragHandle,nodeId:t,isSelectable:U,nodeClickDistance:N}),V=$g();if(k.hidden)return null;const W=rn(k),D=tS(k),A=U||G||r||o||l||a,H=o?K=>o(K,{...j.userNode}):void 0,M=l?K=>l(K,{...j.userNode}):void 0,L=a?K=>a(K,{...j.userNode}):void 0,ne=u?K=>u(K,{...j.userNode}):void 0,re=d?K=>d(K,{...j.userNode}):void 0,ce=K=>{const{selectNodesOnDrag:se,nodeDragThreshold:pe}=te.getState();U&&(!se||!G||pe>0)&&Zu({id:t,store:te,nodeRef:b}),r&&r(K,{...j.userNode})},fe=K=>{if(!(dg(K.nativeEvent)||S)){if(Zp.includes(K.key)&&U){const se=K.key==="Escape";Zu({id:t,store:te,unselect:se,nodeRef:b})}else if(G&&k.selected&&Object.prototype.hasOwnProperty.call(gl,K.key)){K.preventDefault();const{ariaLabelConfig:se}=te.getState();te.setState({ariaLiveMessage:se["node.a11yDescription.ariaLiveMessage"]({direction:K.key.replace("Arrow","").toLowerCase(),x:~~j.positionAbsolute.x,y:~~j.positionAbsolute.y})}),V({direction:gl[K.key],factor:K.shiftKey?4:1})}}},de=()=>{var Ne;if(S||!((Ne=b.current)!=null&&Ne.matches(":focus-visible")))return;const{transform:K,width:se,height:pe,autoPanOnNodeFocus:_e,setCenter:me}=te.getState();if(!_e)return;lc(new Map([[t,k]]),{x:0,y:0,width:se,height:pe},K,!0).length>0||me(k.position.x+W.width/2,k.position.y+W.height/2,{zoom:K[2]})};return p.jsx("div",{className:et(["react-flow__node",`react-flow__node-${T}`,{[_]:G},k.className,{selected:k.selected,selectable:U,parent:R,draggable:G,dragging:Y}]),ref:b,style:{zIndex:j.z,transform:`translate(${j.positionAbsolute.x}px,${j.positionAbsolute.y}px)`,pointerEvents:A?"all":"none",visibility:J?"visible":"hidden",...k.style,...D},"data-id":t,"data-testid":`rf__node-${t}`,onMouseEnter:H,onMouseMove:M,onMouseLeave:L,onContextMenu:ne,onClick:ce,onDoubleClick:re,onKeyDown:q?fe:void 0,tabIndex:q?0:void 0,onFocus:q?de:void 0,role:k.ariaRole??(q?"group":void 0),"aria-roledescription":"node","aria-describedby":S?void 0:`${Pg}-${C}`,"aria-label":k.ariaLabel,...k.domAttributes,children:p.jsx(U_,{value:t,children:p.jsx(B,{id:t,data:k.data,type:T,positionAbsoluteX:j.positionAbsolute.x,positionAbsoluteY:j.positionAbsolute.y,selected:k.selected??!1,selectable:U,draggable:G,deletable:k.deletable??!0,isConnectable:ee,sourcePosition:k.sourcePosition,targetPosition:k.targetPosition,dragging:Y,dragHandle:k.dragHandle,zIndex:j.z,parentId:k.parentId,...W})})})}var fS=$.memo(dS);const hS=t=>({nodesConnectable:t.nodesConnectable,nodesFocusable:t.nodesFocusable,elementsSelectable:t.elementsSelectable,onError:t.onError});function Bg(t){const{nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,onError:a}=Re(hS,Xe),u=lS(t.onlyRenderVisibleElements),d=uS();return p.jsx("div",{className:"react-flow__nodes",style:bl,children:u.map(f=>p.jsx(fS,{id:f,nodeTypes:t.nodeTypes,nodeExtent:t.nodeExtent,onClick:t.onNodeClick,onMouseEnter:t.onNodeMouseEnter,onMouseMove:t.onNodeMouseMove,onMouseLeave:t.onNodeMouseLeave,onContextMenu:t.onNodeContextMenu,onDoubleClick:t.onNodeDoubleClick,noDragClassName:t.noDragClassName,noPanClassName:t.noPanClassName,rfId:t.rfId,disableKeyboardA11y:t.disableKeyboardA11y,resizeObserver:d,nodesDraggable:t.nodesDraggable??!0,nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,nodeClickDistance:t.nodeClickDistance,onError:a},f))})}Bg.displayName="NodeRenderer";const pS=$.memo(Bg);function gS(t){return Re($.useCallback(o=>{if(!t)return o.edges.map(a=>a.id);const l=[];if(o.width&&o.height)for(const a of o.edges){const u=o.nodeLookup.get(a.source),d=o.nodeLookup.get(a.target);u&&d&&a1({sourceNode:u,targetNode:d,width:o.width,height:o.height,transform:o.transform})&&l.push(a.id)}return l},[t]),Xe)}const mS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t}};return p.jsx("polyline",{className:"arrow",style:o,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},yS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t,fill:t}};return p.jsx("polyline",{className:"arrowclosed",style:o,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},Kh={[Eo.Arrow]:mS,[Eo.ArrowClosed]:yS};function vS(t){const r=He();return $.useMemo(()=>{var a,u;return Object.prototype.hasOwnProperty.call(Kh,t)?Kh[t]:((u=(a=r.getState()).onError)==null||u.call(a,"009",tn.error009(t)),null)},[t])}const xS=({id:t,type:r,color:o,width:l=12.5,height:a=12.5,markerUnits:u="strokeWidth",strokeWidth:d,orient:f="auto-start-reverse"})=>{const g=vS(r);return g?p.jsx("marker",{className:"react-flow__arrowhead",id:t,markerWidth:`${l}`,markerHeight:`${a}`,viewBox:"-10 -10 20 20",markerUnits:u,orient:f,refX:"0",refY:"0",children:p.jsx(g,{color:o,strokeWidth:d})}):null},Vg=({defaultColor:t,rfId:r})=>{const o=Re(u=>u.edges),l=Re(u=>u.defaultEdgeOptions),a=$.useMemo(()=>m1(o,{id:r,defaultColor:t,defaultMarkerStart:l==null?void 0:l.markerStart,defaultMarkerEnd:l==null?void 0:l.markerEnd}),[o,l,r,t]);return a.length?p.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:p.jsx("defs",{children:a.map(u=>p.jsx(xS,{id:u.id,type:u.type,color:u.color,width:u.width,height:u.height,markerUnits:u.markerUnits,strokeWidth:u.strokeWidth,orient:u.orient},u.id))})}):null};Vg.displayName="MarkerDefinitions";var wS=$.memo(Vg);function Ug({x:t,y:r,label:o,labelStyle:l,labelShowBg:a=!0,labelBgStyle:u,labelBgPadding:d=[2,4],labelBgBorderRadius:f=2,children:g,className:y,...m}){const[x,v]=$.useState({x:1,y:0,width:0,height:0}),_=et(["react-flow__edge-textwrapper",y]),S=$.useRef(null);return $.useEffect(()=>{if(S.current){const C=S.current.getBBox();v({x:C.x,y:C.y,width:C.width,height:C.height})}},[o]),o?p.jsxs("g",{transform:`translate(${t-x.width/2} ${r-x.height/2})`,className:_,visibility:x.width?"visible":"hidden",...m,children:[a&&p.jsx("rect",{width:x.width+2*d[0],x:-d[0],y:-d[1],height:x.height+2*d[1],className:"react-flow__edge-textbg",style:u,rx:f,ry:f}),p.jsx("text",{className:"react-flow__edge-text",y:x.height/2,dy:"0.3em",ref:S,style:l,children:o}),g]}):null}Ug.displayName="EdgeText";const _S=$.memo(Ug);function Ml({path:t,labelX:r,labelY:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g,interactionWidth:y=20,...m}){return p.jsxs(p.Fragment,{children:[p.jsx("path",{...m,d:t,fill:"none",className:et(["react-flow__edge-path",m.className])}),y?p.jsx("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:y,className:"react-flow__edge-interaction"}):null,l&&Jt(r)&&Jt(o)?p.jsx(_S,{x:r,y:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g}):null]})}function qh({pos:t,x1:r,y1:o,x2:l,y2:a}){return t===Se.Left||t===Se.Right?[.5*(r+l),o]:[r,.5*(o+a)]}function Wg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top}){const[d,f]=qh({pos:o,x1:t,y1:r,x2:l,y2:a}),[g,y]=qh({pos:u,x1:l,y1:a,x2:t,y2:r}),[m,x,v,_]=hg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:d,sourceControlY:f,targetControlX:g,targetControlY:y});return[`M${t},${r} C${d},${f} ${g},${y} ${l},${a}`,m,x,v,_]}function Yg(t){return $.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d,targetPosition:f,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:C,markerStart:E,interactionWidth:N})=>{const[I,k,j]=Wg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f}),R=t.isInternal?void 0:r;return p.jsx(Ml,{id:R,path:I,labelX:k,labelY:j,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:C,markerStart:E,interactionWidth:N})})}const SS=Yg({isInternal:!1}),Xg=Yg({isInternal:!0});SS.displayName="SimpleBezierEdge";Xg.displayName="SimpleBezierEdgeInternal";function Gg(t){return $.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,sourcePosition:_=Se.Bottom,targetPosition:S=Se.Top,markerEnd:C,markerStart:E,pathOptions:N,interactionWidth:I})=>{const[k,j,R]=Gu({sourceX:o,sourceY:l,sourcePosition:_,targetX:a,targetY:u,targetPosition:S,borderRadius:N==null?void 0:N.borderRadius,offset:N==null?void 0:N.offset,stepPosition:N==null?void 0:N.stepPosition}),T=t.isInternal?void 0:r;return p.jsx(Ml,{id:T,path:k,labelX:j,labelY:R,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:C,markerStart:E,interactionWidth:I})})}const Qg=Gg({isInternal:!1}),Kg=Gg({isInternal:!0});Qg.displayName="SmoothStepEdge";Kg.displayName="SmoothStepEdgeInternal";function qg(t){return $.memo(({id:r,...o})=>{var a;const l=t.isInternal?void 0:r;return p.jsx(Qg,{...o,id:l,pathOptions:$.useMemo(()=>{var u;return{borderRadius:0,offset:(u=o.pathOptions)==null?void 0:u.offset}},[(a=o.pathOptions)==null?void 0:a.offset])})})}const kS=qg({isInternal:!1}),Zg=qg({isInternal:!0});kS.displayName="StepEdge";Zg.displayName="StepEdgeInternal";function Jg(t){return $.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:C})=>{const[E,N,I]=mg({sourceX:o,sourceY:l,targetX:a,targetY:u}),k=t.isInternal?void 0:r;return p.jsx(Ml,{id:k,path:E,labelX:N,labelY:I,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:C})})}const ES=Jg({isInternal:!1}),em=Jg({isInternal:!0});ES.displayName="StraightEdge";em.displayName="StraightEdgeInternal";function tm(t){return $.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d=Se.Bottom,targetPosition:f=Se.Top,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:C,markerStart:E,pathOptions:N,interactionWidth:I})=>{const[k,j,R]=pg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f,curvature:N==null?void 0:N.curvature}),T=t.isInternal?void 0:r;return p.jsx(Ml,{id:T,path:k,labelX:j,labelY:R,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:C,markerStart:E,interactionWidth:I})})}const NS=tm({isInternal:!1}),nm=tm({isInternal:!0});NS.displayName="BezierEdge";nm.displayName="BezierEdgeInternal";const Zh={default:nm,straight:em,step:Zg,smoothstep:Kg,simplebezier:Xg},Jh={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null,zIndex:void 0},CS=(t,r,o)=>o===Se.Left?t-r:o===Se.Right?t+r:t,jS=(t,r,o)=>o===Se.Top?t-r:o===Se.Bottom?t+r:t,ep="react-flow__edgeupdater";function tp({position:t,centerX:r,centerY:o,radius:l=10,onMouseDown:a,onMouseEnter:u,onMouseOut:d,type:f}){return p.jsx("circle",{onMouseDown:a,onMouseEnter:u,onMouseOut:d,className:et([ep,`${ep}-${f}`]),cx:CS(r,l,t),cy:jS(o,l,t),r:l,stroke:"transparent",fill:"transparent"})}function bS({isReconnectable:t,reconnectRadius:r,edge:o,sourceX:l,sourceY:a,targetX:u,targetY:d,sourcePosition:f,targetPosition:g,onReconnect:y,onReconnectStart:m,onReconnectEnd:x,setReconnecting:v,setUpdateHover:_}){const S=He(),C=(j,R)=>{if(j.button!==0)return;const{autoPanOnConnect:T,domNode:B,connectionMode:G,connectionRadius:U,lib:ee,onConnectStart:q,cancelConnection:te,nodeLookup:J,rfId:b,panBy:Y,updateConnection:V}=S.getState(),W=R.type==="target",D=(M,L)=>{v(!1),x==null||x(M,o,R.type,L)},A=M=>y==null?void 0:y(o,M),H=(M,L)=>{v(!0),m==null||m(j,o,R.type),q==null||q(M,L)};qu.onPointerDown(j.nativeEvent,{autoPanOnConnect:T,connectionMode:G,connectionRadius:U,domNode:B,handleId:R.id,nodeId:R.nodeId,nodeLookup:J,isTarget:W,edgeUpdaterType:R.type,lib:ee,flowId:b,cancelConnection:te,panBy:Y,isValidConnection:(...M)=>{var L,ne;return((ne=(L=S.getState()).isValidConnection)==null?void 0:ne.call(L,...M))??!0},onConnect:A,onConnectStart:H,onConnectEnd:(...M)=>{var L,ne;return(ne=(L=S.getState()).onConnectEnd)==null?void 0:ne.call(L,...M)},onReconnectEnd:D,updateConnection:V,getTransform:()=>S.getState().transform,getFromHandle:()=>S.getState().connection.fromHandle,dragThreshold:S.getState().connectionDragThreshold,handleDomNode:j.currentTarget})},E=j=>C(j,{nodeId:o.target,id:o.targetHandle??null,type:"target"}),N=j=>C(j,{nodeId:o.source,id:o.sourceHandle??null,type:"source"}),I=()=>_(!0),k=()=>_(!1);return p.jsxs(p.Fragment,{children:[(t===!0||t==="source")&&p.jsx(tp,{position:f,centerX:l,centerY:a,radius:r,onMouseDown:E,onMouseEnter:I,onMouseOut:k,type:"source"}),(t===!0||t==="target")&&p.jsx(tp,{position:g,centerX:u,centerY:d,radius:r,onMouseDown:N,onMouseEnter:I,onMouseOut:k,type:"target"})]})}function MS({id:t,edgesFocusable:r,edgesReconnectable:o,elementsSelectable:l,onClick:a,onDoubleClick:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,rfId:S,edgeTypes:C,noPanClassName:E,onError:N,disableKeyboardA11y:I}){let k=Re(me=>me.edgeLookup.get(t));const j=Re(me=>me.defaultEdgeOptions);k=j?{...j,...k}:k;let R=k.type||"default",T=(C==null?void 0:C[R])||Zh[R];T===void 0&&(N==null||N("011",tn.error011(R)),R="default",T=(C==null?void 0:C.default)||Zh.default);const B=!!(k.focusable||r&&typeof k.focusable>"u"),G=typeof x<"u"&&(k.reconnectable||o&&typeof k.reconnectable>"u"),U=!!(k.selectable||l&&typeof k.selectable>"u"),ee=$.useRef(null),[q,te]=$.useState(!1),[J,b]=$.useState(!1),Y=He(),{zIndex:V=k.zIndex,sourceX:W,sourceY:D,targetX:A,targetY:H,sourcePosition:M,targetPosition:L}=Re($.useCallback(me=>{const ye=me.nodeLookup.get(k.source),Ne=me.nodeLookup.get(k.target);if(!ye||!Ne)return Jh;const Pe=g1({id:t,sourceNode:ye,targetNode:Ne,sourceHandle:k.sourceHandle||null,targetHandle:k.targetHandle||null,connectionMode:me.connectionMode,onError:N}),je=l1({selected:k.selected,zIndex:k.zIndex,sourceNode:ye,targetNode:Ne,elevateOnSelect:me.elevateEdgesOnSelect,zIndexMode:me.zIndexMode});return{...Pe||Jh,zIndex:je}},[k.source,k.target,k.sourceHandle,k.targetHandle,k.selected,k.zIndex,N]),Xe),ne=$.useMemo(()=>k.markerStart?`url('#${Qu(k.markerStart,S)}')`:void 0,[k.markerStart,S]),re=$.useMemo(()=>k.markerEnd?`url('#${Qu(k.markerEnd,S)}')`:void 0,[k.markerEnd,S]);if(k.hidden||W===null||D===null||A===null||H===null)return null;const ce=me=>{var je;const{addSelectedEdges:ye,unselectNodesAndEdges:Ne,multiSelectionActive:Pe}=Y.getState();U&&(Y.setState({nodesSelectionActive:!1}),k.selected&&Pe?(Ne({nodes:[],edges:[k]}),(je=ee.current)==null||je.blur()):ye([t])),a&&a(me,k)},fe=u?me=>{u(me,{...k})}:void 0,de=d?me=>{d(me,{...k})}:void 0,K=f?me=>{f(me,{...k})}:void 0,se=g?me=>{g(me,{...k})}:void 0,pe=y?me=>{y(me,{...k})}:void 0,_e=me=>{var ye;if(!I&&Zp.includes(me.key)&&U){const{unselectNodesAndEdges:Ne,addSelectedEdges:Pe}=Y.getState();me.key==="Escape"?((ye=ee.current)==null||ye.blur(),Ne({edges:[k]})):Pe([t])}};return p.jsx("svg",{style:{zIndex:V},children:p.jsxs("g",{className:et(["react-flow__edge",`react-flow__edge-${R}`,k.className,E,{selected:k.selected,animated:k.animated,inactive:!U&&!a,updating:q,selectable:U}]),onClick:ce,onDoubleClick:fe,onContextMenu:de,onMouseEnter:K,onMouseMove:se,onMouseLeave:pe,onKeyDown:B?_e:void 0,tabIndex:B?0:void 0,role:k.ariaRole??(B?"group":"img"),"aria-roledescription":"edge","data-id":t,"data-testid":`rf__edge-${t}`,"aria-label":k.ariaLabel===null?void 0:k.ariaLabel||`Edge from ${k.source} to ${k.target}`,"aria-describedby":B?`${Ig}-${S}`:void 0,ref:ee,...k.domAttributes,children:[!J&&p.jsx(T,{id:t,source:k.source,target:k.target,type:k.type,selected:k.selected,animated:k.animated,selectable:U,deletable:k.deletable??!0,label:k.label,labelStyle:k.labelStyle,labelShowBg:k.labelShowBg,labelBgStyle:k.labelBgStyle,labelBgPadding:k.labelBgPadding,labelBgBorderRadius:k.labelBgBorderRadius,sourceX:W,sourceY:D,targetX:A,targetY:H,sourcePosition:M,targetPosition:L,data:k.data,style:k.style,sourceHandleId:k.sourceHandle,targetHandleId:k.targetHandle,markerStart:ne,markerEnd:re,pathOptions:"pathOptions"in k?k.pathOptions:void 0,interactionWidth:k.interactionWidth}),G&&p.jsx(bS,{edge:k,isReconnectable:G,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,sourceX:W,sourceY:D,targetX:A,targetY:H,sourcePosition:M,targetPosition:L,setUpdateHover:te,setReconnecting:b})]})})}var PS=$.memo(MS);const IS=t=>({edgesFocusable:t.edgesFocusable,edgesReconnectable:t.edgesReconnectable,elementsSelectable:t.elementsSelectable,connectionMode:t.connectionMode,onError:t.onError});function rm({defaultMarkerColor:t,onlyRenderVisibleElements:r,rfId:o,edgeTypes:l,noPanClassName:a,onReconnect:u,onEdgeContextMenu:d,onEdgeMouseEnter:f,onEdgeMouseMove:g,onEdgeMouseLeave:y,onEdgeClick:m,reconnectRadius:x,onEdgeDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,disableKeyboardA11y:C}){const{edgesFocusable:E,edgesReconnectable:N,elementsSelectable:I,onError:k}=Re(IS,Xe),j=gS(r);return p.jsxs("div",{className:"react-flow__edges",children:[p.jsx(wS,{defaultColor:t,rfId:o}),j.map(R=>p.jsx(PS,{id:R,edgesFocusable:E,edgesReconnectable:N,elementsSelectable:I,noPanClassName:a,onReconnect:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,onClick:m,reconnectRadius:x,onDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,rfId:o,onError:k,edgeTypes:l,disableKeyboardA11y:C},R))]})}rm.displayName="EdgeRenderer";const TS=$.memo(rm),np=t=>`translate(${t[0]}px,${t[1]}px) scale(${t[2]})`;function RS({children:t}){const r=He(),o=$.useRef(null),[l]=$.useState(()=>r.getState().transform);return zg(()=>{let a=null;const u=()=>{const d=r.getState().transform;a&&d[0]===a[0]&&d[1]===a[1]&&d[2]===a[2]||(a=d,o.current&&(o.current.style.transform=np(d)))};return u(),r.subscribe(u)},[r]),p.jsx("div",{ref:o,className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:np(l)},children:t})}function LS(t){const r=mc(),o=$.useRef(!1);$.useEffect(()=>{!o.current&&r.viewportInitialized&&t&&(setTimeout(()=>t(r),1),o.current=!0)},[t,r.viewportInitialized])}const zS=t=>{var r;return(r=t.panZoom)==null?void 0:r.syncViewport};function AS(t){const r=Re(zS),o=He();return $.useEffect(()=>{t&&(r==null||r(t),o.setState({transform:[t.x,t.y,t.zoom]}))},[t,r]),null}function DS(t){return t.connection.inProgress?{...t.connection,to:Lo(t.connection.to,t.transform)}:{...t.connection}}function $S(t){return DS}function OS(t){const r=$S();return Re(r,Xe)}const FS=t=>({nodesConnectable:t.nodesConnectable,isValid:t.connection.isValid,inProgress:t.connection.inProgress,width:t.width,height:t.height});function HS({containerStyle:t,style:r,type:o,component:l}){const{nodesConnectable:a,width:u,height:d,isValid:f,inProgress:g}=Re(FS,Xe);return!(u&&a&&g)?null:p.jsx("svg",{style:t,width:u,height:d,className:"react-flow__connectionline react-flow__container",children:p.jsx("g",{className:et(["react-flow__connection",tg(f)]),children:p.jsx(im,{style:r,type:o,CustomComponent:l,isValid:f})})})}const im=({style:t,type:r=nr.Bezier,CustomComponent:o,isValid:l})=>{const{inProgress:a,from:u,fromNode:d,fromHandle:f,fromPosition:g,to:y,toNode:m,toHandle:x,toPosition:v,pointer:_}=OS();if(!a)return;if(o)return p.jsx(o,{connectionLineType:r,connectionLineStyle:t,fromNode:d,fromHandle:f,fromX:u.x,fromY:u.y,toX:y.x,toY:y.y,fromPosition:g,toPosition:v,connectionStatus:tg(l),toNode:m,toHandle:x,pointer:_});let S="";const C={sourceX:u.x,sourceY:u.y,sourcePosition:g,targetX:y.x,targetY:y.y,targetPosition:v};switch(r){case nr.Bezier:[S]=pg(C);break;case nr.SimpleBezier:[S]=Wg(C);break;case nr.Step:[S]=Gu({...C,borderRadius:0});break;case nr.SmoothStep:[S]=Gu(C);break;default:[S]=mg(C)}return p.jsx("path",{d:S,fill:"none",className:"react-flow__connection-path",style:t})};im.displayName="ConnectionLine";const BS={};function rp(t=BS){$.useRef(t),He(),$.useEffect(()=>{},[t])}function VS(){He(),$.useRef(!1),$.useEffect(()=>{},[])}function om({nodeTypes:t,edgeTypes:r,onInit:o,onNodeClick:l,onEdgeClick:a,onNodeDoubleClick:u,onEdgeDoubleClick:d,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,onSelectionContextMenu:x,onSelectionStart:v,onSelectionEnd:_,connectionLineType:S,connectionLineStyle:C,connectionLineComponent:E,connectionLineContainerStyle:N,selectionKeyCode:I,selectionOnDrag:k,selectionMode:j,multiSelectionKeyCode:R,panActivationKeyCode:T,zoomActivationKeyCode:B,deleteKeyCode:G,onlyRenderVisibleElements:U,elementsSelectable:ee,defaultViewport:q,translateExtent:te,minZoom:J,maxZoom:b,preventScrolling:Y,defaultMarkerColor:V,zoomOnScroll:W,zoomOnPinch:D,panOnScroll:A,panOnScrollSpeed:H,panOnScrollMode:M,zoomOnDoubleClick:L,panOnDrag:ne,autoPanOnSelection:re,onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneScroll:se,onPaneContextMenu:pe,paneClickDistance:_e,nodeClickDistance:me,onEdgeContextMenu:ye,onEdgeMouseEnter:Ne,onEdgeMouseMove:Pe,onEdgeMouseLeave:je,reconnectRadius:Me,onReconnect:tt,onReconnectStart:Ge,onReconnectEnd:nt,noDragClassName:Ke,noWheelClassName:bt,noPanClassName:Dt,disableKeyboardA11y:ot,nodeExtent:ut,rfId:ct,viewport:ht,onViewportChange:wt,nodesDraggable:Mn}){return rp(t),rp(r),VS(),LS(o),AS(ht),p.jsx(oS,{onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneContextMenu:pe,onPaneScroll:se,paneClickDistance:_e,deleteKeyCode:G,selectionKeyCode:I,selectionOnDrag:k,selectionMode:j,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:R,panActivationKeyCode:T,zoomActivationKeyCode:B,elementsSelectable:ee,zoomOnScroll:W,zoomOnPinch:D,zoomOnDoubleClick:L,panOnScroll:A,panOnScrollSpeed:H,panOnScrollMode:M,panOnDrag:ne,autoPanOnSelection:re,defaultViewport:q,translateExtent:te,minZoom:J,maxZoom:b,onSelectionContextMenu:x,preventScrolling:Y,noDragClassName:Ke,noWheelClassName:bt,noPanClassName:Dt,disableKeyboardA11y:ot,onViewportChange:wt,isControlledViewport:!!ht,children:p.jsxs(RS,{children:[p.jsx(TS,{edgeTypes:r,onEdgeClick:a,onEdgeDoubleClick:d,onReconnect:tt,onReconnectStart:Ge,onReconnectEnd:nt,onlyRenderVisibleElements:U,onEdgeContextMenu:ye,onEdgeMouseEnter:Ne,onEdgeMouseMove:Pe,onEdgeMouseLeave:je,reconnectRadius:Me,defaultMarkerColor:V,noPanClassName:Dt,disableKeyboardA11y:ot,rfId:ct}),p.jsx(HS,{style:C,type:S,component:E,containerStyle:N}),p.jsx("div",{className:"react-flow__edgelabel-renderer"}),p.jsx(pS,{nodeTypes:t,onNodeClick:l,onNodeDoubleClick:u,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,nodeClickDistance:me,onlyRenderVisibleElements:U,noPanClassName:Dt,noDragClassName:Ke,disableKeyboardA11y:ot,nodeExtent:ut,rfId:ct,nodesDraggable:Mn}),p.jsx("div",{className:"react-flow__viewport-portal"})]})})}om.displayName="GraphView";const US=$.memo(om),WS=lg(),ip=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g=.5,maxZoom:y=2,nodeOrigin:m,nodeExtent:x,zIndexMode:v="basic"}={})=>{const _=new Map,S=new Map,C=new Map,E=new Map,N=l??r??[],I=o??t??[],k=m??[0,0],j=x??So;xg(C,E,N);const{nodesInitialized:R}=Ku(I,_,S,{nodeOrigin:k,nodeExtent:j,zIndexMode:v});let T=[0,0,1];if(d&&a&&u){const B=To(_,{filter:q=>!!((q.width||q.initialWidth)&&(q.height||q.initialHeight))}),{x:G,y:U,zoom:ee}=uc(B,a,u,g,y,(f==null?void 0:f.padding)??.1);T=[G,U,ee]}return{rfId:"1",width:a??0,height:u??0,transform:T,nodes:I,nodesInitialized:R,nodeLookup:_,parentLookup:S,edges:N,edgeLookup:E,connectionLookup:C,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:o!==void 0,hasDefaultEdges:l!==void 0,panZoom:null,minZoom:g,maxZoom:y,translateExtent:So,nodeExtent:j,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:wi.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:k,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:d??!1,fitViewOptions:f,fitViewResolver:null,connection:{...eg},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:WS,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:Jp,zIndexMode:v,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},YS=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v})=>i_((_,S)=>{async function C(){const{nodeLookup:E,panZoom:N,fitViewOptions:I,fitViewResolver:k,width:j,height:R,minZoom:T,maxZoom:B}=S();N&&(await e1({nodes:E,width:j,height:R,panZoom:N,minZoom:T,maxZoom:B},I),k==null||k.resolve(!0),_({fitViewResolver:null}))}return{...ip({nodes:t,edges:r,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,defaultNodes:o,defaultEdges:l,zIndexMode:v}),setNodes:E=>{const{nodeLookup:N,parentLookup:I,nodeOrigin:k,nodeExtent:j,elevateNodesOnSelect:R,fitViewQueued:T,zIndexMode:B,nodesSelectionActive:G}=S(),{nodesInitialized:U,hasSelectedNodes:ee}=Ku(E,N,I,{nodeOrigin:k,nodeExtent:j,elevateNodesOnSelect:R,checkEquality:!0,zIndexMode:B}),q=G&ⅇT&&U?(C(),_({nodes:E,nodesInitialized:U,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:q})):_({nodes:E,nodesInitialized:U,nodesSelectionActive:q})},setEdges:E=>{const{connectionLookup:N,edgeLookup:I}=S();xg(N,I,E),_({edges:E})},setDefaultNodesAndEdges:(E,N)=>{if(E){const{setNodes:I}=S();I(E),_({hasDefaultNodes:!0})}if(N){const{setEdges:I}=S();I(N),_({hasDefaultEdges:!0})}},updateNodeInternals:E=>{const{triggerNodeChanges:N,nodeLookup:I,parentLookup:k,domNode:j,nodeOrigin:R,nodeExtent:T,debug:B,fitViewQueued:G,zIndexMode:U}=S(),{changes:ee,updatedInternals:q}=k1(E,I,k,j,R,T,U);q&&(x1(I,k,{nodeOrigin:R,nodeExtent:T,zIndexMode:U}),G?(C(),_({fitViewQueued:!1,fitViewOptions:void 0})):_({}),(ee==null?void 0:ee.length)>0&&(B&&console.log("React Flow: trigger node changes",ee),N==null||N(ee)))},updateNodePositions:(E,N=!1)=>{const I=[];let k=[];const{nodeLookup:j,triggerNodeChanges:R,connection:T,updateConnection:B,onNodesChangeMiddlewareMap:G}=S();for(const[U,ee]of E){const q=j.get(U),te=!!(q!=null&&q.expandParent&&(q!=null&&q.parentId)&&(ee!=null&&ee.position)),J={id:U,type:"position",position:te?{x:Math.max(0,ee.position.x),y:Math.max(0,ee.position.y)}:ee.position,dragging:N};if(q&&T.inProgress&&T.fromNode.id===q.id){const b=Ar(q,T.fromHandle,Se.Left,!0);B({...T,from:b})}te&&q.parentId&&I.push({id:U,parentId:q.parentId,rect:{...ee.internals.positionAbsolute,width:ee.measured.width??0,height:ee.measured.height??0}}),k.push(J)}if(I.length>0){const{parentLookup:U,nodeOrigin:ee}=S(),q=gc(I,j,U,ee);k.push(...q)}for(const U of G.values())k=U(k);R(k)},triggerNodeChanges:E=>{const{onNodesChange:N,setNodes:I,nodes:k,hasDefaultNodes:j,debug:R}=S();if(E!=null&&E.length){if(j){const T=N_(E,k);I(T)}R&&console.log("React Flow: trigger node changes",E),N==null||N(E)}},triggerEdgeChanges:E=>{const{onEdgesChange:N,setEdges:I,edges:k,hasDefaultEdges:j,debug:R}=S();if(E!=null&&E.length){if(j){const T=C_(E,k);I(T)}R&&console.log("React Flow: trigger edge changes",E),N==null||N(E)}},addSelectedNodes:E=>{const{multiSelectionActive:N,edgeLookup:I,nodeLookup:k,triggerNodeChanges:j,triggerEdgeChanges:R}=S();if(N){const T=E.map(B=>br(B,!0));j(T);return}j(gi(k,new Set([...E]),!0)),R(gi(I))},addSelectedEdges:E=>{const{multiSelectionActive:N,edgeLookup:I,nodeLookup:k,triggerNodeChanges:j,triggerEdgeChanges:R}=S();if(N){const T=E.map(B=>br(B,!0));R(T);return}R(gi(I,new Set([...E]))),j(gi(k,new Set,!0))},unselectNodesAndEdges:({nodes:E,edges:N}={})=>{const{edges:I,nodes:k,nodeLookup:j,triggerNodeChanges:R,triggerEdgeChanges:T}=S(),B=E||k,G=N||I,U=[];for(const q of B){if(!q.selected)continue;const te=j.get(q.id);te&&(te.selected=!1),U.push(br(q.id,!1))}const ee=[];for(const q of G)q.selected&&ee.push(br(q.id,!1));R(U),T(ee)},setMinZoom:E=>{const{panZoom:N,maxZoom:I}=S();N==null||N.setScaleExtent([E,I]),_({minZoom:E})},setMaxZoom:E=>{const{panZoom:N,minZoom:I}=S();N==null||N.setScaleExtent([I,E]),_({maxZoom:E})},setTranslateExtent:E=>{var N;(N=S().panZoom)==null||N.setTranslateExtent(E),_({translateExtent:E})},resetSelectedElements:()=>{const{edges:E,nodes:N,triggerNodeChanges:I,triggerEdgeChanges:k,elementsSelectable:j}=S();if(!j)return;const R=N.reduce((B,G)=>G.selected?[...B,br(G.id,!1)]:B,[]),T=E.reduce((B,G)=>G.selected?[...B,br(G.id,!1)]:B,[]);I(R),k(T)},setNodeExtent:E=>{const{nodes:N,nodeLookup:I,parentLookup:k,nodeOrigin:j,elevateNodesOnSelect:R,nodeExtent:T,zIndexMode:B}=S();E[0][0]===T[0][0]&&E[0][1]===T[0][1]&&E[1][0]===T[1][0]&&E[1][1]===T[1][1]||(Ku(N,I,k,{nodeOrigin:j,nodeExtent:E,elevateNodesOnSelect:R,checkEquality:!1,zIndexMode:B}),_({nodeExtent:E}))},panBy:E=>{const{transform:N,width:I,height:k,panZoom:j,translateExtent:R}=S();return E1({delta:E,panZoom:j,transform:N,translateExtent:R,width:I,height:k})},setCenter:async(E,N,I)=>{const{width:k,height:j,maxZoom:R,panZoom:T}=S();if(!T)return!1;const B=typeof(I==null?void 0:I.zoom)<"u"?I.zoom:R;return await T.setViewport({x:k/2-E*B,y:j/2-N*B,zoom:B},{duration:I==null?void 0:I.duration,ease:I==null?void 0:I.ease,interpolate:I==null?void 0:I.interpolate}),!0},cancelConnection:()=>{_({connection:{...eg}})},updateConnection:E=>{_({connection:E})},reset:()=>_({...ip()})}},Object.is);function sm({initialNodes:t,initialEdges:r,defaultNodes:o,defaultEdges:l,initialWidth:a,initialHeight:u,initialMinZoom:d,initialMaxZoom:f,initialFitViewOptions:g,fitView:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v,children:_}){const[S]=$.useState(()=>YS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:y,minZoom:d,maxZoom:f,fitViewOptions:g,nodeOrigin:m,nodeExtent:x,zIndexMode:v}));return p.jsx(o_,{value:S,children:p.jsx(I_,{children:p.jsx(Y_,{children:_})})})}function XS({children:t,nodes:r,edges:o,defaultNodes:l,defaultEdges:a,width:u,height:d,fitView:f,fitViewOptions:g,minZoom:y,maxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_}){return $.useContext(Cl)?p.jsx(p.Fragment,{children:t}):p.jsx(sm,{initialNodes:r,initialEdges:o,defaultNodes:l,defaultEdges:a,initialWidth:u,initialHeight:d,fitView:f,initialFitViewOptions:g,initialMinZoom:y,initialMaxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_,children:t})}const GS={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function QS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,className:a,nodeTypes:u,edgeTypes:d,onNodeClick:f,onEdgeClick:g,onInit:y,onMove:m,onMoveStart:x,onMoveEnd:v,onConnect:_,onConnectStart:S,onConnectEnd:C,onClickConnectStart:E,onClickConnectEnd:N,onNodeMouseEnter:I,onNodeMouseMove:k,onNodeMouseLeave:j,onNodeContextMenu:R,onNodeDoubleClick:T,onNodeDragStart:B,onNodeDrag:G,onNodeDragStop:U,onNodesDelete:ee,onEdgesDelete:q,onDelete:te,onSelectionChange:J,onSelectionDragStart:b,onSelectionDrag:Y,onSelectionDragStop:V,onSelectionContextMenu:W,onSelectionStart:D,onSelectionEnd:A,onBeforeDelete:H,connectionMode:M,connectionLineType:L=nr.Bezier,connectionLineStyle:ne,connectionLineComponent:re,connectionLineContainerStyle:ce,deleteKeyCode:fe="Backspace",selectionKeyCode:de="Shift",selectionOnDrag:K=!1,selectionMode:se=ko.Full,panActivationKeyCode:pe="Space",multiSelectionKeyCode:_e=Co()?"Meta":"Control",zoomActivationKeyCode:me=Co()?"Meta":"Control",snapToGrid:ye,snapGrid:Ne,onlyRenderVisibleElements:Pe=!1,selectNodesOnDrag:je,nodesDraggable:Me,autoPanOnNodeFocus:tt,nodesConnectable:Ge,nodesFocusable:nt,nodeOrigin:Ke=Tg,edgesFocusable:bt,edgesReconnectable:Dt,elementsSelectable:ot=!0,defaultViewport:ut=v_,minZoom:ct=.5,maxZoom:ht=2,translateExtent:wt=So,preventScrolling:Mn=!0,nodeExtent:Ut,defaultMarkerColor:gn="#b1b1b7",zoomOnScroll:Ni=!0,zoomOnPinch:$r=!0,panOnScroll:ir=!1,panOnScrollSpeed:Ci=.5,panOnScrollMode:or=Ir.Free,zoomOnDoubleClick:Pn=!0,panOnDrag:mn=!0,onPaneClick:In,onPaneMouseEnter:sr,onPaneMouseMove:on,onPaneMouseLeave:sn,onPaneScroll:lr,onPaneContextMenu:ar,paneClickDistance:ur=1,nodeClickDistance:cr=0,children:dr,onReconnect:Tn,onReconnectStart:fr,onReconnectEnd:F,onEdgeContextMenu:ae,onEdgeDoubleClick:be,onEdgeMouseEnter:$e,onEdgeMouseMove:Ae,onEdgeMouseLeave:Rn,reconnectRadius:Or=10,onNodesChange:ji,onEdgesChange:Il,noDragClassName:Tl="nodrag",noWheelClassName:Rl="nowheel",noPanClassName:ln="nopan",fitView:bi,fitViewOptions:Mi,connectOnClick:Ll,attributionPosition:zo,proOptions:Ao,defaultEdgeOptions:Do,elevateNodesOnSelect:$o=!0,elevateEdgesOnSelect:zl=!1,disableKeyboardA11y:Oo=!1,autoPanOnConnect:Ue,autoPanOnNodeDrag:Al,autoPanOnSelection:Pi=!0,autoPanSpeed:Fo,connectionRadius:Fr,isValidConnection:Dl,onError:Ho,style:Hr,id:Mt,nodeDragThreshold:$l,connectionDragThreshold:Pt,viewport:Ol,onViewportChange:Fl,width:Hl,height:Br,colorMode:Vr="light",debug:hr,onScroll:yn,ariaLabelConfig:Bl,zIndexMode:Bo="basic",...Ii},Vo){const pr=Mt||"1",gr=S_(Vr),Vl=$.useCallback(Ur=>{Ur.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),yn==null||yn(Ur)},[yn]);return p.jsx("div",{"data-testid":"rf__wrapper",...Ii,onScroll:Vl,style:{...Hr,...GS},ref:Vo,className:et(["react-flow",a,gr]),id:Mt,role:"application",children:p.jsxs(XS,{nodes:t,edges:r,width:Hl,height:Br,fitView:bi,fitViewOptions:Mi,minZoom:ct,maxZoom:ht,nodeOrigin:Ke,nodeExtent:Ut,zIndexMode:Bo,children:[p.jsx(__,{nodes:t,edges:r,defaultNodes:o,defaultEdges:l,onConnect:_,onConnectStart:S,onConnectEnd:C,onClickConnectStart:E,onClickConnectEnd:N,nodesDraggable:Me,autoPanOnNodeFocus:tt,nodesConnectable:Ge,nodesFocusable:nt,edgesFocusable:bt,edgesReconnectable:Dt,elementsSelectable:ot,elevateNodesOnSelect:$o,elevateEdgesOnSelect:zl,minZoom:ct,maxZoom:ht,nodeExtent:Ut,onNodesChange:ji,onEdgesChange:Il,snapToGrid:ye,snapGrid:Ne,connectionMode:M,translateExtent:wt,connectOnClick:Ll,defaultEdgeOptions:Do,fitView:bi,fitViewOptions:Mi,onNodesDelete:ee,onEdgesDelete:q,onDelete:te,onNodeDragStart:B,onNodeDrag:G,onNodeDragStop:U,onSelectionDrag:Y,onSelectionDragStart:b,onSelectionDragStop:V,onMove:m,onMoveStart:x,onMoveEnd:v,noPanClassName:ln,nodeOrigin:Ke,rfId:pr,autoPanOnConnect:Ue,autoPanOnNodeDrag:Al,autoPanSpeed:Fo,onError:Ho,connectionRadius:Fr,isValidConnection:Dl,selectNodesOnDrag:je,nodeDragThreshold:$l,connectionDragThreshold:Pt,onBeforeDelete:H,debug:hr,ariaLabelConfig:Bl,zIndexMode:Bo}),p.jsx(US,{onInit:y,onNodeClick:f,onEdgeClick:g,onNodeMouseEnter:I,onNodeMouseMove:k,onNodeMouseLeave:j,onNodeContextMenu:R,onNodeDoubleClick:T,nodeTypes:u,edgeTypes:d,connectionLineType:L,connectionLineStyle:ne,connectionLineComponent:re,connectionLineContainerStyle:ce,selectionKeyCode:de,selectionOnDrag:K,selectionMode:se,deleteKeyCode:fe,multiSelectionKeyCode:_e,panActivationKeyCode:pe,zoomActivationKeyCode:me,onlyRenderVisibleElements:Pe,defaultViewport:ut,translateExtent:wt,minZoom:ct,maxZoom:ht,preventScrolling:Mn,zoomOnScroll:Ni,zoomOnPinch:$r,zoomOnDoubleClick:Pn,panOnScroll:ir,panOnScrollSpeed:Ci,panOnScrollMode:or,panOnDrag:mn,autoPanOnSelection:Pi,onPaneClick:In,onPaneMouseEnter:sr,onPaneMouseMove:on,onPaneMouseLeave:sn,onPaneScroll:lr,onPaneContextMenu:ar,paneClickDistance:ur,nodeClickDistance:cr,onSelectionContextMenu:W,onSelectionStart:D,onSelectionEnd:A,onReconnect:Tn,onReconnectStart:fr,onReconnectEnd:F,onEdgeContextMenu:ae,onEdgeDoubleClick:be,onEdgeMouseEnter:$e,onEdgeMouseMove:Ae,onEdgeMouseLeave:Rn,reconnectRadius:Or,defaultMarkerColor:gn,noDragClassName:Tl,noWheelClassName:Rl,noPanClassName:ln,rfId:pr,disableKeyboardA11y:Oo,nodeExtent:Ut,viewport:Ol,onViewportChange:Fl,nodesDraggable:Me}),p.jsx(y_,{onSelectionChange:J}),dr,p.jsx(f_,{proOptions:Ao,position:zo}),p.jsx(d_,{rfId:pr,disableKeyboardA11y:Oo})]})})}var KS=Lg(QS);function qS({dimensions:t,lineWidth:r,variant:o,className:l}){return p.jsx("path",{strokeWidth:r,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`,className:et(["react-flow__background-pattern",o,l])})}function ZS({radius:t,className:r}){return p.jsx("circle",{cx:t,cy:t,r:t,className:et(["react-flow__background-pattern","dots",r])})}var rr;(function(t){t.Lines="lines",t.Dots="dots",t.Cross="cross"})(rr||(rr={}));const JS={[rr.Dots]:1,[rr.Lines]:1,[rr.Cross]:6},ek=t=>({transform:t.transform,patternId:`pattern-${t.rfId}`});function lm({id:t,variant:r=rr.Dots,gap:o=20,size:l,lineWidth:a=1,offset:u=0,color:d,bgColor:f,style:g,className:y,patternClassName:m}){const x=$.useRef(null),{transform:v,patternId:_}=Re(ek,Xe),S=l||JS[r],C=r===rr.Dots,E=r===rr.Cross,N=Array.isArray(o)?o:[o,o],I=[N[0]*v[2]||1,N[1]*v[2]||1],k=S*v[2],j=Array.isArray(u)?u:[u,u],R=E?[k,k]:I,T=[j[0]*v[2]+R[0]/2,j[1]*v[2]+R[1]/2],B=`${_}${t||""}`;return p.jsxs("svg",{className:et(["react-flow__background",y]),style:{...g,...bl,"--xy-background-color-props":f,"--xy-background-pattern-color-props":d},ref:x,"data-testid":"rf__background",children:[p.jsx("pattern",{id:B,x:v[0]%I[0],y:v[1]%I[1],width:I[0],height:I[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${T[0]},-${T[1]})`,children:C?p.jsx(ZS,{radius:k/2,className:m}):p.jsx(qS,{dimensions:R,lineWidth:a,variant:r,className:m})}),p.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${B})`})]})}lm.displayName="Background";const tk=$.memo(lm);function nk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:p.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function rk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:p.jsx("path",{d:"M0 0h32v4.2H0z"})})}function ik(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:p.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function ok(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function sk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function Js({children:t,className:r,...o}){return p.jsx("button",{type:"button",className:et(["react-flow__controls-button",r]),...o,children:t})}const lk=t=>({isInteractive:t.nodesDraggable||t.nodesConnectable||t.elementsSelectable,minZoomReached:t.transform[2]<=t.minZoom,maxZoomReached:t.transform[2]>=t.maxZoom,ariaLabelConfig:t.ariaLabelConfig});function am({style:t,showZoom:r=!0,showFitView:o=!0,showInteractive:l=!0,fitViewOptions:a,onZoomIn:u,onZoomOut:d,onFitView:f,onInteractiveChange:g,className:y,children:m,position:x="bottom-left",orientation:v="vertical","aria-label":_}){const S=He(),{isInteractive:C,minZoomReached:E,maxZoomReached:N,ariaLabelConfig:I}=Re(lk,Xe),{zoomIn:k,zoomOut:j,fitView:R}=mc(),T=()=>{k(),u==null||u()},B=()=>{j(),d==null||d()},G=()=>{R(a),f==null||f()},U=()=>{S.setState({nodesDraggable:!C,nodesConnectable:!C,elementsSelectable:!C}),g==null||g(!C)},ee=v==="horizontal"?"horizontal":"vertical";return p.jsxs(jl,{className:et(["react-flow__controls",ee,y]),position:x,style:t,"data-testid":"rf__controls","aria-label":_??I["controls.ariaLabel"],children:[r&&p.jsxs(p.Fragment,{children:[p.jsx(Js,{onClick:T,className:"react-flow__controls-zoomin",title:I["controls.zoomIn.ariaLabel"],"aria-label":I["controls.zoomIn.ariaLabel"],disabled:N,children:p.jsx(nk,{})}),p.jsx(Js,{onClick:B,className:"react-flow__controls-zoomout",title:I["controls.zoomOut.ariaLabel"],"aria-label":I["controls.zoomOut.ariaLabel"],disabled:E,children:p.jsx(rk,{})})]}),o&&p.jsx(Js,{className:"react-flow__controls-fitview",onClick:G,title:I["controls.fitView.ariaLabel"],"aria-label":I["controls.fitView.ariaLabel"],children:p.jsx(ik,{})}),l&&p.jsx(Js,{className:"react-flow__controls-interactive",onClick:U,title:I["controls.interactive.ariaLabel"],"aria-label":I["controls.interactive.ariaLabel"],children:C?p.jsx(sk,{}):p.jsx(ok,{})}),m]})}am.displayName="Controls";const ak=$.memo(am);function uk({id:t,x:r,y:o,width:l,height:a,style:u,color:d,strokeColor:f,strokeWidth:g,className:y,borderRadius:m,shapeRendering:x,selected:v,onClick:_}){const{background:S,backgroundColor:C}=u||{},E=d||S||C;return p.jsx("rect",{className:et(["react-flow__minimap-node",{selected:v},y]),x:r,y:o,rx:m,ry:m,width:l,height:a,style:{fill:E,stroke:f,strokeWidth:g},shapeRendering:x,onClick:_?N=>_(N,t):void 0})}const ck=$.memo(uk),dk=t=>t.nodes.map(r=>r.id),Du=t=>t instanceof Function?t:()=>t;function fk({nodeStrokeColor:t,nodeColor:r,nodeClassName:o="",nodeBorderRadius:l=5,nodeStrokeWidth:a,nodeComponent:u=ck,onClick:d}){const f=Re(dk,Xe),g=Du(r),y=Du(t),m=Du(o),x=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return p.jsx(p.Fragment,{children:f.map(v=>p.jsx(pk,{id:v,nodeColorFunc:g,nodeStrokeColorFunc:y,nodeClassNameFunc:m,nodeBorderRadius:l,nodeStrokeWidth:a,NodeComponent:u,onClick:d,shapeRendering:x},v))})}function hk({id:t,nodeColorFunc:r,nodeStrokeColorFunc:o,nodeClassNameFunc:l,nodeBorderRadius:a,nodeStrokeWidth:u,shapeRendering:d,NodeComponent:f,onClick:g}){const{node:y,x:m,y:x,width:v,height:_}=Re(S=>{const C=S.nodeLookup.get(t);if(!C)return{node:void 0,x:0,y:0,width:0,height:0};const E=C.internals.userNode,{x:N,y:I}=C.internals.positionAbsolute,{width:k,height:j}=rn(E);return{node:E,x:N,y:I,width:k,height:j}},Xe);return!y||y.hidden||!ag(y)?null:p.jsx(f,{x:m,y:x,width:v,height:_,style:y.style,selected:!!y.selected,className:l(y),color:r(y),borderRadius:a,strokeColor:o(y),strokeWidth:u,shapeRendering:d,onClick:g,id:y.id})}const pk=$.memo(hk);var gk=$.memo(fk);const mk=200,yk=150,vk=t=>!t.hidden,xk=t=>{const r={x:-t.transform[0]/t.transform[2],y:-t.transform[1]/t.transform[2],width:t.width/t.transform[2],height:t.height/t.transform[2]};return{viewBB:r,boundingRect:t.nodeLookup.size>0?og(To(t.nodeLookup,{filter:vk}),r):r,rfId:t.rfId,panZoom:t.panZoom,translateExtent:t.translateExtent,flowWidth:t.width,flowHeight:t.height,ariaLabelConfig:t.ariaLabelConfig}},op=(t,r)=>t.x===r.x&&t.y===r.y&&t.width===r.width&&t.height===r.height,wk=(t,r)=>op(t.viewBB,r.viewBB)&&op(t.boundingRect,r.boundingRect)&&t.rfId===r.rfId&&t.panZoom===r.panZoom&&t.translateExtent===r.translateExtent&&t.flowWidth===r.flowWidth&&t.flowHeight===r.flowHeight&&t.ariaLabelConfig===r.ariaLabelConfig,_k="react-flow__minimap-desc";function um({style:t,className:r,nodeStrokeColor:o,nodeColor:l,nodeClassName:a="",nodeBorderRadius:u=5,nodeStrokeWidth:d,nodeComponent:f,bgColor:g,maskColor:y,maskStrokeColor:m,maskStrokeWidth:x,position:v="bottom-right",onClick:_,onNodeClick:S,pannable:C=!1,zoomable:E=!1,ariaLabel:N,inversePan:I,zoomStep:k=1,offsetScale:j=5}){const R=He(),T=$.useRef(null),{boundingRect:B,viewBB:G,rfId:U,panZoom:ee,translateExtent:q,flowWidth:te,flowHeight:J,ariaLabelConfig:b}=Re(xk,wk),Y=(t==null?void 0:t.width)??mk,V=(t==null?void 0:t.height)??yk,W=B.width/Y,D=B.height/V,A=Math.max(W,D),H=A*Y,M=A*V,L=j*A,ne=B.x-(H-B.width)/2-L,re=B.y-(M-B.height)/2-L,ce=H+L*2,fe=M+L*2,de=`${_k}-${U}`,K=$.useRef(0),se=$.useRef();K.current=A,$.useEffect(()=>{if(T.current&&ee)return se.current=R1({domNode:T.current,panZoom:ee,getTransform:()=>R.getState().transform,getViewScale:()=>K.current}),()=>{var ye;(ye=se.current)==null||ye.destroy()}},[ee]),$.useEffect(()=>{var ye;(ye=se.current)==null||ye.update({translateExtent:q,width:te,height:J,inversePan:I,pannable:C,zoomStep:k,zoomable:E})},[C,E,I,k,q,te,J]);const pe=_?ye=>{var je;const[Ne,Pe]=((je=se.current)==null?void 0:je.pointer(ye))||[0,0];_(ye,{x:Ne,y:Pe})}:void 0,_e=S?$.useCallback((ye,Ne)=>{const Pe=R.getState().nodeLookup.get(Ne).internals.userNode;S(ye,Pe)},[]):void 0,me=N??b["minimap.ariaLabel"];return p.jsx(jl,{position:v,style:{...t,"--xy-minimap-background-color-props":typeof g=="string"?g:void 0,"--xy-minimap-mask-background-color-props":typeof y=="string"?y:void 0,"--xy-minimap-mask-stroke-color-props":typeof m=="string"?m:void 0,"--xy-minimap-mask-stroke-width-props":typeof x=="number"?x*A:void 0,"--xy-minimap-node-background-color-props":typeof l=="string"?l:void 0,"--xy-minimap-node-stroke-color-props":typeof o=="string"?o:void 0,"--xy-minimap-node-stroke-width-props":typeof d=="number"?d:void 0},className:et(["react-flow__minimap",r]),"data-testid":"rf__minimap",children:p.jsxs("svg",{width:Y,height:V,viewBox:`${ne} ${re} ${ce} ${fe}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":de,ref:T,onClick:pe,children:[me&&p.jsx("title",{id:de,children:me}),p.jsx(gk,{onClick:_e,nodeColor:l,nodeStrokeColor:o,nodeBorderRadius:u,nodeClassName:a,nodeStrokeWidth:d,nodeComponent:f}),p.jsx("path",{className:"react-flow__minimap-mask",d:`M${ne-L},${re-L}h${ce+L*2}v${fe+L*2}h${-ce-L*2}z - M${G.x},${G.y}h${G.width}v${G.height}h${-G.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}um.displayName="MiniMap";const Sk=$.memo(um),kk=t=>r=>t?`${Math.max(1/r.transform[2],1)}`:void 0,Ek={[ki.Line]:"right",[ki.Handle]:"bottom-right"};function Nk({nodeId:t,position:r,variant:o=ki.Handle,className:l,style:a=void 0,children:u,color:d,minWidth:f=10,minHeight:g=10,maxWidth:y=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:x=!1,resizeDirection:v,autoScale:_=!0,shouldResize:S,onResizeStart:C,onResize:E,onResizeEnd:N}){const I=Og(),k=typeof t=="string"?t:I,j=He(),R=$.useRef(null),T=o===ki.Handle,B=Re($.useCallback(kk(T&&_),[T,_]),Xe),G=$.useRef(null),U=r??Ek[o];$.useEffect(()=>{if(!(!R.current||!k))return G.current||(G.current=Y1({domNode:R.current,nodeId:k,getStoreItems:()=>{const{nodeLookup:q,transform:te,snapGrid:J,snapToGrid:b,nodeOrigin:Y,domNode:V}=j.getState();return{nodeLookup:q,transform:te,snapGrid:J,snapToGrid:b,nodeOrigin:Y,paneDomNode:V}},onChange:(q,te)=>{const{triggerNodeChanges:J,nodeLookup:b,parentLookup:Y,nodeOrigin:V}=j.getState(),W=[],D={x:q.x,y:q.y},A=b.get(k);if(A&&A.expandParent&&A.parentId){const H=A.origin??V,M=q.width??A.measured.width??0,L=q.height??A.measured.height??0,ne={id:A.id,parentId:A.parentId,rect:{width:M,height:L,...ug({x:q.x??A.position.x,y:q.y??A.position.y},{width:M,height:L},A.parentId,b,H)}},re=gc([ne],b,Y,V);W.push(...re),D.x=q.x?Math.max(H[0]*M,q.x):void 0,D.y=q.y?Math.max(H[1]*L,q.y):void 0}if(D.x!==void 0&&D.y!==void 0){const H={id:k,type:"position",position:{...D}};W.push(H)}if(q.width!==void 0&&q.height!==void 0){const M={id:k,type:"dimensions",resizing:!0,setAttributes:v?v==="horizontal"?"width":"height":!0,dimensions:{width:q.width,height:q.height}};W.push(M)}for(const H of te){const M={...H,type:"position"};W.push(M)}J(W)},onEnd:({width:q,height:te})=>{const J={id:k,type:"dimensions",resizing:!1,dimensions:{width:q,height:te}};j.getState().triggerNodeChanges([J])}})),G.current.update({controlPosition:U,boundaries:{minWidth:f,minHeight:g,maxWidth:y,maxHeight:m},keepAspectRatio:x,resizeDirection:v,onResizeStart:C,onResize:E,onResizeEnd:N,shouldResize:S}),()=>{var q;(q=G.current)==null||q.destroy()}},[U,f,g,y,m,x,C,E,N,S]);const ee=U.split("-");return p.jsx("div",{className:et(["react-flow__resize-control","nodrag",...ee,o,l]),ref:R,style:{...a,scale:B,...d&&{[T?"backgroundColor":"borderColor"]:d}},children:u})}$.memo(Nk);const Ck={"arch.context":0,"django.app":0,"django.route":1,"django.url_name":1,"django.view":2,"django.viewset_action":2,"django.permission":2,"django.serializer":3,"django.form":3,"django.serializer_field":4,"django.service":4,"django.model":5,"django.field":6,"django.relation":6,"django.task":7,"django.receiver":7,"django.signal":7,"django.test":7,"django.migration_op":7,"django.admin":7,"openapi.path":8,"react.api_client":9,"react.query_key":10,"react.hook":10,"react.feature":10,"react.route":11,"react.page":11,"react.component":12,"react.form_schema":13,"react.test":13,"react.context":12};function Pl(t){return Ck[t]??8}function jk(t){const r=new Map;for(const l of t){const a=Pl(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r)a.sort((u,d)=>u.name.localeCompare(d.name)),a.forEach((u,d)=>{o.set(u.id,{x:l*260,y:d*108})});return o}const cm=90,bk=new Set(["django.field","django.serializer_field","django.relation","django.test","react.test","django.url_name","django.throttle"]),sp={"arch.context":"#edf2f4","django.app":"#8d99ae","django.route":"#4cc9f0","django.view":"#4895ef","django.viewset_action":"#4361ee","django.permission":"#7b8cde","django.serializer":"#f4a261","django.form":"#e9c46a","django.serializer_field":"#e9c46a","django.service":"#90be6d","django.model":"#2a9d8f","django.field":"#8ac926","django.task":"#e76f51","django.receiver":"#e85d04","django.signal":"#f4a261","django.test":"#6c757d","django.admin":"#adb5bd","django.migration_op":"#9d4edd","openapi.path":"#00bbf9","react.api_client":"#ff6b6b","react.query_key":"#adb5bd","react.hook":"#7b2cbf","react.feature":"#9d4edd","react.route":"#c77dff","react.page":"#c77dff","react.component":"#9d4edd","react.form_schema":"#ffd166","react.test":"#6c757d"},Mk=Math.PI*(3-Math.sqrt(5)),dm=220,Pk=26,Ik={0:"context",1:"routes",2:"views",3:"serializers",4:"services",5:"models",6:"fields",7:"jobs / signals",8:"openapi",9:"api client",10:"hooks",11:"pages",12:"components",13:"forms / tests"};function fm(t){return t.startsWith("react.")?"react":t.startsWith("openapi.")?"stitch":t.startsWith("arch.")?"arch":"django"}function cE(t){return sp[t]?sp[t]:t.startsWith("react.")?"#9d4edd":t.startsWith("openapi.")?"#00bbf9":"#4a5568"}function Tk(t){return t>=cm?"3d":"2d"}function Rk(t){return t>=cm?"overview":"full"}function Lk(t,r,o=1){const l=new Set([t]);let a=new Set([t]);for(let u=0;uo.families.has(fm(f.type)));o.detail==="overview"&&(l=l.filter(f=>!bk.has(f.type)));const a=new Set(l.map(f=>f.id)),u=r.filter(f=>a.has(f.src)&&a.has(f.dst)),d=o.focusId?Lk(o.focusId,u,1):new Set;if(o.neighborhoodOnly&&o.focusId&&d.size){l=l.filter(g=>d.has(g.id));const f=new Set(l.map(g=>g.id));return{nodes:l,edges:u.filter(g=>f.has(g.src)&&f.has(g.dst)),neighborIds:d}}return{nodes:l,edges:u,neighborIds:d}}function dE(t){const r=new Map;for(const l of t){const a=Pl(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r){a.sort((d,f)=>d.name.localeCompare(f.name));const u=l*dm;a.forEach((d,f)=>{if(a.length===1){o.set(d.id,{x:u,y:0,z:0});return}const g=Pk*Math.sqrt(f+1),y=f*Mk;o.set(d.id,{x:u,y:g*Math.cos(y),z:g*Math.sin(y)})})}return o}function fE(t){const r=new Map;for(const o of t){const l=Pl(o.type);r.set(l,(r.get(l)||0)+1)}return[...r.entries()].sort((o,l)=>o[0]-l[0]).map(([o,l])=>({layer:o,x:o*dm,count:l}))}const el=16,Ak=12,Dk=new Set(["django.route","react.route","react.page","django.task","django.migration_op","django.permission","django.throttle","django.admin","django.management_command","openapi.path"]),$k=new Set(["django.serializer","django.serializer_field","django.form","openapi.path","react.form_schema","django.route"]),lp={"arch.context":"Ownership boundary from loadpath.yml — the context this code belongs to.","django.app":"Django app package that owns models, views, and jobs.","django.route":"HTTP URL that publishes a view. A sink: this is where a change becomes a public request.","django.url_name":"Named URL used by reverse() / {% url %} lookups.","django.view":"Request handler (class-based view, function view, or ViewSet).","django.viewset_action":"One ViewSet action (list, create, retrieve, update, destroy).","django.permission":"Auth gate on a view — who is allowed to hit this path.","django.throttle":"Rate-limit class attached to a view.","django.serializer":"Request/response contract: which fields go in and come out.","django.form":"Django form that validates submitted input.","django.serializer_field":"One field on a serializer or form — the typed slot on the contract.","django.service":"Internal service or use-case. Work that is not itself an HTTP sink.","django.model":"ORM model. Schema and relations live here.","django.field":"Model column. Type, indexes, and relations are the contract of the table.","django.relation":"Model-to-model relation (FK / M2M / O2O).","django.task":"Celery or Dramatiq job. Once enqueued, this is a sink.","django.receiver":"Signal handler that runs after a model event.","django.signal":"Django signal that receivers subscribe to.","django.test":"Backend test that mentions symbols on this path.","django.admin":"Django admin class for a model.","django.migration_op":"Schema migration operation (CreateModel, AlterField, …).","django.management_command":"manage.py command — an operational sink.","openapi.path":"Generated OpenAPI operation. The typed HTTP contract between stacks.","react.api_client":"Frontend fetch or generated client call to an API path.","react.query_key":"React Query cache key. Invalidation and reads share this name.","react.hook":"Data hook wrapping query or mutation calls.","react.feature":"Frontend feature module (folder).","react.route":"Client-side route. A sink: this is a URL the user can open.","react.page":"Page or screen component rendered by a route.","react.component":"UI component.","react.form_schema":"Zod (or similar) schema — typed form inputs on the client.","react.test":"Frontend test covering a page, hook, or component.","react.context":"React context provider."},Ok={field_type:"Type",fields:"Fields",form_fields:"Form fields",permissions:"Permissions",throttles:"Throttles",authentication:"Authentication",pagination:"Pagination",filterset:"Filterset",bases:"Extends",on_delete:"on_delete",related_name:"related_name",unique:"Unique",db_index:"Indexed",relation:"Relation field",looks_idempotent_on_pk:"Idempotent on pk",broker:"Broker",route:"Route",url_name:"URL name",view:"View",include:"Includes",mounted_at:"Mounted at",full_path:"Full path",method:"Method",path:"Path",operation_id:"Operation",raw:"URL",kind:"Schema",exclude:"Excludes",queryset_in_serializer:"Queryset in serializer",get_queryset:"Custom get_queryset",get_serializer_class:"Dynamic serializer",dynamic:"Dynamic",fbv:"Function view",ninja:"Django Ninja",django_form:"Django form",mutation:"Mutation",has_error_boundary:"Error boundary",invalidation:"Cache invalidation",inferred:"Inferred stitch",generated:"Generated",shared:"Shared module",element:"Renders",model_name:"Model",field_name:"Field",op:"Operation",app:"App",feature:"Feature",from_view:"From view",mentions:"Mentions",nodeid:"Test id",task:"Task",to:"Related to"},ap=["field_type","method","path","operation_id","raw","route","mounted_at","full_path","url_name","view","element","fields","form_fields","exclude","kind","bases","permissions","authentication","throttles","pagination","filterset","on_delete","related_name","to","unique","db_index","relation","looks_idempotent_on_pk","broker","task","model_name","field_name","op","app","feature","from_view","include","fbv","ninja","django_form","mutation","has_error_boundary","invalidation","inferred","generated","shared","queryset_in_serializer","get_queryset","get_serializer_class","dynamic","mentions","nodeid"],up=new Set(["referenced","placeholder","booted","line","call","from","import","local","source","file","plain_handler","string_ref","pagination_sink","match","via","generated_client","django","react","superseded_by_generated","foreign_app","imported"]),Fk=new Set(["looks_idempotent_on_pk"]),Hk=new Set(["inferred","generated","mutation","fbv","ninja"]);function Bk(t){return lp[t]?lp[t]:t.startsWith("react.")?"A React node on the load path.":t.startsWith("django.")?"A Django node on the load path.":t.startsWith("openapi.")?"A stitch node between Django and React.":"A node on the architecture graph."}function Vk(t,r,o){const l=new Map(r.map(x=>[x.id,x])),a=[];Dk.has(t.type)&&a.push("sink"),$k.has(t.type)&&a.push("contract");const u=t.extra??{};u.inferred&&a.push("inferred"),u.generated&&a.push("generated"),u.mutation&&a.push("mutation"),u.fbv&&a.push("function view"),u.ninja&&a.push("ninja");const d=o.filter(x=>x.dst===t.id),f=o.filter(x=>x.src===t.id),g=d.slice(0,el).map(x=>cp(x,l,x.src)),y=f.slice(0,el).map(x=>cp(x,l,x.dst)),m=t.file_path?`${t.file_path}${t.start_line?`:${t.start_line}`:""}`:void 0;return{type:t.type,typeLabel:yo(yl(t.type)),layer:Ik[Pl(t.type)]??"other",purpose:Bk(t.type),name:t.name,qualifiedName:t.qualified_name,file:m,context:t.context,roles:a,facts:Uk(u).filter(x=>!(x.key==="app"&&x.value===t.context)),inputs:g,outputs:y,extraInputs:Math.max(0,d.length-el),extraOutputs:Math.max(0,f.length-el)}}function cp(t,r,o){const l=r.get(o),a=o.includes(":")?o.slice(o.indexOf(":")+1):o;return{id:o,name:(l==null?void 0:l.name)||a,type:(l==null?void 0:l.type)||"",typeLabel:l?yo(yl(l.type)):"",edgeType:t.type,edgeLabel:yo(t.type),inferred:t.confidence<.8}}function Uk(t){const r=[...ap.filter(a=>a in t),...Object.keys(t).filter(a=>!ap.includes(a)&&!up.has(a))],o=[],l=new Set;for(const a of r){if(l.has(a)||up.has(a)||Hk.has(a))continue;l.add(a);const u=Wk(a,t[a]);u!=null&&o.push({key:a,label:Ok[a]??yo(a),value:u})}return o}function Wk(t,r){if(r==null)return null;if(typeof r=="boolean")return!r&&!Fk.has(t)?null:r?"yes":"no";if(typeof r=="number")return String(r);if(typeof r=="string")return r.trim()||null;if(Array.isArray(r)){const o=r.map(u=>typeof u=="string"||typeof u=="number"?String(u):"").filter(Boolean);if(!o.length)return null;const l=o.slice(0,Ak),a=o.length-l.length;return a>0?`${l.join(", ")} +${a} more`:l.join(", ")}return null}const Yk=$.lazy(()=>m0(()=>import("./LayeredGraph3D-mUQO6wms.js"),[],import.meta.url).then(t=>({default:t.LayeredGraph3D}))),Xk={cheap:"var(--edge-cheap)",expensive:"var(--edge-expensive)",critical:"var(--edge-critical)"};function Gk({data:t,selected:r}){return p.jsxs("div",{className:r?"lp-node selected":"lp-node",children:[p.jsx(Ei,{type:"target",position:Se.Left,isConnectable:!1}),p.jsx("div",{className:"t",children:yl(t.type)}),p.jsx("div",{className:"n",title:t.name,children:t.name}),p.jsx(Ei,{type:"source",position:Se.Right,isConnectable:!1})]})}const Qk={load:Gk},dp=180,fp=56,Kk=new Set(["django","react","stitch","arch"]);function qk(t,r,o=null){const l=new Map(t.map(f=>[f.id,f])),a=jk(t),u=t.map(f=>({id:f.id,type:"load",position:a.get(f.id)??{x:0,y:0},data:{name:f.name,type:f.type,file:f.file_path},selected:o===f.id,sourcePosition:Se.Right,targetPosition:Se.Left,width:dp,height:fp,style:{width:dp,height:fp}})),d=r.filter(f=>l.has(f.src)&&l.has(f.dst)).map(f=>{const g=Xk[f.weight]||"var(--edge-cheap)";return{id:f.id,source:f.src,target:f.dst,type:"smoothstep",animated:f.weight==="critical",style:{stroke:g,strokeWidth:f.weight==="critical"?2.4:1.2,strokeDasharray:f.confidence<.8?"6 4":void 0},markerEnd:{type:Eo.ArrowClosed,width:14,height:14,color:g},label:f.type.replaceAll("_"," "),labelStyle:{fill:"var(--muted)",fontSize:10}}});return{rfNodes:u,rfEdges:d}}function hp({node:t,nodes:r,edges:o,onClose:l}){const a=Vk(t,r,o);return $.useEffect(()=>{const u=d=>{d.key==="Escape"&&l()};return window.addEventListener("keydown",u),()=>window.removeEventListener("keydown",u)},[l]),p.jsxs("aside",{className:"inspector","data-testid":"graph-inspector",children:[p.jsxs("div",{className:"inspector-head",children:[p.jsx("div",{className:"t",children:a.typeLabel}),p.jsx("div",{className:"inspector-roles",children:a.roles.map(u=>p.jsx("span",{className:"inspector-chip",children:u},u))}),p.jsx("button",{type:"button",className:"inspector-close","data-testid":"graph-inspector-close","aria-label":"Close inspector",onClick:l,children:"×"})]}),p.jsx("div",{className:"n",children:pi(a.name)}),p.jsx("p",{className:"inspector-purpose","data-testid":"graph-inspector-purpose",children:a.purpose}),a.context?p.jsx("div",{className:"muted",children:pi(a.context)}):null,a.file?p.jsx("div",{className:"file",children:pi(a.file)}):null,p.jsx("div",{className:"muted",children:pi(a.qualifiedName)}),p.jsxs("div",{className:"muted inspector-layer",children:["layer · ",a.layer]}),a.facts.length?p.jsx("dl",{className:"inspector-facts","data-testid":"graph-inspector-facts",children:a.facts.map(u=>p.jsxs("div",{className:"inspector-fact",children:[p.jsx("dt",{children:u.label}),p.jsx("dd",{children:pi(u.value)})]},u.key))}):null,p.jsx(pp,{title:"Inputs",testId:"graph-inspector-inputs",links:a.inputs,extra:a.extraInputs,empty:"Nothing in this graph points here."}),p.jsx(pp,{title:"Outputs",testId:"graph-inspector-outputs",links:a.outputs,extra:a.extraOutputs,empty:"This node does not point at anything in this graph."})]})}function pp({title:t,testId:r,links:o,extra:l,empty:a}){return p.jsxs("section",{className:"inspector-section","data-testid":r,children:[p.jsxs("h3",{children:[t,p.jsx("span",{className:"count",children:o.length+l})]}),o.length?p.jsx("ul",{children:o.map((u,d)=>p.jsxs("li",{children:[p.jsx("span",{className:"inspector-link-name",title:u.name,children:pi(u.name)}),p.jsxs("span",{className:"inspector-link-meta",children:[u.typeLabel?`${u.typeLabel} · `:"",u.edgeLabel,u.inferred?" · inferred":""]})]},`${u.edgeType}:${u.id}:${d}`))}):p.jsx("p",{className:"muted",children:a}),l?p.jsxs("p",{className:"muted",children:["+",l," more"]}):null]})}function $u({nodes:t,edges:r}){const[o,l]=$.useState(null),[a,u]=$.useState(null),[d,f]=$.useState(null),[g,y]=$.useState(new Set(Kk)),[m,x]=$.useState(!1),v=typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,_=a??Tk(t.length),S=d??Rk(t.length),C=$.useMemo(()=>zk(t,r,{detail:S,families:g,focusId:o,neighborhoodOnly:m&&_==="3d"}),[t,r,S,g,o,m,_]),E=$.useMemo(()=>new Map(C.nodes.map(U=>[U.id,U])),[C.nodes]),N=o?E.get(o)??null:null,{rfNodes:I,rfEdges:k}=$.useMemo(()=>{const U=qk(C.nodes,C.edges,o);return v&&(U.rfEdges=U.rfEdges.map(ee=>({...ee,animated:!1}))),U},[C.nodes,C.edges,o,v]);$.useEffect(()=>{o&&!E.has(o)&&l(null)},[E,o]);const j=(U,ee)=>{l(ee.id)},R=()=>{l(null),x(!1)},T=U=>{y(ee=>{const q=new Set(ee);if(q.has(U)){if(q.size===1)return ee;q.delete(U)}else q.add(U);return q})},B=$.useMemo(()=>{const U=new Set;for(const ee of t)U.add(fm(ee.type));return U},[t]),G=t.length-C.nodes.length;return p.jsxs("div",{className:"impact-graph",style:{flex:1,minHeight:0,position:"relative",display:"flex",flexDirection:"column"},children:[p.jsxs("div",{className:"graph-toolbar","data-testid":"graph-toolbar",children:[p.jsxs("div",{className:"seg","aria-label":"Graph projection",children:[p.jsx("button",{type:"button","data-testid":"graph-view-2d",className:_==="2d"?"active":"","aria-pressed":_==="2d",onClick:()=>u("2d"),children:"2D map"}),p.jsx("button",{type:"button","data-testid":"graph-view-3d",className:_==="3d"?"active":"","aria-pressed":_==="3d",onClick:()=>u("3d"),children:"3D layers"})]}),p.jsxs("div",{className:"seg","aria-label":"Graph detail",children:[p.jsx("button",{type:"button","data-testid":"graph-detail-overview",className:S==="overview"?"active":"","aria-pressed":S==="overview",onClick:()=>f("overview"),children:"Overview"}),p.jsx("button",{type:"button","data-testid":"graph-detail-full",className:S==="full"?"active":"","aria-pressed":S==="full",onClick:()=>f("full"),children:"Full"})]}),p.jsx("div",{className:"seg","aria-label":"Graph families",children:["django","stitch","react"].filter(U=>B.has(U)).map(U=>p.jsx("button",{type:"button","data-testid":`graph-family-${U}`,className:g.has(U)?"active":"","aria-pressed":g.has(U),onClick:()=>T(U),children:U},U))}),_==="3d"?p.jsx("button",{type:"button",className:m?"chip-btn active":"chip-btn","data-testid":"graph-neighborhood",disabled:!o,onClick:()=>x(U=>!U),children:m?"Neighborhood":"Focus neighbors"}):null,p.jsxs("span",{className:"muted graph-count",children:[C.nodes.length," nodes · ",C.edges.length," edges",G?` · ${G} hidden`:""]})]}),p.jsx("div",{className:"graph-stage",children:_==="3d"?p.jsxs("div",{className:"graph-3d","data-testid":"graph-3d",children:[p.jsx("p",{className:"graph-3d-hint",children:"Architecture layers are stacked in depth (Django → stitch → React). Drag to orbit, scroll to zoom, click a node to inspect it."}),p.jsx($.Suspense,{fallback:p.jsx("p",{className:"muted graph-3d-hint",children:"Loading 3D layers…"}),children:p.jsx(Yk,{nodes:C.nodes,edges:C.edges,selectedId:o,neighborIds:C.neighborIds,onSelect:U=>{l(U),U||x(!1)}})}),N?p.jsx(hp,{node:N,nodes:t,edges:r,onClose:R}):null]}):p.jsxs(sm,{children:[p.jsxs(KS,{nodes:I,edges:k,nodeTypes:Qk,fitView:!0,fitViewOptions:{padding:.2,maxZoom:1.15},minZoom:.25,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,deleteKeyCode:null,onNodeClick:j,onPaneClick:R,proOptions:{hideAttribution:!1},"data-testid":"impact-graph",children:[p.jsx(tk,{}),p.jsx(Sk,{pannable:!0,zoomable:!0,ariaLabel:"Impact graph overview",nodeColor:"var(--muted)",nodeStrokeColor:"transparent",nodeStrokeWidth:0,maskColor:"rgba(0, 0, 0, 0.45)",maskStrokeColor:"var(--accent)",maskStrokeWidth:1.4,bgColor:"var(--graph-bg)",style:{width:184,height:128}}),p.jsx(ak,{})]}),N?p.jsx(hp,{node:N,nodes:t,edges:r,onClose:R}):null]})})]})}const gp=[{value:"HEAD",label:"HEAD",group:"preset"},{value:"HEAD~1",label:"HEAD~1",group:"preset"}],Zk=["preset","branch","tag","commit"];function Jk(t){var a;if(!(t!=null&&t.git))return[...gp];const r=((a=t.presets)!=null&&a.length?t.presets:gp.map(u=>u.value)).map(u=>({value:u,label:u,group:"preset"})),o=new Set(r.map(u=>u.value)),l=[...r];for(const u of t.branches||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.current?`${u.name} (current)`:u.name,detail:u.subject,group:"branch"}));for(const u of t.tags||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.name,detail:u.subject,group:"tag"}));for(const u of t.commits||[])o.has(u.sha)||(o.add(u.sha),l.push({value:u.sha,label:u.short,detail:u.subject,group:"commit"}));return l}function eE(t,r){const o=r.trim().toLowerCase();return o?t.filter(l=>l.value.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)||(l.detail||"").toLowerCase().includes(o)):t}function tE(t){return Zk.map(r=>({group:r,items:t.filter(o=>o.group===r)})).filter(r=>r.items.length>0)}function nE(t){return t==="preset"?"Common":t==="branch"?"Branches":t==="tag"?"Tags":"Recent commits"}function mp({value:t,onChange:r,placeholder:o,testId:l,menuTestId:a,refs:u,onNeedRefs:d}){const f=$.useId(),g=$.useRef(null),[y,m]=$.useState(!1),[x,v]=$.useState(null),[_,S]=$.useState(0),C=$.useMemo(()=>{const j=Jk(u);return x===null?j:eE(j,x)},[u,x]),E=$.useMemo(()=>tE(C),[C]);$.useEffect(()=>{y&&d()},[y,d]),$.useEffect(()=>{S(0)},[x,y]);const N=()=>{m(!1),v(null)},I=j=>{r(j.value),N()},k=j=>{if(j.key==="ArrowDown"){if(j.preventDefault(),!y){m(!0);return}S(R=>Math.min(R+1,Math.max(C.length-1,0)))}else if(j.key==="ArrowUp"){if(j.preventDefault(),!y)return;S(R=>Math.max(R-1,0))}else if(j.key==="Enter"&&y){j.preventDefault();const R=C[_];R&&I(R)}else j.key==="Escape"&&y&&(j.preventDefault(),N())};return p.jsxs("div",{className:"combo",ref:g,onBlur:j=>{j.currentTarget.contains(j.relatedTarget)||N()},children:[p.jsxs("div",{className:"combo-row",children:[p.jsx("input",{"data-testid":l,value:t,placeholder:o,spellCheck:!1,role:"combobox","aria-expanded":y,"aria-controls":f,"aria-autocomplete":"list",onChange:j=>{r(j.target.value),y&&v(j.target.value)},onKeyDown:k}),p.jsx("button",{type:"button",className:"icon-btn combo-toggle","data-testid":`${l}-toggle`,"aria-label":"Show recent refs","aria-expanded":y,onMouseDown:j=>j.preventDefault(),onClick:()=>y?N():m(!0),children:p.jsx(h0,{})})]}),y?p.jsx("div",{className:"combo-menu",id:f,role:"listbox","data-testid":a,children:E.length===0?p.jsx("div",{className:"combo-empty muted",children:"No matching refs — the typed value is kept"}):E.map(j=>p.jsxs("div",{className:"combo-group",children:[p.jsx("div",{className:"combo-heading",children:nE(j.group)}),j.items.map(R=>{const T=C.indexOf(R);return p.jsxs("button",{type:"button",role:"option","aria-selected":T===_,className:T===_?"combo-option active":"combo-option","data-testid":`ref-option-${R.group}`,onMouseDown:B=>B.preventDefault(),onMouseEnter:()=>S(T),onClick:()=>I(R),children:[p.jsx("span",{className:"combo-label",children:R.label}),R.detail?p.jsx("span",{className:"combo-detail",children:R.detail}):null]},`${R.group}:${R.value}`)})]},j.group))}):null]})}function rE({initialPath:t,onSelect:r,onClose:o}){const[l,a]=$.useState(null),[u,d]=$.useState(t),[f,g]=$.useState(null),[y,m]=$.useState(""),[x,v]=$.useState(!1),_=$.useRef(null),S=$.useRef(0),C=async k=>{const j=S.current+1;S.current=j,v(!0);try{const R=await Ve.browse(k);if(S.current!==j)return;a(R),d(R.path),g(R.is_git?R.path:null),m("")}catch(R){if(S.current!==j)return;m(R instanceof Error?R.message:String(R))}finally{S.current===j&&v(!1)}};$.useEffect(()=>{var k,j;C(t),(k=_.current)==null||k.focus(),(j=_.current)==null||j.select()},[t]);const E=f||(l==null?void 0:l.path)||u,N=f&&f!==(l==null?void 0:l.path)?f.split(/[\\/]/).filter(Boolean).pop():l!=null&&l.is_git?"this repository":"this folder",I=k=>{k.key==="Escape"&&(k.preventDefault(),o())};return p.jsx("div",{className:"modal-backdrop","data-testid":"repo-explorer","data-overlay":"true",onClick:o,onKeyDown:I,children:p.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"explorer-title",onClick:k=>k.stopPropagation(),children:[p.jsxs("div",{className:"modal-head",children:[p.jsxs("div",{children:[p.jsx("h2",{id:"explorer-title",children:"Select repository"}),p.jsx("p",{className:"muted",children:"Browse to a git root, or paste the full path."})]}),p.jsx("button",{type:"button",className:"btn ghost","data-testid":"explorer-cancel",onClick:o,children:"Cancel"})]}),p.jsxs("form",{className:"explorer-path",onSubmit:k=>{k.preventDefault(),C(u)},children:[p.jsx("input",{ref:_,"data-testid":"explorer-path",value:u,onChange:k=>d(k.target.value),spellCheck:!1,"aria-label":"Directory path"}),p.jsx("button",{type:"button",className:"btn",disabled:!(l!=null&&l.parent),onClick:()=>(l==null?void 0:l.parent)&&void C(l.parent),children:"Up"}),p.jsx("button",{type:"button",className:"btn",onClick:()=>l&&void C(l.home),children:"Home"}),p.jsx("button",{type:"submit",className:"btn",children:"Go"})]}),y?p.jsx("div",{className:"error",role:"alert",children:y}):null,p.jsx("div",{className:"explorer-list",role:"listbox","aria-label":"Folders","aria-busy":x,children:l!=null&&l.entries.length?l.entries.map(k=>{const j=f===k.path;return p.jsxs("button",{type:"button",role:"option","aria-selected":j,className:j?"explorer-row active":"explorer-row","data-testid":"explorer-entry","data-path":k.path,onClick:()=>g(k.path),onDoubleClick:()=>void C(k.path),children:[p.jsx(_p,{}),p.jsx("span",{className:"explorer-name",children:k.name}),k.is_git?p.jsx("span",{className:"chip git-badge",children:"git"}):null]},k.path)}):p.jsx("div",{className:"muted explorer-empty",children:x?"Loading…":"No folders here"})}),p.jsxs("div",{className:"modal-foot",children:[p.jsx("span",{className:"muted explorer-current",title:E,children:E}),p.jsxs("button",{type:"button",className:"btn primary","data-testid":"explorer-use",disabled:!E,onClick:()=>E&&r(E),children:["Use ",N]})]})]})})}const ml=[{id:"obsidian",label:"Obsidian",group:"dark"},{id:"nord",label:"Nord",group:"dark"},{id:"solarized-dark",label:"Solarized Dark",group:"dark"},{id:"forest",label:"Forest",group:"dark"},{id:"rose",label:"Rose Pine",group:"dark"},{id:"amber",label:"Midnight Amber",group:"dark"},{id:"volcano",label:"Volcano",group:"dark"},{id:"lavender",label:"Lavender",group:"dark"},{id:"neon-noir",label:"Neon Noir",group:"dark"},{id:"synthwave",label:"Synthwave",group:"dark"},{id:"phosphor",label:"Phosphor",group:"dark"},{id:"aurora",label:"Aurora",group:"dark"},{id:"biolume",label:"Biolume",group:"dark"},{id:"carbon",label:"Carbon",group:"dark"},{id:"paper",label:"Paper",group:"light"},{id:"solarized-light",label:"Solarized Light",group:"light"},{id:"seafoam",label:"Seafoam",group:"light"},{id:"high-contrast",label:"High Contrast",group:"light"},{id:"sakura",label:"Sakura",group:"light"},{id:"citrus",label:"Citrus",group:"light"},{id:"peach",label:"Peach Fuzz",group:"light"},{id:"candy",label:"Cotton Candy",group:"light"},{id:"sky",label:"Clear Sky",group:"light"},{id:"coral",label:"Coral Reef",group:"light"}],iE="obsidian",hm="loadpath.theme";function oE(t){return ml.some(r=>r.id===t)}function pm(){try{const t=localStorage.getItem(hm)||"";if(oE(t))return t}catch{}return iE}function sE(t){var r;return((r=ml.find(o=>o.id===t))==null?void 0:r.group)==="light"?"light":"dark"}function gm(t){document.documentElement.dataset.theme=t,document.documentElement.style.colorScheme=sE(t);try{localStorage.setItem(hm,t)}catch{}}const yp=[{id:"review",label:"Review",testId:"tab-review",shortcut:"1",icon:a0},{id:"architecture",label:"Architecture",testId:"tab-architecture",shortcut:"2",icon:u0},{id:"graph",label:"Impact graph",testId:"tab-graph",shortcut:"3",icon:c0},{id:"prs",label:"Pull requests",testId:"tab-prs",shortcut:"4",icon:d0},{id:"settings",label:"Settings",testId:"tab-settings",shortcut:"5",icon:f0}];function vp(t,r,o){let l;try{l=new URL(t)}catch{return}if(l.protocol!=="https:"||l.username||l.password)return;const a=l.hostname.toLowerCase();a!==r&&!a.endsWith(`.${r}`)||l.pathname.startsWith(o)&&window.open(l.toString(),"_blank","noopener,noreferrer")}function lE(){var lr,ar,ur,cr,dr,Tn,fr;const[t,r]=$.useState("review"),[o,l]=$.useState(localStorage.getItem("loadpath.repo")||""),[a,u]=$.useState(localStorage.getItem("loadpath.base")||"HEAD~1"),[d,f]=$.useState(localStorage.getItem("loadpath.head")||"HEAD"),[g,y]=$.useState(null),[m,x]=$.useState(null),[v,_]=$.useState([]),[S,C]=$.useState("review"),[E,N]=$.useState(""),[I,k]=$.useState(""),[j,R]=$.useState(""),[T,B]=$.useState({}),[G,U]=$.useState([]),[ee,q]=$.useState([]),[te,J]=$.useState(localStorage.getItem("loadpath.scmRepo")||""),[b,Y]=$.useState(localStorage.getItem("loadpath.provider")||"github"),[V,W]=$.useState(localStorage.getItem("loadpath.prNumber")||""),[D,A]=$.useState(""),[H,M]=$.useState(pm),[L,ne]=$.useState(!1),[re,ce]=$.useState(!1),[fe,de]=$.useState(null),[K,se]=$.useState(null),[pe,_e]=$.useState(!1),me=$.useRef(o);me.current=o;const ye=$.useRef(!1);ye.current=re;const Ne=$.useRef(""),Pe=F=>{M(F),gm(F)},je=$.useRef(""),Me=F=>{je.current=F,k(F)};$.useEffect(()=>{Ve.settings().then(B).catch(()=>{}).finally(()=>ne(!0)),Ve.repos().then(F=>_(F.repos)).catch(()=>{})},[]);const tt=()=>o.trim()?!0:(N("Point at a local repository path first."),!1);$.useEffect(()=>{if(t!=="architecture"||!o.trim())return;const F=o;let ae=!1;return Ve.architecture(F).then(be=>{!ae&&me.current===F&&x(be)}).catch(()=>{}),()=>{ae=!0}},[t,o]);const Ge=F=>{l(F),localStorage.setItem("loadpath.repo",F),F.trim()!==Ne.current&&(Ne.current="",de(null))},nt=$.useCallback(()=>{const F=me.current.trim();!F||Ne.current===F||(Ne.current=F,Ve.gitRefs(F).then(ae=>{me.current.trim()===F&&de(ae)}).catch(()=>{Ne.current===F&&(Ne.current="",de(null))}))},[]),Ke=(F,ae)=>{u(F),f(ae),localStorage.setItem("loadpath.base",F),localStorage.setItem("loadpath.head",ae)},bt=(F,ae,be)=>{Y(F),J(ae),localStorage.setItem("loadpath.provider",F),localStorage.setItem("loadpath.scmRepo",ae),be!==void 0&&(W(be),localStorage.setItem("loadpath.prNumber",be))},Dt=F=>F==="github"?!!T.github_token_set:!!T.bitbucket_token_set,ot=$.useCallback(async(F=b)=>{var ae;try{const be=await Ve.scmRepos(F);q(be.repos),(ae=be.user)!=null&&ae.login&&B($e=>({...$e,...F==="github"?{github_user:be.user.login}:{bitbucket_user:be.user.login}}))}catch{q([])}},[b]);$.useEffect(()=>{if(t!=="prs")return;let F=!1;return ot(b).catch(()=>{F||q([])}),()=>{F=!0}},[t,b,ot]),$.useEffect(()=>{if(!K)return;let F=!1,ae=0;const be=async()=>{try{const $e=await Ve.githubOAuthPoll(K.flow_id);if(F)return;if($e.status==="complete"){se(null);const Ae=await Ve.settings();B(Ae),R($e.user?`Signed in to GitHub as ${$e.user}`:"Signed in to GitHub"),ot("github");return}if($e.status==="pending"||$e.status==="slow_down"){ae=window.setTimeout(be,Math.max($e.interval||K.interval,5)*1e3);return}se(null),N($e.status==="denied"?"GitHub sign-in was denied.":"GitHub sign-in expired. Try again.")}catch($e){if(F)return;se(null),N($e instanceof Error?$e.message:String($e))}};return ae=window.setTimeout(be,Math.max(K.interval,5)*1e3),()=>{F=!0,window.clearTimeout(ae)}},[K,ot]),$.useEffect(()=>{if(!pe)return;let F=!1,ae=0;const be=Date.now(),$e=async()=>{try{const Ae=await Ve.oauthStatus();if(F)return;if(Ae.bitbucket.connected){_e(!1);const Rn=await Ve.settings();B(Rn),R(Ae.bitbucket.user?`Signed in to Bitbucket as ${Ae.bitbucket.user}`:"Signed in to Bitbucket"),ot("bitbucket");return}if(Date.now()-be>18e4){_e(!1),N("Bitbucket sign-in timed out. Finish in the browser, or try again.");return}ae=window.setTimeout($e,1500)}catch(Ae){if(F)return;_e(!1),N(Ae instanceof Error?Ae.message:String(Ae))}};return ae=window.setTimeout($e,1500),()=>{F=!0,window.clearTimeout(ae)}},[pe,ot]);const ut=async(F=o)=>{if(!F.trim())return null;const ae=await Ve.architecture(F);return me.current===F&&x(ae),ae},ct=async()=>{if(!je.current&&tt()){N(""),R(""),Me("Tracing load path…"),Ge(o),Ke(a,d);try{const F=await Ve.review(o,a,d,!0);y(F),C("review"),r("review"),await Ve.repos().then(ae=>_(ae.repos)).catch(()=>{}),await ut(o)}catch(F){N(F instanceof Error?F.message:String(F))}finally{Me("")}}},ht=async(F=!0)=>{if(!je.current&&tt()){N(""),R(""),Me(F?"Indexing…":"Full reindex…"),Ge(o);try{await Ve.index(o,F);const ae=await ut(o);await Ve.repos().then(be=>_(be.repos)).catch(()=>{}),ae!=null&&ae.indexed&&(C("architecture"),r("architecture"))}catch(ae){N(ae instanceof Error?ae.message:String(ae))}finally{Me("")}}},wt=async()=>{if(!je.current&&tt()){N(""),R(""),Me("Detecting layout…"),Ge(o);try{const F=await Ve.init(o);R(F.message),await Ve.repos().then(ae=>_(ae.repos)).catch(()=>{})}catch(F){N(F instanceof Error?F.message:String(F))}finally{Me("")}}},Mn=async()=>{if(g!=null&&g.markdown)try{await navigator.clipboard.writeText(g.markdown),R("Copied markdown brief")}catch(F){N(F instanceof Error?F.message:String(F))}},Ut=async()=>{if(!je.current){if(!(g!=null&&g.markdown)||!te||!V){N("Pick a pull request first (Pull requests tab), then post the brief.");return}Me("Posting Loadpath brief…");try{const F=await Ve.postComment(b,te,Number(V),g.markdown);R(F.updated?"Updated the Loadpath PR comment":"Posted the Loadpath PR comment")}catch(F){N(F instanceof Error?F.message:String(F))}finally{Me("")}}},gn=async()=>{if(!je.current){N(""),Me("Fetching pull requests…");try{const F=await Ve.prs(b,te);U(F.pull_requests);const ae=ee.find(be=>be.slug.toLowerCase()===te.trim().toLowerCase());ae!=null&&ae.local_path&&Ge(ae.local_path)}catch(F){N(F instanceof Error?F.message:String(F))}finally{Me("")}}},Ni=async()=>{N("");try{const F=await Ve.githubOAuthStart();se(F),vp(F.verification_uri_complete,"github.com","/login/device")}catch(F){N(F instanceof Error?F.message:String(F))}},$r=async()=>{N("");try{const F=await Ve.bitbucketOAuthStart();_e(!0),vp(F.authorize_url,"bitbucket.org","/site/oauth2/authorize")}catch(F){_e(!1),N(F instanceof Error?F.message:String(F))}},ir=async F=>{N("");try{B(await Ve.oauthDisconnect(F)),b===F&&q([]),R(`Disconnected ${F}`)}catch(ae){N(ae instanceof Error?ae.message:String(ae))}},Ci=async F=>{F.preventDefault();const ae=new FormData(F.currentTarget),be={github_token:String(ae.get("github_token")||""),github_oauth_client_id:String(ae.get("github_oauth_client_id")||""),bitbucket_token:String(ae.get("bitbucket_token")||""),bitbucket_username:String(ae.get("bitbucket_username")||""),bitbucket_oauth_client_id:String(ae.get("bitbucket_oauth_client_id")||""),bitbucket_oauth_client_secret:String(ae.get("bitbucket_oauth_client_secret")||""),ai_provider:String(ae.get("ai_provider")||"none"),ai_api_key:String(ae.get("ai_api_key")||""),ai_model:String(ae.get("ai_model")||""),ai_base_url:String(ae.get("ai_base_url")||"")},$e=v.length?{...be,workspaces:v.map(Ae=>({path:Ae.path,name:Ae.name}))}:be;try{B(await Ve.saveSettings($e)),R("Settings saved on this machine")}catch(Ae){N(Ae instanceof Error?Ae.message:String(Ae))}},or=async()=>{if(!(!g||je.current)){Me("Residual analysis…");try{const F=await Ve.residual(g);A(F.note)}catch(F){N(F instanceof Error?F.message:String(F))}finally{Me("")}}},Pn=$.useRef(ct);Pn.current=ct;const mn=$.useRef(t);mn.current=t,$.useEffect(()=>{const F=ae=>{if(ye.current){ae.key==="Escape"&&(ae.preventDefault(),ce(!1));return}const be=ae.target;if(be&&(be.tagName==="INPUT"||be.tagName==="TEXTAREA"||be.tagName==="SELECT"||be.isContentEditable)){ae.key==="Escape"&&be.blur();return}if(ae.key==="Escape"){N(""),R("");return}const $e=yp.find(Ae=>Ae.shortcut===ae.key);if($e&&!ae.metaKey&&!ae.ctrlKey&&!ae.altKey&&r($e.id),(ae.metaKey||ae.ctrlKey)&&ae.key==="Enter"){if(mn.current==="settings"||mn.current==="prs"||je.current)return;ae.preventDefault(),Pn.current()}};return window.addEventListener("keydown",F),()=>window.removeEventListener("keydown",F)},[]);const In=$.useMemo(()=>S==="architecture"?(m==null?void 0:m.nodes)??[]:(g==null?void 0:g.nodes)??[],[S,m,g]),sr=$.useMemo(()=>S==="architecture"?(m==null?void 0:m.edges)??[]:(g==null?void 0:g.edges)??[],[S,m,g]),on=g!=null&&g.index?`${g.index.counts.nodes} nodes · ${g.index.counts.edges} edges`:m!=null&&m.indexed?`${m.counts.nodes} nodes · ${m.counts.edges} edges`:"Not indexed",sn=((g==null?void 0:g.findings)||[]).filter(F=>!F.waived);return p.jsxs("div",{className:"app",children:[p.jsx("a",{className:"skip",href:"#main",children:"Skip to content"}),p.jsxs("nav",{className:"rail","data-testid":"rail","aria-label":"Primary",children:[p.jsxs("div",{className:"brand",children:[p.jsx("div",{className:"brand-mark",children:"Loadpath"}),p.jsx("div",{className:"brand-sub",children:"Load-path review"})]}),yp.map(F=>{const ae=F.icon,be=t===F.id;return p.jsxs("button",{type:"button","data-testid":F.testId,className:be?"nav-item active":"nav-item","aria-current":be?"page":void 0,"aria-label":F.label,onClick:()=>r(F.id),children:[p.jsx(ae,{}),p.jsx("span",{children:F.label})]},F.id)}),p.jsxs("div",{className:"theme-pick",children:[p.jsx("label",{htmlFor:"theme-select",children:"Theme"}),p.jsx("select",{id:"theme-select","data-testid":"theme-select",value:H,onChange:F=>Pe(F.target.value),children:["dark","light"].map(F=>p.jsx("optgroup",{label:F==="dark"?"Dark":"Light",children:ml.filter(ae=>ae.group===F).map(ae=>p.jsx("option",{value:ae.id,children:ae.label},ae.id))},F))})]}),p.jsxs("div",{className:"rail-foot",children:[p.jsx("div",{className:"muted",role:"status",children:I||on}),p.jsxs("div",{className:"kbd-hint",children:[p.jsx("kbd",{children:"1"}),"–",p.jsx("kbd",{children:"5"})," tabs · ",p.jsx("kbd",{children:"Ctrl"}),"+",p.jsx("kbd",{children:"Enter"})," review"]})]})]}),p.jsxs("div",{className:"main",id:"main",children:[I?p.jsxs("div",{className:"progress",role:"status","aria-live":"polite","aria-busy":"true",children:[p.jsx("i",{}),p.jsx("span",{className:"sr-only",children:I})]}):null,p.jsxs("header",{className:"topbar","data-testid":"topbar",children:[v.length>0?p.jsxs("label",{className:"field workspace",children:[p.jsx("span",{children:"Workspace"}),p.jsxs("select",{"data-testid":"workspace-select",value:v.some(F=>F.path===o)?o:"",onChange:F=>{F.target.value&&Ge(F.target.value)},children:[p.jsx("option",{value:"",children:"Indexed repos…"}),v.map(F=>p.jsxs("option",{value:F.path,children:[F.name,F.indexed?` (${F.counts.nodes})`:""]},F.path))]})]}):null,p.jsxs("label",{className:"field path",children:[p.jsx("span",{children:"Repository"}),p.jsxs("div",{className:"path-row",children:[p.jsx("input",{"data-testid":"repo-path",placeholder:"Local monorepo path",value:o,onChange:F=>{const ae=F.target.value;l(ae),ae.trim()!==Ne.current&&(Ne.current="",de(null))},spellCheck:!1}),p.jsx("button",{type:"button",className:"icon-btn","data-testid":"btn-browse-repo","aria-label":"Browse for a local repository",onClick:()=>ce(!0),children:p.jsx(_p,{})})]})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Base"}),p.jsx(mp,{testId:"base-ref",menuTestId:"base-ref-menu",value:a,onChange:F=>Ke(F,d),placeholder:"base",refs:fe,onNeedRefs:nt})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Head"}),p.jsx(mp,{testId:"head-ref",menuTestId:"head-ref-menu",value:d,onChange:F=>Ke(a,F),placeholder:"head",refs:fe,onNeedRefs:nt})]}),p.jsxs("div",{className:"topbar-actions",children:[p.jsx("button",{type:"button","data-testid":"btn-init",disabled:!!I,onClick:wt,children:"Draft config"}),p.jsx("button",{type:"button","data-testid":"btn-index",disabled:!!I,onClick:()=>ht(!0),children:"Index"}),p.jsx("button",{type:"button","data-testid":"btn-review",className:"btn primary",disabled:!!I,onClick:ct,children:"Review"})]})]}),p.jsxs("div",{className:"alerts",children:[E?p.jsxs("div",{className:"error","data-testid":"error",role:"alert",children:[p.jsx("span",{children:E}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>N(""),"aria-label":"Dismiss error",children:"×"})]}):null,j?p.jsxs("div",{className:"banner","data-testid":"status-note",children:[p.jsx("span",{children:j}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>R(""),"aria-label":"Dismiss",children:"×"})]}):null,((lr=g==null?void 0:g.index)!=null&&lr.stale||m!=null&&m.stale)&&(t==="review"||t==="architecture")?p.jsx("div",{className:"banner stale","data-testid":"index-stale",children:"Index is stale — files changed since the last extract. Index again before trusting this walk."}):null,((ar=g==null?void 0:g.index)==null?void 0:ar.django_boot)==="failed"||(m==null?void 0:m.django_boot)==="failed"?p.jsx("div",{className:"banner warn","data-testid":"django-boot-failed",children:((ur=g==null?void 0:g.index)==null?void 0:ur.django_boot_detail)||(m==null?void 0:m.django_boot_detail)||"django.setup() failed"}):null,(cr=g==null?void 0:g.workspace)!=null&&cr.dirty_overlaps_review&&t==="review"?p.jsxs("div",{className:"banner warn","data-testid":"dirty-tree",children:["Uncommitted files overlap this review: ",(g.workspace.dirty_overlap||[]).slice(0,6).join(", ")]}):null]}),p.jsxs("div",{className:"stage",children:[t==="review"&&p.jsxs("div",{className:"content","data-testid":"review-layout",children:[p.jsx("aside",{className:"brief","data-testid":"brief",children:g?p.jsx(aE,{review:g,findings:sn,aiNote:D,busy:!!I,onAskAi:or,onCopy:Mn,onPost:Ut}):p.jsxs("div",{className:"empty","data-testid":"review-empty",children:[p.jsx("h2",{children:"Trace the force of this diff"}),p.jsx("p",{children:"The graph is the architecture. The brief is where this change travels — not a hunk list."}),p.jsxs("ol",{children:[p.jsx("li",{children:"Point at a Django + React monorepo, or pick an indexed workspace."}),p.jsxs("li",{children:["Index it. Missing ",p.jsx("code",{children:"loadpath.yml"})," is drafted from ",p.jsx("code",{children:"manage.py"})," and"," ",p.jsx("code",{children:"src/features"}),"."]}),p.jsx("li",{children:"Review a git range, or open a pull request so base/head become a three-dot merge-base."})]})]})}),p.jsx("div",{className:"graph-wrap","data-testid":"review-graph",children:g?p.jsx($u,{nodes:g.nodes,edges:g.edges}):null})]}),t==="architecture"&&p.jsxs("div",{className:"content","data-testid":"architecture-panel",children:[p.jsx("aside",{className:"brief","data-testid":"architecture-brief",children:m!=null&&m.indexed?p.jsx(uE,{architecture:m,busy:!!I,onReindex:()=>ht(!1),onReview:ct}):p.jsx("p",{className:"muted","data-testid":"architecture-empty",children:"Index this repo to build the architecture graph. Review then walks that same graph for a git range — it does not start from a hunk list."})}),p.jsx("div",{className:"graph-wrap","data-testid":"architecture-graph",children:m!=null&&m.indexed?p.jsx($u,{nodes:m.nodes,edges:m.edges}):null})]}),t==="graph"&&p.jsxs("div",{className:"graph-wrap","data-testid":"graph-full",style:{height:"100%"},children:[p.jsxs("div",{className:"graph-modes",children:[p.jsxs("div",{className:"seg","aria-label":"Graph scope",children:[p.jsx("button",{type:"button","aria-pressed":S==="review","data-testid":"graph-mode-review",className:S==="review"?"active":"",onClick:()=>C("review"),children:"This review"}),p.jsx("button",{type:"button","aria-pressed":S==="architecture","data-testid":"graph-mode-architecture",className:S==="architecture"?"active":"",onClick:()=>C("architecture"),children:"Indexed architecture"})]}),p.jsxs("div",{className:"legend","aria-hidden":"true",children:[p.jsxs("span",{children:[p.jsx("i",{})," cheap"]}),p.jsxs("span",{children:[p.jsx("i",{className:"exp"})," expensive"]}),p.jsxs("span",{children:[p.jsx("i",{className:"crit"})," critical"]}),p.jsxs("span",{children:[p.jsx("i",{className:"dash"})," inferred"]})]})]}),In.length?p.jsx($u,{nodes:In,edges:sr}):p.jsx("p",{className:"empty","data-testid":"graph-empty",children:"Index the repo or run a review first. Click a node to inspect it."})]}),t==="prs"&&p.jsxs("div",{className:"pr-list","data-testid":"pr-list",children:[p.jsxs("div",{className:"pr-toolbar",children:[p.jsxs("label",{className:"field provider",children:[p.jsx("span",{children:"Provider"}),p.jsxs("select",{"data-testid":"pr-provider",value:b,onChange:F=>bt(F.target.value,te,V),children:[p.jsx("option",{value:"github",children:"GitHub"}),p.jsx("option",{value:"bitbucket",children:"Bitbucket"})]})]}),p.jsxs("label",{className:"field",children:[p.jsx("span",{children:"Repository"}),p.jsx("input",{"data-testid":"pr-repo",placeholder:ee.length?"Search your repos":"owner/repo",value:te,onChange:F=>bt(b,F.target.value,V),list:"scm-repos",spellCheck:!1}),p.jsx("datalist",{id:"scm-repos",children:ee.map(F=>p.jsxs("option",{value:F.slug,children:[F.private?"private":"public",F.local_path?" · local":""]},F.slug))})]}),p.jsx("button",{type:"button","data-testid":"btn-refresh-repos",className:"btn",disabled:!!I||!Dt(b),onClick:()=>{ot(b)},children:"My repos"}),p.jsx("button",{type:"button","data-testid":"btn-list-prs",className:"btn",disabled:!!I,onClick:gn,children:"List PRs"})]}),ee.length>0?p.jsxs("p",{className:"muted scm-count","data-testid":"scm-repo-count",children:[ee.length," ",b," repositor",ee.length===1?"y":"ies",b==="github"&&T.github_user?` · @${String(T.github_user)}`:"",b==="bitbucket"&&T.bitbucket_user?` · ${String(T.bitbucket_user)}`:""]}):null,G.length===0?p.jsxs("div",{className:"empty","data-testid":"pr-empty",children:[p.jsx("h2",{children:"No pull requests loaded"}),p.jsx("p",{children:"Sign in under Settings (or paste a token), load your repositories, then list open PRs. Reviewing a PR fills base and head from its SHAs."})]}):G.map(F=>p.jsxs("article",{className:"pr","data-testid":`pr-${F.number}`,children:[p.jsxs("h3",{children:["#",F.number," ",F.title]}),p.jsxs("div",{className:"pr-meta muted",children:[p.jsx("span",{className:`chip ${F.draft?"":"open"}`,children:F.draft?"draft":F.state}),p.jsx("span",{children:F.author}),p.jsxs("span",{children:[F.source_branch," → ",F.target_branch]})]}),p.jsxs("div",{className:"pr-actions",children:[p.jsxs("a",{href:F.url,target:"_blank",rel:"noreferrer",children:["Open on ",F.provider]}),p.jsx("button",{type:"button",className:"btn primary","data-testid":`pr-review-${F.number}`,onClick:()=>{Ke(F.base_sha||F.target_branch,F.head_sha||F.source_branch),bt(F.provider,F.repo,String(F.number));const ae=ee.find(be=>be.slug.toLowerCase()===F.repo.toLowerCase());ae!=null&&ae.local_path&&Ge(ae.local_path),r("review")},children:"Review this range"})]})]},`${F.provider}-${F.number}`))]}),t==="settings"&&L&&p.jsxs("form",{className:"settings","data-testid":"settings-form",onSubmit:Ci,children:[p.jsxs("div",{children:[p.jsx("h1",{children:"Settings"}),p.jsx("p",{className:"muted",children:"Tokens stay on this machine in ~/.loadpath/settings.json. AI runs only on residual uncertainty the graph could not close."})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Appearance"}),p.jsx("p",{className:"muted",children:"Local to this browser. High contrast is a first-class theme, not an afterthought."}),p.jsx("div",{className:"theme-grid","data-testid":"theme-grid",children:ml.map(F=>p.jsxs("button",{type:"button","data-theme":F.id,className:H===F.id?"theme-swatch active":"theme-swatch","data-testid":`theme-${F.id}`,onClick:()=>Pe(F.id),children:[p.jsx("div",{className:"swatch-bar","aria-hidden":"true"}),p.jsx("div",{className:"name",children:F.label}),p.jsx("div",{className:"group",children:F.group})]},F.id))})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Source control"}),p.jsx("p",{className:"muted",children:"Sign in with OAuth to list every repository the account can access. Tokens stay in ~/.loadpath/settings.json. A classic PAT still works if you prefer not to register an OAuth app."}),p.jsxs("div",{className:"scm-login","data-testid":"scm-github",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitHub"}),p.jsx("p",{className:"muted",children:T.github_token_set?T.github_user?`Signed in as @${String(T.github_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:T.github_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-github-disconnect",onClick:()=>void ir("github"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-github-login",disabled:!!K||!T.github_oauth_ready,onClick:()=>void Ni(),children:K?"Waiting for GitHub…":"Sign in with GitHub"})})]}),K?p.jsxs("p",{className:"oauth-code","data-testid":"github-user-code",children:["Enter ",p.jsx("code",{children:K.user_code})," at GitHub if the browser did not fill it in."]}):null,T.github_oauth_ready?null:p.jsx("p",{className:"muted",children:"Sign-in needs a GitHub OAuth App with Device Flow enabled. Set LOADPATH_GITHUB_CLIENT_ID or paste the client ID below."}),p.jsx("label",{htmlFor:"github_oauth_client_id",children:"GitHub OAuth client ID"}),p.jsx("input",{id:"github_oauth_client_id",name:"github_oauth_client_id","data-testid":"github-oauth-client-id",placeholder:"Ov23…",defaultValue:String(T.github_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"github_token",children:"GitHub token (optional PAT)"}),p.jsx("input",{id:"github_token",name:"github_token",type:"password",placeholder:"ghp_…",autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-bitbucket",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"Bitbucket"}),p.jsx("p",{className:"muted",children:T.bitbucket_token_set?T.bitbucket_user?`Signed in as ${String(T.bitbucket_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:T.bitbucket_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-bitbucket-disconnect",onClick:()=>void ir("bitbucket"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-bitbucket-login",disabled:pe||!T.bitbucket_oauth_ready,onClick:()=>void $r(),children:pe?"Waiting for Bitbucket…":"Sign in with Bitbucket"})})]}),T.bitbucket_oauth_ready?null:p.jsxs("p",{className:"muted",children:["Sign-in needs a Bitbucket OAuth consumer (key + secret). Callback URL:"," ",p.jsx("code",{children:"/api/oauth/bitbucket/callback"})," on this app origin."]}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_id",children:"Bitbucket OAuth key"}),p.jsx("input",{id:"bitbucket_oauth_client_id",name:"bitbucket_oauth_client_id","data-testid":"bitbucket-oauth-client-id",defaultValue:String(T.bitbucket_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_secret",children:"Bitbucket OAuth secret"}),p.jsx("input",{id:"bitbucket_oauth_client_secret",name:"bitbucket_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_token",children:"Bitbucket token (optional app password)"}),p.jsx("input",{id:"bitbucket_token",name:"bitbucket_token",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_username",children:"Bitbucket username (app passwords)"}),p.jsx("input",{id:"bitbucket_username",name:"bitbucket_username",defaultValue:String(T.bitbucket_username||"")})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Residual AI"}),p.jsx("label",{htmlFor:"ai_provider",children:"Provider"}),p.jsxs("select",{id:"ai_provider",name:"ai_provider",defaultValue:String(((dr=T.ai)==null?void 0:dr.provider)||"none"),children:[p.jsx("option",{value:"none",children:"none (graph only)"}),p.jsx("option",{value:"anthropic",children:"Anthropic"}),p.jsx("option",{value:"openai",children:"OpenAI"}),p.jsx("option",{value:"grok",children:"Grok / xAI"}),p.jsx("option",{value:"deepseek",children:"DeepSeek"}),p.jsx("option",{value:"cursor",children:"Cursor-compatible (OpenAI protocol)"}),p.jsx("option",{value:"ollama",children:"Ollama local"})]}),p.jsx("label",{htmlFor:"ai_api_key",children:"API key"}),p.jsx("input",{id:"ai_api_key",name:"ai_api_key",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"ai_model",children:"Model"}),p.jsx("input",{id:"ai_model",name:"ai_model","data-testid":"ai-model",placeholder:"optional override",defaultValue:String(((Tn=T.ai)==null?void 0:Tn.model)||"")}),p.jsx("label",{htmlFor:"ai_base_url",children:"Base URL"}),p.jsx("input",{id:"ai_base_url",name:"ai_base_url","data-testid":"ai-base-url",placeholder:"optional, OpenAI-compatible",defaultValue:String(((fr=T.ai)==null?void 0:fr.base_url)||"")}),p.jsx("button",{className:"btn primary",type:"submit","data-testid":"btn-save-settings",children:"Save"})]})]})]})]}),re?p.jsx(rE,{initialPath:o,onClose:()=>ce(!1),onSelect:F=>{Ge(F),ce(!1)}}):null]})}function aE({review:t,findings:r,aiNote:o,busy:l,onAskAi:a,onCopy:u,onPost:d}){var g,y,m,x,v,_,S,C;const f=[...new Set(t.confidence.reasons||[])];return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:`merge-box ${t.confidence.level}`,children:[p.jsxs("div",{className:`level ${t.confidence.level}`,children:[t.confidence.level.toUpperCase()," — ",t.title]}),f.length?p.jsx("ul",{className:"reasons",children:f.map(E=>p.jsx("li",{children:E},E))}):null,t.low_risk?p.jsx("span",{className:"chip",children:"low-risk"}):null,t.change_kinds.map(E=>p.jsx("span",{className:"chip",children:yo(E)},E))]}),p.jsxs("div",{className:"metrics",children:[p.jsxs("div",{className:"metric",children:[p.jsxs("div",{className:"n",children:[t.confidence.covered_sinks,"/",t.confidence.sinks]}),p.jsx("div",{className:"l",children:"Sinks tested"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:r.length}),p.jsx("div",{className:"l",children:"Findings"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:t.residuals.length}),p.jsx("div",{className:"l",children:"Residuals"})]})]}),p.jsx("pre",{className:"headline",children:t.headline}),t.index?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Index ",p.jsx("span",{className:"count",children:t.index.counts.nodes})]}),p.jsxs("div",{className:"muted",children:["Walked ",t.index.counts.nodes," nodes / ",t.index.counts.edges," edges",t.index.reindex_skipped?" from an unchanged index":t.index.reindexed?" after an incremental refresh":" from the existing index",t.index.django_boot&&t.index.django_boot!=="off"?` · Django boot ${t.index.django_boot}`:"",(g=t.workspace)!=null&&g.three_dot?" · three-dot range":""]})]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Read this ",p.jsx("span",{className:"count",children:t.read_order.length})]}),t.read_order.map((E,N)=>p.jsxs("div",{className:"read-item",children:[p.jsxs("span",{className:"file",children:[N+1,". ",E.path]}),p.jsx("div",{className:"why",children:E.why})]},E.path))]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Clusters ",p.jsx("span",{className:"count",children:t.clusters.length})]}),t.clusters.map(E=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:E.title})," — ",E.files.join(", ")]},E.id))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Architecture ",p.jsx("span",{className:"count",children:r.length})]}),r.length===0?p.jsx("div",{className:"muted",children:t.architecture_note}):r.map(E=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${E.severity}`,children:E.severity}),E.message]},E.rule+E.message))]}),p.jsx(mm,{cards:t.deepening}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Residual ",p.jsx("span",{className:"count",children:t.residuals.length})]}),p.jsx("p",{className:"muted",children:"AI is only used here, on what the graph could not close."}),t.residuals.map(E=>p.jsx("div",{className:"residual muted",children:E},E))]}),(m=(y=t.evolution)==null?void 0:y.notes)!=null&&m.length||(v=(x=t.evolution)==null?void 0:x.hotspots)!=null&&v.some(E=>E.commits)?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Churn & coupling"}),(((_=t.evolution)==null?void 0:_.notes)||[]).map(E=>p.jsx("div",{className:"muted",children:E},E)),(((S=t.evolution)==null?void 0:S.hotspots)||[]).filter(E=>E.commits).slice(0,6).map(E=>p.jsxs("div",{className:"muted",children:[p.jsx("span",{className:"file",children:E.path})," — ",E.commits," commits, bus factor ",E.bus_factor]},E.path))]}):null,p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:l,onClick:a,children:"Ask configured model"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-copy-markdown",onClick:u,children:"Copy markdown"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-post-comment",onClick:d,children:"Post to PR"})]}),o?p.jsx("pre",{className:"headline",children:o}):null,p.jsx("div",{className:"kicker",children:"Reviewers"}),p.jsx("div",{className:"muted",children:t.suggested_reviewers.join(", ")||"—"}),(C=t.knowledge_owners)!=null&&C.length?p.jsxs("div",{className:"muted",children:["Knowledge: ",t.knowledge_owners.join(", ")]}):null]})}function uE({architecture:t,busy:r,onReindex:o,onReview:l}){const a=t.findings.filter(u=>!u.waived);return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"merge-box high",children:[p.jsxs("div",{className:"level high",children:["INDEXED — ",t.counts.nodes," nodes"]}),p.jsxs("div",{className:"muted",style:{marginTop:8},children:[t.indexed_at?`Last index ${l0(t.indexed_at)}`:"Indexed",t.incremental?" · incremental":" · full",t.stale?" · stale":"",t.django_boot&&t.django_boot!=="off"?` · Django boot ${t.django_boot}`:""]}),p.jsxs("span",{className:"chip",children:[t.counts.edges," edges"]}),t.has_config?p.jsx("span",{className:"chip",children:"loadpath.yml"}):null]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Bounded contexts"}),Object.values(t.contexts).map(u=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:u.name})," — ",(u.django_apps||[]).join(", ")||"no apps"," ·"," ",(u.owners||[]).join(", ")||"unowned"]},u.name))]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Rules ",p.jsx("span",{className:"count",children:(t.rules||[]).length})]}),(t.rules||[]).map(u=>p.jsx("div",{className:"muted",children:u},u))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Findings ",p.jsx("span",{className:"count",children:a.length})]}),a.length===0?p.jsx("div",{className:"muted",children:"No architecture rule hits on the full graph."}):a.map(u=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${u.severity}`,children:u.severity}),u.message]},u.rule+u.message))]}),p.jsx(mm,{cards:t.deepening}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Types"}),p.jsx("table",{className:"type-table",children:p.jsx("tbody",{children:Object.entries(t.type_counts||{}).sort((u,d)=>d[1]-u[1]).slice(0,12).map(([u,d])=>p.jsxs("tr",{children:[p.jsx("td",{children:yl(u)}),p.jsx("td",{children:d})]},u))})})]}),p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:r,onClick:o,"data-testid":"btn-full-reindex",children:"Full reindex"}),p.jsx("button",{type:"button",className:"btn primary",disabled:r,onClick:l,children:"Review against this index"})]})]})}function mm({cards:t}){const r=t||[];return r.length?p.jsxs("details",{className:"section",open:!0,"data-testid":"deepening-list",children:[p.jsxs("summary",{children:["Depth ",p.jsx("span",{className:"count",children:r.length})]}),p.jsx("p",{className:"muted",children:"Deepening opportunities: more behaviour behind a smaller interface, at a real seam."}),r.map(o=>p.jsxs("div",{className:"finding","data-testid":"deepening-card",children:[p.jsx("span",{className:`chip ${o.strength}`,children:s0(o.strength)}),o.top?p.jsx("span",{className:"chip",children:"top"}):null,p.jsx("strong",{children:o.title}),p.jsx("div",{className:"why",children:o.message}),o.deletion_test?p.jsxs("div",{className:"muted",children:["Deletion test: ",o.deletion_test]}):null,o.before&&o.after?p.jsxs("div",{className:"muted",children:[o.before," → ",o.after]}):null]},o.rule+o.title))]}):null}gm(pm());r0.createRoot(document.getElementById("root")).render(p.jsx($.StrictMode,{children:p.jsx(lE,{})}));export{Ik as L,fE as a,cE as c,p as j,dE as l,$ as r,yl as t}; diff --git a/src/loadpath/static/assets/index-D9L1hiqG.js b/src/loadpath/static/assets/index-D9L1hiqG.js new file mode 100644 index 0000000..edd309e --- /dev/null +++ b/src/loadpath/static/assets/index-D9L1hiqG.js @@ -0,0 +1,62 @@ +(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))l(a);new MutationObserver(a=>{for(const u of a)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function o(a){const u={};return a.integrity&&(u.integrity=a.integrity),a.referrerPolicy&&(u.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?u.credentials="include":a.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(a){if(a.ep)return;a.ep=!0;const u=o(a);fetch(a.href,u)}})();function xp(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var wu={exports:{}},vo={},_u={exports:{}},Ie={};/** + * @license React + * react.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Bf;function Qy(){if(Bf)return Ie;Bf=1;var t=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),u=Symbol.for("react.provider"),d=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),x=Symbol.iterator;function v(M){return M===null||typeof M!="object"?null:(M=x&&M[x]||M["@@iterator"],typeof M=="function"?M:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},S=Object.assign,j={};function N(M,R,re){this.props=M,this.context=R,this.refs=j,this.updater=re||_}N.prototype.isReactComponent={},N.prototype.setState=function(M,R){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,R,"setState")},N.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function k(){}k.prototype=N.prototype;function T(M,R,re){this.props=M,this.context=R,this.refs=j,this.updater=re||_}var E=T.prototype=new k;E.constructor=T,S(E,N.prototype),E.isPureReactComponent=!0;var b=Array.isArray,$=Object.prototype.hasOwnProperty,O={current:null},H={key:!0,ref:!0,__self:!0,__source:!0};function I(M,R,re){var ie,ce={},fe=null,de=null;if(R!=null)for(ie in R.ref!==void 0&&(de=R.ref),R.key!==void 0&&(fe=""+R.key),R)$.call(R,ie)&&!H.hasOwnProperty(ie)&&(ce[ie]=R[ie]);var K=arguments.length-2;if(K===1)ce.children=re;else if(1>>1,R=z[M];if(0>>1;Ma(ce,W))fea(de,ce)?(z[M]=de,z[fe]=W,M=fe):(z[M]=ce,z[ie]=W,M=ie);else if(fea(de,W))z[M]=de,z[fe]=W,M=fe;else break e}}return D}function a(z,D){var W=z.sortIndex-D.sortIndex;return W!==0?W:z.id-D.id}if(typeof performance=="object"&&typeof performance.now=="function"){var u=performance;t.unstable_now=function(){return u.now()}}else{var d=Date,f=d.now();t.unstable_now=function(){return d.now()-f}}var g=[],y=[],m=1,x=null,v=3,_=!1,S=!1,j=!1,N=typeof setTimeout=="function"?setTimeout:null,k=typeof clearTimeout=="function"?clearTimeout:null,T=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function E(z){for(var D=o(y);D!==null;){if(D.callback===null)l(y);else if(D.startTime<=z)l(y),D.sortIndex=D.expirationTime,r(g,D);else break;D=o(y)}}function b(z){if(j=!1,E(z),!S)if(o(g)!==null)S=!0,V($);else{var D=o(y);D!==null&&U(b,D.startTime-z)}}function $(z,D){S=!1,j&&(j=!1,k(I),I=-1),_=!0;var W=v;try{for(E(D),x=o(g);x!==null&&(!(x.expirationTime>D)||z&&!G());){var M=x.callback;if(typeof M=="function"){x.callback=null,v=x.priorityLevel;var R=M(x.expirationTime<=D);D=t.unstable_now(),typeof R=="function"?x.callback=R:x===o(g)&&l(g),E(D)}else l(g);x=o(g)}if(x!==null)var re=!0;else{var ie=o(y);ie!==null&&U(b,ie.startTime-D),re=!1}return re}finally{x=null,v=W,_=!1}}var O=!1,H=null,I=-1,q=5,ne=-1;function G(){return!(t.unstable_now()-nez||125M?(z.sortIndex=W,r(y,z),o(g)===null&&z===o(y)&&(j?(k(I),I=-1):j=!0,U(b,W-M))):(z.sortIndex=R,r(g,z),S||_||(S=!0,V($))),z},t.unstable_shouldYield=G,t.unstable_wrapCallback=function(z){var D=v;return function(){var W=v;v=D;try{return z.apply(this,arguments)}finally{v=W}}}})(Eu)),Eu}var Gf;function t0(){return Gf||(Gf=1,ku.exports=e0()),ku.exports}/** + * @license React + * react-dom.production.min.js + * + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Xf;function n0(){if(Xf)return Mt;Xf=1;var t=zo(),r=t0();function o(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,i=1;i"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),g=Object.prototype.hasOwnProperty,y=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,m={},x={};function v(e){return g.call(x,e)?!0:g.call(m,e)?!1:y.test(e)?x[e]=!0:(m[e]=!0,!1)}function _(e,n,i,s){if(i!==null&&i.type===0)return!1;switch(typeof n){case"function":case"symbol":return!0;case"boolean":return s?!1:i!==null?!i.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function S(e,n,i,s){if(n===null||typeof n>"u"||_(e,n,i,s))return!0;if(s)return!1;if(i!==null)switch(i.type){case 3:return!n;case 4:return n===!1;case 5:return isNaN(n);case 6:return isNaN(n)||1>n}return!1}function j(e,n,i,s,c,h,w){this.acceptsBooleans=n===2||n===3||n===4,this.attributeName=s,this.attributeNamespace=c,this.mustUseProperty=i,this.propertyName=e,this.type=n,this.sanitizeURL=h,this.removeEmptyString=w}var N={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){N[e]=new j(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var n=e[0];N[n]=new j(n,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){N[e]=new j(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){N[e]=new j(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){N[e]=new j(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){N[e]=new j(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){N[e]=new j(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){N[e]=new j(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){N[e]=new j(e,5,!1,e.toLowerCase(),null,!1,!1)});var k=/[\-:]([a-z])/g;function T(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var n=e.replace(k,T);N[n]=new j(n,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var n=e.replace(k,T);N[n]=new j(n,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var n=e.replace(k,T);N[n]=new j(n,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){N[e]=new j(e,1,!1,e.toLowerCase(),null,!1,!1)}),N.xlinkHref=new j("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){N[e]=new j(e,1,!1,e.toLowerCase(),null,!0,!0)});function E(e,n,i,s){var c=N.hasOwnProperty(n)?N[n]:null;(c!==null?c.type!==0:s||!(2P||c[w]!==h[P]){var A=` +`+c[w].replace(" at new "," at ");return e.displayName&&A.includes("")&&(A=A.replace("",e.displayName)),A}while(1<=w&&0<=P);break}}}finally{re=!1,Error.prepareStackTrace=i}return(e=e?e.displayName||e.name:"")?R(e):""}function ce(e){switch(e.tag){case 5:return R(e.type);case 16:return R("Lazy");case 13:return R("Suspense");case 19:return R("SuspenseList");case 0:case 2:case 15:return e=ie(e.type,!1),e;case 11:return e=ie(e.type.render,!1),e;case 1:return e=ie(e.type,!0),e;default:return""}}function fe(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case H:return"Fragment";case O:return"Portal";case q:return"Profiler";case I:return"StrictMode";case J:return"Suspense";case C:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case G:return(e.displayName||"Context")+".Consumer";case ne:return(e._context.displayName||"Context")+".Provider";case ee:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Y:return n=e.displayName||null,n!==null?n:fe(e.type)||"Memo";case V:n=e._payload,e=e._init;try{return fe(e(n))}catch{}}return null}function de(e){var n=e.type;switch(e.tag){case 24:return"Cache";case 9:return(n.displayName||"Context")+".Consumer";case 10:return(n._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=n.render,e=e.displayName||e.name||"",n.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return n;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return fe(n);case 8:return n===I?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n}return null}function K(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function le(e){var n=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function pe(e){var n=le(e)?"checked":"value",i=Object.getOwnPropertyDescriptor(e.constructor.prototype,n),s=""+e[n];if(!e.hasOwnProperty(n)&&typeof i<"u"&&typeof i.get=="function"&&typeof i.set=="function"){var c=i.get,h=i.set;return Object.defineProperty(e,n,{configurable:!0,get:function(){return c.call(this)},set:function(w){s=""+w,h.call(this,w)}}),Object.defineProperty(e,n,{enumerable:i.enumerable}),{getValue:function(){return s},setValue:function(w){s=""+w},stopTracking:function(){e._valueTracker=null,delete e[n]}}}}function _e(e){e._valueTracker||(e._valueTracker=pe(e))}function xe(e){if(!e)return!1;var n=e._valueTracker;if(!n)return!0;var i=n.getValue(),s="";return e&&(s=le(e)?e.checked?"true":"false":e.value),e=s,e!==i?(n.setValue(e),!0):!1}function ge(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function je(e,n){var i=n.checked;return W({},n,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:i??e._wrapperState.initialChecked})}function Me(e,n){var i=n.defaultValue==null?"":n.defaultValue,s=n.checked!=null?n.checked:n.defaultChecked;i=K(n.value!=null?n.value:i),e._wrapperState={initialChecked:s,initialValue:i,controlled:n.type==="checkbox"||n.type==="radio"?n.checked!=null:n.value!=null}}function Pe(e,n){n=n.checked,n!=null&&E(e,"checked",n,!1)}function Re(e,n){Pe(e,n);var i=K(n.value),s=n.type;if(i!=null)s==="number"?(i===0&&e.value===""||e.value!=i)&&(e.value=""+i):e.value!==""+i&&(e.value=""+i);else if(s==="submit"||s==="reset"){e.removeAttribute("value");return}n.hasOwnProperty("value")?nt(e,n.type,i):n.hasOwnProperty("defaultValue")&&nt(e,n.type,K(n.defaultValue)),n.checked==null&&n.defaultChecked!=null&&(e.defaultChecked=!!n.defaultChecked)}function tt(e,n,i){if(n.hasOwnProperty("value")||n.hasOwnProperty("defaultValue")){var s=n.type;if(!(s!=="submit"&&s!=="reset"||n.value!==void 0&&n.value!==null))return;n=""+e._wrapperState.initialValue,i||n===e.value||(e.value=n),e.defaultValue=n}i=e.name,i!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,i!==""&&(e.name=i)}function nt(e,n,i){(n!=="number"||ge(e.ownerDocument)!==e)&&(i==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+i&&(e.defaultValue=""+i))}var Qe=Array.isArray;function ot(e,n,i,s){if(e=e.options,n){n={};for(var c=0;c"+n.valueOf().toString()+"",n=Je.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;n.firstChild;)e.appendChild(n.firstChild)}});function wt(e,n){if(n){var i=e.firstChild;if(i&&i===e.lastChild&&i.nodeType===3){i.nodeValue=n;return}}e.textContent=n}var Gt={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},zi=["Webkit","ms","Moz","O"];Object.keys(Gt).forEach(function(e){zi.forEach(function(n){n=n+e.charAt(0).toUpperCase()+e.substring(1),Gt[n]=Gt[e]})});function kt(e,n,i){return n==null||typeof n=="boolean"||n===""?"":i||typeof n!="number"||n===0||Gt.hasOwnProperty(e)&&Gt[e]?(""+n).trim():n+"px"}function hr(e,n){e=e.style;for(var i in n)if(n.hasOwnProperty(i)){var s=i.indexOf("--")===0,c=kt(i,n[i],s);i==="float"&&(i="cssFloat"),s?e.setProperty(i,c):e[i]=c}}var An=W({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function zn(e,n){if(n){if(An[e]&&(n.children!=null||n.dangerouslySetInnerHTML!=null))throw Error(o(137,e));if(n.dangerouslySetInnerHTML!=null){if(n.children!=null)throw Error(o(60));if(typeof n.dangerouslySetInnerHTML!="object"||!("__html"in n.dangerouslySetInnerHTML))throw Error(o(61))}if(n.style!=null&&typeof n.style!="object")throw Error(o(62))}}function pr(e,n){if(e.indexOf("-")===-1)return typeof n.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var gr=null;function mr(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var yr=null,un=null,cn=null;function Ur(e){if(e=no(e)){if(typeof yr!="function")throw Error(o(280));var n=e.stateNode;n&&(n=us(n),yr(e.stateNode,e.type,n))}}function Dn(e){un?cn?cn.push(e):cn=[e]:un=e}function Yr(){if(un){var e=un,n=cn;if(cn=un=null,Ur(e),n)for(e=0;e>>=0,e===0?32:31-(Ol(e)/Fl|0)|0}var Jr=64,ei=4194304;function wr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function kn(e,n){var i=e.pendingLanes;if(i===0)return 0;var s=0,c=e.suspendedLanes,h=e.pingedLanes,w=i&268435455;if(w!==0){var P=w&~c;P!==0?s=wr(P):(h&=w,h!==0&&(s=wr(h)))}else w=i&~c,w!==0?s=wr(w):h!==0&&(s=wr(h));if(s===0)return 0;if(n!==0&&n!==s&&(n&c)===0&&(c=s&-s,h=n&-n,c>=h||c===16&&(h&4194240)!==0))return n;if((s&4)!==0&&(s|=i&16),n=e.entangledLanes,n!==0)for(e=e.entanglements,n&=s;0i;i++)n.push(e);return n}function Sr(e,n,i){e.pendingLanes|=n,n!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,n=31-Lt(n),e[n]=i}function Vl(e,n){var i=e.pendingLanes&~n;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=n,e.mutableReadLanes&=n,e.entangledLanes&=n,n=e.entanglements;var s=e.eventTimes;for(e=e.expirationTimes;0=Gi),Lc=" ",Ac=!1;function zc(e,n){switch(e){case"keyup":return Um.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Dc(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ii=!1;function Gm(e,n){switch(e){case"compositionend":return Dc(n);case"keypress":return n.which!==32?null:(Ac=!0,Lc);case"textInput":return e=n.data,e===Lc&&Ac?null:e;default:return null}}function Xm(e,n){if(ii)return e==="compositionend"||!ea&&zc(e,n)?(e=Cc(),Zo=Xl=Gn=null,ii=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:i,offset:n-e};e=s}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=Wc(i)}}function Yc(e,n){return e&&n?e===n?!0:e&&e.nodeType===3?!1:n&&n.nodeType===3?Yc(e,n.parentNode):"contains"in e?e.contains(n):e.compareDocumentPosition?!!(e.compareDocumentPosition(n)&16):!1:!1}function Gc(){for(var e=window,n=ge();n instanceof e.HTMLIFrameElement;){try{var i=typeof n.contentWindow.location.href=="string"}catch{i=!1}if(i)e=n.contentWindow;else break;n=ge(e.document)}return n}function ra(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n&&(n==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||n==="textarea"||e.contentEditable==="true")}function ry(e){var n=Gc(),i=e.focusedElem,s=e.selectionRange;if(n!==i&&i&&i.ownerDocument&&Yc(i.ownerDocument.documentElement,i)){if(s!==null&&ra(i)){if(n=s.start,e=s.end,e===void 0&&(e=n),"selectionStart"in i)i.selectionStart=n,i.selectionEnd=Math.min(e,i.value.length);else if(e=(n=i.ownerDocument||document)&&n.defaultView||window,e.getSelection){e=e.getSelection();var c=i.textContent.length,h=Math.min(s.start,c);s=s.end===void 0?h:Math.min(s.end,c),!e.extend&&h>s&&(c=s,s=h,h=c),c=Uc(i,h);var w=Uc(i,s);c&&w&&(e.rangeCount!==1||e.anchorNode!==c.node||e.anchorOffset!==c.offset||e.focusNode!==w.node||e.focusOffset!==w.offset)&&(n=n.createRange(),n.setStart(c.node,c.offset),e.removeAllRanges(),h>s?(e.addRange(n),e.extend(w.node,w.offset)):(n.setEnd(w.node,w.offset),e.addRange(n)))}}for(n=[],e=i;e=e.parentNode;)e.nodeType===1&&n.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof i.focus=="function"&&i.focus(),i=0;i=document.documentMode,oi=null,ia=null,Ki=null,oa=!1;function Xc(e,n,i){var s=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;oa||oi==null||oi!==ge(s)||(s=oi,"selectionStart"in s&&ra(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),Ki&&Qi(Ki,s)||(Ki=s,s=ss(ia,"onSelect"),0ci||(e.current=ya[ci],ya[ci]=null,ci--)}function Fe(e,n){ci++,ya[ci]=e.current,e.current=n}var Kn={},mt=Qn(Kn),Et=Qn(!1),Er=Kn;function di(e,n){var i=e.type.contextTypes;if(!i)return Kn;var s=e.stateNode;if(s&&s.__reactInternalMemoizedUnmaskedChildContext===n)return s.__reactInternalMemoizedMaskedChildContext;var c={},h;for(h in i)c[h]=n[h];return s&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=n,e.__reactInternalMemoizedMaskedChildContext=c),c}function Nt(e){return e=e.childContextTypes,e!=null}function cs(){Be(Et),Be(mt)}function ud(e,n,i){if(mt.current!==Kn)throw Error(o(168));Fe(mt,n),Fe(Et,i)}function cd(e,n,i){var s=e.stateNode;if(n=n.childContextTypes,typeof s.getChildContext!="function")return i;s=s.getChildContext();for(var c in s)if(!(c in n))throw Error(o(108,de(e)||"Unknown",c));return W({},i,s)}function ds(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Kn,Er=mt.current,Fe(mt,e),Fe(Et,Et.current),!0}function dd(e,n,i){var s=e.stateNode;if(!s)throw Error(o(169));i?(e=cd(e,n,Er),s.__reactInternalMemoizedMergedChildContext=e,Be(Et),Be(mt),Fe(mt,e)):Be(Et),Fe(Et,i)}var Nn=null,fs=!1,va=!1;function fd(e){Nn===null?Nn=[e]:Nn.push(e)}function gy(e){fs=!0,fd(e)}function Zn(){if(!va&&Nn!==null){va=!0;var e=0,n=Oe;try{var i=Nn;for(Oe=1;e>=w,c-=w,jn=1<<32-Lt(n)+c|i<be?(dt=Ne,Ne=null):dt=Ne.sibling;var De=oe(X,Ne,Q[be],ue);if(De===null){Ne===null&&(Ne=dt);break}e&&Ne&&De.alternate===null&&n(X,Ne),B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De,Ne=dt}if(be===Q.length)return i(X,Ne),Ue&&jr(X,be),we;if(Ne===null){for(;bebe?(dt=Ne,Ne=null):dt=Ne.sibling;var lr=oe(X,Ne,De.value,ue);if(lr===null){Ne===null&&(Ne=dt);break}e&&Ne&&lr.alternate===null&&n(X,Ne),B=h(lr,B,be),Ee===null?we=lr:Ee.sibling=lr,Ee=lr,Ne=dt}if(De.done)return i(X,Ne),Ue&&jr(X,be),we;if(Ne===null){for(;!De.done;be++,De=Q.next())De=ae(X,De.value,ue),De!==null&&(B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De);return Ue&&jr(X,be),we}for(Ne=s(X,Ne);!De.done;be++,De=Q.next())De=he(Ne,X,be,De.value,ue),De!==null&&(e&&De.alternate!==null&&Ne.delete(De.key===null?be:De.key),B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De);return e&&Ne.forEach(function(qy){return n(X,qy)}),Ue&&jr(X,be),we}function et(X,B,Q,ue){if(typeof Q=="object"&&Q!==null&&Q.type===H&&Q.key===null&&(Q=Q.props.children),typeof Q=="object"&&Q!==null){switch(Q.$$typeof){case $:e:{for(var we=Q.key,Ee=B;Ee!==null;){if(Ee.key===we){if(we=Q.type,we===H){if(Ee.tag===7){i(X,Ee.sibling),B=c(Ee,Q.props.children),B.return=X,X=B;break e}}else if(Ee.elementType===we||typeof we=="object"&&we!==null&&we.$$typeof===V&&vd(we)===Ee.type){i(X,Ee.sibling),B=c(Ee,Q.props),B.ref=ro(X,Ee,Q),B.return=X,X=B;break e}i(X,Ee);break}else n(X,Ee);Ee=Ee.sibling}Q.type===H?(B=Lr(Q.props.children,X.mode,ue,Q.key),B.return=X,X=B):(ue=Fs(Q.type,Q.key,Q.props,null,X.mode,ue),ue.ref=ro(X,B,Q),ue.return=X,X=ue)}return w(X);case O:e:{for(Ee=Q.key;B!==null;){if(B.key===Ee)if(B.tag===4&&B.stateNode.containerInfo===Q.containerInfo&&B.stateNode.implementation===Q.implementation){i(X,B.sibling),B=c(B,Q.children||[]),B.return=X,X=B;break e}else{i(X,B);break}else n(X,B);B=B.sibling}B=gu(Q,X.mode,ue),B.return=X,X=B}return w(X);case V:return Ee=Q._init,et(X,B,Ee(Q._payload),ue)}if(Qe(Q))return ye(X,B,Q,ue);if(D(Q))return ve(X,B,Q,ue);ms(X,Q)}return typeof Q=="string"&&Q!==""||typeof Q=="number"?(Q=""+Q,B!==null&&B.tag===6?(i(X,B.sibling),B=c(B,Q),B.return=X,X=B):(i(X,B),B=pu(Q,X.mode,ue),B.return=X,X=B),w(X)):i(X,B)}return et}var gi=xd(!0),wd=xd(!1),ys=Qn(null),vs=null,mi=null,Ea=null;function Na(){Ea=mi=vs=null}function ja(e){var n=ys.current;Be(ys),e._currentValue=n}function ba(e,n,i){for(;e!==null;){var s=e.alternate;if((e.childLanes&n)!==n?(e.childLanes|=n,s!==null&&(s.childLanes|=n)):s!==null&&(s.childLanes&n)!==n&&(s.childLanes|=n),e===i)break;e=e.return}}function yi(e,n){vs=e,Ea=mi=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&n)!==0&&(jt=!0),e.firstContext=null)}function Vt(e){var n=e._currentValue;if(Ea!==e)if(e={context:e,memoizedValue:n,next:null},mi===null){if(vs===null)throw Error(o(308));mi=e,vs.dependencies={lanes:0,firstContext:e}}else mi=mi.next=e;return n}var br=null;function Ca(e){br===null?br=[e]:br.push(e)}function _d(e,n,i,s){var c=n.interleaved;return c===null?(i.next=i,Ca(n)):(i.next=c.next,c.next=i),n.interleaved=i,Cn(e,s)}function Cn(e,n){e.lanes|=n;var i=e.alternate;for(i!==null&&(i.lanes|=n),i=e,e=e.return;e!==null;)e.childLanes|=n,i=e.alternate,i!==null&&(i.childLanes|=n),i=e,e=e.return;return i.tag===3?i.stateNode:null}var Jn=!1;function Ma(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Sd(e,n){e=e.updateQueue,n.updateQueue===e&&(n.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Mn(e,n){return{eventTime:e,lane:n,tag:0,payload:null,callback:null,next:null}}function er(e,n,i){var s=e.updateQueue;if(s===null)return null;if(s=s.shared,(Le&2)!==0){var c=s.pending;return c===null?n.next=n:(n.next=c.next,c.next=n),s.pending=n,Cn(e,i)}return c=s.interleaved,c===null?(n.next=n,Ca(s)):(n.next=c.next,c.next=n),s.interleaved=n,Cn(e,i)}function xs(e,n,i){if(n=n.updateQueue,n!==null&&(n=n.shared,(i&4194240)!==0)){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,ti(e,i)}}function kd(e,n){var i=e.updateQueue,s=e.alternate;if(s!==null&&(s=s.updateQueue,i===s)){var c=null,h=null;if(i=i.firstBaseUpdate,i!==null){do{var w={eventTime:i.eventTime,lane:i.lane,tag:i.tag,payload:i.payload,callback:i.callback,next:null};h===null?c=h=w:h=h.next=w,i=i.next}while(i!==null);h===null?c=h=n:h=h.next=n}else c=h=n;i={baseState:s.baseState,firstBaseUpdate:c,lastBaseUpdate:h,shared:s.shared,effects:s.effects},e.updateQueue=i;return}e=i.lastBaseUpdate,e===null?i.firstBaseUpdate=n:e.next=n,i.lastBaseUpdate=n}function ws(e,n,i,s){var c=e.updateQueue;Jn=!1;var h=c.firstBaseUpdate,w=c.lastBaseUpdate,P=c.shared.pending;if(P!==null){c.shared.pending=null;var A=P,Z=A.next;A.next=null,w===null?h=Z:w.next=Z,w=A;var se=e.alternate;se!==null&&(se=se.updateQueue,P=se.lastBaseUpdate,P!==w&&(P===null?se.firstBaseUpdate=Z:P.next=Z,se.lastBaseUpdate=A))}if(h!==null){var ae=c.baseState;w=0,se=Z=A=null,P=h;do{var oe=P.lane,he=P.eventTime;if((s&oe)===oe){se!==null&&(se=se.next={eventTime:he,lane:0,tag:P.tag,payload:P.payload,callback:P.callback,next:null});e:{var ye=e,ve=P;switch(oe=n,he=i,ve.tag){case 1:if(ye=ve.payload,typeof ye=="function"){ae=ye.call(he,ae,oe);break e}ae=ye;break e;case 3:ye.flags=ye.flags&-65537|128;case 0:if(ye=ve.payload,oe=typeof ye=="function"?ye.call(he,ae,oe):ye,oe==null)break e;ae=W({},ae,oe);break e;case 2:Jn=!0}}P.callback!==null&&P.lane!==0&&(e.flags|=64,oe=c.effects,oe===null?c.effects=[P]:oe.push(P))}else he={eventTime:he,lane:oe,tag:P.tag,payload:P.payload,callback:P.callback,next:null},se===null?(Z=se=he,A=ae):se=se.next=he,w|=oe;if(P=P.next,P===null){if(P=c.shared.pending,P===null)break;oe=P,P=oe.next,oe.next=null,c.lastBaseUpdate=oe,c.shared.pending=null}}while(!0);if(se===null&&(A=ae),c.baseState=A,c.firstBaseUpdate=Z,c.lastBaseUpdate=se,n=c.shared.interleaved,n!==null){c=n;do w|=c.lane,c=c.next;while(c!==n)}else h===null&&(c.shared.lanes=0);Pr|=w,e.lanes=w,e.memoizedState=ae}}function Ed(e,n,i){if(e=n.effects,n.effects=null,e!==null)for(n=0;ni?i:4,e(!0);var s=La.transition;La.transition={};try{e(!1),n()}finally{Oe=i,La.transition=s}}function Vd(){return Wt().memoizedState}function xy(e,n,i){var s=ir(e);if(i={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null},Wd(e))Ud(n,i);else if(i=_d(e,n,i,s),i!==null){var c=St();en(i,e,s,c),Yd(i,n,s)}}function wy(e,n,i){var s=ir(e),c={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null};if(Wd(e))Ud(n,c);else{var h=e.alternate;if(e.lanes===0&&(h===null||h.lanes===0)&&(h=n.lastRenderedReducer,h!==null))try{var w=n.lastRenderedState,P=h(w,i);if(c.hasEagerState=!0,c.eagerState=P,qt(P,w)){var A=n.interleaved;A===null?(c.next=c,Ca(n)):(c.next=A.next,A.next=c),n.interleaved=c;return}}catch{}finally{}i=_d(e,n,c,s),i!==null&&(c=St(),en(i,e,s,c),Yd(i,n,s))}}function Wd(e){var n=e.alternate;return e===Xe||n!==null&&n===Xe}function Ud(e,n){lo=ks=!0;var i=e.pending;i===null?n.next=n:(n.next=i.next,i.next=n),e.pending=n}function Yd(e,n,i){if((i&4194240)!==0){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,ti(e,i)}}var js={readContext:Vt,useCallback:yt,useContext:yt,useEffect:yt,useImperativeHandle:yt,useInsertionEffect:yt,useLayoutEffect:yt,useMemo:yt,useReducer:yt,useRef:yt,useState:yt,useDebugValue:yt,useDeferredValue:yt,useTransition:yt,useMutableSource:yt,useSyncExternalStore:yt,useId:yt,unstable_isNewReconciler:!1},_y={readContext:Vt,useCallback:function(e,n){return hn().memoizedState=[e,n===void 0?null:n],e},useContext:Vt,useEffect:Ad,useImperativeHandle:function(e,n,i){return i=i!=null?i.concat([e]):null,Es(4194308,4,$d.bind(null,n,e),i)},useLayoutEffect:function(e,n){return Es(4194308,4,e,n)},useInsertionEffect:function(e,n){return Es(4,2,e,n)},useMemo:function(e,n){var i=hn();return n=n===void 0?null:n,e=e(),i.memoizedState=[e,n],e},useReducer:function(e,n,i){var s=hn();return n=i!==void 0?i(n):n,s.memoizedState=s.baseState=n,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},s.queue=e,e=e.dispatch=xy.bind(null,Xe,e),[s.memoizedState,e]},useRef:function(e){var n=hn();return e={current:e},n.memoizedState=e},useState:Rd,useDebugValue:Ha,useDeferredValue:function(e){return hn().memoizedState=e},useTransition:function(){var e=Rd(!1),n=e[0];return e=vy.bind(null,e[1]),hn().memoizedState=e,[n,e]},useMutableSource:function(){},useSyncExternalStore:function(e,n,i){var s=Xe,c=hn();if(Ue){if(i===void 0)throw Error(o(407));i=i()}else{if(i=n(),ct===null)throw Error(o(349));(Mr&30)!==0||Cd(s,n,i)}c.memoizedState=i;var h={value:i,getSnapshot:n};return c.queue=h,Ad(Pd.bind(null,s,h,e),[e]),s.flags|=2048,co(9,Md.bind(null,s,h,i,n),void 0,null),i},useId:function(){var e=hn(),n=ct.identifierPrefix;if(Ue){var i=bn,s=jn;i=(s&~(1<<32-Lt(s)-1)).toString(32)+i,n=":"+n+"R"+i,i=ao++,0<\/script>",e=e.removeChild(e.firstChild)):typeof s.is=="string"?e=w.createElement(i,{is:s.is}):(e=w.createElement(i),i==="select"&&(w=e,s.multiple?w.multiple=!0:s.size&&(w.size=s.size))):e=w.createElementNS(e,i),e[dn]=n,e[to]=s,hf(e,n,!1,!1),n.stateNode=e;e:{switch(w=pr(i,s),i){case"dialog":He("cancel",e),He("close",e),c=s;break;case"iframe":case"object":case"embed":He("load",e),c=s;break;case"video":case"audio":for(c=0;cSi&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304)}else{if(!s)if(e=_s(w),e!==null){if(n.flags|=128,s=!0,i=e.updateQueue,i!==null&&(n.updateQueue=i,n.flags|=4),fo(h,!0),h.tail===null&&h.tailMode==="hidden"&&!w.alternate&&!Ue)return vt(n),null}else 2*Ye()-h.renderingStartTime>Si&&i!==1073741824&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304);h.isBackwards?(w.sibling=n.child,n.child=w):(i=h.last,i!==null?i.sibling=w:n.child=w,h.last=w)}return h.tail!==null?(n=h.tail,h.rendering=n,h.tail=n.sibling,h.renderingStartTime=Ye(),n.sibling=null,i=Ge.current,Fe(Ge,s?i&1|2:i&1),n):(vt(n),null);case 22:case 23:return du(),s=n.memoizedState!==null,e!==null&&e.memoizedState!==null!==s&&(n.flags|=8192),s&&(n.mode&1)!==0?($t&1073741824)!==0&&(vt(n),n.subtreeFlags&6&&(n.flags|=8192)):vt(n),null;case 24:return null;case 25:return null}throw Error(o(156,n.tag))}function My(e,n){switch(wa(n),n.tag){case 1:return Nt(n.type)&&cs(),e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 3:return vi(),Be(Et),Be(mt),Ra(),e=n.flags,(e&65536)!==0&&(e&128)===0?(n.flags=e&-65537|128,n):null;case 5:return Ia(n),null;case 13:if(Be(Ge),e=n.memoizedState,e!==null&&e.dehydrated!==null){if(n.alternate===null)throw Error(o(340));pi()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 19:return Be(Ge),null;case 4:return vi(),null;case 10:return ja(n.type._context),null;case 22:case 23:return du(),null;case 24:return null;default:return null}}var Ps=!1,xt=!1,Py=typeof WeakSet=="function"?WeakSet:Set,me=null;function wi(e,n){var i=e.ref;if(i!==null)if(typeof i=="function")try{i(null)}catch(s){Ze(e,n,s)}else i.current=null}function Ja(e,n,i){try{i()}catch(s){Ze(e,n,s)}}var mf=!1;function Iy(e,n){if(da=Qo,e=Gc(),ra(e)){if("selectionStart"in e)var i={start:e.selectionStart,end:e.selectionEnd};else e:{i=(i=e.ownerDocument)&&i.defaultView||window;var s=i.getSelection&&i.getSelection();if(s&&s.rangeCount!==0){i=s.anchorNode;var c=s.anchorOffset,h=s.focusNode;s=s.focusOffset;try{i.nodeType,h.nodeType}catch{i=null;break e}var w=0,P=-1,A=-1,Z=0,se=0,ae=e,oe=null;t:for(;;){for(var he;ae!==i||c!==0&&ae.nodeType!==3||(P=w+c),ae!==h||s!==0&&ae.nodeType!==3||(A=w+s),ae.nodeType===3&&(w+=ae.nodeValue.length),(he=ae.firstChild)!==null;)oe=ae,ae=he;for(;;){if(ae===e)break t;if(oe===i&&++Z===c&&(P=w),oe===h&&++se===s&&(A=w),(he=ae.nextSibling)!==null)break;ae=oe,oe=ae.parentNode}ae=he}i=P===-1||A===-1?null:{start:P,end:A}}else i=null}i=i||{start:0,end:0}}else i=null;for(fa={focusedElem:e,selectionRange:i},Qo=!1,me=n;me!==null;)if(n=me,e=n.child,(n.subtreeFlags&1028)!==0&&e!==null)e.return=n,me=e;else for(;me!==null;){n=me;try{var ye=n.alternate;if((n.flags&1024)!==0)switch(n.tag){case 0:case 11:case 15:break;case 1:if(ye!==null){var ve=ye.memoizedProps,et=ye.memoizedState,X=n.stateNode,B=X.getSnapshotBeforeUpdate(n.elementType===n.type?ve:Kt(n.type,ve),et);X.__reactInternalSnapshotBeforeUpdate=B}break;case 3:var Q=n.stateNode.containerInfo;Q.nodeType===1?Q.textContent="":Q.nodeType===9&&Q.documentElement&&Q.removeChild(Q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(ue){Ze(n,n.return,ue)}if(e=n.sibling,e!==null){e.return=n.return,me=e;break}me=n.return}return ye=mf,mf=!1,ye}function ho(e,n,i){var s=n.updateQueue;if(s=s!==null?s.lastEffect:null,s!==null){var c=s=s.next;do{if((c.tag&e)===e){var h=c.destroy;c.destroy=void 0,h!==void 0&&Ja(n,i,h)}c=c.next}while(c!==s)}}function Is(e,n){if(n=n.updateQueue,n=n!==null?n.lastEffect:null,n!==null){var i=n=n.next;do{if((i.tag&e)===e){var s=i.create;i.destroy=s()}i=i.next}while(i!==n)}}function eu(e){var n=e.ref;if(n!==null){var i=e.stateNode;switch(e.tag){case 5:e=i;break;default:e=i}typeof n=="function"?n(e):n.current=e}}function yf(e){var n=e.alternate;n!==null&&(e.alternate=null,yf(n)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(n=e.stateNode,n!==null&&(delete n[dn],delete n[to],delete n[ma],delete n[hy],delete n[py])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function vf(e){return e.tag===5||e.tag===3||e.tag===4}function xf(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||vf(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.nodeType===8?i.parentNode.insertBefore(e,n):i.insertBefore(e,n):(i.nodeType===8?(n=i.parentNode,n.insertBefore(e,i)):(n=i,n.appendChild(e)),i=i._reactRootContainer,i!=null||n.onclick!==null||(n.onclick=as));else if(s!==4&&(e=e.child,e!==null))for(tu(e,n,i),e=e.sibling;e!==null;)tu(e,n,i),e=e.sibling}function nu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.insertBefore(e,n):i.appendChild(e);else if(s!==4&&(e=e.child,e!==null))for(nu(e,n,i),e=e.sibling;e!==null;)nu(e,n,i),e=e.sibling}var ht=null,Zt=!1;function tr(e,n,i){for(i=i.child;i!==null;)wf(e,n,i),i=i.sibling}function wf(e,n,i){if(Rt&&typeof Rt.onCommitFiberUnmount=="function")try{Rt.onCommitFiberUnmount(Zr,i)}catch{}switch(i.tag){case 5:xt||wi(i,n);case 6:var s=ht,c=Zt;ht=null,tr(e,n,i),ht=s,Zt=c,ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?e.parentNode.removeChild(i):e.removeChild(i)):ht.removeChild(i.stateNode));break;case 18:ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?ga(e.parentNode,i):e.nodeType===1&&ga(e,i),Wi(e)):ga(ht,i.stateNode));break;case 4:s=ht,c=Zt,ht=i.stateNode.containerInfo,Zt=!0,tr(e,n,i),ht=s,Zt=c;break;case 0:case 11:case 14:case 15:if(!xt&&(s=i.updateQueue,s!==null&&(s=s.lastEffect,s!==null))){c=s=s.next;do{var h=c,w=h.destroy;h=h.tag,w!==void 0&&((h&2)!==0||(h&4)!==0)&&Ja(i,n,w),c=c.next}while(c!==s)}tr(e,n,i);break;case 1:if(!xt&&(wi(i,n),s=i.stateNode,typeof s.componentWillUnmount=="function"))try{s.props=i.memoizedProps,s.state=i.memoizedState,s.componentWillUnmount()}catch(P){Ze(i,n,P)}tr(e,n,i);break;case 21:tr(e,n,i);break;case 22:i.mode&1?(xt=(s=xt)||i.memoizedState!==null,tr(e,n,i),xt=s):tr(e,n,i);break;default:tr(e,n,i)}}function _f(e){var n=e.updateQueue;if(n!==null){e.updateQueue=null;var i=e.stateNode;i===null&&(i=e.stateNode=new Py),n.forEach(function(s){var c=Fy.bind(null,e,s);i.has(s)||(i.add(s),s.then(c,c))})}}function Jt(e,n){var i=n.deletions;if(i!==null)for(var s=0;sc&&(c=w),s&=~h}if(s=c,s=Ye()-s,s=(120>s?120:480>s?480:1080>s?1080:1920>s?1920:3e3>s?3e3:4320>s?4320:1960*Ry(s/1960))-s,10e?16:e,rr===null)var s=!1;else{if(e=rr,rr=null,zs=0,(Le&6)!==0)throw Error(o(331));var c=Le;for(Le|=4,me=e.current;me!==null;){var h=me,w=h.child;if((me.flags&16)!==0){var P=h.deletions;if(P!==null){for(var A=0;AYe()-ou?Tr(e,0):iu|=i),Ct(e,n)}function Lf(e,n){n===0&&((e.mode&1)===0?n=1:(n=ei,ei<<=1,(ei&130023424)===0&&(ei=4194304)));var i=St();e=Cn(e,n),e!==null&&(Sr(e,n,i),Ct(e,i))}function Oy(e){var n=e.memoizedState,i=0;n!==null&&(i=n.retryLane),Lf(e,i)}function Fy(e,n){var i=0;switch(e.tag){case 13:var s=e.stateNode,c=e.memoizedState;c!==null&&(i=c.retryLane);break;case 19:s=e.stateNode;break;default:throw Error(o(314))}s!==null&&s.delete(n),Lf(e,i)}var Af;Af=function(e,n,i){if(e!==null)if(e.memoizedProps!==n.pendingProps||Et.current)jt=!0;else{if((e.lanes&i)===0&&(n.flags&128)===0)return jt=!1,by(e,n,i);jt=(e.flags&131072)!==0}else jt=!1,Ue&&(n.flags&1048576)!==0&&hd(n,ps,n.index);switch(n.lanes=0,n.tag){case 2:var s=n.type;Ms(e,n),e=n.pendingProps;var c=di(n,mt.current);yi(n,i),c=za(null,n,s,e,c,i);var h=Da();return n.flags|=1,typeof c=="object"&&c!==null&&typeof c.render=="function"&&c.$$typeof===void 0?(n.tag=1,n.memoizedState=null,n.updateQueue=null,Nt(s)?(h=!0,ds(n)):h=!1,n.memoizedState=c.state!==null&&c.state!==void 0?c.state:null,Ma(n),c.updater=bs,n.stateNode=c,c._reactInternals=n,Va(n,s,e,i),n=Ga(null,n,s,!0,h,i)):(n.tag=0,Ue&&h&&xa(n),_t(null,n,c,i),n=n.child),n;case 16:s=n.elementType;e:{switch(Ms(e,n),e=n.pendingProps,c=s._init,s=c(s._payload),n.type=s,c=n.tag=By(s),e=Kt(s,e),c){case 0:n=Ya(null,n,s,e,i);break e;case 1:n=lf(null,n,s,e,i);break e;case 11:n=tf(null,n,s,e,i);break e;case 14:n=nf(null,n,s,Kt(s.type,e),i);break e}throw Error(o(306,s,""))}return n;case 0:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ya(e,n,s,c,i);case 1:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),lf(e,n,s,c,i);case 3:e:{if(af(n),e===null)throw Error(o(387));s=n.pendingProps,h=n.memoizedState,c=h.element,Sd(e,n),ws(n,s,null,i);var w=n.memoizedState;if(s=w.element,h.isDehydrated)if(h={element:s,isDehydrated:!1,cache:w.cache,pendingSuspenseBoundaries:w.pendingSuspenseBoundaries,transitions:w.transitions},n.updateQueue.baseState=h,n.memoizedState=h,n.flags&256){c=xi(Error(o(423)),n),n=uf(e,n,s,i,c);break e}else if(s!==c){c=xi(Error(o(424)),n),n=uf(e,n,s,i,c);break e}else for(Dt=qn(n.stateNode.containerInfo.firstChild),zt=n,Ue=!0,Qt=null,i=wd(n,null,s,i),n.child=i;i;)i.flags=i.flags&-3|4096,i=i.sibling;else{if(pi(),s===c){n=Pn(e,n,i);break e}_t(e,n,s,i)}n=n.child}return n;case 5:return Nd(n),e===null&&Sa(n),s=n.type,c=n.pendingProps,h=e!==null?e.memoizedProps:null,w=c.children,ha(s,c)?w=null:h!==null&&ha(s,h)&&(n.flags|=32),sf(e,n),_t(e,n,w,i),n.child;case 6:return e===null&&Sa(n),null;case 13:return cf(e,n,i);case 4:return Pa(n,n.stateNode.containerInfo),s=n.pendingProps,e===null?n.child=gi(n,null,s,i):_t(e,n,s,i),n.child;case 11:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),tf(e,n,s,c,i);case 7:return _t(e,n,n.pendingProps,i),n.child;case 8:return _t(e,n,n.pendingProps.children,i),n.child;case 12:return _t(e,n,n.pendingProps.children,i),n.child;case 10:e:{if(s=n.type._context,c=n.pendingProps,h=n.memoizedProps,w=c.value,Fe(ys,s._currentValue),s._currentValue=w,h!==null)if(qt(h.value,w)){if(h.children===c.children&&!Et.current){n=Pn(e,n,i);break e}}else for(h=n.child,h!==null&&(h.return=n);h!==null;){var P=h.dependencies;if(P!==null){w=h.child;for(var A=P.firstContext;A!==null;){if(A.context===s){if(h.tag===1){A=Mn(-1,i&-i),A.tag=2;var Z=h.updateQueue;if(Z!==null){Z=Z.shared;var se=Z.pending;se===null?A.next=A:(A.next=se.next,se.next=A),Z.pending=A}}h.lanes|=i,A=h.alternate,A!==null&&(A.lanes|=i),ba(h.return,i,n),P.lanes|=i;break}A=A.next}}else if(h.tag===10)w=h.type===n.type?null:h.child;else if(h.tag===18){if(w=h.return,w===null)throw Error(o(341));w.lanes|=i,P=w.alternate,P!==null&&(P.lanes|=i),ba(w,i,n),w=h.sibling}else w=h.child;if(w!==null)w.return=h;else for(w=h;w!==null;){if(w===n){w=null;break}if(h=w.sibling,h!==null){h.return=w.return,w=h;break}w=w.return}h=w}_t(e,n,c.children,i),n=n.child}return n;case 9:return c=n.type,s=n.pendingProps.children,yi(n,i),c=Vt(c),s=s(c),n.flags|=1,_t(e,n,s,i),n.child;case 14:return s=n.type,c=Kt(s,n.pendingProps),c=Kt(s.type,c),nf(e,n,s,c,i);case 15:return rf(e,n,n.type,n.pendingProps,i);case 17:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ms(e,n),n.tag=1,Nt(s)?(e=!0,ds(n)):e=!1,yi(n,i),Xd(n,s,c),Va(n,s,c,i),Ga(null,n,s,!0,e,i);case 19:return ff(e,n,i);case 22:return of(e,n,i)}throw Error(o(156,n.tag))};function zf(e,n){return Ce(e,n)}function Hy(e,n,i,s){this.tag=e,this.key=i,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=s,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Yt(e,n,i,s){return new Hy(e,n,i,s)}function hu(e){return e=e.prototype,!(!e||!e.isReactComponent)}function By(e){if(typeof e=="function")return hu(e)?1:0;if(e!=null){if(e=e.$$typeof,e===ee)return 11;if(e===Y)return 14}return 2}function sr(e,n){var i=e.alternate;return i===null?(i=Yt(e.tag,n,e.key,e.mode),i.elementType=e.elementType,i.type=e.type,i.stateNode=e.stateNode,i.alternate=e,e.alternate=i):(i.pendingProps=n,i.type=e.type,i.flags=0,i.subtreeFlags=0,i.deletions=null),i.flags=e.flags&14680064,i.childLanes=e.childLanes,i.lanes=e.lanes,i.child=e.child,i.memoizedProps=e.memoizedProps,i.memoizedState=e.memoizedState,i.updateQueue=e.updateQueue,n=e.dependencies,i.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext},i.sibling=e.sibling,i.index=e.index,i.ref=e.ref,i}function Fs(e,n,i,s,c,h){var w=2;if(s=e,typeof e=="function")hu(e)&&(w=1);else if(typeof e=="string")w=5;else e:switch(e){case H:return Lr(i.children,c,h,n);case I:w=8,c|=8;break;case q:return e=Yt(12,i,n,c|2),e.elementType=q,e.lanes=h,e;case J:return e=Yt(13,i,n,c),e.elementType=J,e.lanes=h,e;case C:return e=Yt(19,i,n,c),e.elementType=C,e.lanes=h,e;case U:return Hs(i,c,h,n);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case ne:w=10;break e;case G:w=9;break e;case ee:w=11;break e;case Y:w=14;break e;case V:w=16,s=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return n=Yt(w,i,n,c),n.elementType=e,n.type=s,n.lanes=h,n}function Lr(e,n,i,s){return e=Yt(7,e,s,n),e.lanes=i,e}function Hs(e,n,i,s){return e=Yt(22,e,s,n),e.elementType=U,e.lanes=i,e.stateNode={isHidden:!1},e}function pu(e,n,i){return e=Yt(6,e,null,n),e.lanes=i,e}function gu(e,n,i){return n=Yt(4,e.children!==null?e.children:[],e.key,n),n.lanes=i,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}function Vy(e,n,i,s,c){this.tag=n,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=_r(0),this.expirationTimes=_r(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=_r(0),this.identifierPrefix=s,this.onRecoverableError=c,this.mutableSourceEagerHydrationData=null}function mu(e,n,i,s,c,h,w,P,A){return e=new Vy(e,n,i,P,A),n===1?(n=1,h===!0&&(n|=8)):n=0,h=Yt(3,null,null,n),e.current=h,h.stateNode=e,h.memoizedState={element:s,isDehydrated:i,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(h),e}function Wy(e,n,i){var s=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Su.exports=n0(),Su.exports}var Qf;function r0(){if(Qf)return Xs;Qf=1;var t=wp();return Xs.createRoot=t.createRoot,Xs.hydrateRoot=t.hydrateRoot,Xs}var i0=r0();function o0(t,r="Request failed"){const o=(t||"").trim();if(!o)return r;try{const a=JSON.parse(o).detail;if(typeof a=="string"&&a.trim())return a;if(Array.isArray(a)){const u=a.map(d=>typeof d=="string"?d:d&&typeof d=="object"&&"msg"in d?String(d.msg):"").filter(Boolean);if(u.length)return u.join("; ")}}catch{}return o}async function Ve(t,r){const o=await fetch(t,{...r,headers:{"Content-Type":"application/json",...(r==null?void 0:r.headers)||{}}});if(!o.ok){const l=await o.text();throw new Error(o0(l,o.statusText||"Request failed"))}return o.json()}const s0=["github_token","gitlab_token","gitlab_oauth_client_secret","bitbucket_token","bitbucket_oauth_client_secret","ai_api_key","ai_model","ai_base_url"],$e={health:()=>Ve("/api/health"),settings:()=>Ve("/api/settings"),saveSettings:t=>{const r={...t};for(const o of s0)r[o]===""&&delete r[o];return Ve("/api/settings",{method:"PUT",body:JSON.stringify(r)})},repos:()=>Ve("/api/repos"),browse:t=>Ve(`/api/fs${t?`?path=${encodeURIComponent(t)}`:""}`),gitRefs:(t,r=50)=>Ve(`/api/git/refs?repo_path=${encodeURIComponent(t)}&limit=${r}`),index:(t,r=!0)=>Ve("/api/index",{method:"POST",body:JSON.stringify({repo_path:t,incremental:r})}),indexStatus:t=>Ve(`/api/index?repo_path=${encodeURIComponent(t)}`),indexProgress:t=>Ve(`/api/index/progress?repo_path=${encodeURIComponent(t)}`),architecture:t=>Ve(`/api/architecture?repo_path=${encodeURIComponent(t)}`),review:(t,r,o,l=!0,a=!1)=>Ve("/api/review",{method:"POST",body:JSON.stringify({repo_path:t,base:r,head:o||null,reindex:l,incremental:!0,three_dot:!0,dirty:a})}),whatIf:(t,r)=>Ve("/api/whatif",{method:"POST",body:JSON.stringify({repo_path:t,node_id:r})}),reviewPr:(t,r,o,l)=>Ve("/api/prs/review",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,repo_path:l||null})}),init:(t,r=!1)=>Ve("/api/init",{method:"POST",body:JSON.stringify({repo_path:t,overwrite:r})}),postComment:(t,r,o,l)=>Ve("/api/prs/comment",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,markdown:l})}),graph:(t,r="full")=>Ve(`/api/graph?repo_path=${encodeURIComponent(t)}&scope=${r}`),prs:(t,r,o="open")=>Ve("/api/prs",{method:"POST",body:JSON.stringify({provider:t,repo:r,state:o})}),scmRepos:t=>Ve(`/api/scm/repos?provider=${encodeURIComponent(t)}`),oauthStatus:()=>Ve("/api/oauth/status"),githubOAuthStart:()=>Ve("/api/oauth/github/start",{method:"POST",body:"{}"}),githubOAuthPoll:t=>Ve("/api/oauth/github/poll",{method:"POST",body:JSON.stringify({flow_id:t})}),bitbucketOAuthStart:()=>Ve("/api/oauth/bitbucket/start"),gitlabOAuthStart:()=>Ve("/api/oauth/gitlab/start"),oauthDisconnect:t=>Ve("/api/oauth/disconnect",{method:"POST",body:JSON.stringify({provider:t})}),residual:t=>Ve("/api/ai/residual",{method:"POST",body:JSON.stringify({review:t})})};function No(t){return t.replaceAll("_"," ")}function l0(t){return t.replaceAll("_"," ")}function _l(t){return t.split(".").pop()||t}function _p(t){if(!t)return"";const r=new Date(t);return Number.isNaN(r.getTime())?t:r.toLocaleString()}function Ni(t){return t.replace(/([/\\._:@-])/g,"$1​")}function Wr({className:t,children:r}){return p.jsx("svg",{className:t,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:r})}function a0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("path",{d:"M3 3.5h6.5L13 7v5.5H3z"}),p.jsx("path",{d:"M9.5 3.5V7H13"}),p.jsx("path",{d:"M5.5 9.5h5M5.5 11.5h3.5"})]})}function u0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("rect",{x:"2.5",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"2.5",y:"9",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"9",width:"4.5",height:"4.5",rx:"0.8"})]})}function c0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4",cy:"8",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"4",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"12",r:"1.6"}),p.jsx("path",{d:"M5.5 7.2 10.4 4.8M5.5 8.8 10.4 11.2"})]})}function d0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4.5",cy:"4",r:"1.4"}),p.jsx("circle",{cx:"4.5",cy:"12",r:"1.4"}),p.jsx("circle",{cx:"11.5",cy:"12",r:"1.4"}),p.jsx("path",{d:"M4.5 5.5v5M4.5 8h4.2a3 3 0 0 1 3 3"})]})}function f0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"8",cy:"8",r:"2.1"}),p.jsx("path",{d:"M8 2.5v1.6M8 11.9v1.6M2.5 8h1.6M11.9 8h1.6M4.1 4.1l1.1 1.1M10.8 10.8l1.1 1.1M11.9 4.1l-1.1 1.1M5.2 10.8l-1.1 1.1"})]})}function Sp({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M2.5 4.5h4L8 6h5.5v6.5h-11z"})})}function h0({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M4 6.5 8 10.5 12 6.5"})})}const p0="modulepreload",g0=function(t,r){return new URL(t,r).href},Kf={},m0=function(r,o,l){let a=Promise.resolve();if(o&&o.length>0){let d=function(m){return Promise.all(m.map(x=>Promise.resolve(x).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};const f=document.getElementsByTagName("link"),g=document.querySelector("meta[property=csp-nonce]"),y=(g==null?void 0:g.nonce)||(g==null?void 0:g.getAttribute("nonce"));a=d(o.map(m=>{if(m=g0(m,l),m in Kf)return;Kf[m]=!0;const x=m.endsWith(".css"),v=x?'[rel="stylesheet"]':"";if(!!l)for(let j=f.length-1;j>=0;j--){const N=f[j];if(N.href===m&&(!x||N.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${m}"]${v}`))return;const S=document.createElement("link");if(S.rel=x?"stylesheet":p0,x||(S.as="script"),S.crossOrigin="",S.href=m,y&&S.setAttribute("nonce",y),document.head.appendChild(S),x)return new Promise((j,N)=>{S.addEventListener("load",j),S.addEventListener("error",()=>N(new Error(`Unable to preload CSS for ${m}`)))})}))}function u(d){const f=new Event("vite:preloadError",{cancelable:!0});if(f.payload=d,window.dispatchEvent(f),!f.defaultPrevented)throw d}return a.then(d=>{for(const f of d||[])f.status==="rejected"&&u(f.reason);return r().catch(u)})};function it(t){if(typeof t=="string"||typeof t=="number")return""+t;let r="";if(Array.isArray(t))for(let o=0,l;o{}};function Sl(){for(var t=0,r=arguments.length,o={},l;t=0&&(l=o.slice(a+1),o=o.slice(0,a)),o&&!r.hasOwnProperty(o))throw new Error("unknown type: "+o);return{type:o,name:l}})}ol.prototype=Sl.prototype={constructor:ol,on:function(t,r){var o=this._,l=v0(t+"",o),a,u=-1,d=l.length;if(arguments.length<2){for(;++u0)for(var o=new Array(a),l=0,a,u;l=0&&(r=t.slice(0,o))!=="xmlns"&&(t=t.slice(o+1)),Jf.hasOwnProperty(r)?{space:Jf[r],local:t}:t}function w0(t){return function(){var r=this.ownerDocument,o=this.namespaceURI;return o===Fu&&r.documentElement.namespaceURI===Fu?r.createElement(t):r.createElementNS(o,t)}}function _0(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function kp(t){var r=kl(t);return(r.local?_0:w0)(r)}function S0(){}function ec(t){return t==null?S0:function(){return this.querySelector(t)}}function k0(t){typeof t!="function"&&(t=ec(t));for(var r=this._groups,o=r.length,l=new Array(o),a=0;a=E&&(E=T+1);!($=N[E])&&++E=0;)(d=l[a])&&(u&&d.compareDocumentPosition(u)^4&&u.parentNode.insertBefore(d,u),u=d);return this}function X0(t){t||(t=q0);function r(x,v){return x&&v?t(x.__data__,v.__data__):!x-!v}for(var o=this._groups,l=o.length,a=new Array(l),u=0;ur?1:t>=r?0:NaN}function Q0(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function K0(){return Array.from(this)}function Z0(){for(var t=this._groups,r=0,o=t.length;r1?this.each((r==null?uv:typeof r=="function"?dv:cv)(t,r,o??"")):Mi(this.node(),t)}function Mi(t,r){return t.style.getPropertyValue(r)||Cp(t).getComputedStyle(t,null).getPropertyValue(r)}function hv(t){return function(){delete this[t]}}function pv(t,r){return function(){this[t]=r}}function gv(t,r){return function(){var o=r.apply(this,arguments);o==null?delete this[t]:this[t]=o}}function mv(t,r){return arguments.length>1?this.each((r==null?hv:typeof r=="function"?gv:pv)(t,r)):this.node()[t]}function Mp(t){return t.trim().split(/^|\s+/)}function tc(t){return t.classList||new Pp(t)}function Pp(t){this._node=t,this._names=Mp(t.getAttribute("class")||"")}Pp.prototype={add:function(t){var r=this._names.indexOf(t);r<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var r=this._names.indexOf(t);r>=0&&(this._names.splice(r,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Ip(t,r){for(var o=tc(t),l=-1,a=r.length;++l=0&&(o=r.slice(l+1),r=r.slice(0,l)),{type:r,name:o}})}function Wv(t){return function(){var r=this.__on;if(r){for(var o=0,l=-1,a=r.length,u;o()=>t;function Hu(t,{sourceEvent:r,subject:o,target:l,identifier:a,active:u,x:d,y:f,dx:g,dy:y,dispatch:m}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},subject:{value:o,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},identifier:{value:a,enumerable:!0,configurable:!0},active:{value:u,enumerable:!0,configurable:!0},x:{value:d,enumerable:!0,configurable:!0},y:{value:f,enumerable:!0,configurable:!0},dx:{value:g,enumerable:!0,configurable:!0},dy:{value:y,enumerable:!0,configurable:!0},_:{value:m}})}Hu.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};function ex(t){return!t.ctrlKey&&!t.button}function tx(){return this.parentNode}function nx(t,r){return r??{x:t.x,y:t.y}}function rx(){return navigator.maxTouchPoints||"ontouchstart"in this}function Dp(){var t=ex,r=tx,o=nx,l=rx,a={},u=Sl("start","drag","end"),d=0,f,g,y,m,x=0;function v(b){b.on("mousedown.drag",_).filter(l).on("touchstart.drag",N).on("touchmove.drag",k,Jv).on("touchend.drag touchcancel.drag",T).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(b,$){if(!(m||!t.call(this,b,$))){var O=E(this,r.call(this,b,$),b,$,"mouse");O&&(Ot(b.view).on("mousemove.drag",S,jo).on("mouseup.drag",j,jo),Ap(b.view),Nu(b),y=!1,f=b.clientX,g=b.clientY,O("start",b))}}function S(b){if(bi(b),!y){var $=b.clientX-f,O=b.clientY-g;y=$*$+O*O>x}a.mouse("drag",b)}function j(b){Ot(b.view).on("mousemove.drag mouseup.drag",null),zp(b.view,y),bi(b),a.mouse("end",b)}function N(b,$){if(t.call(this,b,$)){var O=b.changedTouches,H=r.call(this,b,$),I=O.length,q,ne;for(q=0;q>8&15|r>>4&240,r>>4&15|r&240,(r&15)<<4|r&15,1):o===8?Qs(r>>24&255,r>>16&255,r>>8&255,(r&255)/255):o===4?Qs(r>>12&15|r>>8&240,r>>8&15|r>>4&240,r>>4&15|r&240,((r&15)<<4|r&15)/255):null):(r=ox.exec(t))?new Pt(r[1],r[2],r[3],1):(r=sx.exec(t))?new Pt(r[1]*255/100,r[2]*255/100,r[3]*255/100,1):(r=lx.exec(t))?Qs(r[1],r[2],r[3],r[4]):(r=ax.exec(t))?Qs(r[1]*255/100,r[2]*255/100,r[3]*255/100,r[4]):(r=ux.exec(t))?sh(r[1],r[2]/100,r[3]/100,1):(r=cx.exec(t))?sh(r[1],r[2]/100,r[3]/100,r[4]):eh.hasOwnProperty(t)?rh(eh[t]):t==="transparent"?new Pt(NaN,NaN,NaN,0):null}function rh(t){return new Pt(t>>16&255,t>>8&255,t&255,1)}function Qs(t,r,o,l){return l<=0&&(t=r=o=NaN),new Pt(t,r,o,l)}function hx(t){return t instanceof $o||(t=Or(t)),t?(t=t.rgb(),new Pt(t.r,t.g,t.b,t.opacity)):new Pt}function Bu(t,r,o,l){return arguments.length===1?hx(t):new Pt(t,r,o,l??1)}function Pt(t,r,o,l){this.r=+t,this.g=+r,this.b=+o,this.opacity=+l}nc(Pt,Bu,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new Pt(Dr(this.r),Dr(this.g),Dr(this.b),fl(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:ih,formatHex:ih,formatHex8:px,formatRgb:oh,toString:oh}));function ih(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}`}function px(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}${zr((isNaN(this.opacity)?1:this.opacity)*255)}`}function oh(){const t=fl(this.opacity);return`${t===1?"rgb(":"rgba("}${Dr(this.r)}, ${Dr(this.g)}, ${Dr(this.b)}${t===1?")":`, ${t})`}`}function fl(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Dr(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function zr(t){return t=Dr(t),(t<16?"0":"")+t.toString(16)}function sh(t,r,o,l){return l<=0?t=r=o=NaN:o<=0||o>=1?t=r=NaN:r<=0&&(t=NaN),new nn(t,r,o,l)}function Op(t){if(t instanceof nn)return new nn(t.h,t.s,t.l,t.opacity);if(t instanceof $o||(t=Or(t)),!t)return new nn;if(t instanceof nn)return t;t=t.rgb();var r=t.r/255,o=t.g/255,l=t.b/255,a=Math.min(r,o,l),u=Math.max(r,o,l),d=NaN,f=u-a,g=(u+a)/2;return f?(r===u?d=(o-l)/f+(o0&&g<1?0:d,new nn(d,f,g,t.opacity)}function gx(t,r,o,l){return arguments.length===1?Op(t):new nn(t,r,o,l??1)}function nn(t,r,o,l){this.h=+t,this.s=+r,this.l=+o,this.opacity=+l}nc(nn,gx,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new nn(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new nn(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,r=isNaN(t)||isNaN(this.s)?0:this.s,o=this.l,l=o+(o<.5?o:1-o)*r,a=2*o-l;return new Pt(ju(t>=240?t-240:t+120,a,l),ju(t,a,l),ju(t<120?t+240:t-120,a,l),this.opacity)},clamp(){return new nn(lh(this.h),Ks(this.s),Ks(this.l),fl(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=fl(this.opacity);return`${t===1?"hsl(":"hsla("}${lh(this.h)}, ${Ks(this.s)*100}%, ${Ks(this.l)*100}%${t===1?")":`, ${t})`}`}}));function lh(t){return t=(t||0)%360,t<0?t+360:t}function Ks(t){return Math.max(0,Math.min(1,t||0))}function ju(t,r,o){return(t<60?r+(o-r)*t/60:t<180?o:t<240?r+(o-r)*(240-t)/60:r)*255}const rc=t=>()=>t;function mx(t,r){return function(o){return t+o*r}}function yx(t,r,o){return t=Math.pow(t,o),r=Math.pow(r,o)-t,o=1/o,function(l){return Math.pow(t+l*r,o)}}function vx(t){return(t=+t)==1?Fp:function(r,o){return o-r?yx(r,o,t):rc(isNaN(r)?o:r)}}function Fp(t,r){var o=r-t;return o?mx(t,o):rc(isNaN(t)?r:t)}const hl=(function t(r){var o=vx(r);function l(a,u){var d=o((a=Bu(a)).r,(u=Bu(u)).r),f=o(a.g,u.g),g=o(a.b,u.b),y=Fp(a.opacity,u.opacity);return function(m){return a.r=d(m),a.g=f(m),a.b=g(m),a.opacity=y(m),a+""}}return l.gamma=t,l})(1);function xx(t,r){r||(r=[]);var o=t?Math.min(r.length,t.length):0,l=r.slice(),a;return function(u){for(a=0;ao&&(u=r.slice(o,u),f[d]?f[d]+=u:f[++d]=u),(l=l[0])===(a=a[0])?f[d]?f[d]+=a:f[++d]=a:(f[++d]=null,g.push({i:d,x:gn(l,a)})),o=bu.lastIndex;return o180?m+=360:m-y>180&&(y+=360),v.push({i:x.push(a(x)+"rotate(",null,l)-2,x:gn(y,m)})):m&&x.push(a(x)+"rotate("+m+l)}function f(y,m,x,v){y!==m?v.push({i:x.push(a(x)+"skewX(",null,l)-2,x:gn(y,m)}):m&&x.push(a(x)+"skewX("+m+l)}function g(y,m,x,v,_,S){if(y!==x||m!==v){var j=_.push(a(_)+"scale(",null,",",null,")");S.push({i:j-4,x:gn(y,x)},{i:j-2,x:gn(m,v)})}else(x!==1||v!==1)&&_.push(a(_)+"scale("+x+","+v+")")}return function(y,m){var x=[],v=[];return y=t(y),m=t(m),u(y.translateX,y.translateY,m.translateX,m.translateY,x,v),d(y.rotate,m.rotate,x,v),f(y.skewX,m.skewX,x,v),g(y.scaleX,y.scaleY,m.scaleX,m.scaleY,x,v),y=m=null,function(_){for(var S=-1,j=v.length,N;++S=0&&t._call.call(void 0,r),t=t._next;--Pi}function ch(){Fr=(gl=Mo.now())+El,Pi=_o=0;try{Lx()}finally{Pi=0,zx(),Fr=0}}function Ax(){var t=Mo.now(),r=t-gl;r>Wp&&(El-=r,gl=t)}function zx(){for(var t,r=pl,o,l=1/0;r;)r._call?(l>r._time&&(l=r._time),t=r,r=r._next):(o=r._next,r._next=null,r=t?t._next=o:pl=o);So=t,Uu(l)}function Uu(t){if(!Pi){_o&&(_o=clearTimeout(_o));var r=t-Fr;r>24?(t<1/0&&(_o=setTimeout(ch,t-Mo.now()-El)),xo&&(xo=clearInterval(xo))):(xo||(gl=Mo.now(),xo=setInterval(Ax,Wp)),Pi=1,Up(ch))}}function dh(t,r,o){var l=new ml;return r=r==null?0:+r,l.restart(a=>{l.stop(),t(a+r)},r,o),l}var Dx=Sl("start","end","cancel","interrupt"),$x=[],Gp=0,fh=1,Yu=2,ll=3,hh=4,Gu=5,al=6;function Nl(t,r,o,l,a,u){var d=t.__transition;if(!d)t.__transition={};else if(o in d)return;Ox(t,o,{name:r,index:l,group:a,on:Dx,tween:$x,time:u.time,delay:u.delay,duration:u.duration,ease:u.ease,timer:null,state:Gp})}function oc(t,r){var o=ln(t,r);if(o.state>Gp)throw new Error("too late; already scheduled");return o}function yn(t,r){var o=ln(t,r);if(o.state>ll)throw new Error("too late; already running");return o}function ln(t,r){var o=t.__transition;if(!o||!(o=o[r]))throw new Error("transition not found");return o}function Ox(t,r,o){var l=t.__transition,a;l[r]=o,o.timer=Yp(u,0,o.time);function u(y){o.state=fh,o.timer.restart(d,o.delay,o.time),o.delay<=y&&d(y-o.delay)}function d(y){var m,x,v,_;if(o.state!==fh)return g();for(m in l)if(_=l[m],_.name===o.name){if(_.state===ll)return dh(d);_.state===hh?(_.state=al,_.timer.stop(),_.on.call("interrupt",t,t.__data__,_.index,_.group),delete l[m]):+mYu&&l.state=0&&(r=r.slice(0,o)),!r||r==="start"})}function gw(t,r,o){var l,a,u=pw(r)?oc:yn;return function(){var d=u(this,t),f=d.on;f!==l&&(a=(l=f).copy()).on(r,o),d.on=a}}function mw(t,r){var o=this._id;return arguments.length<2?ln(this.node(),o).on.on(t):this.each(gw(o,t,r))}function yw(t){return function(){var r=this.parentNode;for(var o in this.__transition)if(+o!==t)return;r&&r.removeChild(this)}}function vw(){return this.on("end.remove",yw(this._id))}function xw(t){var r=this._name,o=this._id;typeof t!="function"&&(t=ec(t));for(var l=this._groups,a=l.length,u=new Array(a),d=0;d()=>t;function Ww(t,{sourceEvent:r,target:o,transform:l,dispatch:a}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},transform:{value:l,enumerable:!0,configurable:!0},_:{value:a}})}function Rn(t,r,o){this.k=t,this.x=r,this.y=o}Rn.prototype={constructor:Rn,scale:function(t){return t===1?this:new Rn(this.k*t,this.x,this.y)},translate:function(t,r){return t===0&r===0?this:new Rn(this.k,this.x+this.k*t,this.y+this.k*r)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var jl=new Rn(1,0,0);Kp.prototype=Rn.prototype;function Kp(t){for(;!t.__zoom;)if(!(t=t.parentNode))return jl;return t.__zoom}function Cu(t){t.stopImmediatePropagation()}function wo(t){t.preventDefault(),t.stopImmediatePropagation()}function Uw(t){return(!t.ctrlKey||t.type==="wheel")&&!t.button}function Yw(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t,t.hasAttribute("viewBox")?(t=t.viewBox.baseVal,[[t.x,t.y],[t.x+t.width,t.y+t.height]]):[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]):[[0,0],[t.clientWidth,t.clientHeight]]}function ph(){return this.__zoom||jl}function Gw(t){return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Xw(){return navigator.maxTouchPoints||"ontouchstart"in this}function qw(t,r,o){var l=t.invertX(r[0][0])-o[0][0],a=t.invertX(r[1][0])-o[1][0],u=t.invertY(r[0][1])-o[0][1],d=t.invertY(r[1][1])-o[1][1];return t.translate(a>l?(l+a)/2:Math.min(0,l)||Math.max(0,a),d>u?(u+d)/2:Math.min(0,u)||Math.max(0,d))}function Zp(){var t=Uw,r=Yw,o=qw,l=Gw,a=Xw,u=[0,1/0],d=[[-1/0,-1/0],[1/0,1/0]],f=250,g=sl,y=Sl("start","zoom","end"),m,x,v,_=500,S=150,j=0,N=10;function k(C){C.property("__zoom",ph).on("wheel.zoom",I,{passive:!1}).on("mousedown.zoom",q).on("dblclick.zoom",ne).filter(a).on("touchstart.zoom",G).on("touchmove.zoom",ee).on("touchend.zoom touchcancel.zoom",J).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}k.transform=function(C,Y,V,U){var z=C.selection?C.selection():C;z.property("__zoom",ph),C!==z?$(C,Y,V,U):z.interrupt().each(function(){O(this,arguments).event(U).start().zoom(null,typeof Y=="function"?Y.apply(this,arguments):Y).end()})},k.scaleBy=function(C,Y,V,U){k.scaleTo(C,function(){var z=this.__zoom.k,D=typeof Y=="function"?Y.apply(this,arguments):Y;return z*D},V,U)},k.scaleTo=function(C,Y,V,U){k.transform(C,function(){var z=r.apply(this,arguments),D=this.__zoom,W=V==null?b(z):typeof V=="function"?V.apply(this,arguments):V,M=D.invert(W),R=typeof Y=="function"?Y.apply(this,arguments):Y;return o(E(T(D,R),W,M),z,d)},V,U)},k.translateBy=function(C,Y,V,U){k.transform(C,function(){return o(this.__zoom.translate(typeof Y=="function"?Y.apply(this,arguments):Y,typeof V=="function"?V.apply(this,arguments):V),r.apply(this,arguments),d)},null,U)},k.translateTo=function(C,Y,V,U,z){k.transform(C,function(){var D=r.apply(this,arguments),W=this.__zoom,M=U==null?b(D):typeof U=="function"?U.apply(this,arguments):U;return o(jl.translate(M[0],M[1]).scale(W.k).translate(typeof Y=="function"?-Y.apply(this,arguments):-Y,typeof V=="function"?-V.apply(this,arguments):-V),D,d)},U,z)};function T(C,Y){return Y=Math.max(u[0],Math.min(u[1],Y)),Y===C.k?C:new Rn(Y,C.x,C.y)}function E(C,Y,V){var U=Y[0]-V[0]*C.k,z=Y[1]-V[1]*C.k;return U===C.x&&z===C.y?C:new Rn(C.k,U,z)}function b(C){return[(+C[0][0]+ +C[1][0])/2,(+C[0][1]+ +C[1][1])/2]}function $(C,Y,V,U){C.on("start.zoom",function(){O(this,arguments).event(U).start()}).on("interrupt.zoom end.zoom",function(){O(this,arguments).event(U).end()}).tween("zoom",function(){var z=this,D=arguments,W=O(z,D).event(U),M=r.apply(z,D),R=V==null?b(M):typeof V=="function"?V.apply(z,D):V,re=Math.max(M[1][0]-M[0][0],M[1][1]-M[0][1]),ie=z.__zoom,ce=typeof Y=="function"?Y.apply(z,D):Y,fe=g(ie.invert(R).concat(re/ie.k),ce.invert(R).concat(re/ce.k));return function(de){if(de===1)de=ce;else{var K=fe(de),le=re/K[2];de=new Rn(le,R[0]-K[0]*le,R[1]-K[1]*le)}W.zoom(null,de)}})}function O(C,Y,V){return!V&&C.__zooming||new H(C,Y)}function H(C,Y){this.that=C,this.args=Y,this.active=0,this.sourceEvent=null,this.extent=r.apply(C,Y),this.taps=0}H.prototype={event:function(C){return C&&(this.sourceEvent=C),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(C,Y){return this.mouse&&C!=="mouse"&&(this.mouse[1]=Y.invert(this.mouse[0])),this.touch0&&C!=="touch"&&(this.touch0[1]=Y.invert(this.touch0[0])),this.touch1&&C!=="touch"&&(this.touch1[1]=Y.invert(this.touch1[0])),this.that.__zoom=Y,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(C){var Y=Ot(this.that).datum();y.call(C,this.that,new Ww(C,{sourceEvent:this.sourceEvent,target:k,transform:this.that.__zoom,dispatch:y}),Y)}};function I(C,...Y){if(!t.apply(this,arguments))return;var V=O(this,Y).event(C),U=this.__zoom,z=Math.max(u[0],Math.min(u[1],U.k*Math.pow(2,l.apply(this,arguments)))),D=tn(C);if(V.wheel)(V.mouse[0][0]!==D[0]||V.mouse[0][1]!==D[1])&&(V.mouse[1]=U.invert(V.mouse[0]=D)),clearTimeout(V.wheel);else{if(U.k===z)return;V.mouse=[D,U.invert(D)],ul(this),V.start()}wo(C),V.wheel=setTimeout(W,S),V.zoom("mouse",o(E(T(U,z),V.mouse[0],V.mouse[1]),V.extent,d));function W(){V.wheel=null,V.end()}}function q(C,...Y){if(v||!t.apply(this,arguments))return;var V=C.currentTarget,U=O(this,Y,!0).event(C),z=Ot(C.view).on("mousemove.zoom",R,!0).on("mouseup.zoom",re,!0),D=tn(C,V),W=C.clientX,M=C.clientY;Ap(C.view),Cu(C),U.mouse=[D,this.__zoom.invert(D)],ul(this),U.start();function R(ie){if(wo(ie),!U.moved){var ce=ie.clientX-W,fe=ie.clientY-M;U.moved=ce*ce+fe*fe>j}U.event(ie).zoom("mouse",o(E(U.that.__zoom,U.mouse[0]=tn(ie,V),U.mouse[1]),U.extent,d))}function re(ie){z.on("mousemove.zoom mouseup.zoom",null),zp(ie.view,U.moved),wo(ie),U.event(ie).end()}}function ne(C,...Y){if(t.apply(this,arguments)){var V=this.__zoom,U=tn(C.changedTouches?C.changedTouches[0]:C,this),z=V.invert(U),D=V.k*(C.shiftKey?.5:2),W=o(E(T(V,D),U,z),r.apply(this,Y),d);wo(C),f>0?Ot(this).transition().duration(f).call($,W,U,C):Ot(this).call(k.transform,W,U,C)}}function G(C,...Y){if(t.apply(this,arguments)){var V=C.touches,U=V.length,z=O(this,Y,C.changedTouches.length===U).event(C),D,W,M,R;for(Cu(C),W=0;W`Seems like you have not used ${t==="svelte"?"SvelteFlowProvider":"ReactFlowProvider"} as an ancestor. Help: https://${t}flow.dev/error#001`,error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:t=>`Node type "${t}" not found. Using fallback type "default".`,error004:()=>"The parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:t=>`The old edge with id=${t} does not exist.`,error009:t=>`Marker type "${t}" doesn't exist.`,error008:(t,{id:r,sourceHandle:o,targetHandle:l})=>`Couldn't create edge for ${t} handle id: "${t==="source"?o:l}", edge id: ${r}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:t=>`Edge type "${t}" not found. Using fallback type "default".`,error012:t=>`Node with id "${t}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(t="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${t}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs.",error016:t=>`Edge with id "${t}" does not exist, it may have been removed. This can happen when an edge is deleted before the "onEdgeClick" handler is called.`},Po=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Jp=["Enter"," ","Escape"],eg={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:t,x:r,y:o})=>`Moved selected node ${t}. New position, x: ${r}, y: ${o}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"};var Ii;(function(t){t.Strict="strict",t.Loose="loose"})(Ii||(Ii={}));var $r;(function(t){t.Free="free",t.Vertical="vertical",t.Horizontal="horizontal"})($r||($r={}));var Io;(function(t){t.Partial="partial",t.Full="full"})(Io||(Io={}));const tg={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};var dr;(function(t){t.Bezier="default",t.Straight="straight",t.Step="step",t.SmoothStep="smoothstep",t.SimpleBezier="simplebezier"})(dr||(dr={}));var To;(function(t){t.Arrow="arrow",t.ArrowClosed="arrowclosed"})(To||(To={}));var Se;(function(t){t.Left="left",t.Top="top",t.Right="right",t.Bottom="bottom"})(Se||(Se={}));const gh={[Se.Left]:Se.Right,[Se.Right]:Se.Left,[Se.Top]:Se.Bottom,[Se.Bottom]:Se.Top};function ng(t){return t===null?null:t?"valid":"invalid"}const rg=t=>!!t&&typeof t=="object"&&"id"in t&&"source"in t&&"target"in t,Qw=t=>!!t&&typeof t=="object"&&"id"in t&&"position"in t&&!("source"in t)&&!("target"in t),lc=t=>!!t&&typeof t=="object"&&"id"in t&&"internals"in t&&!("source"in t)&&!("target"in t),Oo=(t,r=[0,0])=>{const{width:o,height:l}=an(t),a=t.origin??r,u=o*a[0],d=l*a[1];return{x:t.position.x-u,y:t.position.y-d}},Kw=(t,r={nodeOrigin:[0,0]})=>{if(t.length===0)return{x:0,y:0,width:0,height:0};let o=!1;const l=t.reduce((a,u)=>{const d=typeof u=="string";let f=!r.nodeLookup&&!d?u:void 0;return r.nodeLookup&&(f=d?r.nodeLookup.get(u):lc(u)?u:r.nodeLookup.get(u.id)),f?(o=!0,bl(a,yl(f,r.nodeOrigin))):a},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return o?Cl(l):{x:0,y:0,width:0,height:0}},Fo=(t,r={})=>{let o={x:1/0,y:1/0,x2:-1/0,y2:-1/0},l=!1;return t.forEach(a=>{(r.filter===void 0||r.filter(a))&&(o=bl(o,yl(a)),l=!0)}),l?Cl(o):{x:0,y:0,width:0,height:0}},ac=(t,r,[o,l,a]=[0,0,1],u=!1,d=!1)=>{const f=(r.x-o)/a,g=(r.y-l)/a,y=r.width/a,m=r.height/a,x=[];for(const v of t.values()){const{measured:_,selectable:S=!0,hidden:j=!1}=v;if(d&&!S||j)continue;const N=_.width??v.width??v.initialWidth??0,k=_.height??v.height??v.initialHeight??0,{x:T,y:E}=v.internals.positionAbsolute,b=lg(f,g,y,m,T,E,N,k),$=N*k,O=u&&b>0;(!v.internals.handleBounds||O||b>=$||v.dragging)&&x.push(v)}return x},Zw=(t,r)=>{const o=new Set;return t.forEach(l=>{o.add(l.id)}),r.filter(l=>o.has(l.source)||o.has(l.target))};function Jw(t,r){const o=new Map,l=r!=null&&r.nodes?new Set(r.nodes.map(a=>a.id)):null;return t.forEach(a=>{let u;if(r!=null&&r.includeHiddenNodes){const{width:d,height:f}=an(a);u=d>0&&f>0}else u=!!(a.measured.width&&a.measured.height&&!a.hidden);u&&(!l||l.has(a.id))&&o.set(a.id,a)}),o}async function e1({nodes:t,width:r,height:o,panZoom:l,minZoom:a,maxZoom:u},d){if(t.size===0)return!0;const f=Jw(t,d),g=Fo(f),y=cc(g,r,o,(d==null?void 0:d.minZoom)??a,(d==null?void 0:d.maxZoom)??u,(d==null?void 0:d.padding)??.1);return await l.setViewport(y,{duration:d==null?void 0:d.duration,ease:d==null?void 0:d.ease,interpolate:d==null?void 0:d.interpolate}),!0}function ig({nodeId:t,nextPosition:r,nodeLookup:o,nodeOrigin:l=[0,0],nodeExtent:a,onError:u}){const d=o.get(t),f=d.parentId?o.get(d.parentId):void 0,{x:g,y}=f?f.internals.positionAbsolute:{x:0,y:0},m=d.origin??l;let x=d.extent||a;if(d.extent==="parent"&&!d.expandParent)if(!f)u==null||u("005",sn.error005());else{const{width:_,height:S}=an(f);_&&S&&(x=[[g,y],[g+_,y+S]])}else f&&Br(d.extent)&&(x=[[d.extent[0][0]+g,d.extent[0][1]+y],[d.extent[1][0]+g,d.extent[1][1]+y]]);const v=Br(x)?Hr(r,x,d.measured):r;return(d.measured.width===void 0||d.measured.height===void 0)&&(u==null||u("015",sn.error015())),{position:{x:v.x-g+(d.measured.width??0)*m[0],y:v.y-y+(d.measured.height??0)*m[1]},positionAbsolute:v}}async function t1({nodesToRemove:t=[],edgesToRemove:r=[],nodes:o,edges:l,onBeforeDelete:a}){const u=new Set(t.map(v=>v.id)),d=[];for(const v of o){if(v.deletable===!1)continue;const _=u.has(v.id),S=!_&&v.parentId&&d.find(j=>j.id===v.parentId);(_||S)&&d.push(v)}const f=new Set(r.map(v=>v.id)),g=l.filter(v=>v.deletable!==!1),m=Zw(d,g);for(const v of g)f.has(v.id)&&!m.find(S=>S.id===v.id)&&m.push(v);if(!a)return{edges:m,nodes:d};const x=await a({nodes:d,edges:m});return typeof x=="boolean"?x?{edges:m,nodes:d}:{edges:[],nodes:[]}:x}const Ti=(t,r=0,o=1)=>Math.min(Math.max(t,r),o),Hr=(t={x:0,y:0},r,o)=>({x:Ti(t.x,r[0][0],r[1][0]-((o==null?void 0:o.width)??0)),y:Ti(t.y,r[0][1],r[1][1]-((o==null?void 0:o.height)??0))});function og(t,r,o){const{width:l,height:a}=an(o),{x:u,y:d}=o.internals.positionAbsolute;return Hr(t,[[u,d],[u+l,d+a]],r)}const mh=(t,r,o)=>to?-Ti(Math.abs(t-o),1,r)/r:0,uc=(t,r,o=15,l=40)=>{const a=mh(t.x,l,r.width-l)*o,u=mh(t.y,l,r.height-l)*o;return[a,u]},bl=(t,r)=>({x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),x2:Math.max(t.x2,r.x2),y2:Math.max(t.y2,r.y2)}),Xu=({x:t,y:r,width:o,height:l})=>({x:t,y:r,x2:t+o,y2:r+l}),Cl=({x:t,y:r,x2:o,y2:l})=>({x:t,y:r,width:o-t,height:l-r}),Ro=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,width:((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0,height:((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0}},yl=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,x2:o+(((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0),y2:l+(((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0)}},sg=(t,r)=>Cl(bl(Xu(t),Xu(r))),lg=(t,r,o,l,a,u,d,f)=>{const g=Math.max(0,Math.min(t+o,a+d)-Math.max(t,a)),y=Math.max(0,Math.min(r+l,u+f)-Math.max(r,u));return Math.ceil(g*y)},vl=(t,r)=>lg(t.x,t.y,t.width,t.height,r.x,r.y,r.width,r.height),yh=t=>rn(t.width)&&rn(t.height)&&rn(t.x)&&rn(t.y),rn=t=>!isNaN(t)&&isFinite(t),ag=(t,r)=>(o,l)=>{},Ho=(t,r=[1,1])=>({x:r[0]*Math.round(t.x/r[0]),y:r[1]*Math.round(t.y/r[1])}),Bo=({x:t,y:r},[o,l,a],u=!1,d=[1,1])=>{const f={x:(t-o)/a,y:(r-l)/a};return u?Ho(f,d):f},Ri=({x:t,y:r},[o,l,a])=>({x:t*a+o,y:r*a+l});function Ei(t,r){if(typeof t=="number")return Math.floor((r-r/(1+t))*.5);if(typeof t=="string"&&t.endsWith("px")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(o)}if(typeof t=="string"&&t.endsWith("%")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(r*o*.01)}return console.error(`The padding value "${t}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function n1(t,r,o){if(typeof t=="string"||typeof t=="number"){const l=Ei(t,o),a=Ei(t,r);return{top:l,right:a,bottom:l,left:a,x:a*2,y:l*2}}if(typeof t=="object"){const l=Ei(t.top??t.y??0,o),a=Ei(t.bottom??t.y??0,o),u=Ei(t.left??t.x??0,r),d=Ei(t.right??t.x??0,r);return{top:l,right:d,bottom:a,left:u,x:u+d,y:l+a}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function r1(t,r,o,l,a,u){const{x:d,y:f}=Ri(t,[r,o,l]),{x:g,y}=Ri({x:t.x+t.width,y:t.y+t.height},[r,o,l]),m=a-g,x=u-y;return{left:Math.floor(d),top:Math.floor(f),right:Math.floor(m),bottom:Math.floor(x)}}const cc=(t,r,o,l,a,u)=>{const d=n1(u,r,o),f=(r-d.x)/t.width,g=(o-d.y)/t.height,y=Math.min(f,g),m=Ti(y,l,a),x=t.x+t.width/2,v=t.y+t.height/2,_=r/2-x*m,S=o/2-v*m,j=r1(t,_,S,m,r,o),N={left:Math.min(j.left-d.left,0),top:Math.min(j.top-d.top,0),right:Math.min(j.right-d.right,0),bottom:Math.min(j.bottom-d.bottom,0)};return{x:_-N.left+N.right,y:S-N.top+N.bottom,zoom:m}},Lo=()=>{var t;return typeof navigator<"u"&&((t=navigator==null?void 0:navigator.userAgent)==null?void 0:t.indexOf("Mac"))>=0};function Br(t){return t!=null&&t!=="parent"}function an(t){var r,o;return{width:((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth??0,height:((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight??0}}function ug(t){var r,o;return(((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth)!==void 0&&(((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight)!==void 0}function cg(t,r={width:0,height:0},o,l,a){const u={...t},d=l.get(o);if(d){const f=d.origin||a;u.x+=d.internals.positionAbsolute.x-(r.width??0)*f[0],u.y+=d.internals.positionAbsolute.y-(r.height??0)*f[1]}return u}function vh(t,r){if(t.size!==r.size)return!1;for(const o of t)if(!r.has(o))return!1;return!0}function i1(){let t,r;return{promise:new Promise((l,a)=>{t=l,r=a}),resolve:t,reject:r}}function o1(t){return{...eg,...t||{}}}function Eo(t,{snapGrid:r=[0,0],snapToGrid:o=!1,transform:l,containerBounds:a}){const{x:u,y:d}=on(t),f=Bo({x:u-((a==null?void 0:a.left)??0),y:d-((a==null?void 0:a.top)??0)},l),{x:g,y}=o?Ho(f,r):f;return{xSnapped:g,ySnapped:y,...f}}const dc=t=>({width:t.offsetWidth,height:t.offsetHeight}),dg=t=>{var r;return((r=t==null?void 0:t.getRootNode)==null?void 0:r.call(t))||(window==null?void 0:window.document)},s1=["INPUT","SELECT","TEXTAREA"];function fg(t){var l,a;const r=((a=(l=t.composedPath)==null?void 0:l.call(t))==null?void 0:a[0])||t.target;return(r==null?void 0:r.nodeType)!==1?!1:s1.includes(r.nodeName)||r.hasAttribute("contenteditable")||!!r.closest(".nokey")}const hg=t=>"clientX"in t,on=(t,r)=>{var u,d;const o=hg(t),l=o?t.clientX:(u=t.touches)==null?void 0:u[0].clientX,a=o?t.clientY:(d=t.touches)==null?void 0:d[0].clientY;return{x:l-((r==null?void 0:r.left)??0),y:a-((r==null?void 0:r.top)??0)}},xh=(t,r,o,l,a)=>{const u=r.querySelectorAll(`.${t}`);return!u||!u.length?null:Array.from(u).map(d=>{const f=d.getBoundingClientRect();return{id:d.getAttribute("data-handleid"),type:t,nodeId:a,position:d.getAttribute("data-handlepos"),x:(f.left-o.left)/l,y:(f.top-o.top)/l,...dc(d)}})};function pg({sourceX:t,sourceY:r,targetX:o,targetY:l,sourceControlX:a,sourceControlY:u,targetControlX:d,targetControlY:f}){const g=t*.125+a*.375+d*.375+o*.125,y=r*.125+u*.375+f*.375+l*.125,m=Math.abs(g-t),x=Math.abs(y-r);return[g,y,m,x]}function el(t,r){return t>=0?.5*t:r*25*Math.sqrt(-t)}function wh({pos:t,x1:r,y1:o,x2:l,y2:a,c:u}){switch(t){case Se.Left:return[r-el(r-l,u),o];case Se.Right:return[r+el(l-r,u),o];case Se.Top:return[r,o-el(o-a,u)];case Se.Bottom:return[r,o+el(a-o,u)]}}function gg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top,curvature:d=.25}){const[f,g]=wh({pos:o,x1:t,y1:r,x2:l,y2:a,c:d}),[y,m]=wh({pos:u,x1:l,y1:a,x2:t,y2:r,c:d}),[x,v,_,S]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:f,sourceControlY:g,targetControlX:y,targetControlY:m});return[`M${t},${r} C${f},${g} ${y},${m} ${l},${a}`,x,v,_,S]}function mg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const a=Math.abs(o-t)/2,u=o0}const u1=({source:t,sourceHandle:r,target:o,targetHandle:l})=>`xy-edge__${t}${r||""}-${o}${l||""}`,c1=(t,r)=>r.some(o=>o.source===t.source&&o.target===t.target&&(o.sourceHandle===t.sourceHandle||!o.sourceHandle&&!t.sourceHandle)&&(o.targetHandle===t.targetHandle||!o.targetHandle&&!t.targetHandle)),d1=(t,r,o={})=>{var u;if(!t.source||!t.target)return(u=o.onError)==null||u.call(o,"006",sn.error006()),r;const l=o.getEdgeId||u1;let a;return rg(t)?a={...t}:a={...t,id:l(t)},c1(a,r)?r:(a.sourceHandle===null&&delete a.sourceHandle,a.targetHandle===null&&delete a.targetHandle,r.concat(a))};function yg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const[a,u,d,f]=mg({sourceX:t,sourceY:r,targetX:o,targetY:l});return[`M ${t},${r}L ${o},${l}`,a,u,d,f]}const _h={[Se.Left]:{x:-1,y:0},[Se.Right]:{x:1,y:0},[Se.Top]:{x:0,y:-1},[Se.Bottom]:{x:0,y:1}},f1=({source:t,sourcePosition:r=Se.Bottom,target:o})=>r===Se.Left||r===Se.Right?t.xMath.sqrt(Math.pow(r.x-t.x,2)+Math.pow(r.y-t.y,2));function h1({source:t,sourcePosition:r=Se.Bottom,target:o,targetPosition:l=Se.Top,center:a,offset:u,stepPosition:d}){const f=_h[r],g=_h[l],y={x:t.x+f.x*u,y:t.y+f.y*u},m={x:o.x+g.x*u,y:o.y+g.y*u},x=f1({source:y,sourcePosition:r,target:m}),v=x.x!==0?"x":"y",_=x[v];let S=[],j,N;const k={x:0,y:0},T={x:0,y:0},[,,E,b]=mg({sourceX:t.x,sourceY:t.y,targetX:o.x,targetY:o.y});if(f[v]*g[v]===-1){v==="x"?(j=a.x??y.x+(m.x-y.x)*d,N=a.y??(y.y+m.y)/2):(j=a.x??(y.x+m.x)/2,N=a.y??y.y+(m.y-y.y)*d);const I=[{x:j,y:y.y},{x:j,y:m.y}],q=[{x:y.x,y:N},{x:m.x,y:N}];f[v]===_?S=v==="x"?I:q:S=v==="x"?q:I}else{const I=[{x:y.x,y:m.y}],q=[{x:m.x,y:y.y}];if(v==="x"?S=f.x===_?q:I:S=f.y===_?I:q,r===l){const C=Math.abs(t[v]-o[v]);if(C<=u){const Y=Math.min(u-1,u-C);f[v]===_?k[v]=(y[v]>t[v]?-1:1)*Y:T[v]=(m[v]>o[v]?-1:1)*Y}}if(r!==l){const C=v==="x"?"y":"x",Y=f[v]===g[C],V=y[C]>m[C],U=y[C]=J?(j=(ne.x+G.x)/2,N=S[0].y):(j=S[0].x,N=(ne.y+G.y)/2)}const $={x:y.x+k.x,y:y.y+k.y},O={x:m.x+T.x,y:m.y+T.y};return[[t,...$.x!==S[0].x||$.y!==S[0].y?[$]:[],...S,...O.x!==S[S.length-1].x||O.y!==S[S.length-1].y?[O]:[],o],j,N,E,b]}function p1(t,r,o,l){const a=Math.min(Sh(t,r)/2,Sh(r,o)/2,l),{x:u,y:d}=r;if(t.x===u&&u===o.x||t.y===d&&d===o.y)return`L${u} ${d}`;if(t.y===d){const y=t.xo.id===r):t[0])||null}function Qu(t,r){return t?typeof t=="string"?t:`${r?`${r}__`:""}${Object.keys(t).sort().map(l=>`${l}=${t[l]}`).join("&")}`:""}function m1(t,{id:r,defaultColor:o,defaultMarkerStart:l,defaultMarkerEnd:a}){const u=new Set;return t.reduce((d,f)=>([f.markerStart||l,f.markerEnd||a].forEach(g=>{if(g&&typeof g=="object"){const y=Qu(g,r);u.has(y)||(d.push({id:y,color:g.color||o,...g}),u.add(y))}}),d),[]).sort((d,f)=>d.id.localeCompare(f.id))}const vg=1e3,y1=10,fc={nodeOrigin:[0,0],nodeExtent:Po,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},v1={...fc,checkEquality:!0};function hc(t,r){const o={...t};for(const l in r)r[l]!==void 0&&(o[l]=r[l]);return o}function x1(t,r,o){const l=hc(fc,o);for(const a of t.values())if(a.parentId)gc(a,t,r,l);else{const u=Oo(a,l.nodeOrigin),d=Br(a.extent)?a.extent:l.nodeExtent,f=Hr(u,d,an(a));a.internals.positionAbsolute=f}}function w1(t,r){if(!t.handles)return t.measured?r==null?void 0:r.internals.handleBounds:void 0;const o=[],l=[];for(const a of t.handles){const u={id:a.id,width:a.width??1,height:a.height??1,nodeId:t.id,x:a.x,y:a.y,position:a.position,type:a.type};a.type==="source"?o.push(u):a.type==="target"&&l.push(u)}return{source:o,target:l}}function pc(t){return t==="manual"}function Ku(t,r,o,l={}){var m,x;const a=hc(v1,l),u={i:0},d=new Map(r),f=a!=null&&a.elevateNodesOnSelect&&!pc(a.zIndexMode)?vg:0;let g=t.length>0,y=!1;r.clear(),o.clear();for(const v of t){let _=d.get(v.id);if(a.checkEquality&&v===(_==null?void 0:_.internals.userNode))r.set(v.id,_);else{const S=Oo(v,a.nodeOrigin),j=Br(v.extent)?v.extent:a.nodeExtent,N=Hr(S,j,an(v));_={...a.defaults,...v,measured:{width:(m=v.measured)==null?void 0:m.width,height:(x=v.measured)==null?void 0:x.height},internals:{positionAbsolute:N,handleBounds:w1(v,_),z:xg(v,f,a.zIndexMode),userNode:v}},r.set(v.id,_)}(_.measured===void 0||_.measured.width===void 0||_.measured.height===void 0)&&!_.hidden&&(g=!1),v.parentId&&gc(_,r,o,l,u),y||(y=v.selected??!1)}return{nodesInitialized:g,hasSelectedNodes:y}}function _1(t,r){if(!t.parentId)return;const o=r.get(t.parentId);o?o.set(t.id,t):r.set(t.parentId,new Map([[t.id,t]]))}function gc(t,r,o,l,a){const{elevateNodesOnSelect:u,nodeOrigin:d,nodeExtent:f,zIndexMode:g}=hc(fc,l),y=t.parentId,m=r.get(y);if(!m){console.warn(`Parent node ${y} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}_1(t,o),a&&!m.parentId&&m.internals.rootParentIndex===void 0&&g==="auto"&&(m.internals.rootParentIndex=++a.i,m.internals.z=m.internals.z+a.i*y1),a&&m.internals.rootParentIndex!==void 0&&(a.i=m.internals.rootParentIndex);const x=u&&!pc(g)?vg:0,{x:v,y:_,z:S}=S1(t,m,d,f,x,g),{positionAbsolute:j}=t.internals,N=v!==j.x||_!==j.y;(N||S!==t.internals.z)&&r.set(t.id,{...t,internals:{...t.internals,positionAbsolute:N?{x:v,y:_}:j,z:S}})}function xg(t,r,o){const l=rn(t.zIndex)?t.zIndex:0;return pc(o)?l:l+(t.selected?r:0)}function S1(t,r,o,l,a,u){const{x:d,y:f}=r.internals.positionAbsolute,g=an(t),y=Oo(t,o),m=Br(t.extent)?Hr(y,t.extent,g):y;let x=Hr({x:d+m.x,y:f+m.y},l,g);t.extent==="parent"&&(x=og(x,g,r));const v=xg(t,a,u),_=r.internals.z??0;return{x:x.x,y:x.y,z:_>=v?_+1:v}}function mc(t,r,o,l=[0,0]){var d;const a=[],u=new Map;for(const f of t){const g=r.get(f.parentId);if(!g)continue;const y=((d=u.get(f.parentId))==null?void 0:d.expandedRect)??Ro(g),m=sg(y,f.rect);u.set(f.parentId,{expandedRect:m,parent:g})}return u.size>0&&u.forEach(({expandedRect:f,parent:g},y)=>{var E;const m=g.internals.positionAbsolute,x=an(g),v=g.origin??l,_=f.x0||S>0||k||T)&&(a.push({id:y,type:"position",position:{x:g.position.x-_+k,y:g.position.y-S+T}}),(E=o.get(y))==null||E.forEach(b=>{t.some($=>$.id===b.id)||a.push({id:b.id,type:"position",position:{x:b.position.x+_,y:b.position.y+S}})})),(x.width0){const _=mc(v,r,o,a);y.push(..._)}return{changes:y,updatedInternals:g}}async function E1({delta:t,panZoom:r,transform:o,translateExtent:l,width:a,height:u}){if(!r||!t.x&&!t.y)return!1;const d=await r.setViewportConstrained({x:o[0]+t.x,y:o[1]+t.y,zoom:o[2]},[[0,0],[a,u]],l);return!!d&&(d.x!==o[0]||d.y!==o[1]||d.k!==o[2])}function jh(t,r,o,l,a,u){let d=a;const f=l.get(d)||new Map;l.set(d,f.set(o,r)),d=`${a}-${t}`;const g=l.get(d)||new Map;if(l.set(d,g.set(o,r)),u){d=`${a}-${t}-${u}`;const y=l.get(d)||new Map;l.set(d,y.set(o,r))}}function wg(t,r,o){t.clear(),r.clear();for(const l of o){const{source:a,target:u,sourceHandle:d=null,targetHandle:f=null}=l,g={edgeId:l.id,source:a,target:u,sourceHandle:d,targetHandle:f},y=`${a}-${d}--${u}-${f}`,m=`${u}-${f}--${a}-${d}`;jh("source",g,m,t,a,d),jh("target",g,y,t,u,f),r.set(l.id,l)}}function _g(t,r){if(!t.parentId)return!1;const o=r.get(t.parentId);return o?o.selected?!0:_g(o,r):!1}function bh(t,r,o){var a;let l=t;do{if((a=l==null?void 0:l.matches)!=null&&a.call(l,r))return!0;if(l===o)return!1;l=l==null?void 0:l.parentElement}while(l);return!1}function N1(t,r,o,l){const a=new Map;for(const[u,d]of t)if((d.selected||d.id===l)&&(!d.parentId||!_g(d,t))&&(d.draggable||r&&typeof d.draggable>"u")){const f=t.get(u);f&&a.set(u,{id:u,position:f.position||{x:0,y:0},distance:{x:o.x-f.internals.positionAbsolute.x,y:o.y-f.internals.positionAbsolute.y},extent:f.extent,parentId:f.parentId,origin:f.origin,expandParent:f.expandParent,internals:{positionAbsolute:f.internals.positionAbsolute||{x:0,y:0}},measured:{width:f.measured.width??0,height:f.measured.height??0}})}return a}function Mu({nodeId:t,dragItems:r,nodeLookup:o,dragging:l=!0}){var d,f,g;const a=[];for(const[y,m]of r){const x=(d=o.get(y))==null?void 0:d.internals.userNode;x&&a.push({...x,position:m.position,dragging:l})}if(!t)return[a[0],a];const u=(f=o.get(t))==null?void 0:f.internals.userNode;return[u?{...u,position:((g=r.get(t))==null?void 0:g.position)||u.position,dragging:l}:a[0],a]}function j1({dragItems:t,snapGrid:r,x:o,y:l}){const a=t.values().next().value;if(!a)return null;const u={x:o-a.distance.x,y:l-a.distance.y},d=Ho(u,r);return{x:d.x-u.x,y:d.y-u.y}}function b1({onNodeMouseDown:t,getStoreItems:r,onDragStart:o,onDrag:l,onDragStop:a}){let u={x:null,y:null},d=0,f=new Map,g=!1,y={x:0,y:0},m=null,x=!1,v=null,_=!1,S=!1,j=null;function N({noDragClassName:T,handleSelector:E,domNode:b,isSelectable:$,nodeId:O,nodeClickDistance:H=0}){v=Ot(b);function I({x:ee,y:J}){const{nodeLookup:C,nodeExtent:Y,snapGrid:V,snapToGrid:U,nodeOrigin:z,onNodeDrag:D,onSelectionDrag:W,onError:M,updateNodePositions:R}=r();u={x:ee,y:J};let re=!1;const ie=f.size>1,ce=ie&&Y?Xu(Fo(f)):null,fe=ie&&U?j1({dragItems:f,snapGrid:V,x:ee,y:J}):null;for(const[de,K]of f){if(!C.has(de))continue;let le={x:ee-K.distance.x,y:J-K.distance.y};U&&(le=fe?{x:Math.round(le.x+fe.x),y:Math.round(le.y+fe.y)}:Ho(le,V));let pe=null;if(ie&&Y&&!K.extent&&ce){const{positionAbsolute:ge}=K.internals,je=ge.x-ce.x+Y[0][0],Me=ge.x+K.measured.width-ce.x2+Y[1][0],Pe=ge.y-ce.y+Y[0][1],Re=ge.y+K.measured.height-ce.y2+Y[1][1];pe=[[je,Pe],[Me,Re]]}const{position:_e,positionAbsolute:xe}=ig({nodeId:de,nextPosition:le,nodeLookup:C,nodeExtent:pe||Y,nodeOrigin:z,onError:M});re=re||K.position.x!==_e.x||K.position.y!==_e.y,K.position=_e,K.internals.positionAbsolute=xe}if(S=S||re,!!re&&(R(f,!0),j&&(l||D||!O&&W))){const[de,K]=Mu({nodeId:O,dragItems:f,nodeLookup:C});l==null||l(j,f,de,K),D==null||D(j,de,K),O||W==null||W(j,K)}}async function q(){if(!m)return;const{transform:ee,panBy:J,autoPanSpeed:C,autoPanOnNodeDrag:Y}=r();if(!Y){g=!1,cancelAnimationFrame(d);return}const[V,U]=uc(y,m,C);(V!==0||U!==0)&&(u.x=(u.x??0)-V/ee[2],u.y=(u.y??0)-U/ee[2],await J({x:V,y:U})&&I(u)),d=requestAnimationFrame(q)}function ne(ee){var ie;const{nodeLookup:J,multiSelectionActive:C,nodesDraggable:Y,transform:V,snapGrid:U,snapToGrid:z,selectNodesOnDrag:D,onNodeDragStart:W,onSelectionDragStart:M,unselectNodesAndEdges:R}=r();x=!0,(!D||!$)&&!C&&O&&((ie=J.get(O))!=null&&ie.selected||R()),$&&D&&O&&(t==null||t(O));const re=Eo(ee.sourceEvent,{transform:V,snapGrid:U,snapToGrid:z,containerBounds:m});if(u=re,f=N1(J,Y,re,O),f.size>0&&(o||W||!O&&M)){const[ce,fe]=Mu({nodeId:O,dragItems:f,nodeLookup:J});o==null||o(ee.sourceEvent,f,ce,fe),W==null||W(ee.sourceEvent,ce,fe),O||M==null||M(ee.sourceEvent,fe)}}const G=Dp().clickDistance(H).on("start",ee=>{const{domNode:J,nodeDragThreshold:C,transform:Y,snapGrid:V,snapToGrid:U}=r();m=(J==null?void 0:J.getBoundingClientRect())||null,_=!1,S=!1,j=ee.sourceEvent,C===0&&ne(ee),u=Eo(ee.sourceEvent,{transform:Y,snapGrid:V,snapToGrid:U,containerBounds:m}),y=on(ee.sourceEvent,m)}).on("drag",ee=>{const{autoPanOnNodeDrag:J,transform:C,snapGrid:Y,snapToGrid:V,nodeDragThreshold:U,nodeLookup:z}=r(),D=Eo(ee.sourceEvent,{transform:C,snapGrid:Y,snapToGrid:V,containerBounds:m});if(j=ee.sourceEvent,(ee.sourceEvent.type==="touchmove"&&ee.sourceEvent.touches.length>1||O&&!z.has(O))&&(_=!0),!_){if(!g&&J&&x&&(g=!0,q()),!x){const W=on(ee.sourceEvent,m),M=W.x-y.x,R=W.y-y.y;Math.sqrt(M*M+R*R)>U&&ne(ee)}(u.x!==D.xSnapped||u.y!==D.ySnapped)&&f&&x&&(y=on(ee.sourceEvent,m),I(D))}}).on("end",ee=>{if(!x||_){_&&f.size>0&&r().updateNodePositions(f,!1);return}if(g=!1,x=!1,cancelAnimationFrame(d),f.size>0){const{nodeLookup:J,updateNodePositions:C,onNodeDragStop:Y,onSelectionDragStop:V}=r();if(S&&(C(f,!1),S=!1),a||Y||!O&&V){const[U,z]=Mu({nodeId:O,dragItems:f,nodeLookup:J,dragging:!1});a==null||a(ee.sourceEvent,f,U,z),Y==null||Y(ee.sourceEvent,U,z),O||V==null||V(ee.sourceEvent,z)}}}).filter(ee=>{const J=ee.target;return!ee.button&&(!T||!bh(J,`.${T}`,b))&&(!E||bh(J,E,b))});v.call(G)}function k(){v==null||v.on(".drag",null)}return{update:N,destroy:k}}function C1(t,r,o){const l=[],a={x:t.x-o,y:t.y-o,width:o*2,height:o*2};for(const u of r.values())vl(a,Ro(u))>0&&l.push(u);return l}const M1=250;function P1(t,r,o,l){var f,g;let a=[],u=1/0;const d=C1(t,o,r+M1);for(const y of d){const m=[...((f=y.internals.handleBounds)==null?void 0:f.source)??[],...((g=y.internals.handleBounds)==null?void 0:g.target)??[]];for(const x of m){if(l.nodeId===x.nodeId&&l.type===x.type&&l.id===x.id)continue;const{x:v,y:_}=Vr(y,x,x.position,!0),S=Math.sqrt(Math.pow(v-t.x,2)+Math.pow(_-t.y,2));S>r||(S1){const y=l.type==="source"?"target":"source";return a.find(m=>m.type===y)??a[0]}return a[0]}function Sg(t,r,o,l,a,u=!1){var y,m,x;const d=l.get(t);if(!d)return null;const f=a==="strict"?(y=d.internals.handleBounds)==null?void 0:y[r]:[...((m=d.internals.handleBounds)==null?void 0:m.source)??[],...((x=d.internals.handleBounds)==null?void 0:x.target)??[]],g=(o?f==null?void 0:f.find(v=>v.id===o):f==null?void 0:f[0])??null;return g&&u?{...g,...Vr(d,g,g.position,!0)}:g}function kg(t,r){return t||(r!=null&&r.classList.contains("target")?"target":r!=null&&r.classList.contains("source")?"source":null)}function I1(t,r){let o=null;return r?o=!0:t&&!r&&(o=!1),o}const Eg=()=>!0;function T1(t,{connectionMode:r,connectionRadius:o,handleId:l,nodeId:a,edgeUpdaterType:u,isTarget:d,domNode:f,nodeLookup:g,lib:y,autoPanOnConnect:m,flowId:x,panBy:v,cancelConnection:_,onConnectStart:S,onConnect:j,onConnectEnd:N,isValidConnection:k=Eg,onReconnectEnd:T,updateConnection:E,getTransform:b,getFromHandle:$,autoPanSpeed:O,dragThreshold:H=1,handleDomNode:I}){const q=dg(t.target);let ne=0,G;const{x:ee,y:J}=on(t),C=kg(u,I),Y=f==null?void 0:f.getBoundingClientRect();let V=!1;if(!Y||!C)return;const U=Sg(a,C,l,g,r);if(!U)return;let z=on(t,Y),D=!1,W=null,M=!1,R=null;function re(){if(!m||!Y)return;const[_e,xe]=uc(z,Y,O);v({x:_e,y:xe}),ne=requestAnimationFrame(re)}const ie={...U,nodeId:a,type:C,position:U.position},ce=g.get(a);let de={inProgress:!0,isValid:null,from:Vr(ce,ie,Se.Left,!0),fromHandle:ie,fromPosition:ie.position,fromNode:ce,to:z,toHandle:null,toPosition:gh[ie.position],toNode:null,pointer:z};function K(){V=!0,E(de),S==null||S(t,{nodeId:a,handleId:l,handleType:C})}H===0&&K();function le(_e){if(!V){const{x:Re,y:tt}=on(_e),nt=Re-ee,Qe=tt-J;if(!(nt*nt+Qe*Qe>H*H))return;K()}if(!$()||!ie){pe(_e);return}const xe=b();z=on(_e,Y),G=P1(Bo(z,xe,!1,[1,1]),o,g,ie),D||(re(),D=!0);const ge=Ng(_e,{handle:G,connectionMode:r,fromNodeId:a,fromHandleId:l,fromType:d?"target":"source",isValidConnection:k,doc:q,lib:y,flowId:x,nodeLookup:g});R=ge.handleDomNode,W=ge.connection,M=I1(!!G,ge.isValid);const je=g.get(a),Me=je?Vr(je,ie,Se.Left,!0):de.from,Pe={...de,from:Me,isValid:M,to:ge.toHandle&&M?Ri({x:ge.toHandle.x,y:ge.toHandle.y},xe):z,toHandle:ge.toHandle,toPosition:M&&ge.toHandle?ge.toHandle.position:gh[ie.position],toNode:ge.toHandle?g.get(ge.toHandle.nodeId):null,pointer:z};E(Pe),de=Pe}function pe(_e){if(!("touches"in _e&&_e.touches.length>0)){if(V){(G||R)&&W&&M&&(j==null||j(W));const{inProgress:xe,...ge}=de,je={...ge,toPosition:de.toHandle?de.toPosition:null};N==null||N(_e,je),u&&(T==null||T(_e,je))}_(),cancelAnimationFrame(ne),D=!1,M=!1,W=null,R=null,q.removeEventListener("mousemove",le),q.removeEventListener("mouseup",pe),q.removeEventListener("touchmove",le),q.removeEventListener("touchend",pe)}}q.addEventListener("mousemove",le),q.addEventListener("mouseup",pe),q.addEventListener("touchmove",le),q.addEventListener("touchend",pe)}function Ng(t,{handle:r,connectionMode:o,fromNodeId:l,fromHandleId:a,fromType:u,doc:d,lib:f,flowId:g,isValidConnection:y=Eg,nodeLookup:m}){const x=u==="target",v=r?d.querySelector(`.${f}-flow__handle[data-id="${g}-${r==null?void 0:r.nodeId}-${r==null?void 0:r.id}-${r==null?void 0:r.type}"]`):null,{x:_,y:S}=on(t),j=d.elementFromPoint(_,S),N=j!=null&&j.classList.contains(`${f}-flow__handle`)?j:v,k={handleDomNode:N,isValid:!1,connection:null,toHandle:null};if(N){const T=kg(void 0,N),E=N.getAttribute("data-nodeid"),b=N.getAttribute("data-handleid"),$=N.classList.contains("connectable"),O=N.classList.contains("connectableend");if(!E||!T)return k;const H={source:x?E:l,sourceHandle:x?b:a,target:x?l:E,targetHandle:x?a:b};k.connection=H;const q=$&&O&&(o===Ii.Strict?x&&T==="source"||!x&&T==="target":E!==l||b!==a);k.isValid=q&&y(H),k.toHandle=Sg(E,T,b,m,o,!0)}return k}const Zu={onPointerDown:T1,isValid:Ng};function R1({domNode:t,panZoom:r,getTransform:o,getViewScale:l}){const a=Ot(t);function u({translateExtent:f,width:g,height:y,zoomStep:m=1,pannable:x=!0,zoomable:v=!0,inversePan:_=!1}){const S=E=>{if(E.sourceEvent.type!=="wheel"||!r)return;const b=o(),$=E.sourceEvent.ctrlKey&&Lo()?10:1,O=-E.sourceEvent.deltaY*(E.sourceEvent.deltaMode===1?.05:E.sourceEvent.deltaMode?1:.002)*m,H=b[2]*Math.pow(2,O*$);r.scaleTo(H)};let j=[0,0];const N=E=>{(E.sourceEvent.type==="mousedown"||E.sourceEvent.type==="touchstart")&&(j=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY])},k=E=>{const b=o();if(E.sourceEvent.type!=="mousemove"&&E.sourceEvent.type!=="touchmove"||!r)return;const $=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY],O=[$[0]-j[0],$[1]-j[1]];j=$;const H=l()*Math.max(b[2],Math.log(b[2]))*(_?-1:1),I={x:b[0]-O[0]*H,y:b[1]-O[1]*H},q=[[0,0],[g,y]];r.setViewportConstrained({x:I.x,y:I.y,zoom:b[2]},q,f)},T=Zp().on("start",N).on("zoom",x?k:null).on("zoom.wheel",v?S:null);a.call(T,{})}function d(){a.on("zoom",null)}return{update:u,destroy:d,pointer:tn}}const Ml=t=>({x:t.x,y:t.y,zoom:t.k}),Pu=({x:t,y:r,zoom:o})=>jl.translate(t,r).scale(o),cr=(t,r)=>t.target.closest(`.${r}`),jg=(t,r)=>r===2&&Array.isArray(t)&&t.includes(2),L1=t=>((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2,Iu=(t,r=0,o=L1,l=()=>{})=>{const a=typeof r=="number"&&r>0;return a||l(),a?t.transition().duration(r).ease(o).on("end",l):t},bg=t=>{const r=t.ctrlKey&&Lo()?10:1;return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*r};function A1({zoomPanValues:t,noWheelClassName:r,d3Selection:o,d3Zoom:l,panOnScrollMode:a,panOnScrollSpeed:u,zoomOnPinch:d,onPanZoomStart:f,onPanZoom:g,onPanZoomEnd:y}){return m=>{if(cr(m,r))return m.ctrlKey&&m.preventDefault(),!1;m.preventDefault(),m.stopImmediatePropagation();const x=o.property("__zoom").k||1;if(m.ctrlKey&&d){const N=tn(m),k=bg(m),T=x*Math.pow(2,k);l.scaleTo(o,T,N,m);return}const v=m.deltaMode===1?20:1;let _=a===$r.Vertical?0:m.deltaX*v,S=a===$r.Horizontal?0:m.deltaY*v;!Lo()&&m.shiftKey&&a!==$r.Vertical&&(_=m.deltaY*v,S=0),l.translateBy(o,-(_/x)*u,-(S/x)*u,{internal:!0});const j=Ml(o.property("__zoom"));clearTimeout(t.panScrollTimeout),t.isPanScrolling?g==null||g(m,j):(t.isPanScrolling=!0,f==null||f(m,j)),t.panScrollTimeout=setTimeout(()=>{y==null||y(m,j),t.isPanScrolling=!1},150)}}function z1({noWheelClassName:t,preventScrolling:r,d3ZoomHandler:o}){return function(l,a){const u=l.type==="wheel",d=!r&&u&&!l.ctrlKey,f=cr(l,t);if(l.ctrlKey&&u&&f&&l.preventDefault(),d||f)return null;l.preventDefault(),o.call(this,l,a)}}function D1({zoomPanValues:t,onDraggingChange:r,onPanZoomStart:o}){return l=>{var u,d,f;if((u=l.sourceEvent)!=null&&u.internal)return;const a=Ml(l.transform);t.mouseButton=((d=l.sourceEvent)==null?void 0:d.button)||0,t.isZoomingOrPanning=!0,t.prevViewport=a,((f=l.sourceEvent)==null?void 0:f.type)==="mousedown"&&r(!0),o&&(o==null||o(l.sourceEvent,a))}}function $1({zoomPanValues:t,panOnDrag:r,onPaneContextMenu:o,onTransformChange:l,onPanZoom:a}){return u=>{var d,f;t.usedRightMouseButton=!!(o&&jg(r,t.mouseButton??0)),(d=u.sourceEvent)!=null&&d.sync||l([u.transform.x,u.transform.y,u.transform.k]),a&&!((f=u.sourceEvent)!=null&&f.internal)&&(a==null||a(u.sourceEvent,Ml(u.transform)))}}function O1({zoomPanValues:t,panOnDrag:r,panOnScroll:o,onDraggingChange:l,onPanZoomEnd:a,onPaneContextMenu:u}){return d=>{var f;if(!((f=d.sourceEvent)!=null&&f.internal)&&(t.isZoomingOrPanning=!1,u&&jg(r,t.mouseButton??0)&&!t.usedRightMouseButton&&d.sourceEvent&&u(d.sourceEvent),t.usedRightMouseButton=!1,l(!1),a)){const g=Ml(d.transform);t.prevViewport=g,clearTimeout(t.timerId),t.timerId=setTimeout(()=>{a==null||a(d.sourceEvent,g)},o?150:0)}}}function F1({panActivationKeyPressed:t,zoomActivationKeyPressed:r,zoomOnScroll:o,zoomOnPinch:l,panOnDrag:a,panOnScroll:u,zoomOnDoubleClick:d,userSelectionActive:f,noWheelClassName:g,noPanClassName:y,lib:m,connectionInProgress:x}){return v=>{var k;const _=r||o,S=l&&v.ctrlKey,j=v.type==="wheel";if(v.button===1&&v.type==="mousedown"&&(cr(v,`${m}-flow__node`)||cr(v,`${m}-flow__edge`)||cr(v,`${m}-flow__selection`)||cr(v,`${m}-flow__nodesselection`)))return!0;if(!a&&!_&&!u&&!d&&!l||f||x&&!j||cr(v,g)&&j||cr(v,y)&&(!j||u&&j&&!r)||!l&&v.ctrlKey&&j)return!1;if(!l&&v.type==="touchstart"&&((k=v.touches)==null?void 0:k.length)>1)return v.preventDefault(),!1;if(!_&&!u&&!S&&j||!a&&(v.type==="mousedown"||v.type==="touchstart")||Array.isArray(a)&&!a.includes(v.button)&&v.type==="mousedown")return!1;const N=Array.isArray(a)&&a.includes(v.button)||!v.button||v.button<=1;return(!v.ctrlKey||j||t)&&N}}function H1({domNode:t,minZoom:r,maxZoom:o,translateExtent:l,viewport:a,onPanZoom:u,onPanZoomStart:d,onPanZoomEnd:f,onDraggingChange:g}){const y={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},m=t.getBoundingClientRect();let x=[[0,0],[m.width,m.height]];const v=typeof ResizeObserver<"u"?new ResizeObserver(J=>{const C=J[0];C&&(x=[[0,0],[C.contentRect.width,C.contentRect.height]])}):null;v==null||v.observe(t);const _=Zp().extent(()=>x).scaleExtent([r,o]).translateExtent(l),S=Ot(t).call(_);b({x:a.x,y:a.y,zoom:Ti(a.zoom,r,o)},[[0,0],[m.width,m.height]],l);const j=S.on("wheel.zoom"),N=S.on("dblclick.zoom");_.wheelDelta(bg);async function k(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).transform(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function T({noWheelClassName:J,noPanClassName:C,onPaneContextMenu:Y,userSelectionActive:V,panOnScroll:U,panOnDrag:z,panOnScrollMode:D,panOnScrollSpeed:W,preventScrolling:M,zoomOnPinch:R,zoomOnScroll:re,zoomOnDoubleClick:ie,panActivationKeyPressed:ce=!1,zoomActivationKeyPressed:fe,lib:de,onTransformChange:K,connectionInProgress:le,paneClickDistance:pe,selectionOnDrag:_e}){V&&!y.isZoomingOrPanning&&E();const xe=U&&!fe&&!V;_.clickDistance(_e?1/0:!rn(pe)||pe<0?0:pe);const ge=xe?A1({zoomPanValues:y,noWheelClassName:J,d3Selection:S,d3Zoom:_,panOnScrollMode:D,panOnScrollSpeed:W,zoomOnPinch:R,onPanZoomStart:d,onPanZoom:u,onPanZoomEnd:f}):z1({noWheelClassName:J,preventScrolling:M,d3ZoomHandler:j});S.on("wheel.zoom",ge,{passive:!1});const je=D1({zoomPanValues:y,onDraggingChange:g,onPanZoomStart:d});_.on("start",je);const Me=$1({zoomPanValues:y,panOnDrag:z,onPaneContextMenu:!!Y,onPanZoom:u,onTransformChange:K});_.on("zoom",Me);const Pe=O1({zoomPanValues:y,panOnDrag:z,panOnScroll:U,onPaneContextMenu:Y,onPanZoomEnd:f,onDraggingChange:g});_.on("end",Pe);const Re=F1({panActivationKeyPressed:ce,zoomActivationKeyPressed:fe,panOnDrag:z,zoomOnScroll:re,panOnScroll:U,zoomOnDoubleClick:ie,zoomOnPinch:R,userSelectionActive:V,noPanClassName:C,noWheelClassName:J,lib:de,connectionInProgress:le});_.filter(Re),ie?S.on("dblclick.zoom",N):S.on("dblclick.zoom",null)}function E(){_.on("zoom",null)}async function b(J,C,Y){const V=Pu(J),U=_==null?void 0:_.constrain()(V,C,Y);return U&&await k(U),U}async function $(J,C){const Y=Pu(J);return await k(Y,C),Y}function O(J){if(S){const C=Pu(J),Y=S.property("__zoom");(Y.k!==J.zoom||Y.x!==J.x||Y.y!==J.y)&&(_==null||_.transform(S,C,null,{sync:!0}))}}function H(){const J=S?Kp(S.node()):{x:0,y:0,k:1};return{x:J.x,y:J.y,zoom:J.k}}async function I(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleTo(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}async function q(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleBy(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function ne(J){_==null||_.scaleExtent(J)}function G(J){_==null||_.translateExtent(J)}function ee(J){const C=!rn(J)||J<0?0:J;_==null||_.clickDistance(C)}return{update:T,destroy:E,setViewport:$,setViewportConstrained:b,getViewport:H,scaleTo:I,scaleBy:q,setScaleExtent:ne,setTranslateExtent:G,syncViewport:O,setClickDistance:ee}}var Li;(function(t){t.Line="line",t.Handle="handle"})(Li||(Li={}));function B1({width:t,prevWidth:r,height:o,prevHeight:l,affectsX:a,affectsY:u}){const d=t-r,f=o-l,g=[d>0?1:d<0?-1:0,f>0?1:f<0?-1:0];return d&&a&&(g[0]=g[0]*-1),f&&u&&(g[1]=g[1]*-1),g}function Ch(t){const r=t.includes("right")||t.includes("left"),o=t.includes("bottom")||t.includes("top"),l=t.includes("left"),a=t.includes("top");return{isHorizontal:r,isVertical:o,affectsX:l,affectsY:a}}function ar(t,r){return Math.max(0,r-t)}function ur(t,r){return Math.max(0,t-r)}function tl(t,r,o){return Math.max(0,r-t,t-o)}function Mh(t,r){return t?!r:r}function V1(t,r,o,l,a,u,d,f){let{affectsX:g,affectsY:y}=r;const{isHorizontal:m,isVertical:x}=r,v=m&&x,{xSnapped:_,ySnapped:S}=o,{minWidth:j,maxWidth:N,minHeight:k,maxHeight:T}=l,{x:E,y:b,width:$,height:O,aspectRatio:H}=t;let I=Math.floor(m?_-t.pointerX:0),q=Math.floor(x?S-t.pointerY:0);const ne=$+(g?-I:I),G=O+(y?-q:q),ee=-u[0]*$,J=-u[1]*O;let C=tl(ne,j,N),Y=tl(G,k,T);if(d){let z=0,D=0;g&&I<0?z=ar(E+I+ee,d[0][0]):!g&&I>0&&(z=ur(E+ne+ee,d[1][0])),y&&q<0?D=ar(b+q+J,d[0][1]):!y&&q>0&&(D=ur(b+G+J,d[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(f){let z=0,D=0;g&&I>0?z=ur(E+I,f[0][0]):!g&&I<0&&(z=ar(E+ne,f[1][0])),y&&q>0?D=ur(b+q,f[0][1]):!y&&q<0&&(D=ar(b+G,f[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(a){if(m){const z=tl(ne/H,k,T)*H;if(C=Math.max(C,z),d){let D=0;!g&&!y||g&&!y&&v?D=ur(b+J+ne/H,d[1][1])*H:D=ar(b+J+(g?I:-I)/H,d[0][1])*H,C=Math.max(C,D)}if(f){let D=0;!g&&!y||g&&!y&&v?D=ar(b+ne/H,f[1][1])*H:D=ur(b+(g?I:-I)/H,f[0][1])*H,C=Math.max(C,D)}}if(x){const z=tl(G*H,j,N)/H;if(Y=Math.max(Y,z),d){let D=0;!g&&!y||y&&!g&&v?D=ur(E+G*H+ee,d[1][0])/H:D=ar(E+(y?q:-q)*H+ee,d[0][0])/H,Y=Math.max(Y,D)}if(f){let D=0;!g&&!y||y&&!g&&v?D=ar(E+G*H,f[1][0])/H:D=ur(E+(y?q:-q)*H,f[0][0])/H,Y=Math.max(Y,D)}}}q=q+(q<0?Y:-Y),I=I+(I<0?C:-C),a&&(v?ne>G*H?q=(Mh(g,y)?-I:I)/H:I=(Mh(g,y)?-q:q)*H:m?(q=I/H,y=g):(I=q*H,g=y));const V=g?E+I:E,U=y?b+q:b;return{width:$+(g?-I:I),height:O+(y?-q:q),x:u[0]*I*(g?-1:1)+V,y:u[1]*q*(y?-1:1)+U}}const Cg={width:0,height:0,x:0,y:0},W1={...Cg,pointerX:0,pointerY:0,aspectRatio:1};function U1(t,r,o){const l=r.position.x+t.position.x,a=r.position.y+t.position.y,u=t.measured.width??0,d=t.measured.height??0,f=o[0]*u,g=o[1]*d;return[[l-f,a-g],[l+u-f,a+d-g]]}function Y1({domNode:t,nodeId:r,getStoreItems:o,onChange:l,onEnd:a}){const u=Ot(t);let d={controlDirection:Ch("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function f({controlPosition:y,boundaries:m,keepAspectRatio:x,resizeDirection:v,onResizeStart:_,onResize:S,onResizeEnd:j,shouldResize:N}){let k={...Cg},T={...W1};d={boundaries:m,resizeDirection:v,keepAspectRatio:x,controlDirection:Ch(y)};let E,b=null,$=[],O,H,I,q=!1;const ne=Dp().on("start",G=>{const{nodeLookup:ee,transform:J,snapGrid:C,snapToGrid:Y,nodeOrigin:V,paneDomNode:U}=o();if(E=ee.get(r),!E)return;b=(U==null?void 0:U.getBoundingClientRect())??null;const{xSnapped:z,ySnapped:D}=Eo(G.sourceEvent,{transform:J,snapGrid:C,snapToGrid:Y,containerBounds:b});k={width:E.measured.width??0,height:E.measured.height??0,x:E.position.x??0,y:E.position.y??0},T={...k,pointerX:z,pointerY:D,aspectRatio:k.width/k.height},O=void 0,H=Br(E.extent)?E.extent:void 0,E.parentId&&(E.extent==="parent"||E.expandParent)&&(O=ee.get(E.parentId)),O&&E.extent==="parent"&&(H=[[0,0],[O.measured.width,O.measured.height]]),$=[],I=void 0;for(const[W,M]of ee)if(M.parentId===r&&($.push({id:W,position:{...M.position},extent:M.extent}),M.extent==="parent"||M.expandParent)){const R=U1(M,E,M.origin??V);I?I=[[Math.min(R[0][0],I[0][0]),Math.min(R[0][1],I[0][1])],[Math.max(R[1][0],I[1][0]),Math.max(R[1][1],I[1][1])]]:I=R}_==null||_(G,{...k})}).on("drag",G=>{const{transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y}=o(),V=Eo(G.sourceEvent,{transform:ee,snapGrid:J,snapToGrid:C,containerBounds:b}),U=[];if(!E)return;const{x:z,y:D,width:W,height:M}=k,R={},re=E.origin??Y,{width:ie,height:ce,x:fe,y:de}=V1(T,d.controlDirection,V,d.boundaries,d.keepAspectRatio,re,H,I),K=ie!==W,le=ce!==M,pe=fe!==z&&K,_e=de!==D&≤if(!pe&&!_e&&!K&&!le)return;if((pe||_e||re[0]===1||re[1]===1)&&(R.x=pe?fe:k.x,R.y=_e?de:k.y,k.x=R.x,k.y=R.y,$.length>0)){const Me=fe-z,Pe=de-D;for(const Re of $)Re.position={x:Re.position.x-Me+re[0]*(ie-W),y:Re.position.y-Pe+re[1]*(ce-M)},U.push(Re)}if((K||le)&&(R.width=K&&(!d.resizeDirection||d.resizeDirection==="horizontal")?ie:k.width,R.height=le&&(!d.resizeDirection||d.resizeDirection==="vertical")?ce:k.height,k.width=R.width,k.height=R.height),O&&E.expandParent){const Me=re[0]*(R.width??0);R.x&&R.x{q&&(j==null||j(G,{...k}),a==null||a({...k}),q=!1)});u.call(ne)}function g(){u.on(".drag",null)}return{update:f,destroy:g}}var Tu={exports:{}},Ru={},Lu={exports:{}},Au={};/** + * @license React + * use-sync-external-store-shim.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Ph;function G1(){if(Ph)return Au;Ph=1;var t=zo();function r(x,v){return x===v&&(x!==0||1/x===1/v)||x!==x&&v!==v}var o=typeof Object.is=="function"?Object.is:r,l=t.useState,a=t.useEffect,u=t.useLayoutEffect,d=t.useDebugValue;function f(x,v){var _=v(),S=l({inst:{value:_,getSnapshot:v}}),j=S[0].inst,N=S[1];return u(function(){j.value=_,j.getSnapshot=v,g(j)&&N({inst:j})},[x,_,v]),a(function(){return g(j)&&N({inst:j}),x(function(){g(j)&&N({inst:j})})},[x]),d(_),_}function g(x){var v=x.getSnapshot;x=x.value;try{var _=v();return!o(x,_)}catch{return!0}}function y(x,v){return v()}var m=typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"?y:f;return Au.useSyncExternalStore=t.useSyncExternalStore!==void 0?t.useSyncExternalStore:m,Au}var Ih;function X1(){return Ih||(Ih=1,Lu.exports=G1()),Lu.exports}/** + * @license React + * use-sync-external-store-shim/with-selector.production.js + * + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */var Th;function q1(){if(Th)return Ru;Th=1;var t=zo(),r=X1();function o(y,m){return y===m&&(y!==0||1/y===1/m)||y!==y&&m!==m}var l=typeof Object.is=="function"?Object.is:o,a=r.useSyncExternalStore,u=t.useRef,d=t.useEffect,f=t.useMemo,g=t.useDebugValue;return Ru.useSyncExternalStoreWithSelector=function(y,m,x,v,_){var S=u(null);if(S.current===null){var j={hasValue:!1,value:null};S.current=j}else j=S.current;S=f(function(){function k(O){if(!T){if(T=!0,E=O,O=v(O),_!==void 0&&j.hasValue){var H=j.value;if(_(H,O))return b=H}return b=O}if(H=b,l(E,O))return H;var I=v(O);return _!==void 0&&_(H,I)?(E=O,H):(E=O,b=I)}var T=!1,E,b,$=x===void 0?null:x;return[function(){return k(m())},$===null?void 0:function(){return k($())}]},[m,x,v,_]);var N=a(y,S[0],S[1]);return d(function(){j.hasValue=!0,j.value=N},[N]),g(N),N},Ru}var Rh;function Q1(){return Rh||(Rh=1,Tu.exports=q1()),Tu.exports}var K1=Q1();const Z1=xp(K1),J1={},Lh=t=>{let r;const o=new Set,l=(m,x)=>{const v=typeof m=="function"?m(r):m;if(!Object.is(v,r)){const _=r;r=x??(typeof v!="object"||v===null)?v:Object.assign({},r,v),o.forEach(S=>S(r,_))}},a=()=>r,g={setState:l,getState:a,getInitialState:()=>y,subscribe:m=>(o.add(m),()=>o.delete(m)),destroy:()=>{(J1?"production":void 0)!=="production"&&console.warn("[DEPRECATED] The `destroy` method will be unsupported in a future version. Instead use unsubscribe function returned by subscribe. Everything will be garbage-collected if store is garbage-collected."),o.clear()}},y=r=t(l,a,g);return g},e_=t=>t?Lh(t):Lh,{useDebugValue:t_}=Jy,{useSyncExternalStoreWithSelector:n_}=Z1,r_=t=>t;function Mg(t,r=r_,o){const l=n_(t.subscribe,t.getState,t.getServerState||t.getInitialState,r,o);return t_(l),l}const Ah=(t,r)=>{const o=e_(t),l=(a,u=r)=>Mg(o,a,u);return Object.assign(l,o),l},i_=(t,r)=>t?Ah(t,r):Ah;function qe(t,r){if(Object.is(t,r))return!0;if(typeof t!="object"||t===null||typeof r!="object"||r===null)return!1;if(t instanceof Map&&r instanceof Map){if(t.size!==r.size)return!1;for(const[l,a]of t)if(!Object.is(a,r.get(l)))return!1;return!0}if(t instanceof Set&&r instanceof Set){if(t.size!==r.size)return!1;for(const l of t)if(!r.has(l))return!1;return!0}const o=Object.keys(t);if(o.length!==Object.keys(r).length)return!1;for(const l of o)if(!Object.prototype.hasOwnProperty.call(r,l)||!Object.is(t[l],r[l]))return!1;return!0}wp();const Pl=F.createContext(null),o_=Pl.Provider,Pg=sn.error001("react");function Ae(t,r){const o=F.useContext(Pl);if(o===null)throw new Error(Pg);return Mg(o,t,r)}function We(){const t=F.useContext(Pl);if(t===null)throw new Error(Pg);return F.useMemo(()=>({getState:t.getState,setState:t.setState,subscribe:t.subscribe}),[t])}const zh={display:"none"},s_={position:"absolute",width:1,height:1,margin:-1,border:0,padding:0,overflow:"hidden",clip:"rect(0px, 0px, 0px, 0px)",clipPath:"inset(100%)"},Ig="react-flow__node-desc",Tg="react-flow__edge-desc",l_="react-flow__aria-live",a_=t=>t.ariaLiveMessage,u_=t=>t.ariaLabelConfig;function c_({rfId:t}){const r=Ae(a_);return p.jsx("div",{id:`${l_}-${t}`,"aria-live":"assertive","aria-atomic":"true",style:s_,children:r})}function d_({rfId:t,disableKeyboardA11y:r}){const o=Ae(u_);return p.jsxs(p.Fragment,{children:[p.jsx("div",{id:`${Ig}-${t}`,style:zh,children:r?o["node.a11yDescription.default"]:o["node.a11yDescription.keyboardDisabled"]}),p.jsx("div",{id:`${Tg}-${t}`,style:zh,children:o["edge.a11yDescription.default"]}),!r&&p.jsx(c_,{rfId:t})]})}const Il=F.forwardRef(({position:t="top-left",children:r,className:o,style:l,...a},u)=>{const d=`${t}`.split("-");return p.jsx("div",{className:it(["react-flow__panel",o,...d]),style:l,ref:u,...a,children:r})});Il.displayName="Panel";const Dh="https://reactflow.dev?utm_source=attribution";function f_({proOptions:t,position:r="bottom-right"}){return t!=null&&t.hideAttribution?null:p.jsx(Il,{position:r,className:"react-flow__attribution","data-message":`Please only hide this attribution when you are subscribed to React Flow Pro: ${Dh}`,children:p.jsx("a",{href:Dh,target:"_blank",rel:"noopener noreferrer","aria-label":"React Flow attribution",children:"React Flow"})})}const h_=t=>{const r=[],o=[];for(const[,l]of t.nodeLookup)l.selected&&r.push(l.internals.userNode);for(const[,l]of t.edgeLookup)l.selected&&o.push(l);return{selectedNodes:r,selectedEdges:o}},nl=t=>t.id;function p_(t,r){return qe(t.selectedNodes.map(nl),r.selectedNodes.map(nl))&&qe(t.selectedEdges.map(nl),r.selectedEdges.map(nl))}function g_({onSelectionChange:t}){const r=We(),{selectedNodes:o,selectedEdges:l}=Ae(h_,p_);return F.useEffect(()=>{const a={nodes:o,edges:l};t==null||t(a),r.getState().onSelectionChangeHandlers.forEach(u=>u(a))},[o,l,t]),null}const m_=t=>!!t.onSelectionChangeHandlers;function y_({onSelectionChange:t}){const r=Ae(m_);return t||r?p.jsx(g_,{onSelectionChange:t}):null}const Rg=[0,0],v_={x:0,y:0,zoom:1},x_=["nodes","edges","defaultNodes","defaultEdges","onConnect","onConnectStart","onConnectEnd","onClickConnectStart","onClickConnectEnd","nodesDraggable","autoPanOnNodeFocus","nodesConnectable","nodesFocusable","edgesFocusable","edgesReconnectable","elevateNodesOnSelect","elevateEdgesOnSelect","minZoom","maxZoom","nodeExtent","onNodesChange","onEdgesChange","elementsSelectable","connectionMode","snapGrid","snapToGrid","translateExtent","connectOnClick","defaultEdgeOptions","fitView","fitViewOptions","onNodesDelete","onEdgesDelete","onDelete","onNodeDrag","onNodeDragStart","onNodeDragStop","onSelectionDrag","onSelectionDragStart","onSelectionDragStop","onMoveStart","onMove","onMoveEnd","noPanClassName","nodeOrigin","autoPanOnConnect","autoPanOnNodeDrag","onError","connectionRadius","isValidConnection","selectNodesOnDrag","nodeDragThreshold","connectionDragThreshold","onBeforeDelete","debug","autoPanSpeed","ariaLabelConfig","zIndexMode"],$h=[...x_,"rfId"],w_=t=>({setNodes:t.setNodes,setEdges:t.setEdges,setMinZoom:t.setMinZoom,setMaxZoom:t.setMaxZoom,setTranslateExtent:t.setTranslateExtent,setNodeExtent:t.setNodeExtent,reset:t.reset,setDefaultNodesAndEdges:t.setDefaultNodesAndEdges}),Oh={translateExtent:Po,nodeOrigin:Rg,minZoom:.5,maxZoom:2,elementsSelectable:!0,noPanClassName:"nopan",rfId:"1"};function __(t){const{setNodes:r,setEdges:o,setMinZoom:l,setMaxZoom:a,setTranslateExtent:u,setNodeExtent:d,reset:f,setDefaultNodesAndEdges:g}=Ae(w_,qe),y=We();F.useEffect(()=>(g(t.defaultNodes,t.defaultEdges),()=>{m.current=Oh,f()}),[]);const m=F.useRef(Oh);return F.useEffect(()=>{for(const x of $h){const v=t[x],_=m.current[x];v!==_&&(typeof t[x]>"u"||(x==="nodes"?r(v):x==="edges"?o(v):x==="minZoom"?l(v):x==="maxZoom"?a(v):x==="translateExtent"?u(v):x==="nodeExtent"?d(v):x==="ariaLabelConfig"?y.setState({ariaLabelConfig:o1(v)}):x==="fitView"?y.setState({fitViewQueued:v}):x==="fitViewOptions"?y.setState({fitViewOptions:v}):y.setState({[x]:v})))}m.current=t},$h.map(x=>t[x])),null}function Fh(){return typeof window>"u"||!window.matchMedia?null:window.matchMedia("(prefers-color-scheme: dark)")}function S_(t){var l;const[r,o]=F.useState(t==="system"?null:t);return F.useEffect(()=>{if(t!=="system"){o(t);return}const a=Fh(),u=()=>o(a!=null&&a.matches?"dark":"light");return u(),a==null||a.addEventListener("change",u),()=>{a==null||a.removeEventListener("change",u)}},[t]),r!==null?r:(l=Fh())!=null&&l.matches?"dark":"light"}const Hh=typeof document<"u"?document:null;function Ao(t=null,r={target:Hh,actInsideInputWithModifier:!0}){const[o,l]=F.useState(!1),a=F.useRef(!1),u=F.useRef(new Set([])),[d,f]=F.useMemo(()=>{if(t!==null){const y=(Array.isArray(t)?t:[t]).filter(x=>typeof x=="string").map(x=>x.replace(/\+/g,` +`).replace(` + +`,` ++`).split(` +`)),m=y.reduce((x,v)=>x.concat(...v),[]);return[y,m]}return[[],[]]},[t]);return F.useEffect(()=>{const g=(r==null?void 0:r.target)??Hh,y=(r==null?void 0:r.actInsideInputWithModifier)??!0;if(t!==null){const m=_=>{var N,k;if(a.current=_.ctrlKey||_.metaKey||_.shiftKey||_.altKey,(!a.current||a.current&&!y)&&fg(_))return!1;const j=Vh(_.code,f);if(u.current.add(_[j]),Bh(d,u.current,!1)){const T=((k=(N=_.composedPath)==null?void 0:N.call(_))==null?void 0:k[0])||_.target,E=(T==null?void 0:T.nodeName)==="BUTTON"||(T==null?void 0:T.nodeName)==="A";r.preventDefault!==!1&&(a.current||!E)&&_.preventDefault(),l(!0)}},x=_=>{const S=Vh(_.code,f);Bh(d,u.current,!0)?(l(!1),u.current.clear()):u.current.delete(_[S]),_.key==="Meta"&&u.current.clear(),a.current=!1},v=()=>{u.current.clear(),l(!1)};return g==null||g.addEventListener("keydown",m),g==null||g.addEventListener("keyup",x),window.addEventListener("blur",v),window.addEventListener("contextmenu",v),()=>{g==null||g.removeEventListener("keydown",m),g==null||g.removeEventListener("keyup",x),window.removeEventListener("blur",v),window.removeEventListener("contextmenu",v)}}},[t,l]),o}function Bh(t,r,o){return t.filter(l=>o||l.length===r.size).some(l=>l.every(a=>r.has(a)))}function Vh(t,r){return r.includes(t)?"code":"key"}const k_=()=>{const t=We();return F.useMemo(()=>({zoomIn:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1.2,r):!1},zoomOut:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1/1.2,r):!1},zoomTo:async(r,o)=>{const{panZoom:l}=t.getState();return l?l.scaleTo(r,o):!1},getZoom:()=>t.getState().transform[2],setViewport:async(r,o)=>{const{transform:[l,a,u],panZoom:d}=t.getState();return d?(await d.setViewport({x:r.x??l,y:r.y??a,zoom:r.zoom??u},o),!0):!1},getViewport:()=>{const[r,o,l]=t.getState().transform;return{x:r,y:o,zoom:l}},setCenter:async(r,o,l)=>t.getState().setCenter(r,o,l),fitBounds:async(r,o)=>{const{width:l,height:a,minZoom:u,maxZoom:d,panZoom:f}=t.getState(),g=cc(r,l,a,u,d,(o==null?void 0:o.padding)??.1);return f?(await f.setViewport(g,{duration:o==null?void 0:o.duration,ease:o==null?void 0:o.ease,interpolate:o==null?void 0:o.interpolate}),!0):!1},screenToFlowPosition:(r,o={})=>{const{transform:l,snapGrid:a,snapToGrid:u,domNode:d}=t.getState();if(!d)return r;const{x:f,y:g}=d.getBoundingClientRect(),y={x:r.x-f,y:r.y-g},m=o.snapGrid??a,x=o.snapToGrid??u;return Bo(y,l,x,m)},flowToScreenPosition:r=>{const{transform:o,domNode:l}=t.getState();if(!l)return r;const{x:a,y:u}=l.getBoundingClientRect(),d=Ri(r,o);return{x:d.x+a,y:d.y+u}}}),[])};function Lg(t,r){const o=[],l=new Map,a=[];for(const u of t)if(u.type==="add"){a.push(u);continue}else if(u.type==="remove"||u.type==="replace")l.set(u.id,[u]);else{const d=l.get(u.id);d?d.push(u):l.set(u.id,[u])}for(const u of r){const d=l.get(u.id);if(!d){o.push(u);continue}if(d[0].type==="remove")continue;if(d[0].type==="replace"){o.push({...d[0].item});continue}const f={...u};for(const g of d)E_(g,f);o.push(f)}return a.length&&a.forEach(u=>{u.index!==void 0?o.splice(u.index,0,{...u.item}):o.push({...u.item})}),o}function E_(t,r){switch(t.type){case"select":{r.selected=t.selected;break}case"position":{typeof t.position<"u"&&(r.position=t.position),typeof t.dragging<"u"&&(r.dragging=t.dragging);break}case"dimensions":{typeof t.dimensions<"u"&&(r.measured={...t.dimensions},t.setAttributes&&((t.setAttributes===!0||t.setAttributes==="width")&&(r.width=t.dimensions.width),(t.setAttributes===!0||t.setAttributes==="height")&&(r.height=t.dimensions.height))),typeof t.resizing=="boolean"&&(r.resizing=t.resizing);break}}}function N_(t,r){return Lg(t,r)}function j_(t,r){return Lg(t,r)}function Ar(t,r){return{id:t,type:"select",selected:r}}function ji(t,r=new Set,o=!1){const l=[];for(const[a,u]of t){const d=r.has(a);!(u.selected===void 0&&!d)&&u.selected!==d&&(o&&(u.selected=d),l.push(Ar(u.id,d)))}return l}function Wh({items:t=[],lookup:r}){var a;const o=[],l=new Map(t.map(u=>[u.id,u]));for(const[u,d]of t.entries()){const f=r.get(d.id),g=((a=f==null?void 0:f.internals)==null?void 0:a.userNode)??f;g!==void 0&&g!==d&&o.push({id:d.id,item:d,type:"replace"}),g===void 0&&o.push({item:d,type:"add",index:u})}for(const[u]of r)l.get(u)===void 0&&o.push({id:u,type:"remove"});return o}function Uh(t){return{id:t.id,type:"remove"}}const b_=ag();function C_(t,r,o={}){return d1(t,r,{...o,onError:o.onError??b_})}const Yh=t=>Qw(t),M_=t=>rg(t);function Ag(t){return F.forwardRef(t)}const zg=typeof window<"u"?F.useLayoutEffect:F.useEffect;function Gh(t){const[r,o]=F.useState(BigInt(0)),[l]=F.useState(()=>P_(()=>o(a=>a+BigInt(1))));return zg(()=>{const a=l.get();a.length&&(t(a),l.reset())},[r]),l}function P_(t){let r=[];return{get:()=>r,reset:()=>{r=[]},push:o=>{r.push(o),t()}}}const Dg=F.createContext(null);function I_({children:t}){const r=We(),o=F.useCallback(f=>{const{nodes:g=[],setNodes:y,hasDefaultNodes:m,onNodesChange:x,nodeLookup:v,fitViewQueued:_,onNodesChangeMiddlewareMap:S}=r.getState();let j=g;for(const k of f)j=typeof k=="function"?k(j):k;let N=Wh({items:j,lookup:v});for(const k of S.values())N=k(N);m&&y(j),N.length>0?x==null||x(N):_&&window.requestAnimationFrame(()=>{const{fitViewQueued:k,nodes:T,setNodes:E}=r.getState();k&&E(T)})},[]),l=Gh(o),a=F.useCallback(f=>{const{edges:g=[],setEdges:y,hasDefaultEdges:m,onEdgesChange:x,edgeLookup:v}=r.getState();let _=g;for(const S of f)_=typeof S=="function"?S(_):S;m?y(_):x&&x(Wh({items:_,lookup:v}))},[]),u=Gh(a),d=F.useMemo(()=>({nodeQueue:l,edgeQueue:u}),[]);return p.jsx(Dg.Provider,{value:d,children:t})}function T_(){const t=F.useContext(Dg);if(!t)throw new Error("useBatchContext must be used within a BatchProvider");return t}const R_=t=>!!t.panZoom;function yc(){const t=k_(),r=We(),o=T_(),l=Ae(R_),a=F.useMemo(()=>{const u=x=>r.getState().nodeLookup.get(x),d=x=>{o.nodeQueue.push(x)},f=x=>{o.edgeQueue.push(x)},g=x=>{var k,T;const{nodeLookup:v,nodeOrigin:_}=r.getState(),S=Yh(x)?x:v.get(x.id),j=S.parentId?cg(S.position,S.measured,S.parentId,v,_):S.position,N={...S,position:j,width:((k=S.measured)==null?void 0:k.width)??S.width,height:((T=S.measured)==null?void 0:T.height)??S.height};return Ro(N)},y=(x,v,_={replace:!1})=>{d(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&Yh(N)?N:{...j,...N}}return j}))},m=(x,v,_={replace:!1})=>{f(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&M_(N)?N:{...j,...N}}return j}))};return{getNodes:()=>r.getState().nodes.map(x=>({...x})),getNode:x=>{var v;return(v=u(x))==null?void 0:v.internals.userNode},getInternalNode:u,getEdges:()=>{const{edges:x=[]}=r.getState();return x.map(v=>({...v}))},getEdge:x=>r.getState().edgeLookup.get(x),setNodes:d,setEdges:f,addNodes:x=>{const v=Array.isArray(x)?x:[x];o.nodeQueue.push(_=>[..._,...v])},addEdges:x=>{const v=Array.isArray(x)?x:[x];o.edgeQueue.push(_=>[..._,...v])},toObject:()=>{const{nodes:x=[],edges:v=[],transform:_}=r.getState(),[S,j,N]=_;return{nodes:x.map(k=>({...k})),edges:v.map(k=>({...k})),viewport:{x:S,y:j,zoom:N}}},deleteElements:async({nodes:x=[],edges:v=[]})=>{const{nodes:_,edges:S,onNodesDelete:j,onEdgesDelete:N,triggerNodeChanges:k,triggerEdgeChanges:T,onDelete:E,onBeforeDelete:b}=r.getState(),{nodes:$,edges:O}=await t1({nodesToRemove:x,edgesToRemove:v,nodes:_,edges:S,onBeforeDelete:b}),H=O.length>0,I=$.length>0;if(H){const q=O.map(Uh);N==null||N(O),T(q)}if(I){const q=$.map(Uh);j==null||j($),k(q)}return(I||H)&&(E==null||E({nodes:$,edges:O})),{deletedNodes:$,deletedEdges:O}},getIntersectingNodes:(x,v=!0,_)=>{const S=yh(x),j=S?x:g(x),N=_!==void 0;return j?(_||r.getState().nodes).filter(k=>{const T=r.getState().nodeLookup.get(k.id);if(T&&!S&&(k.id===x.id||!T.internals.positionAbsolute))return!1;const E=Ro(N?k:T),b=vl(E,j);return v&&b>0||b>=E.width*E.height||b>=j.width*j.height}):[]},isNodeIntersecting:(x,v,_=!0)=>{const j=yh(x)?x:g(x);if(!j)return!1;const N=vl(j,v);return _&&N>0||N>=v.width*v.height||N>=j.width*j.height},updateNode:y,updateNodeData:(x,v,_={replace:!1})=>{y(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},updateEdge:m,updateEdgeData:(x,v,_={replace:!1})=>{m(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},getNodesBounds:x=>{const{nodeLookup:v,nodeOrigin:_}=r.getState();return Kw(x,{nodeLookup:v,nodeOrigin:_})},getHandleConnections:({type:x,id:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}-${x}${v?`-${v}`:""}`))==null?void 0:S.values())??[])},getNodeConnections:({type:x,handleId:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}${x?v?`-${x}-${v}`:`-${x}`:""}`))==null?void 0:S.values())??[])},fitView:async x=>{const v=r.getState().fitViewResolver??i1();return r.setState({fitViewQueued:!0,fitViewOptions:x,fitViewResolver:v}),o.nodeQueue.push(_=>[..._]),v.promise}}},[]);return F.useMemo(()=>({...a,...t,viewportInitialized:l}),[l])}const Xh=t=>t.selected,L_=typeof window<"u"?window:void 0;function A_({deleteKeyCode:t,multiSelectionKeyCode:r}){const o=We(),{deleteElements:l}=yc(),a=Ao(t,{actInsideInputWithModifier:!1}),u=Ao(r,{target:L_});F.useEffect(()=>{if(a){const{edges:d,nodes:f}=o.getState();l({nodes:f.filter(Xh),edges:d.filter(Xh)}),o.setState({nodesSelectionActive:!1})}},[a]),F.useEffect(()=>{o.setState({multiSelectionActive:u})},[u])}function z_(t){const r=We();F.useEffect(()=>{const o=()=>{var a,u,d,f;if(!t.current||!(((u=(a=t.current).checkVisibility)==null?void 0:u.call(a))??!0))return!1;const l=dc(t.current);(l.height===0||l.width===0)&&((f=(d=r.getState()).onError)==null||f.call(d,"004",sn.error004())),r.setState({width:l.width||500,height:l.height||500})};if(t.current){o(),window.addEventListener("resize",o);const l=new ResizeObserver(()=>o());return l.observe(t.current),()=>{window.removeEventListener("resize",o),l&&t.current&&l.unobserve(t.current)}}},[])}const Tl={position:"absolute",width:"100%",height:"100%",top:0,left:0},D_=t=>({userSelectionActive:t.userSelectionActive,lib:t.lib,connectionInProgress:t.connection.inProgress});function $_({onPaneContextMenu:t,zoomOnScroll:r=!0,zoomOnPinch:o=!0,panOnScroll:l=!1,panActivationKeyPressed:a,panOnScrollSpeed:u=.5,panOnScrollMode:d=$r.Free,zoomOnDoubleClick:f=!0,panOnDrag:g=!0,defaultViewport:y,translateExtent:m,minZoom:x,maxZoom:v,zoomActivationKeyCode:_,preventScrolling:S=!0,children:j,noWheelClassName:N,noPanClassName:k,onViewportChange:T,isControlledViewport:E,paneClickDistance:b,selectionOnDrag:$}){const O=We(),H=F.useRef(null),{userSelectionActive:I,lib:q,connectionInProgress:ne}=Ae(D_,qe),G=Ao(_),ee=F.useRef();z_(H);const J=F.useCallback(C=>{T==null||T({x:C[0],y:C[1],zoom:C[2]}),E||O.setState({transform:C})},[T,E]);return F.useEffect(()=>{if(H.current){ee.current=H1({domNode:H.current,minZoom:x,maxZoom:v,translateExtent:m,viewport:y,onDraggingChange:U=>O.setState(z=>z.paneDragging===U?z:{paneDragging:U}),onPanZoomStart:(U,z)=>{const{onViewportChangeStart:D,onMoveStart:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoom:(U,z)=>{const{onViewportChange:D,onMove:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoomEnd:(U,z)=>{const{onViewportChangeEnd:D,onMoveEnd:W}=O.getState();W==null||W(U,z),D==null||D(z)}});const{x:C,y:Y,zoom:V}=ee.current.getViewport();return O.setState({panZoom:ee.current,transform:[C,Y,V],domNode:H.current.closest(".react-flow")}),()=>{var U;(U=ee.current)==null||U.destroy()}}},[]),F.useEffect(()=>{var C;(C=ee.current)==null||C.update({onPaneContextMenu:t,zoomOnScroll:r,zoomOnPinch:o,panOnScroll:l,panActivationKeyPressed:a,panOnScrollSpeed:u,panOnScrollMode:d,zoomOnDoubleClick:f,panOnDrag:g,zoomActivationKeyPressed:G,preventScrolling:S,noPanClassName:k,userSelectionActive:I,noWheelClassName:N,lib:q,onTransformChange:J,connectionInProgress:ne,selectionOnDrag:$,paneClickDistance:b})},[t,r,o,l,a,u,d,f,g,G,S,k,I,N,q,J,ne,$,b]),p.jsx("div",{className:"react-flow__renderer",ref:H,style:Tl,children:j})}const O_=t=>({userSelectionActive:t.userSelectionActive,userSelectionRect:t.userSelectionRect});function F_(){const{userSelectionActive:t,userSelectionRect:r}=Ae(O_,qe);return t&&r?p.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:r.width,height:r.height,transform:`translate(${r.x}px, ${r.y}px)`}}):null}const zu=(t,r)=>o=>{o.target===r.current&&(t==null||t(o))},H_=t=>({userSelectionActive:t.userSelectionActive,elementsSelectable:t.elementsSelectable,dragging:t.paneDragging,panBy:t.panBy,autoPanSpeed:t.autoPanSpeed});function B_({isSelecting:t,selectionKeyPressed:r,selectionMode:o=Io.Full,panOnDrag:l,autoPanOnSelection:a,paneClickDistance:u,selectionOnDrag:d,onSelectionStart:f,onSelectionEnd:g,onPaneClick:y,onPaneContextMenu:m,onPaneScroll:x,onPaneMouseEnter:v,onPaneMouseMove:_,onPaneMouseLeave:S,children:j}){const N=F.useRef(0),k=We(),{userSelectionActive:T,elementsSelectable:E,dragging:b,panBy:$,autoPanSpeed:O}=Ae(H_,qe),H=E&&(t||T),I=F.useRef(null),q=F.useRef(),ne=F.useRef(new Set),G=F.useRef(new Set),ee=F.useRef(!1),J=F.useRef(!1),C=F.useRef({x:0,y:0}),Y=F.useRef(!1),V=K=>{if(J.current||ee.current||k.getState().connection.inProgress){J.current=!1,ee.current=!1;return}y==null||y(K),k.getState().resetSelectedElements(),k.setState({nodesSelectionActive:!1})},U=K=>{if(Array.isArray(l)&&(l!=null&&l.includes(2))){K.preventDefault();return}m==null||m(K)},z=x?K=>x(K):void 0,D=K=>{J.current&&(K.stopPropagation(),J.current=!1)},W=K=>{var Re,tt;if(K.pointerType==="touch"&&l!==!1&&!r)return;const{domNode:le,transform:pe}=k.getState();if(q.current=le==null?void 0:le.getBoundingClientRect(),!q.current)return;const _e=K.target===I.current;if(!_e&&!!K.target.closest(".nokey")||!t||!(d&&_e||r)||K.button!==0||!K.isPrimary)return;(tt=(Re=K.target)==null?void 0:Re.setPointerCapture)==null||tt.call(Re,K.pointerId),J.current=!1;const{x:je,y:Me}=on(K.nativeEvent,q.current),Pe=Bo({x:je,y:Me},pe);k.setState({userSelectionRect:{width:0,height:0,startX:Pe.x,startY:Pe.y,x:je,y:Me}}),_e||(K.stopPropagation(),K.preventDefault())};function M(K,le){const{userSelectionRect:pe}=k.getState();if(!pe)return;const{transform:_e,nodeLookup:xe,edgeLookup:ge,connectionLookup:je,triggerNodeChanges:Me,triggerEdgeChanges:Pe,defaultEdgeOptions:Re}=k.getState(),tt={x:pe.startX,y:pe.startY},{x:nt,y:Qe}=Ri(tt,_e),ot={startX:tt.x,startY:tt.y,x:Kze.id)),G.current=new Set;const Ke=(Re==null?void 0:Re.selectable)??!0;for(const ze of ne.current){const gt=je.get(ze);if(gt)for(const{edgeId:ft}of gt.values()){const Je=ge.get(ft);Je&&(Je.selectable??Ke)&&G.current.add(ft)}}if(!vh(at,ne.current)){const ze=ji(xe,ne.current,!0);Me(ze)}if(!vh(It,G.current)){const ze=ji(ge,G.current);Pe(ze)}k.setState({userSelectionRect:ot,userSelectionActive:!0,nodesSelectionActive:!1})}function R(){if(!a||!q.current)return;const[K,le]=uc(C.current,q.current,O);$({x:K,y:le}).then(pe=>{if(!J.current||!pe){N.current=requestAnimationFrame(R);return}const{x:_e,y:xe}=C.current;M(_e,xe),N.current=requestAnimationFrame(R)})}const re=()=>{cancelAnimationFrame(N.current),N.current=0,Y.current=!1};F.useEffect(()=>()=>re(),[]);const ie=K=>{const{userSelectionRect:le,transform:pe,resetSelectedElements:_e}=k.getState();if(!q.current||!le)return;const{x:xe,y:ge}=on(K.nativeEvent,q.current);C.current={x:xe,y:ge};const je=Ri({x:le.startX,y:le.startY},pe);if(!J.current){const Me=r?0:u;if(Math.hypot(xe-je.x,ge-je.y)<=Me)return;_e(),f==null||f(K)}J.current=!0,Y.current||(R(),Y.current=!0),M(xe,ge)},ce=K=>{var le,pe;if(!H){K.target===I.current&&k.getState().connection.inProgress&&(ee.current=!0);return}K.button===0&&((pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),!T&&K.target===I.current&&k.getState().userSelectionRect&&(V==null||V(K)),k.setState({userSelectionActive:!1,userSelectionRect:null}),J.current&&(g==null||g(K),k.setState({nodesSelectionActive:ne.current.size>0})),re())},fe=K=>{var le,pe;(pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),re()},de=l===!0||Array.isArray(l)&&l.includes(0);return p.jsxs("div",{className:it(["react-flow__pane",{draggable:de,dragging:b,selection:t}]),onClick:H?void 0:zu(V,I),onContextMenu:zu(U,I),onWheel:zu(z,I),onPointerEnter:H?void 0:v,onPointerMove:H?ie:_,onPointerUp:ce,onPointerCancel:H?fe:void 0,onPointerDownCapture:H?W:void 0,onClickCapture:H?D:void 0,onPointerLeave:S,ref:I,style:Tl,children:[j,p.jsx(F_,{})]})}function Ju({id:t,store:r,unselect:o=!1,nodeRef:l}){const{addSelectedNodes:a,unselectNodesAndEdges:u,multiSelectionActive:d,nodeLookup:f,onError:g}=r.getState(),y=f.get(t);if(!y){g==null||g("012",sn.error012(t));return}r.setState({nodesSelectionActive:!1}),y.selected?(o||y.selected&&d)&&(u({nodes:[y],edges:[]}),requestAnimationFrame(()=>{var m;return(m=l==null?void 0:l.current)==null?void 0:m.blur()})):a([t])}function $g({nodeRef:t,disabled:r=!1,noDragClassName:o,handleSelector:l,nodeId:a,isSelectable:u,nodeClickDistance:d}){const f=We(),[g,y]=F.useState(!1),m=F.useRef();return F.useEffect(()=>{if(!r)return m.current=b1({getStoreItems:()=>f.getState(),onNodeMouseDown:x=>{Ju({id:x,store:f,nodeRef:t})},onDragStart:()=>{y(!0)},onDragStop:()=>{y(!1)}}),()=>{var x;(x=m.current)==null||x.destroy(),m.current=void 0}},[r,f,t]),F.useEffect(()=>{r||!t.current||!m.current||m.current.update({noDragClassName:o,handleSelector:l,domNode:t.current,isSelectable:u,nodeId:a,nodeClickDistance:d})},[o,l,r,u,t,a,d]),g}const V_=t=>r=>r.selected&&(r.draggable||t&&typeof r.draggable>"u");function Og(){const t=We();return F.useCallback(o=>{const{nodeExtent:l,snapToGrid:a,snapGrid:u,nodesDraggable:d,onError:f,updateNodePositions:g,nodeLookup:y,nodeOrigin:m}=t.getState(),x=new Map,v=V_(d),_=a?u[0]:5,S=a?u[1]:5,j=o.direction.x*_*o.factor,N=o.direction.y*S*o.factor;for(const[,k]of y){if(!v(k))continue;let T={x:k.internals.positionAbsolute.x+j,y:k.internals.positionAbsolute.y+N};a&&(T=Ho(T,u));const{position:E,positionAbsolute:b}=ig({nodeId:k.id,nextPosition:T,nodeLookup:y,nodeExtent:l,nodeOrigin:m,onError:f});k.position=E,k.internals.positionAbsolute=b,x.set(k.id,k)}g(x)},[])}const vc=F.createContext(null),W_=vc.Provider;vc.Consumer;const Fg=()=>F.useContext(vc),U_=t=>({connectOnClick:t.connectOnClick,noPanClassName:t.noPanClassName,rfId:t.rfId}),Hg=F.createContext(null);function Y_({children:t}){const r=Ae(U_,qe);return p.jsx(Hg.Provider,{value:r,children:t})}function G_(){const t=F.useContext(Hg);if(!t)throw new Error("useHandleConfig must be used within a HandleConfigProvider");return t}const X_={connectingFrom:!1,connectingTo:!1,clickConnecting:!1,isPossibleEndHandle:!0,connectionInProcess:!1,clickConnectionInProcess:!1,valid:!1},q_=(t,r,o)=>l=>{const{connectionClickStartHandle:a,connectionMode:u,connection:d}=l,{fromHandle:f,toHandle:g,isValid:y}=d;if(!f&&!a)return X_;const m=(g==null?void 0:g.nodeId)===t&&(g==null?void 0:g.id)===r&&(g==null?void 0:g.type)===o;return{connectingFrom:(f==null?void 0:f.nodeId)===t&&(f==null?void 0:f.id)===r&&(f==null?void 0:f.type)===o,connectingTo:m,clickConnecting:(a==null?void 0:a.nodeId)===t&&(a==null?void 0:a.id)===r&&(a==null?void 0:a.type)===o,isPossibleEndHandle:u===Ii.Strict?(f==null?void 0:f.type)!==o:t!==(f==null?void 0:f.nodeId)||r!==(f==null?void 0:f.id),connectionInProcess:!!f,clickConnectionInProcess:!!a,valid:m&&y}};function Q_({type:t="source",position:r=Se.Top,isValidConnection:o,isConnectable:l=!0,isConnectableStart:a=!0,isConnectableEnd:u=!0,id:d,onConnect:f,children:g,className:y,onMouseDown:m,onTouchStart:x,...v},_){var Y,V;const S=d||null,j=t==="target",N=We(),k=Fg(),{connectOnClick:T,noPanClassName:E,rfId:b}=G_(),{connectingFrom:$,connectingTo:O,clickConnecting:H,isPossibleEndHandle:I,connectionInProcess:q,clickConnectionInProcess:ne,valid:G}=Ae(q_(k,S,t),qe);k||(V=(Y=N.getState()).onError)==null||V.call(Y,"010",sn.error010());const ee=U=>{const{defaultEdgeOptions:z,onConnect:D,hasDefaultEdges:W}=N.getState(),M={...z,...U};if(W){const{edges:R,setEdges:re,onError:ie}=N.getState();re(C_(M,R,{onError:ie}))}D==null||D(M),f==null||f(M)},J=U=>{if(!k)return;const z=hg(U.nativeEvent);if(a&&(z&&U.button===0||!z)){const D=N.getState();Zu.onPointerDown(U.nativeEvent,{handleDomNode:U.currentTarget,autoPanOnConnect:D.autoPanOnConnect,connectionMode:D.connectionMode,connectionRadius:D.connectionRadius,domNode:D.domNode,nodeLookup:D.nodeLookup,lib:D.lib,isTarget:j,handleId:S,nodeId:k,flowId:D.rfId,panBy:D.panBy,cancelConnection:D.cancelConnection,onConnectStart:D.onConnectStart,onConnectEnd:(...W)=>{var M,R;return(R=(M=N.getState()).onConnectEnd)==null?void 0:R.call(M,...W)},updateConnection:D.updateConnection,onConnect:ee,isValidConnection:o||((...W)=>{var M,R;return((R=(M=N.getState()).isValidConnection)==null?void 0:R.call(M,...W))??!0}),getTransform:()=>N.getState().transform,getFromHandle:()=>N.getState().connection.fromHandle,autoPanSpeed:D.autoPanSpeed,dragThreshold:D.connectionDragThreshold})}z?m==null||m(U):x==null||x(U)},C=U=>{const{onClickConnectStart:z,onClickConnectEnd:D,connectionClickStartHandle:W,connectionMode:M,isValidConnection:R,lib:re,rfId:ie,nodeLookup:ce,connection:fe}=N.getState();if(!k||!W&&!a)return;if(!W){z==null||z(U.nativeEvent,{nodeId:k,handleId:S,handleType:t}),N.setState({connectionClickStartHandle:{nodeId:k,type:t,id:S}});return}const de=dg(U.target),K=o||R,{connection:le,isValid:pe}=Zu.isValid(U.nativeEvent,{handle:{nodeId:k,id:S,type:t},connectionMode:M,fromNodeId:W.nodeId,fromHandleId:W.id||null,fromType:W.type,isValidConnection:K,flowId:ie,doc:de,lib:re,nodeLookup:ce});pe&&le&&ee(le);const _e=structuredClone(fe);delete _e.inProgress,_e.toPosition=_e.toHandle?_e.toHandle.position:null,D==null||D(U,_e),N.setState({connectionClickStartHandle:null})};return p.jsx("div",{"data-handleid":S,"data-nodeid":k,"data-handlepos":r,"data-id":`${b}-${k}-${S}-${t}`,className:it(["react-flow__handle",`react-flow__handle-${r}`,"nodrag",E,y,{source:!j,target:j,connectable:l,connectablestart:a,connectableend:u,clickconnecting:H,connectingfrom:$,connectingto:O,valid:G,connectionindicator:l&&(!q||I)&&(q||ne?u:a)}]),onMouseDown:J,onTouchStart:J,onClick:T?C:void 0,ref:_,...v,children:g})}const Ai=F.memo(Ag(Q_));function K_({data:t,isConnectable:r,sourcePosition:o=Se.Bottom}){return p.jsxs(p.Fragment,{children:[t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:o,isConnectable:r})]})}function Z_({data:t,isConnectable:r,targetPosition:o=Se.Top,sourcePosition:l=Se.Bottom}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:l,isConnectable:r})]})}function J_(){return null}function eS({data:t,isConnectable:r,targetPosition:o=Se.Top}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label]})}const xl={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},qh={input:K_,default:Z_,output:eS,group:J_};function tS(t){var r,o,l,a;return t.internals.handleBounds===void 0?{width:t.width??t.initialWidth??((r=t.style)==null?void 0:r.width),height:t.height??t.initialHeight??((o=t.style)==null?void 0:o.height)}:{width:t.width??((l=t.style)==null?void 0:l.width),height:t.height??((a=t.style)==null?void 0:a.height)}}const nS=t=>{const{width:r,height:o,x:l,y:a}=Fo(t.nodeLookup,{filter:u=>!!u.selected});return{width:rn(r)?r:null,height:rn(o)?o:null,userSelectionActive:t.userSelectionActive,transformString:`translate(${t.transform[0]}px,${t.transform[1]}px) scale(${t.transform[2]}) translate(${l}px,${a}px)`}};function rS({onSelectionContextMenu:t,noPanClassName:r,disableKeyboardA11y:o}){const l=We(),{width:a,height:u,transformString:d,userSelectionActive:f}=Ae(nS,qe),g=Og(),y=F.useRef(null);F.useEffect(()=>{var _;o||(_=y.current)==null||_.focus({preventScroll:!0})},[o]);const m=!f&&a!==null&&u!==null;if($g({nodeRef:y,disabled:!m}),!m)return null;const x=t?_=>{const S=l.getState().nodes.filter(j=>j.selected);t(_,S)}:void 0,v=_=>{Object.prototype.hasOwnProperty.call(xl,_.key)&&(_.preventDefault(),g({direction:xl[_.key],factor:_.shiftKey?4:1}))};return p.jsx("div",{className:it(["react-flow__nodesselection","react-flow__container",r]),style:{transform:d},children:p.jsx("div",{ref:y,className:"react-flow__nodesselection-rect",onContextMenu:x,tabIndex:o?void 0:-1,onKeyDown:o?void 0:v,style:{width:a,height:u}})})}const Qh=typeof window<"u"?window:void 0,iS=t=>({nodesSelectionActive:t.nodesSelectionActive,userSelectionActive:t.userSelectionActive});function Bg({children:t,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,paneClickDistance:f,deleteKeyCode:g,selectionKeyCode:y,selectionOnDrag:m,selectionMode:x,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:S,panActivationKeyCode:j,zoomActivationKeyCode:N,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:b,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:I,autoPanOnSelection:q,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,preventScrolling:C,onSelectionContextMenu:Y,noWheelClassName:V,noPanClassName:U,disableKeyboardA11y:z,onViewportChange:D,isControlledViewport:W}){const{nodesSelectionActive:M,userSelectionActive:R}=Ae(iS,qe),re=Ao(y,{target:Qh}),ie=Ao(j,{target:Qh}),ce=ie||I,fe=ie||b,de=m&&ce!==!0,K=re||R||de;return A_({deleteKeyCode:g,multiSelectionKeyCode:S}),p.jsx($_,{onPaneContextMenu:u,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:fe,panActivationKeyPressed:ie,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:!re&&ce,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,zoomActivationKeyCode:N,preventScrolling:C,noWheelClassName:V,noPanClassName:U,onViewportChange:D,isControlledViewport:W,paneClickDistance:f,selectionOnDrag:de,children:p.jsxs(B_,{onSelectionStart:v,onSelectionEnd:_,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,panOnDrag:ce,autoPanOnSelection:q,isSelecting:!!K,selectionMode:x,selectionKeyPressed:re,paneClickDistance:f,selectionOnDrag:de,children:[t,M&&p.jsx(rS,{onSelectionContextMenu:Y,noPanClassName:U,disableKeyboardA11y:z})]})})}Bg.displayName="FlowRenderer";const oS=F.memo(Bg),sS=t=>r=>t?ac(r.nodeLookup,{x:0,y:0,width:r.width,height:r.height},r.transform,!0).map(o=>o.id):Array.from(r.nodeLookup.keys());function lS(t){return Ae(F.useCallback(sS(t),[t]),qe)}const aS=t=>t.updateNodeInternals;function uS(){const t=Ae(aS),[r]=F.useState(()=>typeof ResizeObserver>"u"?null:new ResizeObserver(o=>{const l=new Map;o.forEach(a=>{const u=a.target.getAttribute("data-id");l.set(u,{id:u,nodeElement:a.target,force:!0})}),t(l)}));return F.useEffect(()=>()=>{r==null||r.disconnect()},[r]),r}function cS({node:t,nodeType:r,hasDimensions:o,resizeObserver:l}){const a=We(),u=F.useRef(null),d=F.useRef(null),f=F.useRef(t.sourcePosition),g=F.useRef(t.targetPosition),y=F.useRef(r),m=o&&!!t.internals.handleBounds;return F.useEffect(()=>{u.current&&!t.hidden&&(!m||d.current!==u.current)&&(d.current&&(l==null||l.unobserve(d.current)),l==null||l.observe(u.current),d.current=u.current)},[m,t.hidden]),F.useEffect(()=>()=>{d.current&&(l==null||l.unobserve(d.current),d.current=null)},[]),F.useEffect(()=>{if(u.current){const x=y.current!==r,v=f.current!==t.sourcePosition,_=g.current!==t.targetPosition;(x||v||_)&&(y.current=r,f.current=t.sourcePosition,g.current=t.targetPosition,a.getState().updateNodeInternals(new Map([[t.id,{id:t.id,nodeElement:u.current,force:!0}]])))}},[t.id,r,t.sourcePosition,t.targetPosition]),u}function dS({id:t,onClick:r,onMouseEnter:o,onMouseMove:l,onMouseLeave:a,onContextMenu:u,onDoubleClick:d,nodesDraggable:f,elementsSelectable:g,nodesConnectable:y,nodesFocusable:m,resizeObserver:x,noDragClassName:v,noPanClassName:_,disableKeyboardA11y:S,rfId:j,nodeTypes:N,nodeClickDistance:k,onError:T}){const{node:E,internals:b,isParent:$}=Ae(K=>{const le=K.nodeLookup.get(t),pe=K.parentLookup.has(t);return{node:le,internals:le.internals,isParent:pe}},qe);let O=E.type||"default",H=(N==null?void 0:N[O])||qh[O];H===void 0&&(T==null||T("003",sn.error003(O)),O="default",H=(N==null?void 0:N.default)||qh.default);const I=!!(E.draggable||f&&typeof E.draggable>"u"),q=!!(E.selectable||g&&typeof E.selectable>"u"),ne=!!(E.connectable||y&&typeof E.connectable>"u"),G=!!(E.focusable||m&&typeof E.focusable>"u"),ee=We(),J=ug(E),C=cS({node:E,nodeType:O,hasDimensions:J,resizeObserver:x}),Y=$g({nodeRef:C,disabled:E.hidden||!I,noDragClassName:v,handleSelector:E.dragHandle,nodeId:t,isSelectable:q,nodeClickDistance:k}),V=Og();if(E.hidden)return null;const U=an(E),z=tS(E),D=q||I||r||o||l||a,W=o?K=>o(K,{...b.userNode}):void 0,M=l?K=>l(K,{...b.userNode}):void 0,R=a?K=>a(K,{...b.userNode}):void 0,re=u?K=>u(K,{...b.userNode}):void 0,ie=d?K=>d(K,{...b.userNode}):void 0,ce=K=>{const{selectNodesOnDrag:le,nodeDragThreshold:pe}=ee.getState();q&&(!le||!I||pe>0)&&Ju({id:t,store:ee,nodeRef:C}),r&&r(K,{...b.userNode})},fe=K=>{if(!(fg(K.nativeEvent)||S)){if(Jp.includes(K.key)&&q){const le=K.key==="Escape";Ju({id:t,store:ee,unselect:le,nodeRef:C})}else if(I&&E.selected&&Object.prototype.hasOwnProperty.call(xl,K.key)){K.preventDefault();const{ariaLabelConfig:le}=ee.getState();ee.setState({ariaLiveMessage:le["node.a11yDescription.ariaLiveMessage"]({direction:K.key.replace("Arrow","").toLowerCase(),x:~~b.positionAbsolute.x,y:~~b.positionAbsolute.y})}),V({direction:xl[K.key],factor:K.shiftKey?4:1})}}},de=()=>{var je;if(S||!((je=C.current)!=null&&je.matches(":focus-visible")))return;const{transform:K,width:le,height:pe,autoPanOnNodeFocus:_e,setCenter:xe}=ee.getState();if(!_e)return;ac(new Map([[t,E]]),{x:0,y:0,width:le,height:pe},K,!0).length>0||xe(E.position.x+U.width/2,E.position.y+U.height/2,{zoom:K[2]})};return p.jsx("div",{className:it(["react-flow__node",`react-flow__node-${O}`,{[_]:I},E.className,{selected:E.selected,selectable:q,parent:$,draggable:I,dragging:Y}]),ref:C,style:{zIndex:b.z,transform:`translate(${b.positionAbsolute.x}px,${b.positionAbsolute.y}px)`,pointerEvents:D?"all":"none",visibility:J?"visible":"hidden",...E.style,...z},"data-id":t,"data-testid":`rf__node-${t}`,onMouseEnter:W,onMouseMove:M,onMouseLeave:R,onContextMenu:re,onClick:ce,onDoubleClick:ie,onKeyDown:G?fe:void 0,tabIndex:G?0:void 0,onFocus:G?de:void 0,role:E.ariaRole??(G?"group":void 0),"aria-roledescription":"node","aria-describedby":S?void 0:`${Ig}-${j}`,"aria-label":E.ariaLabel,...E.domAttributes,children:p.jsx(W_,{value:t,children:p.jsx(H,{id:t,data:E.data,type:O,positionAbsoluteX:b.positionAbsolute.x,positionAbsoluteY:b.positionAbsolute.y,selected:E.selected??!1,selectable:q,draggable:I,deletable:E.deletable??!0,isConnectable:ne,sourcePosition:E.sourcePosition,targetPosition:E.targetPosition,dragging:Y,dragHandle:E.dragHandle,zIndex:b.z,parentId:E.parentId,...U})})})}var fS=F.memo(dS);const hS=t=>({nodesConnectable:t.nodesConnectable,nodesFocusable:t.nodesFocusable,elementsSelectable:t.elementsSelectable,onError:t.onError});function Vg(t){const{nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,onError:a}=Ae(hS,qe),u=lS(t.onlyRenderVisibleElements),d=uS();return p.jsx("div",{className:"react-flow__nodes",style:Tl,children:u.map(f=>p.jsx(fS,{id:f,nodeTypes:t.nodeTypes,nodeExtent:t.nodeExtent,onClick:t.onNodeClick,onMouseEnter:t.onNodeMouseEnter,onMouseMove:t.onNodeMouseMove,onMouseLeave:t.onNodeMouseLeave,onContextMenu:t.onNodeContextMenu,onDoubleClick:t.onNodeDoubleClick,noDragClassName:t.noDragClassName,noPanClassName:t.noPanClassName,rfId:t.rfId,disableKeyboardA11y:t.disableKeyboardA11y,resizeObserver:d,nodesDraggable:t.nodesDraggable??!0,nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,nodeClickDistance:t.nodeClickDistance,onError:a},f))})}Vg.displayName="NodeRenderer";const pS=F.memo(Vg);function gS(t){return Ae(F.useCallback(o=>{if(!t)return o.edges.map(a=>a.id);const l=[];if(o.width&&o.height)for(const a of o.edges){const u=o.nodeLookup.get(a.source),d=o.nodeLookup.get(a.target);u&&d&&a1({sourceNode:u,targetNode:d,width:o.width,height:o.height,transform:o.transform})&&l.push(a.id)}return l},[t]),qe)}const mS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t}};return p.jsx("polyline",{className:"arrow",style:o,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},yS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t,fill:t}};return p.jsx("polyline",{className:"arrowclosed",style:o,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},Kh={[To.Arrow]:mS,[To.ArrowClosed]:yS};function vS(t){const r=We();return F.useMemo(()=>{var a,u;return Object.prototype.hasOwnProperty.call(Kh,t)?Kh[t]:((u=(a=r.getState()).onError)==null||u.call(a,"009",sn.error009(t)),null)},[t])}const xS=({id:t,type:r,color:o,width:l=12.5,height:a=12.5,markerUnits:u="strokeWidth",strokeWidth:d,orient:f="auto-start-reverse"})=>{const g=vS(r);return g?p.jsx("marker",{className:"react-flow__arrowhead",id:t,markerWidth:`${l}`,markerHeight:`${a}`,viewBox:"-10 -10 20 20",markerUnits:u,orient:f,refX:"0",refY:"0",children:p.jsx(g,{color:o,strokeWidth:d})}):null},Wg=({defaultColor:t,rfId:r})=>{const o=Ae(u=>u.edges),l=Ae(u=>u.defaultEdgeOptions),a=F.useMemo(()=>m1(o,{id:r,defaultColor:t,defaultMarkerStart:l==null?void 0:l.markerStart,defaultMarkerEnd:l==null?void 0:l.markerEnd}),[o,l,r,t]);return a.length?p.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:p.jsx("defs",{children:a.map(u=>p.jsx(xS,{id:u.id,type:u.type,color:u.color,width:u.width,height:u.height,markerUnits:u.markerUnits,strokeWidth:u.strokeWidth,orient:u.orient},u.id))})}):null};Wg.displayName="MarkerDefinitions";var wS=F.memo(Wg);function Ug({x:t,y:r,label:o,labelStyle:l,labelShowBg:a=!0,labelBgStyle:u,labelBgPadding:d=[2,4],labelBgBorderRadius:f=2,children:g,className:y,...m}){const[x,v]=F.useState({x:1,y:0,width:0,height:0}),_=it(["react-flow__edge-textwrapper",y]),S=F.useRef(null);return F.useEffect(()=>{if(S.current){const j=S.current.getBBox();v({x:j.x,y:j.y,width:j.width,height:j.height})}},[o]),o?p.jsxs("g",{transform:`translate(${t-x.width/2} ${r-x.height/2})`,className:_,visibility:x.width?"visible":"hidden",...m,children:[a&&p.jsx("rect",{width:x.width+2*d[0],x:-d[0],y:-d[1],height:x.height+2*d[1],className:"react-flow__edge-textbg",style:u,rx:f,ry:f}),p.jsx("text",{className:"react-flow__edge-text",y:x.height/2,dy:"0.3em",ref:S,style:l,children:o}),g]}):null}Ug.displayName="EdgeText";const _S=F.memo(Ug);function Rl({path:t,labelX:r,labelY:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g,interactionWidth:y=20,...m}){return p.jsxs(p.Fragment,{children:[p.jsx("path",{...m,d:t,fill:"none",className:it(["react-flow__edge-path",m.className])}),y?p.jsx("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:y,className:"react-flow__edge-interaction"}):null,l&&rn(r)&&rn(o)?p.jsx(_S,{x:r,y:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g}):null]})}function Zh({pos:t,x1:r,y1:o,x2:l,y2:a}){return t===Se.Left||t===Se.Right?[.5*(r+l),o]:[r,.5*(o+a)]}function Yg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top}){const[d,f]=Zh({pos:o,x1:t,y1:r,x2:l,y2:a}),[g,y]=Zh({pos:u,x1:l,y1:a,x2:t,y2:r}),[m,x,v,_]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:d,sourceControlY:f,targetControlX:g,targetControlY:y});return[`M${t},${r} C${d},${f} ${g},${y} ${l},${a}`,m,x,v,_]}function Gg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d,targetPosition:f,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})=>{const[T,E,b]=Yg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f}),$=t.isInternal?void 0:r;return p.jsx(Rl,{id:$,path:T,labelX:E,labelY:b,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})})}const SS=Gg({isInternal:!1}),Xg=Gg({isInternal:!0});SS.displayName="SimpleBezierEdge";Xg.displayName="SimpleBezierEdgeInternal";function qg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,sourcePosition:_=Se.Bottom,targetPosition:S=Se.Top,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=qu({sourceX:o,sourceY:l,sourcePosition:_,targetX:a,targetY:u,targetPosition:S,borderRadius:k==null?void 0:k.borderRadius,offset:k==null?void 0:k.offset,stepPosition:k==null?void 0:k.stepPosition}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:j,markerStart:N,interactionWidth:T})})}const Qg=qg({isInternal:!1}),Kg=qg({isInternal:!0});Qg.displayName="SmoothStepEdge";Kg.displayName="SmoothStepEdgeInternal";function Zg(t){return F.memo(({id:r,...o})=>{var a;const l=t.isInternal?void 0:r;return p.jsx(Qg,{...o,id:l,pathOptions:F.useMemo(()=>{var u;return{borderRadius:0,offset:(u=o.pathOptions)==null?void 0:u.offset}},[(a=o.pathOptions)==null?void 0:a.offset])})})}const kS=Zg({isInternal:!1}),Jg=Zg({isInternal:!0});kS.displayName="StepEdge";Jg.displayName="StepEdgeInternal";function em(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})=>{const[N,k,T]=yg({sourceX:o,sourceY:l,targetX:a,targetY:u}),E=t.isInternal?void 0:r;return p.jsx(Rl,{id:E,path:N,labelX:k,labelY:T,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})})}const ES=em({isInternal:!1}),tm=em({isInternal:!0});ES.displayName="StraightEdge";tm.displayName="StraightEdgeInternal";function nm(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d=Se.Bottom,targetPosition:f=Se.Top,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=gg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f,curvature:k==null?void 0:k.curvature}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:T})})}const NS=nm({isInternal:!1}),rm=nm({isInternal:!0});NS.displayName="BezierEdge";rm.displayName="BezierEdgeInternal";const Jh={default:rm,straight:tm,step:Jg,smoothstep:Kg,simplebezier:Xg},ep={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null,zIndex:void 0},jS=(t,r,o)=>o===Se.Left?t-r:o===Se.Right?t+r:t,bS=(t,r,o)=>o===Se.Top?t-r:o===Se.Bottom?t+r:t,tp="react-flow__edgeupdater";function np({position:t,centerX:r,centerY:o,radius:l=10,onMouseDown:a,onMouseEnter:u,onMouseOut:d,type:f}){return p.jsx("circle",{onMouseDown:a,onMouseEnter:u,onMouseOut:d,className:it([tp,`${tp}-${f}`]),cx:jS(r,l,t),cy:bS(o,l,t),r:l,stroke:"transparent",fill:"transparent"})}function CS({isReconnectable:t,reconnectRadius:r,edge:o,sourceX:l,sourceY:a,targetX:u,targetY:d,sourcePosition:f,targetPosition:g,onReconnect:y,onReconnectStart:m,onReconnectEnd:x,setReconnecting:v,setUpdateHover:_}){const S=We(),j=(b,$)=>{if(b.button!==0)return;const{autoPanOnConnect:O,domNode:H,connectionMode:I,connectionRadius:q,lib:ne,onConnectStart:G,cancelConnection:ee,nodeLookup:J,rfId:C,panBy:Y,updateConnection:V}=S.getState(),U=$.type==="target",z=(M,R)=>{v(!1),x==null||x(M,o,$.type,R)},D=M=>y==null?void 0:y(o,M),W=(M,R)=>{v(!0),m==null||m(b,o,$.type),G==null||G(M,R)};Zu.onPointerDown(b.nativeEvent,{autoPanOnConnect:O,connectionMode:I,connectionRadius:q,domNode:H,handleId:$.id,nodeId:$.nodeId,nodeLookup:J,isTarget:U,edgeUpdaterType:$.type,lib:ne,flowId:C,cancelConnection:ee,panBy:Y,isValidConnection:(...M)=>{var R,re;return((re=(R=S.getState()).isValidConnection)==null?void 0:re.call(R,...M))??!0},onConnect:D,onConnectStart:W,onConnectEnd:(...M)=>{var R,re;return(re=(R=S.getState()).onConnectEnd)==null?void 0:re.call(R,...M)},onReconnectEnd:z,updateConnection:V,getTransform:()=>S.getState().transform,getFromHandle:()=>S.getState().connection.fromHandle,dragThreshold:S.getState().connectionDragThreshold,handleDomNode:b.currentTarget})},N=b=>j(b,{nodeId:o.target,id:o.targetHandle??null,type:"target"}),k=b=>j(b,{nodeId:o.source,id:o.sourceHandle??null,type:"source"}),T=()=>_(!0),E=()=>_(!1);return p.jsxs(p.Fragment,{children:[(t===!0||t==="source")&&p.jsx(np,{position:f,centerX:l,centerY:a,radius:r,onMouseDown:N,onMouseEnter:T,onMouseOut:E,type:"source"}),(t===!0||t==="target")&&p.jsx(np,{position:g,centerX:u,centerY:d,radius:r,onMouseDown:k,onMouseEnter:T,onMouseOut:E,type:"target"})]})}function MS({id:t,edgesFocusable:r,edgesReconnectable:o,elementsSelectable:l,onClick:a,onDoubleClick:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,rfId:S,edgeTypes:j,noPanClassName:N,onError:k,disableKeyboardA11y:T}){let E=Ae(xe=>xe.edgeLookup.get(t));const b=Ae(xe=>xe.defaultEdgeOptions);E=b?{...b,...E}:E;let $=E.type||"default",O=(j==null?void 0:j[$])||Jh[$];O===void 0&&(k==null||k("011",sn.error011($)),$="default",O=(j==null?void 0:j.default)||Jh.default);const H=!!(E.focusable||r&&typeof E.focusable>"u"),I=typeof x<"u"&&(E.reconnectable||o&&typeof E.reconnectable>"u"),q=!!(E.selectable||l&&typeof E.selectable>"u"),ne=F.useRef(null),[G,ee]=F.useState(!1),[J,C]=F.useState(!1),Y=We(),{zIndex:V=E.zIndex,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R}=Ae(F.useCallback(xe=>{const ge=xe.nodeLookup.get(E.source),je=xe.nodeLookup.get(E.target);if(!ge||!je)return ep;const Me=g1({id:t,sourceNode:ge,targetNode:je,sourceHandle:E.sourceHandle||null,targetHandle:E.targetHandle||null,connectionMode:xe.connectionMode,onError:k}),Pe=l1({selected:E.selected,zIndex:E.zIndex,sourceNode:ge,targetNode:je,elevateOnSelect:xe.elevateEdgesOnSelect,zIndexMode:xe.zIndexMode});return{...Me||ep,zIndex:Pe}},[E.source,E.target,E.sourceHandle,E.targetHandle,E.selected,E.zIndex,k]),qe),re=F.useMemo(()=>E.markerStart?`url('#${Qu(E.markerStart,S)}')`:void 0,[E.markerStart,S]),ie=F.useMemo(()=>E.markerEnd?`url('#${Qu(E.markerEnd,S)}')`:void 0,[E.markerEnd,S]);if(E.hidden||U===null||z===null||D===null||W===null)return null;const ce=xe=>{var Pe;const{addSelectedEdges:ge,unselectNodesAndEdges:je,multiSelectionActive:Me}=Y.getState();q&&(Y.setState({nodesSelectionActive:!1}),E.selected&&Me?(je({nodes:[],edges:[E]}),(Pe=ne.current)==null||Pe.blur()):ge([t])),a&&a(xe,E)},fe=u?xe=>{u(xe,{...E})}:void 0,de=d?xe=>{d(xe,{...E})}:void 0,K=f?xe=>{f(xe,{...E})}:void 0,le=g?xe=>{g(xe,{...E})}:void 0,pe=y?xe=>{y(xe,{...E})}:void 0,_e=xe=>{var ge;if(!T&&Jp.includes(xe.key)&&q){const{unselectNodesAndEdges:je,addSelectedEdges:Me}=Y.getState();xe.key==="Escape"?((ge=ne.current)==null||ge.blur(),je({edges:[E]})):Me([t])}};return p.jsx("svg",{style:{zIndex:V},children:p.jsxs("g",{className:it(["react-flow__edge",`react-flow__edge-${$}`,E.className,N,{selected:E.selected,animated:E.animated,inactive:!q&&!a,updating:G,selectable:q}]),onClick:ce,onDoubleClick:fe,onContextMenu:de,onMouseEnter:K,onMouseMove:le,onMouseLeave:pe,onKeyDown:H?_e:void 0,tabIndex:H?0:void 0,role:E.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":t,"data-testid":`rf__edge-${t}`,"aria-label":E.ariaLabel===null?void 0:E.ariaLabel||`Edge from ${E.source} to ${E.target}`,"aria-describedby":H?`${Tg}-${S}`:void 0,ref:ne,...E.domAttributes,children:[!J&&p.jsx(O,{id:t,source:E.source,target:E.target,type:E.type,selected:E.selected,animated:E.animated,selectable:q,deletable:E.deletable??!0,label:E.label,labelStyle:E.labelStyle,labelShowBg:E.labelShowBg,labelBgStyle:E.labelBgStyle,labelBgPadding:E.labelBgPadding,labelBgBorderRadius:E.labelBgBorderRadius,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,data:E.data,style:E.style,sourceHandleId:E.sourceHandle,targetHandleId:E.targetHandle,markerStart:re,markerEnd:ie,pathOptions:"pathOptions"in E?E.pathOptions:void 0,interactionWidth:E.interactionWidth}),I&&p.jsx(CS,{edge:E,isReconnectable:I,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,setUpdateHover:ee,setReconnecting:C})]})})}var PS=F.memo(MS);const IS=t=>({edgesFocusable:t.edgesFocusable,edgesReconnectable:t.edgesReconnectable,elementsSelectable:t.elementsSelectable,connectionMode:t.connectionMode,onError:t.onError});function im({defaultMarkerColor:t,onlyRenderVisibleElements:r,rfId:o,edgeTypes:l,noPanClassName:a,onReconnect:u,onEdgeContextMenu:d,onEdgeMouseEnter:f,onEdgeMouseMove:g,onEdgeMouseLeave:y,onEdgeClick:m,reconnectRadius:x,onEdgeDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,disableKeyboardA11y:j}){const{edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,onError:E}=Ae(IS,qe),b=gS(r);return p.jsxs("div",{className:"react-flow__edges",children:[p.jsx(wS,{defaultColor:t,rfId:o}),b.map($=>p.jsx(PS,{id:$,edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,noPanClassName:a,onReconnect:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,onClick:m,reconnectRadius:x,onDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,rfId:o,onError:E,edgeTypes:l,disableKeyboardA11y:j},$))]})}im.displayName="EdgeRenderer";const TS=F.memo(im),rp=t=>`translate(${t[0]}px,${t[1]}px) scale(${t[2]})`;function RS({children:t}){const r=We(),o=F.useRef(null),[l]=F.useState(()=>r.getState().transform);return zg(()=>{let a=null;const u=()=>{const d=r.getState().transform;a&&d[0]===a[0]&&d[1]===a[1]&&d[2]===a[2]||(a=d,o.current&&(o.current.style.transform=rp(d)))};return u(),r.subscribe(u)},[r]),p.jsx("div",{ref:o,className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:rp(l)},children:t})}function LS(t){const r=yc(),o=F.useRef(!1);F.useEffect(()=>{!o.current&&r.viewportInitialized&&t&&(setTimeout(()=>t(r),1),o.current=!0)},[t,r.viewportInitialized])}const AS=t=>{var r;return(r=t.panZoom)==null?void 0:r.syncViewport};function zS(t){const r=Ae(AS),o=We();return F.useEffect(()=>{t&&(r==null||r(t),o.setState({transform:[t.x,t.y,t.zoom]}))},[t,r]),null}function DS(t){return t.connection.inProgress?{...t.connection,to:Bo(t.connection.to,t.transform)}:{...t.connection}}function $S(t){return DS}function OS(t){const r=$S();return Ae(r,qe)}const FS=t=>({nodesConnectable:t.nodesConnectable,isValid:t.connection.isValid,inProgress:t.connection.inProgress,width:t.width,height:t.height});function HS({containerStyle:t,style:r,type:o,component:l}){const{nodesConnectable:a,width:u,height:d,isValid:f,inProgress:g}=Ae(FS,qe);return!(u&&a&&g)?null:p.jsx("svg",{style:t,width:u,height:d,className:"react-flow__connectionline react-flow__container",children:p.jsx("g",{className:it(["react-flow__connection",ng(f)]),children:p.jsx(om,{style:r,type:o,CustomComponent:l,isValid:f})})})}const om=({style:t,type:r=dr.Bezier,CustomComponent:o,isValid:l})=>{const{inProgress:a,from:u,fromNode:d,fromHandle:f,fromPosition:g,to:y,toNode:m,toHandle:x,toPosition:v,pointer:_}=OS();if(!a)return;if(o)return p.jsx(o,{connectionLineType:r,connectionLineStyle:t,fromNode:d,fromHandle:f,fromX:u.x,fromY:u.y,toX:y.x,toY:y.y,fromPosition:g,toPosition:v,connectionStatus:ng(l),toNode:m,toHandle:x,pointer:_});let S="";const j={sourceX:u.x,sourceY:u.y,sourcePosition:g,targetX:y.x,targetY:y.y,targetPosition:v};switch(r){case dr.Bezier:[S]=gg(j);break;case dr.SimpleBezier:[S]=Yg(j);break;case dr.Step:[S]=qu({...j,borderRadius:0});break;case dr.SmoothStep:[S]=qu(j);break;default:[S]=yg(j)}return p.jsx("path",{d:S,fill:"none",className:"react-flow__connection-path",style:t})};om.displayName="ConnectionLine";const BS={};function ip(t=BS){F.useRef(t),We(),F.useEffect(()=>{},[t])}function VS(){We(),F.useRef(!1),F.useEffect(()=>{},[])}function sm({nodeTypes:t,edgeTypes:r,onInit:o,onNodeClick:l,onEdgeClick:a,onNodeDoubleClick:u,onEdgeDoubleClick:d,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,onSelectionContextMenu:x,onSelectionStart:v,onSelectionEnd:_,connectionLineType:S,connectionLineStyle:j,connectionLineComponent:N,connectionLineContainerStyle:k,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,deleteKeyCode:I,onlyRenderVisibleElements:q,elementsSelectable:ne,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,preventScrolling:Y,defaultMarkerColor:V,zoomOnScroll:U,zoomOnPinch:z,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,zoomOnDoubleClick:R,panOnDrag:re,autoPanOnSelection:ie,onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneScroll:le,onPaneContextMenu:pe,paneClickDistance:_e,nodeClickDistance:xe,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Me,onEdgeMouseLeave:Pe,reconnectRadius:Re,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,viewport:ft,onViewportChange:Je,nodesDraggable:vn}){return ip(t),ip(r),VS(),LS(o),zS(ft),p.jsx(oS,{onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneContextMenu:pe,onPaneScroll:le,paneClickDistance:_e,deleteKeyCode:I,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,elementsSelectable:ne,zoomOnScroll:U,zoomOnPinch:z,zoomOnDoubleClick:R,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,panOnDrag:re,autoPanOnSelection:ie,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,onSelectionContextMenu:x,preventScrolling:Y,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,onViewportChange:Je,isControlledViewport:!!ft,children:p.jsxs(RS,{children:[p.jsx(TS,{edgeTypes:r,onEdgeClick:a,onEdgeDoubleClick:d,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,onlyRenderVisibleElements:q,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Me,onEdgeMouseLeave:Pe,reconnectRadius:Re,defaultMarkerColor:V,noPanClassName:It,disableKeyboardA11y:Ke,rfId:gt}),p.jsx(HS,{style:j,type:S,component:N,containerStyle:k}),p.jsx("div",{className:"react-flow__edgelabel-renderer"}),p.jsx(pS,{nodeTypes:t,onNodeClick:l,onNodeDoubleClick:u,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,nodeClickDistance:xe,onlyRenderVisibleElements:q,noPanClassName:It,noDragClassName:ot,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,nodesDraggable:vn}),p.jsx("div",{className:"react-flow__viewport-portal"})]})})}sm.displayName="GraphView";const WS=F.memo(sm),US=ag(),op=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g=.5,maxZoom:y=2,nodeOrigin:m,nodeExtent:x,zIndexMode:v="basic"}={})=>{const _=new Map,S=new Map,j=new Map,N=new Map,k=l??r??[],T=o??t??[],E=m??[0,0],b=x??Po;wg(j,N,k);const{nodesInitialized:$}=Ku(T,_,S,{nodeOrigin:E,nodeExtent:b,zIndexMode:v});let O=[0,0,1];if(d&&a&&u){const H=Fo(_,{filter:G=>!!((G.width||G.initialWidth)&&(G.height||G.initialHeight))}),{x:I,y:q,zoom:ne}=cc(H,a,u,g,y,(f==null?void 0:f.padding)??.1);O=[I,q,ne]}return{rfId:"1",width:a??0,height:u??0,transform:O,nodes:T,nodesInitialized:$,nodeLookup:_,parentLookup:S,edges:k,edgeLookup:N,connectionLookup:j,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:o!==void 0,hasDefaultEdges:l!==void 0,panZoom:null,minZoom:g,maxZoom:y,translateExtent:Po,nodeExtent:b,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Ii.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:E,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:d??!1,fitViewOptions:f,fitViewResolver:null,connection:{...tg},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:US,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:eg,zIndexMode:v,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},YS=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v})=>i_((_,S)=>{async function j(){const{nodeLookup:N,panZoom:k,fitViewOptions:T,fitViewResolver:E,width:b,height:$,minZoom:O,maxZoom:H}=S();k&&(await e1({nodes:N,width:b,height:$,panZoom:k,minZoom:O,maxZoom:H},T),E==null||E.resolve(!0),_({fitViewResolver:null}))}return{...op({nodes:t,edges:r,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,defaultNodes:o,defaultEdges:l,zIndexMode:v}),setNodes:N=>{const{nodeLookup:k,parentLookup:T,nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,fitViewQueued:O,zIndexMode:H,nodesSelectionActive:I}=S(),{nodesInitialized:q,hasSelectedNodes:ne}=Ku(N,k,T,{nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,checkEquality:!0,zIndexMode:H}),G=I&≠O&&q?(j(),_({nodes:N,nodesInitialized:q,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:G})):_({nodes:N,nodesInitialized:q,nodesSelectionActive:G})},setEdges:N=>{const{connectionLookup:k,edgeLookup:T}=S();wg(k,T,N),_({edges:N})},setDefaultNodesAndEdges:(N,k)=>{if(N){const{setNodes:T}=S();T(N),_({hasDefaultNodes:!0})}if(k){const{setEdges:T}=S();T(k),_({hasDefaultEdges:!0})}},updateNodeInternals:N=>{const{triggerNodeChanges:k,nodeLookup:T,parentLookup:E,domNode:b,nodeOrigin:$,nodeExtent:O,debug:H,fitViewQueued:I,zIndexMode:q}=S(),{changes:ne,updatedInternals:G}=k1(N,T,E,b,$,O,q);G&&(x1(T,E,{nodeOrigin:$,nodeExtent:O,zIndexMode:q}),I?(j(),_({fitViewQueued:!1,fitViewOptions:void 0})):_({}),(ne==null?void 0:ne.length)>0&&(H&&console.log("React Flow: trigger node changes",ne),k==null||k(ne)))},updateNodePositions:(N,k=!1)=>{const T=[];let E=[];const{nodeLookup:b,triggerNodeChanges:$,connection:O,updateConnection:H,onNodesChangeMiddlewareMap:I}=S();for(const[q,ne]of N){const G=b.get(q),ee=!!(G!=null&&G.expandParent&&(G!=null&&G.parentId)&&(ne!=null&&ne.position)),J={id:q,type:"position",position:ee?{x:Math.max(0,ne.position.x),y:Math.max(0,ne.position.y)}:ne.position,dragging:k};if(G&&O.inProgress&&O.fromNode.id===G.id){const C=Vr(G,O.fromHandle,Se.Left,!0);H({...O,from:C})}ee&&G.parentId&&T.push({id:q,parentId:G.parentId,rect:{...ne.internals.positionAbsolute,width:ne.measured.width??0,height:ne.measured.height??0}}),E.push(J)}if(T.length>0){const{parentLookup:q,nodeOrigin:ne}=S(),G=mc(T,b,q,ne);E.push(...G)}for(const q of I.values())E=q(E);$(E)},triggerNodeChanges:N=>{const{onNodesChange:k,setNodes:T,nodes:E,hasDefaultNodes:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=N_(N,E);T(O)}$&&console.log("React Flow: trigger node changes",N),k==null||k(N)}},triggerEdgeChanges:N=>{const{onEdgesChange:k,setEdges:T,edges:E,hasDefaultEdges:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=j_(N,E);T(O)}$&&console.log("React Flow: trigger edge changes",N),k==null||k(N)}},addSelectedNodes:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));b(O);return}b(ji(E,new Set([...N]),!0)),$(ji(T))},addSelectedEdges:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));$(O);return}$(ji(T,new Set([...N]))),b(ji(E,new Set,!0))},unselectNodesAndEdges:({nodes:N,edges:k}={})=>{const{edges:T,nodes:E,nodeLookup:b,triggerNodeChanges:$,triggerEdgeChanges:O}=S(),H=N||E,I=k||T,q=[];for(const G of H){if(!G.selected)continue;const ee=b.get(G.id);ee&&(ee.selected=!1),q.push(Ar(G.id,!1))}const ne=[];for(const G of I)G.selected&&ne.push(Ar(G.id,!1));$(q),O(ne)},setMinZoom:N=>{const{panZoom:k,maxZoom:T}=S();k==null||k.setScaleExtent([N,T]),_({minZoom:N})},setMaxZoom:N=>{const{panZoom:k,minZoom:T}=S();k==null||k.setScaleExtent([T,N]),_({maxZoom:N})},setTranslateExtent:N=>{var k;(k=S().panZoom)==null||k.setTranslateExtent(N),_({translateExtent:N})},resetSelectedElements:()=>{const{edges:N,nodes:k,triggerNodeChanges:T,triggerEdgeChanges:E,elementsSelectable:b}=S();if(!b)return;const $=k.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]),O=N.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]);T($),E(O)},setNodeExtent:N=>{const{nodes:k,nodeLookup:T,parentLookup:E,nodeOrigin:b,elevateNodesOnSelect:$,nodeExtent:O,zIndexMode:H}=S();N[0][0]===O[0][0]&&N[0][1]===O[0][1]&&N[1][0]===O[1][0]&&N[1][1]===O[1][1]||(Ku(k,T,E,{nodeOrigin:b,nodeExtent:N,elevateNodesOnSelect:$,checkEquality:!1,zIndexMode:H}),_({nodeExtent:N}))},panBy:N=>{const{transform:k,width:T,height:E,panZoom:b,translateExtent:$}=S();return E1({delta:N,panZoom:b,transform:k,translateExtent:$,width:T,height:E})},setCenter:async(N,k,T)=>{const{width:E,height:b,maxZoom:$,panZoom:O}=S();if(!O)return!1;const H=typeof(T==null?void 0:T.zoom)<"u"?T.zoom:$;return await O.setViewport({x:E/2-N*H,y:b/2-k*H,zoom:H},{duration:T==null?void 0:T.duration,ease:T==null?void 0:T.ease,interpolate:T==null?void 0:T.interpolate}),!0},cancelConnection:()=>{_({connection:{...tg}})},updateConnection:N=>{_({connection:N})},reset:()=>_({...op()})}},Object.is);function lm({initialNodes:t,initialEdges:r,defaultNodes:o,defaultEdges:l,initialWidth:a,initialHeight:u,initialMinZoom:d,initialMaxZoom:f,initialFitViewOptions:g,fitView:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v,children:_}){const[S]=F.useState(()=>YS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:y,minZoom:d,maxZoom:f,fitViewOptions:g,nodeOrigin:m,nodeExtent:x,zIndexMode:v}));return p.jsx(o_,{value:S,children:p.jsx(I_,{children:p.jsx(Y_,{children:_})})})}function GS({children:t,nodes:r,edges:o,defaultNodes:l,defaultEdges:a,width:u,height:d,fitView:f,fitViewOptions:g,minZoom:y,maxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_}){return F.useContext(Pl)?p.jsx(p.Fragment,{children:t}):p.jsx(lm,{initialNodes:r,initialEdges:o,defaultNodes:l,defaultEdges:a,initialWidth:u,initialHeight:d,fitView:f,initialFitViewOptions:g,initialMinZoom:y,initialMaxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_,children:t})}const XS={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function qS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,className:a,nodeTypes:u,edgeTypes:d,onNodeClick:f,onEdgeClick:g,onInit:y,onMove:m,onMoveStart:x,onMoveEnd:v,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onSelectionChange:J,onSelectionDragStart:C,onSelectionDrag:Y,onSelectionDragStop:V,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onBeforeDelete:W,connectionMode:M,connectionLineType:R=dr.Bezier,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,deleteKeyCode:fe="Backspace",selectionKeyCode:de="Shift",selectionOnDrag:K=!1,selectionMode:le=Io.Full,panActivationKeyCode:pe="Space",multiSelectionKeyCode:_e=Lo()?"Meta":"Control",zoomActivationKeyCode:xe=Lo()?"Meta":"Control",snapToGrid:ge,snapGrid:je,onlyRenderVisibleElements:Me=!1,selectNodesOnDrag:Pe,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,nodeOrigin:ot=Rg,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke=!0,defaultViewport:ze=v_,minZoom:gt=.5,maxZoom:ft=2,translateExtent:Je=Po,preventScrolling:vn=!0,nodeExtent:wt,defaultMarkerColor:Gt="#b1b1b7",zoomOnScroll:zi=!0,zoomOnPinch:kt=!0,panOnScroll:hr=!1,panOnScrollSpeed:An=.5,panOnScrollMode:zn=$r.Free,zoomOnDoubleClick:pr=!0,panOnDrag:gr=!0,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr=1,nodeClickDistance:$n=0,children:Gr,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn=10,onNodesChange:Fn,onEdgesChange:Xr,noDragClassName:qr="nodrag",noWheelClassName:Qr="nowheel",noPanClassName:Tt="nopan",fitView:Hn,fitViewOptions:L,connectOnClick:te,attributionPosition:ke,proOptions:Te,defaultEdgeOptions:Ce,elevateNodesOnSelect:Bn=!0,elevateEdgesOnSelect:Al=!1,disableKeyboardA11y:Vo=!1,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanOnSelection:$i=!0,autoPanSpeed:Wo,connectionRadius:Kr,isValidConnection:Dl,onError:Uo,style:Zr,id:Rt,nodeDragThreshold:$l,connectionDragThreshold:Lt,viewport:Ol,onViewportChange:Fl,width:Hl,height:Jr,colorMode:ei="light",debug:wr,onScroll:kn,ariaLabelConfig:Bl,zIndexMode:Yo="basic",...Oi},Go){const _r=Rt||"1",Sr=S_(ei),Vl=F.useCallback(ti=>{ti.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),kn==null||kn(ti)},[kn]);return p.jsx("div",{"data-testid":"rf__wrapper",...Oi,onScroll:Vl,style:{...Zr,...XS},ref:Go,className:it(["react-flow",a,Sr]),id:Rt,role:"application",children:p.jsxs(GS,{nodes:t,edges:r,width:Hl,height:Jr,fitView:Hn,fitViewOptions:L,minZoom:gt,maxZoom:ft,nodeOrigin:ot,nodeExtent:wt,zIndexMode:Yo,children:[p.jsx(__,{nodes:t,edges:r,defaultNodes:o,defaultEdges:l,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke,elevateNodesOnSelect:Bn,elevateEdgesOnSelect:Al,minZoom:gt,maxZoom:ft,nodeExtent:wt,onNodesChange:Fn,onEdgesChange:Xr,snapToGrid:ge,snapGrid:je,connectionMode:M,translateExtent:Je,connectOnClick:te,defaultEdgeOptions:Ce,fitView:Hn,fitViewOptions:L,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onSelectionDrag:Y,onSelectionDragStart:C,onSelectionDragStop:V,onMove:m,onMoveStart:x,onMoveEnd:v,noPanClassName:Tt,nodeOrigin:ot,rfId:_r,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanSpeed:Wo,onError:Uo,connectionRadius:Kr,isValidConnection:Dl,selectNodesOnDrag:Pe,nodeDragThreshold:$l,connectionDragThreshold:Lt,onBeforeDelete:W,debug:wr,ariaLabelConfig:Bl,zIndexMode:Yo}),p.jsx(WS,{onInit:y,onNodeClick:f,onEdgeClick:g,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,nodeTypes:u,edgeTypes:d,connectionLineType:R,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,selectionKeyCode:de,selectionOnDrag:K,selectionMode:le,deleteKeyCode:fe,multiSelectionKeyCode:_e,panActivationKeyCode:pe,zoomActivationKeyCode:xe,onlyRenderVisibleElements:Me,defaultViewport:ze,translateExtent:Je,minZoom:gt,maxZoom:ft,preventScrolling:vn,zoomOnScroll:zi,zoomOnPinch:kt,zoomOnDoubleClick:pr,panOnScroll:hr,panOnScrollSpeed:An,panOnScrollMode:zn,panOnDrag:gr,autoPanOnSelection:$i,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr,nodeClickDistance:$n,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn,defaultMarkerColor:Gt,noDragClassName:qr,noWheelClassName:Qr,noPanClassName:Tt,rfId:_r,disableKeyboardA11y:Vo,nodeExtent:wt,viewport:Ol,onViewportChange:Fl,nodesDraggable:Re}),p.jsx(y_,{onSelectionChange:J}),Gr,p.jsx(f_,{proOptions:Te,position:ke}),p.jsx(d_,{rfId:_r,disableKeyboardA11y:Vo})]})})}var QS=Ag(qS);function KS({dimensions:t,lineWidth:r,variant:o,className:l}){return p.jsx("path",{strokeWidth:r,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`,className:it(["react-flow__background-pattern",o,l])})}function ZS({radius:t,className:r}){return p.jsx("circle",{cx:t,cy:t,r:t,className:it(["react-flow__background-pattern","dots",r])})}var fr;(function(t){t.Lines="lines",t.Dots="dots",t.Cross="cross"})(fr||(fr={}));const JS={[fr.Dots]:1,[fr.Lines]:1,[fr.Cross]:6},ek=t=>({transform:t.transform,patternId:`pattern-${t.rfId}`});function am({id:t,variant:r=fr.Dots,gap:o=20,size:l,lineWidth:a=1,offset:u=0,color:d,bgColor:f,style:g,className:y,patternClassName:m}){const x=F.useRef(null),{transform:v,patternId:_}=Ae(ek,qe),S=l||JS[r],j=r===fr.Dots,N=r===fr.Cross,k=Array.isArray(o)?o:[o,o],T=[k[0]*v[2]||1,k[1]*v[2]||1],E=S*v[2],b=Array.isArray(u)?u:[u,u],$=N?[E,E]:T,O=[b[0]*v[2]+$[0]/2,b[1]*v[2]+$[1]/2],H=`${_}${t||""}`;return p.jsxs("svg",{className:it(["react-flow__background",y]),style:{...g,...Tl,"--xy-background-color-props":f,"--xy-background-pattern-color-props":d},ref:x,"data-testid":"rf__background",children:[p.jsx("pattern",{id:H,x:v[0]%T[0],y:v[1]%T[1],width:T[0],height:T[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${O[0]},-${O[1]})`,children:j?p.jsx(ZS,{radius:E/2,className:m}):p.jsx(KS,{dimensions:$,lineWidth:a,variant:r,className:m})}),p.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}am.displayName="Background";const tk=F.memo(am);function nk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:p.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function rk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:p.jsx("path",{d:"M0 0h32v4.2H0z"})})}function ik(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:p.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function ok(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function sk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function rl({children:t,className:r,...o}){return p.jsx("button",{type:"button",className:it(["react-flow__controls-button",r]),...o,children:t})}const lk=t=>({isInteractive:t.nodesDraggable||t.nodesConnectable||t.elementsSelectable,minZoomReached:t.transform[2]<=t.minZoom,maxZoomReached:t.transform[2]>=t.maxZoom,ariaLabelConfig:t.ariaLabelConfig});function um({style:t,showZoom:r=!0,showFitView:o=!0,showInteractive:l=!0,fitViewOptions:a,onZoomIn:u,onZoomOut:d,onFitView:f,onInteractiveChange:g,className:y,children:m,position:x="bottom-left",orientation:v="vertical","aria-label":_}){const S=We(),{isInteractive:j,minZoomReached:N,maxZoomReached:k,ariaLabelConfig:T}=Ae(lk,qe),{zoomIn:E,zoomOut:b,fitView:$}=yc(),O=()=>{E(),u==null||u()},H=()=>{b(),d==null||d()},I=()=>{$(a),f==null||f()},q=()=>{S.setState({nodesDraggable:!j,nodesConnectable:!j,elementsSelectable:!j}),g==null||g(!j)},ne=v==="horizontal"?"horizontal":"vertical";return p.jsxs(Il,{className:it(["react-flow__controls",ne,y]),position:x,style:t,"data-testid":"rf__controls","aria-label":_??T["controls.ariaLabel"],children:[r&&p.jsxs(p.Fragment,{children:[p.jsx(rl,{onClick:O,className:"react-flow__controls-zoomin",title:T["controls.zoomIn.ariaLabel"],"aria-label":T["controls.zoomIn.ariaLabel"],disabled:k,children:p.jsx(nk,{})}),p.jsx(rl,{onClick:H,className:"react-flow__controls-zoomout",title:T["controls.zoomOut.ariaLabel"],"aria-label":T["controls.zoomOut.ariaLabel"],disabled:N,children:p.jsx(rk,{})})]}),o&&p.jsx(rl,{className:"react-flow__controls-fitview",onClick:I,title:T["controls.fitView.ariaLabel"],"aria-label":T["controls.fitView.ariaLabel"],children:p.jsx(ik,{})}),l&&p.jsx(rl,{className:"react-flow__controls-interactive",onClick:q,title:T["controls.interactive.ariaLabel"],"aria-label":T["controls.interactive.ariaLabel"],children:j?p.jsx(sk,{}):p.jsx(ok,{})}),m]})}um.displayName="Controls";const ak=F.memo(um);function uk({id:t,x:r,y:o,width:l,height:a,style:u,color:d,strokeColor:f,strokeWidth:g,className:y,borderRadius:m,shapeRendering:x,selected:v,onClick:_}){const{background:S,backgroundColor:j}=u||{},N=d||S||j;return p.jsx("rect",{className:it(["react-flow__minimap-node",{selected:v},y]),x:r,y:o,rx:m,ry:m,width:l,height:a,style:{fill:N,stroke:f,strokeWidth:g},shapeRendering:x,onClick:_?k=>_(k,t):void 0})}const ck=F.memo(uk),dk=t=>t.nodes.map(r=>r.id),Du=t=>t instanceof Function?t:()=>t;function fk({nodeStrokeColor:t,nodeColor:r,nodeClassName:o="",nodeBorderRadius:l=5,nodeStrokeWidth:a,nodeComponent:u=ck,onClick:d}){const f=Ae(dk,qe),g=Du(r),y=Du(t),m=Du(o),x=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return p.jsx(p.Fragment,{children:f.map(v=>p.jsx(pk,{id:v,nodeColorFunc:g,nodeStrokeColorFunc:y,nodeClassNameFunc:m,nodeBorderRadius:l,nodeStrokeWidth:a,NodeComponent:u,onClick:d,shapeRendering:x},v))})}function hk({id:t,nodeColorFunc:r,nodeStrokeColorFunc:o,nodeClassNameFunc:l,nodeBorderRadius:a,nodeStrokeWidth:u,shapeRendering:d,NodeComponent:f,onClick:g}){const{node:y,x:m,y:x,width:v,height:_}=Ae(S=>{const j=S.nodeLookup.get(t);if(!j)return{node:void 0,x:0,y:0,width:0,height:0};const N=j.internals.userNode,{x:k,y:T}=j.internals.positionAbsolute,{width:E,height:b}=an(N);return{node:N,x:k,y:T,width:E,height:b}},qe);return!y||y.hidden||!ug(y)?null:p.jsx(f,{x:m,y:x,width:v,height:_,style:y.style,selected:!!y.selected,className:l(y),color:r(y),borderRadius:a,strokeColor:o(y),strokeWidth:u,shapeRendering:d,onClick:g,id:y.id})}const pk=F.memo(hk);var gk=F.memo(fk);const mk=200,yk=150,vk=t=>!t.hidden,xk=t=>{const r={x:-t.transform[0]/t.transform[2],y:-t.transform[1]/t.transform[2],width:t.width/t.transform[2],height:t.height/t.transform[2]};return{viewBB:r,boundingRect:t.nodeLookup.size>0?sg(Fo(t.nodeLookup,{filter:vk}),r):r,rfId:t.rfId,panZoom:t.panZoom,translateExtent:t.translateExtent,flowWidth:t.width,flowHeight:t.height,ariaLabelConfig:t.ariaLabelConfig}},sp=(t,r)=>t.x===r.x&&t.y===r.y&&t.width===r.width&&t.height===r.height,wk=(t,r)=>sp(t.viewBB,r.viewBB)&&sp(t.boundingRect,r.boundingRect)&&t.rfId===r.rfId&&t.panZoom===r.panZoom&&t.translateExtent===r.translateExtent&&t.flowWidth===r.flowWidth&&t.flowHeight===r.flowHeight&&t.ariaLabelConfig===r.ariaLabelConfig,_k="react-flow__minimap-desc";function cm({style:t,className:r,nodeStrokeColor:o,nodeColor:l,nodeClassName:a="",nodeBorderRadius:u=5,nodeStrokeWidth:d,nodeComponent:f,bgColor:g,maskColor:y,maskStrokeColor:m,maskStrokeWidth:x,position:v="bottom-right",onClick:_,onNodeClick:S,pannable:j=!1,zoomable:N=!1,ariaLabel:k,inversePan:T,zoomStep:E=1,offsetScale:b=5}){const $=We(),O=F.useRef(null),{boundingRect:H,viewBB:I,rfId:q,panZoom:ne,translateExtent:G,flowWidth:ee,flowHeight:J,ariaLabelConfig:C}=Ae(xk,wk),Y=(t==null?void 0:t.width)??mk,V=(t==null?void 0:t.height)??yk,U=H.width/Y,z=H.height/V,D=Math.max(U,z),W=D*Y,M=D*V,R=b*D,re=H.x-(W-H.width)/2-R,ie=H.y-(M-H.height)/2-R,ce=W+R*2,fe=M+R*2,de=`${_k}-${q}`,K=F.useRef(0),le=F.useRef();K.current=D,F.useEffect(()=>{if(O.current&&ne)return le.current=R1({domNode:O.current,panZoom:ne,getTransform:()=>$.getState().transform,getViewScale:()=>K.current}),()=>{var ge;(ge=le.current)==null||ge.destroy()}},[ne]),F.useEffect(()=>{var ge;(ge=le.current)==null||ge.update({translateExtent:G,width:ee,height:J,inversePan:T,pannable:j,zoomStep:E,zoomable:N})},[j,N,T,E,G,ee,J]);const pe=_?ge=>{var Pe;const[je,Me]=((Pe=le.current)==null?void 0:Pe.pointer(ge))||[0,0];_(ge,{x:je,y:Me})}:void 0,_e=S?F.useCallback((ge,je)=>{const Me=$.getState().nodeLookup.get(je).internals.userNode;S(ge,Me)},[]):void 0,xe=k??C["minimap.ariaLabel"];return p.jsx(Il,{position:v,style:{...t,"--xy-minimap-background-color-props":typeof g=="string"?g:void 0,"--xy-minimap-mask-background-color-props":typeof y=="string"?y:void 0,"--xy-minimap-mask-stroke-color-props":typeof m=="string"?m:void 0,"--xy-minimap-mask-stroke-width-props":typeof x=="number"?x*D:void 0,"--xy-minimap-node-background-color-props":typeof l=="string"?l:void 0,"--xy-minimap-node-stroke-color-props":typeof o=="string"?o:void 0,"--xy-minimap-node-stroke-width-props":typeof d=="number"?d:void 0},className:it(["react-flow__minimap",r]),"data-testid":"rf__minimap",children:p.jsxs("svg",{width:Y,height:V,viewBox:`${re} ${ie} ${ce} ${fe}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":de,ref:O,onClick:pe,children:[xe&&p.jsx("title",{id:de,children:xe}),p.jsx(gk,{onClick:_e,nodeColor:l,nodeStrokeColor:o,nodeBorderRadius:u,nodeClassName:a,nodeStrokeWidth:d,nodeComponent:f}),p.jsx("path",{className:"react-flow__minimap-mask",d:`M${re-R},${ie-R}h${ce+R*2}v${fe+R*2}h${-ce-R*2}z + M${I.x},${I.y}h${I.width}v${I.height}h${-I.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}cm.displayName="MiniMap";const Sk=F.memo(cm),kk=t=>r=>t?`${Math.max(1/r.transform[2],1)}`:void 0,Ek={[Li.Line]:"right",[Li.Handle]:"bottom-right"};function Nk({nodeId:t,position:r,variant:o=Li.Handle,className:l,style:a=void 0,children:u,color:d,minWidth:f=10,minHeight:g=10,maxWidth:y=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:x=!1,resizeDirection:v,autoScale:_=!0,shouldResize:S,onResizeStart:j,onResize:N,onResizeEnd:k}){const T=Fg(),E=typeof t=="string"?t:T,b=We(),$=F.useRef(null),O=o===Li.Handle,H=Ae(F.useCallback(kk(O&&_),[O,_]),qe),I=F.useRef(null),q=r??Ek[o];F.useEffect(()=>{if(!(!$.current||!E))return I.current||(I.current=Y1({domNode:$.current,nodeId:E,getStoreItems:()=>{const{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,domNode:V}=b.getState();return{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,paneDomNode:V}},onChange:(G,ee)=>{const{triggerNodeChanges:J,nodeLookup:C,parentLookup:Y,nodeOrigin:V}=b.getState(),U=[],z={x:G.x,y:G.y},D=C.get(E);if(D&&D.expandParent&&D.parentId){const W=D.origin??V,M=G.width??D.measured.width??0,R=G.height??D.measured.height??0,re={id:D.id,parentId:D.parentId,rect:{width:M,height:R,...cg({x:G.x??D.position.x,y:G.y??D.position.y},{width:M,height:R},D.parentId,C,W)}},ie=mc([re],C,Y,V);U.push(...ie),z.x=G.x?Math.max(W[0]*M,G.x):void 0,z.y=G.y?Math.max(W[1]*R,G.y):void 0}if(z.x!==void 0&&z.y!==void 0){const W={id:E,type:"position",position:{...z}};U.push(W)}if(G.width!==void 0&&G.height!==void 0){const M={id:E,type:"dimensions",resizing:!0,setAttributes:v?v==="horizontal"?"width":"height":!0,dimensions:{width:G.width,height:G.height}};U.push(M)}for(const W of ee){const M={...W,type:"position"};U.push(M)}J(U)},onEnd:({width:G,height:ee})=>{const J={id:E,type:"dimensions",resizing:!1,dimensions:{width:G,height:ee}};b.getState().triggerNodeChanges([J])}})),I.current.update({controlPosition:q,boundaries:{minWidth:f,minHeight:g,maxWidth:y,maxHeight:m},keepAspectRatio:x,resizeDirection:v,onResizeStart:j,onResize:N,onResizeEnd:k,shouldResize:S}),()=>{var G;(G=I.current)==null||G.destroy()}},[q,f,g,y,m,x,j,N,k,S]);const ne=q.split("-");return p.jsx("div",{className:it(["react-flow__resize-control","nodrag",...ne,o,l]),ref:$,style:{...a,scale:H,...d&&{[O?"backgroundColor":"borderColor"]:d}},children:u})}F.memo(Nk);const jk={"arch.context":0,"django.app":0,"django.route":1,"django.url_name":1,"django.view":2,"django.viewset_action":2,"django.permission":2,"django.serializer":3,"django.form":3,"django.serializer_field":4,"django.service":4,"django.model":5,"django.field":6,"django.relation":6,"django.task":7,"django.receiver":7,"django.signal":7,"django.test":7,"django.migration_op":7,"django.admin":7,"django.management_command":7,"django.consumer":7,"django.websocket_route":1,"django.template":11,"django.htmx":9,"django.cache_key":7,"django.feature_flag":7,"django.side_effect":7,"graphql.type":3,"graphql.field":4,"graphql.operation":8,"fastapi.route":1,"fastapi.model":3,"openapi.path":8,"react.api_client":9,"react.query_key":10,"react.hook":10,"react.feature":10,"react.route":11,"react.page":11,"react.component":12,"react.form_schema":13,"react.test":13,"react.context":12};function Ll(t){return jk[t]??8}function bk(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r)a.sort((u,d)=>u.name.localeCompare(d.name)),a.forEach((u,d)=>{o.set(u.id,{x:l*260,y:d*108})});return o}const dm=90,Ck=new Set(["django.field","django.serializer_field","django.relation","django.test","react.test","graphql.field","django.url_name","django.throttle"]),lp={"arch.context":"#edf2f4","django.app":"#8d99ae","django.route":"#4cc9f0","django.view":"#4895ef","django.viewset_action":"#4361ee","django.permission":"#7b8cde","django.serializer":"#f4a261","django.form":"#e9c46a","django.serializer_field":"#e9c46a","django.service":"#90be6d","django.model":"#2a9d8f","django.field":"#8ac926","django.task":"#e76f51","django.receiver":"#e85d04","django.signal":"#f4a261","django.test":"#6c757d","django.admin":"#adb5bd","django.migration_op":"#9d4edd","django.consumer":"#e76f51","django.websocket_route":"#4cc9f0","django.template":"#c77dff","django.htmx":"#ff6b6b","django.cache_key":"#6c757d","django.feature_flag":"#f4a261","django.side_effect":"#e85d04","graphql.type":"#00bbf9","graphql.operation":"#00bbf9","fastapi.route":"#4cc9f0","fastapi.model":"#f4a261","openapi.path":"#00bbf9","react.api_client":"#ff6b6b","react.query_key":"#adb5bd","react.hook":"#7b2cbf","react.feature":"#9d4edd","react.route":"#c77dff","react.page":"#c77dff","react.component":"#9d4edd","react.form_schema":"#ffd166","react.test":"#6c757d"},Mk=Math.PI*(3-Math.sqrt(5)),fm=220,Pk=26,Ik={0:"context",1:"routes",2:"views",3:"serializers",4:"services",5:"models",6:"fields",7:"jobs / signals",8:"openapi",9:"api client",10:"hooks",11:"pages",12:"components",13:"forms / tests"};function hm(t){return t.startsWith("react.")?"react":t.startsWith("openapi.")||t.startsWith("graphql.")||t.startsWith("fastapi.")?"stitch":t.startsWith("arch.")?"arch":"django"}function dE(t){return lp[t]?lp[t]:t.startsWith("react.")?"#9d4edd":t.startsWith("openapi.")?"#00bbf9":"#4a5568"}function Tk(t){return t>=dm?"3d":"2d"}function Rk(t){return t>=dm?"overview":"full"}function Lk(t,r,o=1){const l=new Set([t]);let a=new Set([t]);for(let u=0;uo.families.has(hm(f.type)));o.detail==="overview"&&(l=l.filter(f=>!Ck.has(f.type)));const a=new Set(l.map(f=>f.id)),u=r.filter(f=>a.has(f.src)&&a.has(f.dst)),d=o.focusId?Lk(o.focusId,u,1):new Set;if(o.neighborhoodOnly&&o.focusId&&d.size){l=l.filter(g=>d.has(g.id));const f=new Set(l.map(g=>g.id));return{nodes:l,edges:u.filter(g=>f.has(g.src)&&f.has(g.dst)),neighborIds:d}}return{nodes:l,edges:u,neighborIds:d}}function fE(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r){a.sort((d,f)=>d.name.localeCompare(f.name));const u=l*fm;a.forEach((d,f)=>{if(a.length===1){o.set(d.id,{x:u,y:0,z:0});return}const g=Pk*Math.sqrt(f+1),y=f*Mk;o.set(d.id,{x:u,y:g*Math.cos(y),z:g*Math.sin(y)})})}return o}function hE(t){const r=new Map;for(const o of t){const l=Ll(o.type);r.set(l,(r.get(l)||0)+1)}return[...r.entries()].sort((o,l)=>o[0]-l[0]).map(([o,l])=>({layer:o,x:o*fm,count:l}))}const il=16,zk=12,Dk=new Set(["django.route","react.route","react.page","django.task","django.migration_op","django.permission","django.throttle","django.admin","django.management_command","openapi.path","django.consumer","django.websocket_route","django.template","django.cache_key","django.feature_flag","django.side_effect","graphql.operation","fastapi.route"]),$k=new Set(["django.serializer","django.serializer_field","django.form","openapi.path","react.form_schema","django.route","graphql.type","graphql.field","graphql.operation","fastapi.model","fastapi.route"]),ap={"arch.context":"Ownership boundary from loadpath.yml — the context this code belongs to.","django.app":"Django app package that owns models, views, and jobs.","django.route":"HTTP URL that publishes a view. A sink: this is where a change becomes a public request.","django.url_name":"Named URL used by reverse() / {% url %} lookups.","django.view":"Request handler (class-based view, function view, or ViewSet).","django.viewset_action":"One ViewSet action (list, create, retrieve, update, destroy).","django.permission":"Auth gate on a view — who is allowed to hit this path.","django.throttle":"Rate-limit class attached to a view.","django.serializer":"Request/response contract: which fields go in and come out.","django.form":"Django form that validates submitted input.","django.serializer_field":"One field on a serializer or form — the typed slot on the contract.","django.service":"Internal service or use-case. Work that is not itself an HTTP sink.","django.model":"ORM model. Schema and relations live here.","django.field":"Model column. Type, indexes, and relations are the contract of the table.","django.relation":"Model-to-model relation (FK / M2M / O2O).","django.task":"Celery or Dramatiq job. Once enqueued, this is a sink.","django.receiver":"Signal handler that runs after a model event.","django.signal":"Django signal that receivers subscribe to.","django.test":"Backend test that mentions symbols on this path.","django.admin":"Django admin class for a model.","django.migration_op":"Schema migration operation (CreateModel, AlterField, …).","django.management_command":"manage.py command — an operational sink.","django.consumer":"Django Channels WebSocket/HTTP consumer. A sink once a client connects.","django.websocket_route":"ASGI WebSocket URL. A sink: this is where a change becomes a live connection.","django.template":"Django template. HTML (and HTMX) the server renders.","django.htmx":"HTMX call from a template to a URL — another published seam.","django.cache_key":"Cache get/set key. Invalidation is part of the load path.","django.feature_flag":"Feature flag checked on this path. The change may be dark-launched.","django.side_effect":"transaction.on_commit (or similar) side effect that runs after the request commits.","graphql.type":"GraphQL object/input type — a published contract.","graphql.field":"One field on a GraphQL type.","graphql.operation":"GraphQL query, mutation, or subscription. A published contract and a sink.","fastapi.route":"FastAPI path operation sitting next to Django in this repo.","fastapi.model":"Pydantic response/request model — the FastAPI contract.","openapi.path":"Generated OpenAPI operation. The typed HTTP contract between stacks.","react.api_client":"Frontend fetch or generated client call to an API path.","react.query_key":"React Query cache key. Invalidation and reads share this name.","react.hook":"Data hook wrapping query or mutation calls.","react.feature":"Frontend feature module (folder).","react.route":"Client-side route. A sink: this is a URL the user can open.","react.page":"Page or screen component rendered by a route.","react.component":"UI component.","react.form_schema":"Zod (or similar) schema — typed form inputs on the client.","react.test":"Frontend test covering a page, hook, or component.","react.context":"React context provider."},Ok={field_type:"Type",fields:"Fields",form_fields:"Form fields",permissions:"Permissions",throttles:"Throttles",authentication:"Authentication",pagination:"Pagination",filterset:"Filterset",bases:"Extends",on_delete:"on_delete",related_name:"related_name",unique:"Unique",db_index:"Indexed",relation:"Relation field",looks_idempotent_on_pk:"Idempotent on pk",broker:"Broker",route:"Route",url_name:"URL name",view:"View",include:"Includes",mounted_at:"Mounted at",full_path:"Full path",method:"Method",path:"Path",operation_id:"Operation",raw:"URL",kind:"Schema",exclude:"Excludes",queryset_in_serializer:"Queryset in serializer",get_queryset:"Custom get_queryset",get_serializer_class:"Dynamic serializer",dynamic:"Dynamic",fbv:"Function view",ninja:"Django Ninja",django_form:"Django form",mutation:"Mutation",has_error_boundary:"Error boundary",invalidation:"Cache invalidation",inferred:"Inferred stitch",generated:"Generated",shared:"Shared module",element:"Renders",model_name:"Model",field_name:"Field",op:"Operation",app:"App",feature:"Feature",from_view:"From view",mentions:"Mentions",nodeid:"Test id",task:"Task",to:"Related to"},up=["field_type","method","path","operation_id","raw","route","mounted_at","full_path","url_name","view","element","fields","form_fields","exclude","kind","bases","permissions","authentication","throttles","pagination","filterset","on_delete","related_name","to","unique","db_index","relation","looks_idempotent_on_pk","broker","task","model_name","field_name","op","app","feature","from_view","include","fbv","ninja","django_form","mutation","has_error_boundary","invalidation","inferred","generated","shared","queryset_in_serializer","get_queryset","get_serializer_class","dynamic","mentions","nodeid"],cp=new Set(["referenced","placeholder","booted","line","call","from","import","local","source","file","plain_handler","string_ref","pagination_sink","match","via","generated_client","django","react","superseded_by_generated","foreign_app","imported"]),Fk=new Set(["looks_idempotent_on_pk"]),Hk=new Set(["inferred","generated","mutation","fbv","ninja"]);function Bk(t){return ap[t]?ap[t]:t.startsWith("react.")?"A React node on the load path.":t.startsWith("django.")?"A Django node on the load path.":t.startsWith("openapi.")?"A stitch node between Django and React.":"A node on the architecture graph."}function Vk(t,r,o){const l=new Map(r.map(x=>[x.id,x])),a=[];Dk.has(t.type)&&a.push("sink"),$k.has(t.type)&&a.push("contract");const u=t.extra??{};u.inferred&&a.push("inferred"),u.generated&&a.push("generated"),u.mutation&&a.push("mutation"),u.fbv&&a.push("function view"),u.ninja&&a.push("ninja");const d=o.filter(x=>x.dst===t.id),f=o.filter(x=>x.src===t.id),g=d.slice(0,il).map(x=>dp(x,l,x.src)),y=f.slice(0,il).map(x=>dp(x,l,x.dst)),m=t.file_path?`${t.file_path}${t.start_line?`:${t.start_line}`:""}`:void 0;return{type:t.type,typeLabel:No(_l(t.type)),layer:Ik[Ll(t.type)]??"other",purpose:Bk(t.type),name:t.name,qualifiedName:t.qualified_name,file:m,context:t.context,roles:a,facts:Wk(u).filter(x=>!(x.key==="app"&&x.value===t.context)),inputs:g,outputs:y,extraInputs:Math.max(0,d.length-il),extraOutputs:Math.max(0,f.length-il)}}function dp(t,r,o){const l=r.get(o),a=o.includes(":")?o.slice(o.indexOf(":")+1):o;return{id:o,name:(l==null?void 0:l.name)||a,type:(l==null?void 0:l.type)||"",typeLabel:l?No(_l(l.type)):"",edgeType:t.type,edgeLabel:No(t.type),inferred:t.confidence<.8}}function Wk(t){const r=[...up.filter(a=>a in t),...Object.keys(t).filter(a=>!up.includes(a)&&!cp.has(a))],o=[],l=new Set;for(const a of r){if(l.has(a)||cp.has(a)||Hk.has(a))continue;l.add(a);const u=Uk(a,t[a]);u!=null&&o.push({key:a,label:Ok[a]??No(a),value:u})}return o}function Uk(t,r){if(r==null)return null;if(typeof r=="boolean")return!r&&!Fk.has(t)?null:r?"yes":"no";if(typeof r=="number")return String(r);if(typeof r=="string")return r.trim()||null;if(Array.isArray(r)){const o=r.map(u=>typeof u=="string"||typeof u=="number"?String(u):"").filter(Boolean);if(!o.length)return null;const l=o.slice(0,zk),a=o.length-l.length;return a>0?`${l.join(", ")} +${a} more`:l.join(", ")}return null}const Yk=F.lazy(()=>m0(()=>import("./LayeredGraph3D-CNVAazxv.js"),[],import.meta.url).then(t=>({default:t.LayeredGraph3D}))),Gk={cheap:"var(--edge-cheap)",expensive:"var(--edge-expensive)",critical:"var(--edge-critical)"};function Xk({data:t,selected:r}){return p.jsxs("div",{className:r?"lp-node selected":"lp-node",children:[p.jsx(Ai,{type:"target",position:Se.Left,isConnectable:!1}),p.jsx("div",{className:"t",children:_l(t.type)}),p.jsx("div",{className:"n",title:t.name,children:t.name}),p.jsx(Ai,{type:"source",position:Se.Right,isConnectable:!1})]})}const qk={load:Xk},fp=180,hp=56,Qk=new Set(["django","react","stitch","arch"]);function Kk(t,r,o=null){const l=new Map(t.map(f=>[f.id,f])),a=bk(t),u=t.map(f=>({id:f.id,type:"load",position:a.get(f.id)??{x:0,y:0},data:{name:f.name,type:f.type,file:f.file_path},selected:o===f.id,sourcePosition:Se.Right,targetPosition:Se.Left,width:fp,height:hp,style:{width:fp,height:hp}})),d=r.filter(f=>l.has(f.src)&&l.has(f.dst)).map(f=>{const g=Gk[f.weight]||"var(--edge-cheap)";return{id:f.id,source:f.src,target:f.dst,type:"smoothstep",animated:f.weight==="critical",style:{stroke:g,strokeWidth:f.weight==="critical"?2.4:1.2,strokeDasharray:f.confidence<.8?"6 4":void 0},markerEnd:{type:To.ArrowClosed,width:14,height:14,color:g},label:f.type.replaceAll("_"," "),labelStyle:{fill:"var(--muted)",fontSize:10}}});return{rfNodes:u,rfEdges:d}}function pp({node:t,nodes:r,edges:o,onClose:l,onWhatIf:a}){const u=Vk(t,r,o);return F.useEffect(()=>{const d=f=>{f.key==="Escape"&&l()};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[l]),p.jsxs("aside",{className:"inspector","data-testid":"graph-inspector",children:[p.jsxs("div",{className:"inspector-head",children:[p.jsx("div",{className:"t",children:u.typeLabel}),p.jsx("div",{className:"inspector-roles",children:u.roles.map(d=>p.jsx("span",{className:"inspector-chip",children:d},d))}),p.jsx("button",{type:"button",className:"inspector-close","data-testid":"graph-inspector-close","aria-label":"Close inspector",onClick:l,children:"×"})]}),p.jsx("div",{className:"n",children:Ni(u.name)}),p.jsx("p",{className:"inspector-purpose","data-testid":"graph-inspector-purpose",children:u.purpose}),u.context?p.jsx("div",{className:"muted",children:Ni(u.context)}):null,u.file?p.jsx("div",{className:"file",children:Ni(u.file)}):null,p.jsx("div",{className:"muted",children:Ni(u.qualifiedName)}),p.jsxs("div",{className:"muted inspector-layer",children:["layer · ",u.layer]}),u.facts.length?p.jsx("dl",{className:"inspector-facts","data-testid":"graph-inspector-facts",children:u.facts.map(d=>p.jsxs("div",{className:"inspector-fact",children:[p.jsx("dt",{children:d.label}),p.jsx("dd",{children:Ni(d.value)})]},d.key))}):null,p.jsx(gp,{title:"Inputs",testId:"graph-inspector-inputs",links:u.inputs,extra:u.extraInputs,empty:"Nothing in this graph points here."}),p.jsx(gp,{title:"Outputs",testId:"graph-inspector-outputs",links:u.outputs,extra:u.extraOutputs,empty:"This node does not point at anything in this graph."}),a?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-whatif",onClick:()=>a(t.id),children:"What if this changes"}):null]})}function gp({title:t,testId:r,links:o,extra:l,empty:a}){return p.jsxs("section",{className:"inspector-section","data-testid":r,children:[p.jsxs("h3",{children:[t,p.jsx("span",{className:"count",children:o.length+l})]}),o.length?p.jsx("ul",{children:o.map((u,d)=>p.jsxs("li",{children:[p.jsx("span",{className:"inspector-link-name",title:u.name,children:Ni(u.name)}),p.jsxs("span",{className:"inspector-link-meta",children:[u.typeLabel?`${u.typeLabel} · `:"",u.edgeLabel,u.inferred?" · inferred":""]})]},`${u.edgeType}:${u.id}:${d}`))}):p.jsx("p",{className:"muted",children:a}),l?p.jsxs("p",{className:"muted",children:["+",l," more"]}):null]})}function $u({nodes:t,edges:r,onWhatIf:o,focusPath:l}){const[a,u]=F.useState(null),[d,f]=F.useState(null),[g,y]=F.useState(null),[m,x]=F.useState(new Set(Qk)),[v,_]=F.useState(!1),S=typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,j=d??Tk(t.length),N=g??Rk(t.length),k=F.useMemo(()=>Ak(t,r,{detail:N,families:m,focusId:a,neighborhoodOnly:v&&j==="3d"}),[t,r,N,m,a,v,j]),T=F.useMemo(()=>new Map(k.nodes.map(G=>[G.id,G])),[k.nodes]),E=a?T.get(a)??null:null,{rfNodes:b,rfEdges:$}=F.useMemo(()=>{const G=Kk(k.nodes,k.edges,a);return S&&(G.rfEdges=G.rfEdges.map(ee=>({...ee,animated:!1}))),G},[k.nodes,k.edges,a,S]);F.useEffect(()=>{a&&!T.has(a)&&u(null)},[T,a]),F.useEffect(()=>{if(!l)return;const G=t.find(ee=>ee.file_path===l);G&&u(G.id)},[l,t]);const O=(G,ee)=>{u(ee.id)},H=()=>{u(null),_(!1)},I=G=>{x(ee=>{const J=new Set(ee);if(J.has(G)){if(J.size===1)return ee;J.delete(G)}else J.add(G);return J})},q=F.useMemo(()=>{const G=new Set;for(const ee of t)G.add(hm(ee.type));return G},[t]),ne=t.length-k.nodes.length;return p.jsxs("div",{className:"impact-graph",style:{flex:1,minHeight:0,position:"relative",display:"flex",flexDirection:"column"},children:[p.jsxs("div",{className:"graph-toolbar","data-testid":"graph-toolbar",children:[p.jsxs("div",{className:"seg","aria-label":"Graph projection",children:[p.jsx("button",{type:"button","data-testid":"graph-view-2d",className:j==="2d"?"active":"","aria-pressed":j==="2d",onClick:()=>f("2d"),children:"2D map"}),p.jsx("button",{type:"button","data-testid":"graph-view-3d",className:j==="3d"?"active":"","aria-pressed":j==="3d",onClick:()=>f("3d"),children:"3D layers"})]}),p.jsxs("div",{className:"seg","aria-label":"Graph detail",children:[p.jsx("button",{type:"button","data-testid":"graph-detail-overview",className:N==="overview"?"active":"","aria-pressed":N==="overview",onClick:()=>y("overview"),children:"Overview"}),p.jsx("button",{type:"button","data-testid":"graph-detail-full",className:N==="full"?"active":"","aria-pressed":N==="full",onClick:()=>y("full"),children:"Full"})]}),p.jsx("div",{className:"seg","aria-label":"Graph families",children:["django","stitch","react"].filter(G=>q.has(G)).map(G=>p.jsx("button",{type:"button","data-testid":`graph-family-${G}`,className:m.has(G)?"active":"","aria-pressed":m.has(G),onClick:()=>I(G),children:G},G))}),j==="3d"?p.jsx("button",{type:"button",className:v?"chip-btn active":"chip-btn","data-testid":"graph-neighborhood",disabled:!a,onClick:()=>_(G=>!G),children:v?"Neighborhood":"Focus neighbors"}):null,p.jsxs("span",{className:"muted graph-count",children:[k.nodes.length," nodes · ",k.edges.length," edges",ne?` · ${ne} hidden`:""]})]}),p.jsx("div",{className:"graph-stage",children:j==="3d"?p.jsxs("div",{className:"graph-3d","data-testid":"graph-3d",children:[p.jsx("p",{className:"graph-3d-hint",children:"Architecture layers are stacked in depth (Django → stitch → React). Drag to orbit, scroll to zoom, click a node to inspect it."}),p.jsx(F.Suspense,{fallback:p.jsx("p",{className:"muted graph-3d-hint",children:"Loading 3D layers…"}),children:p.jsx(Yk,{nodes:k.nodes,edges:k.edges,selectedId:a,neighborIds:k.neighborIds,onSelect:G=>{u(G),G||_(!1)}})}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]}):p.jsxs(lm,{children:[p.jsxs(QS,{nodes:b,edges:$,nodeTypes:qk,fitView:!0,fitViewOptions:{padding:.2,maxZoom:1.15},minZoom:.25,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,deleteKeyCode:null,onNodeClick:O,onPaneClick:H,proOptions:{hideAttribution:!1},"data-testid":"impact-graph",children:[p.jsx(tk,{}),p.jsx(Sk,{pannable:!0,zoomable:!0,ariaLabel:"Impact graph overview",nodeColor:"var(--muted)",nodeStrokeColor:"transparent",nodeStrokeWidth:0,maskColor:"rgba(0, 0, 0, 0.45)",maskStrokeColor:"var(--accent)",maskStrokeWidth:1.4,bgColor:"var(--graph-bg)",style:{width:184,height:128}}),p.jsx(ak,{})]}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]})})]})}const mp=[{value:"HEAD",label:"HEAD",group:"preset"},{value:"HEAD~1",label:"HEAD~1",group:"preset"}],Zk=["preset","branch","tag","commit"];function Jk(t){var a;if(!(t!=null&&t.git))return[...mp];const r=((a=t.presets)!=null&&a.length?t.presets:mp.map(u=>u.value)).map(u=>({value:u,label:u,group:"preset"})),o=new Set(r.map(u=>u.value)),l=[...r];for(const u of t.branches||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.current?`${u.name} (current)`:u.name,detail:u.subject,group:"branch"}));for(const u of t.tags||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.name,detail:u.subject,group:"tag"}));for(const u of t.commits||[])o.has(u.sha)||(o.add(u.sha),l.push({value:u.sha,label:u.short,detail:u.subject,group:"commit"}));return l}function eE(t,r){const o=r.trim().toLowerCase();return o?t.filter(l=>l.value.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)||(l.detail||"").toLowerCase().includes(o)):t}function tE(t){return Zk.map(r=>({group:r,items:t.filter(o=>o.group===r)})).filter(r=>r.items.length>0)}function nE(t){return t==="preset"?"Common":t==="branch"?"Branches":t==="tag"?"Tags":"Recent commits"}function yp({value:t,onChange:r,placeholder:o,testId:l,menuTestId:a,refs:u,onNeedRefs:d}){const f=F.useId(),g=F.useRef(null),[y,m]=F.useState(!1),[x,v]=F.useState(null),[_,S]=F.useState(0),j=F.useMemo(()=>{const b=Jk(u);return x===null?b:eE(b,x)},[u,x]),N=F.useMemo(()=>tE(j),[j]);F.useEffect(()=>{y&&d()},[y,d]),F.useEffect(()=>{S(0)},[x,y]);const k=()=>{m(!1),v(null)},T=b=>{r(b.value),k()},E=b=>{if(b.key==="ArrowDown"){if(b.preventDefault(),!y){m(!0);return}S($=>Math.min($+1,Math.max(j.length-1,0)))}else if(b.key==="ArrowUp"){if(b.preventDefault(),!y)return;S($=>Math.max($-1,0))}else if(b.key==="Enter"&&y){b.preventDefault();const $=j[_];$&&T($)}else b.key==="Escape"&&y&&(b.preventDefault(),k())};return p.jsxs("div",{className:"combo",ref:g,onBlur:b=>{b.currentTarget.contains(b.relatedTarget)||k()},children:[p.jsxs("div",{className:"combo-row",children:[p.jsx("input",{"data-testid":l,value:t,placeholder:o,spellCheck:!1,role:"combobox","aria-expanded":y,"aria-controls":f,"aria-autocomplete":"list",onChange:b=>{r(b.target.value),y&&v(b.target.value)},onKeyDown:E}),p.jsx("button",{type:"button",className:"icon-btn combo-toggle","data-testid":`${l}-toggle`,"aria-label":"Show recent refs","aria-expanded":y,onMouseDown:b=>b.preventDefault(),onClick:()=>y?k():m(!0),children:p.jsx(h0,{})})]}),y?p.jsx("div",{className:"combo-menu",id:f,role:"listbox","data-testid":a,children:N.length===0?p.jsx("div",{className:"combo-empty muted",children:"No matching refs — the typed value is kept"}):N.map(b=>p.jsxs("div",{className:"combo-group",children:[p.jsx("div",{className:"combo-heading",children:nE(b.group)}),b.items.map($=>{const O=j.indexOf($);return p.jsxs("button",{type:"button",role:"option","aria-selected":O===_,className:O===_?"combo-option active":"combo-option","data-testid":`ref-option-${$.group}`,onMouseDown:H=>H.preventDefault(),onMouseEnter:()=>S(O),onClick:()=>T($),children:[p.jsx("span",{className:"combo-label",children:$.label}),$.detail?p.jsx("span",{className:"combo-detail",children:$.detail}):null]},`${$.group}:${$.value}`)})]},b.group))}):null]})}function rE({initialPath:t,onSelect:r,onClose:o}){const[l,a]=F.useState(null),[u,d]=F.useState(t),[f,g]=F.useState(null),[y,m]=F.useState(""),[x,v]=F.useState(!1),_=F.useRef(null),S=F.useRef(0),j=async E=>{const b=S.current+1;S.current=b,v(!0);try{const $=await $e.browse(E);if(S.current!==b)return;a($),d($.path),g($.is_git?$.path:null),m("")}catch($){if(S.current!==b)return;m($ instanceof Error?$.message:String($))}finally{S.current===b&&v(!1)}};F.useEffect(()=>{var E,b;j(t),(E=_.current)==null||E.focus(),(b=_.current)==null||b.select()},[t]);const N=f||(l==null?void 0:l.path)||u,k=f&&f!==(l==null?void 0:l.path)?f.split(/[\\/]/).filter(Boolean).pop():l!=null&&l.is_git?"this repository":"this folder",T=E=>{E.key==="Escape"&&(E.preventDefault(),o())};return p.jsx("div",{className:"modal-backdrop","data-testid":"repo-explorer","data-overlay":"true",onClick:o,onKeyDown:T,children:p.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"explorer-title",onClick:E=>E.stopPropagation(),children:[p.jsxs("div",{className:"modal-head",children:[p.jsxs("div",{children:[p.jsx("h2",{id:"explorer-title",children:"Select repository"}),p.jsx("p",{className:"muted",children:"Browse to a git root, or paste the full path."})]}),p.jsx("button",{type:"button",className:"btn ghost","data-testid":"explorer-cancel",onClick:o,children:"Cancel"})]}),p.jsxs("form",{className:"explorer-path",onSubmit:E=>{E.preventDefault(),j(u)},children:[p.jsx("input",{ref:_,"data-testid":"explorer-path",value:u,onChange:E=>d(E.target.value),spellCheck:!1,"aria-label":"Directory path"}),p.jsx("button",{type:"button",className:"btn",disabled:!(l!=null&&l.parent),onClick:()=>(l==null?void 0:l.parent)&&void j(l.parent),children:"Up"}),p.jsx("button",{type:"button",className:"btn",onClick:()=>l&&void j(l.home),children:"Home"}),p.jsx("button",{type:"submit",className:"btn",children:"Go"})]}),y?p.jsx("div",{className:"error",role:"alert",children:y}):null,p.jsx("div",{className:"explorer-list",role:"listbox","aria-label":"Folders","aria-busy":x,children:l!=null&&l.entries.length?l.entries.map(E=>{const b=f===E.path;return p.jsxs("button",{type:"button",role:"option","aria-selected":b,className:b?"explorer-row active":"explorer-row","data-testid":"explorer-entry","data-path":E.path,onClick:()=>g(E.path),onDoubleClick:()=>void j(E.path),children:[p.jsx(Sp,{}),p.jsx("span",{className:"explorer-name",children:E.name}),E.is_git?p.jsx("span",{className:"chip git-badge",children:"git"}):null]},E.path)}):p.jsx("div",{className:"muted explorer-empty",children:x?"Loading…":"No folders here"})}),p.jsxs("div",{className:"modal-foot",children:[p.jsx("span",{className:"muted explorer-current",title:N,children:N}),p.jsxs("button",{type:"button",className:"btn primary","data-testid":"explorer-use",disabled:!N,onClick:()=>N&&r(N),children:["Use ",k]})]})]})})}const wl=[{id:"obsidian",label:"Obsidian",group:"dark"},{id:"nord",label:"Nord",group:"dark"},{id:"solarized-dark",label:"Solarized Dark",group:"dark"},{id:"forest",label:"Forest",group:"dark"},{id:"rose",label:"Rose Pine",group:"dark"},{id:"amber",label:"Midnight Amber",group:"dark"},{id:"volcano",label:"Volcano",group:"dark"},{id:"lavender",label:"Lavender",group:"dark"},{id:"neon-noir",label:"Neon Noir",group:"dark"},{id:"synthwave",label:"Synthwave",group:"dark"},{id:"phosphor",label:"Phosphor",group:"dark"},{id:"aurora",label:"Aurora",group:"dark"},{id:"biolume",label:"Biolume",group:"dark"},{id:"carbon",label:"Carbon",group:"dark"},{id:"paper",label:"Paper",group:"light"},{id:"solarized-light",label:"Solarized Light",group:"light"},{id:"seafoam",label:"Seafoam",group:"light"},{id:"high-contrast",label:"High Contrast",group:"light"},{id:"sakura",label:"Sakura",group:"light"},{id:"citrus",label:"Citrus",group:"light"},{id:"peach",label:"Peach Fuzz",group:"light"},{id:"candy",label:"Cotton Candy",group:"light"},{id:"sky",label:"Clear Sky",group:"light"},{id:"coral",label:"Coral Reef",group:"light"}],iE="obsidian",pm="loadpath.theme";function oE(t){return wl.some(r=>r.id===t)}function gm(){try{const t=localStorage.getItem(pm)||"";if(oE(t))return t}catch{}return iE}function sE(t){var r;return((r=wl.find(o=>o.id===t))==null?void 0:r.group)==="light"?"light":"dark"}function mm(t){document.documentElement.dataset.theme=t,document.documentElement.style.colorScheme=sE(t);try{localStorage.setItem(pm,t)}catch{}}const vp=[{id:"review",label:"Review",testId:"tab-review",shortcut:"1",icon:a0},{id:"architecture",label:"Architecture",testId:"tab-architecture",shortcut:"2",icon:u0},{id:"graph",label:"Impact graph",testId:"tab-graph",shortcut:"3",icon:c0},{id:"prs",label:"Pull requests",testId:"tab-prs",shortcut:"4",icon:d0},{id:"settings",label:"Settings",testId:"tab-settings",shortcut:"5",icon:f0}];function lE(t){const r=t.total||0;return r<=0?null:Math.min(100,Math.round(100*(t.done||0)/r))}function Ou(t,r,o){let l;try{l=new URL(t)}catch{return}if(l.protocol!=="https:"||l.username||l.password)return;const a=l.hostname.toLowerCase();a!==r&&!a.endsWith(`.${r}`)||l.pathname.startsWith(o)&&window.open(l.toString(),"_blank","noopener,noreferrer")}function aE(){var _n,Sn,Fn,Xr,qr,Qr,Tt,Hn;const[t,r]=F.useState("review"),[o,l]=F.useState(localStorage.getItem("loadpath.repo")||""),[a,u]=F.useState(localStorage.getItem("loadpath.base")||"HEAD~1"),[d,f]=F.useState(localStorage.getItem("loadpath.head")||"HEAD"),[g,y]=F.useState(null),[m,x]=F.useState(null),[v,_]=F.useState([]),[S,j]=F.useState("review"),[N,k]=F.useState(""),[T,E]=F.useState(""),[b,$]=F.useState(null),[O,H]=F.useState(""),[I,q]=F.useState({}),[ne,G]=F.useState([]),[ee,J]=F.useState([]),[C,Y]=F.useState(localStorage.getItem("loadpath.scmRepo")||""),[V,U]=F.useState(localStorage.getItem("loadpath.provider")||"github"),[z,D]=F.useState(localStorage.getItem("loadpath.prNumber")||""),[W,M]=F.useState(localStorage.getItem("loadpath.dirty")==="1"),[R,re]=F.useState(0),[ie,ce]=F.useState(""),[fe,de]=F.useState(gm),[K,le]=F.useState(!1),[pe,_e]=F.useState(!1),[xe,ge]=F.useState(null),[je,Me]=F.useState(null),[Pe,Re]=F.useState(!1),[tt,nt]=F.useState(!1),Qe=F.useRef(o);Qe.current=o;const ot=F.useRef(!1);ot.current=pe;const at=F.useRef(""),It=L=>{de(L),mm(L)},Ke=F.useRef(""),ze=L=>{Ke.current=L,E(L)},gt=L=>{const te=()=>{$e.indexProgress(L).then(Te=>{Ke.current&&(Te.message&&ze(Te.message),$(lE(Te)))}).catch(()=>{})};te();const ke=window.setInterval(te,250);return()=>{window.clearInterval(ke),$(null)}};F.useEffect(()=>{$e.settings().then(q).catch(()=>{}).finally(()=>le(!0)),$e.repos().then(L=>_(L.repos)).catch(()=>{})},[]);const ft=()=>o.trim()?!0:(k("Point at a local repository path first."),!1);F.useEffect(()=>{if(t!=="architecture"||!o.trim())return;const L=o;let te=!1;return $e.architecture(L).then(ke=>{!te&&Qe.current===L&&x(ke)}).catch(()=>{}),()=>{te=!0}},[t,o]);const Je=L=>{l(L),localStorage.setItem("loadpath.repo",L),L.trim()!==at.current&&(at.current="",ge(null))},vn=F.useCallback(()=>{const L=Qe.current.trim();!L||at.current===L||(at.current=L,$e.gitRefs(L).then(te=>{Qe.current.trim()===L&&ge(te)}).catch(()=>{at.current===L&&(at.current="",ge(null))}))},[]),wt=(L,te)=>{u(L),f(te),localStorage.setItem("loadpath.base",L),localStorage.setItem("loadpath.head",te)},Gt=(L,te,ke)=>{U(L),Y(te),localStorage.setItem("loadpath.provider",L),localStorage.setItem("loadpath.scmRepo",te),ke!==void 0&&(D(ke),localStorage.setItem("loadpath.prNumber",ke))},zi=L=>L==="github"?!!I.github_token_set:L==="gitlab"?!!I.gitlab_token_set:!!I.bitbucket_token_set,kt=F.useCallback(async(L=V)=>{var te;try{const ke=await $e.scmRepos(L);J(ke.repos),(te=ke.user)!=null&&te.login&&q(Te=>({...Te,...L==="github"?{github_user:ke.user.login}:L==="gitlab"?{gitlab_user:ke.user.login}:{bitbucket_user:ke.user.login}}))}catch{J([])}},[V]);F.useEffect(()=>{if(t!=="prs")return;let L=!1;return kt(V).catch(()=>{L||J([])}),()=>{L=!0}},[t,V,kt]),F.useEffect(()=>{if(!je)return;let L=!1,te=0;const ke=async()=>{try{const Te=await $e.githubOAuthPoll(je.flow_id);if(L)return;if(Te.status==="complete"){Me(null);const Ce=await $e.settings();q(Ce),H(Te.user?`Signed in to GitHub as ${Te.user}`:"Signed in to GitHub"),kt("github");return}if(Te.status==="pending"||Te.status==="slow_down"){te=window.setTimeout(ke,Math.max(Te.interval||je.interval,5)*1e3);return}Me(null),k(Te.status==="denied"?"GitHub sign-in was denied.":"GitHub sign-in expired. Try again.")}catch(Te){if(L)return;Me(null),k(Te instanceof Error?Te.message:String(Te))}};return te=window.setTimeout(ke,Math.max(je.interval,5)*1e3),()=>{L=!0,window.clearTimeout(te)}},[je,kt]),F.useEffect(()=>{if(!Pe)return;let L=!1,te=0;const ke=Date.now(),Te=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.bitbucket.connected){Re(!1);const Bn=await $e.settings();q(Bn),H(Ce.bitbucket.user?`Signed in to Bitbucket as ${Ce.bitbucket.user}`:"Signed in to Bitbucket"),kt("bitbucket");return}if(Date.now()-ke>18e4){Re(!1),k("Bitbucket sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Te,1500)}catch(Ce){if(L)return;Re(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Te,1500),()=>{L=!0,window.clearTimeout(te)}},[Pe,kt]),F.useEffect(()=>{if(!tt)return;let L=!1,te=0;const ke=Date.now(),Te=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.gitlab.connected){nt(!1);const Bn=await $e.settings();q(Bn),H(Ce.gitlab.user?`Signed in to GitLab as ${Ce.gitlab.user}`:"Signed in to GitLab"),kt("gitlab");return}if(Date.now()-ke>18e4){nt(!1),k("GitLab sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Te,1500)}catch(Ce){if(L)return;nt(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Te,1500),()=>{L=!0,window.clearTimeout(te)}},[tt,kt]);const hr=async(L=o)=>{if(!L.trim())return null;const te=await $e.architecture(L);return Qe.current===L&&x(te),te},An=async()=>{if(Ke.current||!ft())return;k(""),H(""),ze("Tracing load path…"),Je(o),wt(a,d);const L=gt(o);try{const te=await $e.review(o,a,d,!0,W);y(te),re(0),j("review"),r("review"),await $e.repos().then(ke=>_(ke.repos)).catch(()=>{}),await hr(o)}catch(te){k(te instanceof Error?te.message:String(te))}finally{L(),ze("")}},zn=async(L=!0)=>{if(Ke.current||!ft())return;k(""),H(""),ze(L?"Indexing…":"Full reindex…"),Je(o);const te=gt(o);try{await $e.index(o,L);const ke=await hr(o);await $e.repos().then(Te=>_(Te.repos)).catch(()=>{}),ke!=null&&ke.indexed&&(j("architecture"),r("architecture"))}catch(ke){k(ke instanceof Error?ke.message:String(ke))}finally{te(),ze("")}},pr=async()=>{if(!Ke.current&&ft()){k(""),H(""),ze("Detecting layout…"),Je(o);try{const L=await $e.init(o);H(L.message),await $e.repos().then(te=>_(te.repos)).catch(()=>{})}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},gr=async()=>{if(g!=null&&g.markdown)try{await navigator.clipboard.writeText(g.markdown),H("Copied markdown brief")}catch(L){k(L instanceof Error?L.message:String(L))}},mr=async()=>{if(!Ke.current){if(!(g!=null&&g.markdown)||!C||!z){k("Pick a pull request first (Pull requests tab), then post the brief.");return}ze("Posting Loadpath brief…");try{const L=await $e.postComment(V,C,Number(z),g.markdown);H(L.updated?"Updated the Loadpath PR comment":"Posted the Loadpath PR comment")}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},yr=async()=>{if(!Ke.current){k(""),ze("Fetching pull requests…");try{const L=await $e.prs(V,C);G(L.pull_requests);const te=ee.find(ke=>ke.slug.toLowerCase()===C.trim().toLowerCase());te!=null&&te.local_path&&Je(te.local_path)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},un=async()=>{k("");try{const L=await $e.githubOAuthStart();Me(L),Ou(L.verification_uri_complete,"github.com","/login/device")}catch(L){k(L instanceof Error?L.message:String(L))}},cn=async()=>{k("");try{const L=await $e.bitbucketOAuthStart();Re(!0),Ou(L.authorize_url,"bitbucket.org","/site/oauth2/authorize")}catch(L){Re(!1),k(L instanceof Error?L.message:String(L))}},Ur=async()=>{k("");try{const L=await $e.gitlabOAuthStart();nt(!0),Ou(L.authorize_url,new URL(L.authorize_url).hostname,"/oauth/authorize")}catch(L){nt(!1),k(L instanceof Error?L.message:String(L))}},Dn=async L=>{if(!(Ke.current||!o.trim())){k(""),ze("Walking what-if path…");try{const te=await $e.whatIf(o,L);H(`${te.title} — ${te.confidence.level} · ${(te.sinks||[]).length} sinks`),y({...te,markdown:te.markdown||"",index:te.index||(g==null?void 0:g.index),workspace:te.workspace||(g==null?void 0:g.workspace)}),re(0),j("review"),r("review")}catch(te){k(te instanceof Error?te.message:String(te))}finally{ze("")}}},Yr=async L=>{if(Ke.current)return;Gt(L.provider,L.repo,String(L.number));const te=ee.find(Ce=>Ce.slug.toLowerCase()===L.repo.toLowerCase());te!=null&&te.local_path&&Je(te.local_path),k(""),ze(`Fetching ${L.provider} #${L.number}…`);const ke=(te==null?void 0:te.local_path)||o,Te=ke?gt(ke):()=>{};try{const Ce=await $e.reviewPr(L.provider,L.repo,L.number,(te==null?void 0:te.local_path)||o||void 0);y(Ce),re(0),Ce.pull_request&&typeof Ce.pull_request.repo_path=="string"&&Je(Ce.pull_request.repo_path),wt(String(Ce.base||L.target_branch),String(Ce.head||L.source_branch)),j("review"),r("review")}catch(Ce){wt(L.base_sha||L.target_branch,L.head_sha||L.source_branch),r("review"),k(Ce instanceof Error?Ce.message:String(Ce))}finally{Te(),ze("")}},$n=async L=>{k("");try{q(await $e.oauthDisconnect(L)),V===L&&J([]),H(`Disconnected ${L}`)}catch(te){k(te instanceof Error?te.message:String(te))}},Gr=async L=>{L.preventDefault();const te=new FormData(L.currentTarget),ke={github_token:String(te.get("github_token")||""),github_oauth_client_id:String(te.get("github_oauth_client_id")||""),github_host:String(te.get("github_host")||""),gitlab_token:String(te.get("gitlab_token")||""),gitlab_host:String(te.get("gitlab_host")||""),gitlab_oauth_client_id:String(te.get("gitlab_oauth_client_id")||""),gitlab_oauth_client_secret:String(te.get("gitlab_oauth_client_secret")||""),bitbucket_token:String(te.get("bitbucket_token")||""),bitbucket_username:String(te.get("bitbucket_username")||""),bitbucket_oauth_client_id:String(te.get("bitbucket_oauth_client_id")||""),bitbucket_oauth_client_secret:String(te.get("bitbucket_oauth_client_secret")||""),ai_provider:String(te.get("ai_provider")||"none"),ai_api_key:String(te.get("ai_api_key")||""),ai_model:String(te.get("ai_model")||""),ai_base_url:String(te.get("ai_base_url")||"")},Te=v.length?{...ke,workspaces:v.map(Ce=>({path:Ce.path,name:Ce.name}))}:ke;try{q(await $e.saveSettings(Te)),H("Settings saved on this machine")}catch(Ce){k(Ce instanceof Error?Ce.message:String(Ce))}},vr=async()=>{if(!(!g||Ke.current)){ze("Residual analysis…");try{const L=await $e.residual(g);ce(L.note)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},xr=F.useRef(An);xr.current=An;const Xt=F.useRef(t);Xt.current=t,F.useEffect(()=>{const L=te=>{if(ot.current){te.key==="Escape"&&(te.preventDefault(),_e(!1));return}const ke=te.target;if(ke&&(ke.tagName==="INPUT"||ke.tagName==="TEXTAREA"||ke.tagName==="SELECT"||ke.isContentEditable)){te.key==="Escape"&&ke.blur();return}if(te.key==="Escape"){k(""),H("");return}const Te=vp.find(Ce=>Ce.shortcut===te.key);if(Te&&!te.metaKey&&!te.ctrlKey&&!te.altKey&&r(Te.id),(te.metaKey||te.ctrlKey)&&te.key==="Enter"){if(Xt.current==="settings"||Xt.current==="prs"||Ke.current)return;te.preventDefault(),xr.current()}};return window.addEventListener("keydown",L),()=>window.removeEventListener("keydown",L)},[]);const On=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.nodes)??[]:(g==null?void 0:g.nodes)??[],[S,m,g]),xn=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.edges)??[]:(g==null?void 0:g.edges)??[],[S,m,g]),Di=g!=null&&g.index?`${g.index.counts.nodes} nodes · ${g.index.counts.edges} edges`:m!=null&&m.indexed?`${m.counts.nodes} nodes · ${m.counts.edges} edges`:"Not indexed",wn=((g==null?void 0:g.findings)||[]).filter(L=>!L.waived);return p.jsxs("div",{className:"app",children:[p.jsx("a",{className:"skip",href:"#main",children:"Skip to content"}),p.jsxs("nav",{className:"rail","data-testid":"rail","aria-label":"Primary",children:[p.jsxs("div",{className:"brand",children:[p.jsx("div",{className:"brand-mark",children:"Loadpath"}),p.jsx("div",{className:"brand-sub",children:"Load-path review"})]}),vp.map(L=>{const te=L.icon,ke=t===L.id;return p.jsxs("button",{type:"button","data-testid":L.testId,className:ke?"nav-item active":"nav-item","aria-current":ke?"page":void 0,"aria-label":L.label,onClick:()=>r(L.id),children:[p.jsx(te,{}),p.jsx("span",{children:L.label})]},L.id)}),p.jsxs("div",{className:"theme-pick",children:[p.jsx("label",{htmlFor:"theme-select",children:"Theme"}),p.jsx("select",{id:"theme-select","data-testid":"theme-select",value:fe,onChange:L=>It(L.target.value),children:["dark","light"].map(L=>p.jsx("optgroup",{label:L==="dark"?"Dark":"Light",children:wl.filter(te=>te.group===L).map(te=>p.jsx("option",{value:te.id,children:te.label},te.id))},L))})]}),p.jsxs("div",{className:"rail-foot",children:[p.jsx("div",{className:"muted",role:"status",children:T||Di}),p.jsxs("div",{className:"kbd-hint",children:[p.jsx("kbd",{children:"1"}),"–",p.jsx("kbd",{children:"5"})," tabs · ",p.jsx("kbd",{children:"Ctrl"}),"+",p.jsx("kbd",{children:"Enter"})," review"]})]})]}),p.jsxs("div",{className:"main",id:"main",children:[T?p.jsxs("div",{className:b!=null?"progress determinate":"progress",role:"status","aria-live":"polite","aria-busy":"true","data-testid":"index-progress",children:[p.jsx("i",{style:b!=null?{width:`${b}%`}:void 0}),p.jsx("span",{className:"sr-only",children:T})]}):null,p.jsxs("header",{className:"topbar","data-testid":"topbar",children:[v.length>0?p.jsxs("label",{className:"field workspace",children:[p.jsx("span",{children:"Workspace"}),p.jsxs("select",{"data-testid":"workspace-select",value:v.some(L=>L.path===o)?o:"",onChange:L=>{L.target.value&&Je(L.target.value)},children:[p.jsx("option",{value:"",children:"Indexed repos…"}),v.map(L=>p.jsxs("option",{value:L.path,children:[L.name,L.indexed?` (${L.counts.nodes})`:""]},L.path))]})]}):null,p.jsxs("label",{className:"field path",children:[p.jsx("span",{children:"Repository"}),p.jsxs("div",{className:"path-row",children:[p.jsx("input",{"data-testid":"repo-path",placeholder:"Local monorepo path",value:o,onChange:L=>{const te=L.target.value;l(te),te.trim()!==at.current&&(at.current="",ge(null))},spellCheck:!1}),p.jsx("button",{type:"button",className:"icon-btn","data-testid":"btn-browse-repo","aria-label":"Browse for a local repository",onClick:()=>_e(!0),children:p.jsx(Sp,{})})]})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Base"}),p.jsx(yp,{testId:"base-ref",menuTestId:"base-ref-menu",value:a,onChange:L=>wt(L,d),placeholder:"base",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Head"}),p.jsx(yp,{testId:"head-ref",menuTestId:"head-ref-menu",value:d,onChange:L=>wt(a,L),placeholder:"head",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field dirty",children:[p.jsx("span",{children:"Working tree"}),p.jsx("button",{type:"button",className:W?"chip-btn active":"chip-btn","data-testid":"btn-dirty","aria-pressed":W,onClick:()=>{const L=!W;M(L),localStorage.setItem("loadpath.dirty",L?"1":"0")},children:W?"Include uncommitted":"Committed range"})]}),p.jsxs("div",{className:"topbar-actions",children:[p.jsx("button",{type:"button","data-testid":"btn-init",disabled:!!T,onClick:pr,children:"Draft config"}),p.jsx("button",{type:"button","data-testid":"btn-index",disabled:!!T,onClick:()=>zn(!0),children:"Index"}),p.jsx("button",{type:"button","data-testid":"btn-review",className:"btn primary",disabled:!!T,onClick:An,children:"Review"})]})]}),p.jsxs("div",{className:"alerts",children:[N?p.jsxs("div",{className:"error","data-testid":"error",role:"alert",children:[p.jsx("span",{children:N}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>k(""),"aria-label":"Dismiss error",children:"×"})]}):null,O?p.jsxs("div",{className:"banner","data-testid":"status-note",children:[p.jsx("span",{children:O}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>H(""),"aria-label":"Dismiss",children:"×"})]}):null,((_n=g==null?void 0:g.index)!=null&&_n.stale||m!=null&&m.stale)&&(t==="review"||t==="architecture")?p.jsx("div",{className:"banner stale","data-testid":"index-stale",children:"Index is stale — files changed since the last extract. Index again before trusting this walk."}):null,((Sn=g==null?void 0:g.index)==null?void 0:Sn.django_boot)==="failed"||(m==null?void 0:m.django_boot)==="failed"?p.jsx("div",{className:"banner warn","data-testid":"django-boot-failed",children:((Fn=g==null?void 0:g.index)==null?void 0:Fn.django_boot_detail)||(m==null?void 0:m.django_boot_detail)||"django.setup() failed"}):null,(Xr=g==null?void 0:g.workspace)!=null&&Xr.dirty_overlaps_review&&t==="review"?p.jsxs("div",{className:"banner warn","data-testid":"dirty-tree",children:["Uncommitted files overlap this review: ",(g.workspace.dirty_overlap||[]).slice(0,6).join(", ")]}):null]}),p.jsxs("div",{className:"stage",children:[t==="review"&&p.jsxs("div",{className:"content","data-testid":"review-layout",children:[p.jsx("aside",{className:"brief","data-testid":"brief",children:g?p.jsx(uE,{review:g,findings:wn,aiNote:ie,busy:!!T,tourIndex:R,onTour:re,onAskAi:vr,onCopy:gr,onPost:mr}):p.jsxs("div",{className:"empty","data-testid":"review-empty",children:[p.jsx("h2",{children:"Trace the force of this diff"}),p.jsx("p",{children:"The graph is the architecture. The brief is where this change travels — not a hunk list."}),p.jsxs("ol",{children:[p.jsx("li",{children:"Point at a Django + React monorepo, or pick an indexed workspace."}),p.jsxs("li",{children:["Index it. Missing ",p.jsx("code",{children:"loadpath.yml"})," is drafted from ",p.jsx("code",{children:"manage.py"})," and"," ",p.jsx("code",{children:"src/features"}),"."]}),p.jsx("li",{children:"Review a git range, or open a pull request so base/head become a three-dot merge-base."})]})]})}),p.jsx("div",{className:"graph-wrap","data-testid":"review-graph",children:g?p.jsx($u,{nodes:g.nodes,edges:g.edges,onWhatIf:Dn,focusPath:(qr=g.read_order[R])==null?void 0:qr.path}):null})]}),t==="architecture"&&p.jsxs("div",{className:"content","data-testid":"architecture-panel",children:[p.jsx("aside",{className:"brief","data-testid":"architecture-brief",children:m!=null&&m.indexed?p.jsx(cE,{architecture:m,busy:!!T,onReindex:()=>zn(!1),onReview:An}):p.jsx("p",{className:"muted","data-testid":"architecture-empty",children:"Index this repo to build the architecture graph. Review then walks that same graph for a git range — it does not start from a hunk list."})}),p.jsx("div",{className:"graph-wrap","data-testid":"architecture-graph",children:m!=null&&m.indexed?p.jsx($u,{nodes:m.nodes,edges:m.edges,onWhatIf:Dn}):null})]}),t==="graph"&&p.jsxs("div",{className:"graph-wrap","data-testid":"graph-full",style:{height:"100%"},children:[p.jsxs("div",{className:"graph-modes",children:[p.jsxs("div",{className:"seg","aria-label":"Graph scope",children:[p.jsx("button",{type:"button","aria-pressed":S==="review","data-testid":"graph-mode-review",className:S==="review"?"active":"",onClick:()=>j("review"),children:"This review"}),p.jsx("button",{type:"button","aria-pressed":S==="architecture","data-testid":"graph-mode-architecture",className:S==="architecture"?"active":"",onClick:()=>j("architecture"),children:"Indexed architecture"})]}),p.jsxs("div",{className:"legend","aria-hidden":"true",children:[p.jsxs("span",{children:[p.jsx("i",{})," cheap"]}),p.jsxs("span",{children:[p.jsx("i",{className:"exp"})," expensive"]}),p.jsxs("span",{children:[p.jsx("i",{className:"crit"})," critical"]}),p.jsxs("span",{children:[p.jsx("i",{className:"dash"})," inferred"]})]})]}),On.length?p.jsx($u,{nodes:On,edges:xn,onWhatIf:Dn}):p.jsx("p",{className:"empty","data-testid":"graph-empty",children:"Index the repo or run a review first. Click a node to inspect it."})]}),t==="prs"&&p.jsxs("div",{className:"pr-list","data-testid":"pr-list",children:[p.jsxs("div",{className:"pr-toolbar",children:[p.jsxs("label",{className:"field provider",children:[p.jsx("span",{children:"Provider"}),p.jsxs("select",{"data-testid":"pr-provider",value:V,onChange:L=>Gt(L.target.value,C,z),children:[p.jsx("option",{value:"github",children:"GitHub"}),p.jsx("option",{value:"gitlab",children:"GitLab"}),p.jsx("option",{value:"bitbucket",children:"Bitbucket"})]})]}),p.jsxs("label",{className:"field",children:[p.jsx("span",{children:"Repository"}),p.jsx("input",{"data-testid":"pr-repo",placeholder:ee.length?"Search your repos":"owner/repo",value:C,onChange:L=>Gt(V,L.target.value,z),list:"scm-repos",spellCheck:!1}),p.jsx("datalist",{id:"scm-repos",children:ee.map(L=>p.jsxs("option",{value:L.slug,children:[L.private?"private":"public",L.local_path?" · local":""]},L.slug))})]}),p.jsx("button",{type:"button","data-testid":"btn-refresh-repos",className:"btn",disabled:!!T||!zi(V),onClick:()=>{kt(V)},children:"My repos"}),p.jsx("button",{type:"button","data-testid":"btn-list-prs",className:"btn",disabled:!!T,onClick:yr,children:"List PRs"})]}),ee.length>0?p.jsxs("p",{className:"muted scm-count","data-testid":"scm-repo-count",children:[ee.length," ",V," repositor",ee.length===1?"y":"ies",V==="github"&&I.github_user?` · @${String(I.github_user)}`:"",V==="gitlab"&&I.gitlab_user?` · @${String(I.gitlab_user)}`:"",V==="bitbucket"&&I.bitbucket_user?` · ${String(I.bitbucket_user)}`:""]}):null,ne.length===0?p.jsxs("div",{className:"empty","data-testid":"pr-empty",children:[p.jsx("h2",{children:"No pull requests loaded"}),p.jsx("p",{children:"Sign in under Settings (or paste a token), load your repositories, then list open PRs. Reviewing a PR fills base and head from its SHAs."})]}):ne.map(L=>p.jsxs("article",{className:"pr","data-testid":`pr-${L.number}`,children:[p.jsxs("h3",{children:["#",L.number," ",L.title]}),p.jsxs("div",{className:"pr-meta muted",children:[p.jsx("span",{className:`chip ${L.draft?"":"open"}`,children:L.draft?"draft":L.state}),p.jsx("span",{children:L.author}),p.jsxs("span",{children:[L.source_branch," → ",L.target_branch]})]}),p.jsxs("div",{className:"pr-actions",children:[p.jsxs("a",{href:L.url,target:"_blank",rel:"noreferrer",children:["Open on ",L.provider]}),p.jsx("button",{type:"button",className:"btn primary","data-testid":`pr-review-${L.number}`,onClick:()=>void Yr(L),children:"Review this PR"})]})]},`${L.provider}-${L.number}`))]}),t==="settings"&&K&&p.jsxs("form",{className:"settings","data-testid":"settings-form",onSubmit:Gr,children:[p.jsxs("div",{children:[p.jsx("h1",{children:"Settings"}),p.jsx("p",{className:"muted",children:"Tokens stay on this machine in ~/.loadpath/settings.json. AI runs only on residual uncertainty the graph could not close."})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Appearance"}),p.jsx("p",{className:"muted",children:"Local to this browser. High contrast is a first-class theme, not an afterthought."}),p.jsx("div",{className:"theme-grid","data-testid":"theme-grid",children:wl.map(L=>p.jsxs("button",{type:"button","data-theme":L.id,className:fe===L.id?"theme-swatch active":"theme-swatch","data-testid":`theme-${L.id}`,onClick:()=>It(L.id),children:[p.jsx("div",{className:"swatch-bar","aria-hidden":"true"}),p.jsx("div",{className:"name",children:L.label}),p.jsx("div",{className:"group",children:L.group})]},L.id))})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Source control"}),p.jsx("p",{className:"muted",children:"Sign in with OAuth to list every repository the account can access. Tokens stay in ~/.loadpath/settings.json. A classic PAT still works if you prefer not to register an OAuth app."}),p.jsxs("div",{className:"scm-login","data-testid":"scm-github",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitHub"}),p.jsx("p",{className:"muted",children:I.github_token_set?I.github_user?`Signed in as @${String(I.github_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.github_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-github-disconnect",onClick:()=>void $n("github"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-github-login",disabled:!!je||!I.github_oauth_ready,onClick:()=>void un(),children:je?"Waiting for GitHub…":"Sign in with GitHub"})})]}),je?p.jsxs("p",{className:"oauth-code","data-testid":"github-user-code",children:["Enter ",p.jsx("code",{children:je.user_code})," at GitHub if the browser did not fill it in."]}):null,I.github_oauth_ready?null:p.jsx("p",{className:"muted",children:"Sign-in needs a GitHub OAuth App with Device Flow enabled. Set LOADPATH_GITHUB_CLIENT_ID or paste the client ID below."}),p.jsx("label",{htmlFor:"github_oauth_client_id",children:"GitHub OAuth client ID"}),p.jsx("input",{id:"github_oauth_client_id",name:"github_oauth_client_id","data-testid":"github-oauth-client-id",placeholder:"Ov23…",defaultValue:String(I.github_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"github_token",children:"GitHub token (optional PAT)"}),p.jsx("input",{id:"github_token",name:"github_token",type:"password",placeholder:"ghp_…",autoComplete:"off"}),p.jsx("label",{htmlFor:"github_host",children:"GitHub host (Enterprise)"}),p.jsx("input",{id:"github_host",name:"github_host","data-testid":"github-host",placeholder:"github.com",defaultValue:String(I.github_host||""),autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-gitlab",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitLab"}),p.jsx("p",{className:"muted",children:I.gitlab_token_set?I.gitlab_user?`Signed in as @${String(I.gitlab_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.gitlab_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-gitlab-disconnect",onClick:()=>void $n("gitlab"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-gitlab-login",disabled:tt||!I.gitlab_oauth_ready,onClick:()=>void Ur(),children:tt?"Waiting for GitLab…":"Sign in with GitLab"})})]}),p.jsx("label",{htmlFor:"gitlab_host",children:"GitLab host"}),p.jsx("input",{id:"gitlab_host",name:"gitlab_host","data-testid":"gitlab-host",placeholder:"gitlab.com",defaultValue:String(I.gitlab_host||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_id",children:"GitLab OAuth application ID"}),p.jsx("input",{id:"gitlab_oauth_client_id",name:"gitlab_oauth_client_id","data-testid":"gitlab-oauth-client-id",defaultValue:String(I.gitlab_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_secret",children:"GitLab OAuth secret"}),p.jsx("input",{id:"gitlab_oauth_client_secret",name:"gitlab_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_token",children:"GitLab token (optional PAT)"}),p.jsx("input",{id:"gitlab_token",name:"gitlab_token",type:"password",placeholder:"glpat-…",autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-bitbucket",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"Bitbucket"}),p.jsx("p",{className:"muted",children:I.bitbucket_token_set?I.bitbucket_user?`Signed in as ${String(I.bitbucket_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.bitbucket_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-bitbucket-disconnect",onClick:()=>void $n("bitbucket"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-bitbucket-login",disabled:Pe||!I.bitbucket_oauth_ready,onClick:()=>void cn(),children:Pe?"Waiting for Bitbucket…":"Sign in with Bitbucket"})})]}),I.bitbucket_oauth_ready?null:p.jsxs("p",{className:"muted",children:["Sign-in needs a Bitbucket OAuth consumer (key + secret). Callback URL:"," ",p.jsx("code",{children:"/api/oauth/bitbucket/callback"})," on this app origin."]}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_id",children:"Bitbucket OAuth key"}),p.jsx("input",{id:"bitbucket_oauth_client_id",name:"bitbucket_oauth_client_id","data-testid":"bitbucket-oauth-client-id",defaultValue:String(I.bitbucket_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_secret",children:"Bitbucket OAuth secret"}),p.jsx("input",{id:"bitbucket_oauth_client_secret",name:"bitbucket_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_token",children:"Bitbucket token (optional app password)"}),p.jsx("input",{id:"bitbucket_token",name:"bitbucket_token",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_username",children:"Bitbucket username (app passwords)"}),p.jsx("input",{id:"bitbucket_username",name:"bitbucket_username",defaultValue:String(I.bitbucket_username||"")})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Residual AI"}),p.jsx("label",{htmlFor:"ai_provider",children:"Provider"}),p.jsxs("select",{id:"ai_provider",name:"ai_provider",defaultValue:String(((Qr=I.ai)==null?void 0:Qr.provider)||"none"),children:[p.jsx("option",{value:"none",children:"none (graph only)"}),p.jsx("option",{value:"anthropic",children:"Anthropic"}),p.jsx("option",{value:"openai",children:"OpenAI"}),p.jsx("option",{value:"grok",children:"Grok / xAI"}),p.jsx("option",{value:"deepseek",children:"DeepSeek"}),p.jsx("option",{value:"cursor",children:"Cursor-compatible (OpenAI protocol)"}),p.jsx("option",{value:"ollama",children:"Ollama local"})]}),p.jsx("label",{htmlFor:"ai_api_key",children:"API key"}),p.jsx("input",{id:"ai_api_key",name:"ai_api_key",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"ai_model",children:"Model"}),p.jsx("input",{id:"ai_model",name:"ai_model","data-testid":"ai-model",placeholder:"optional override",defaultValue:String(((Tt=I.ai)==null?void 0:Tt.model)||"")}),p.jsx("label",{htmlFor:"ai_base_url",children:"Base URL"}),p.jsx("input",{id:"ai_base_url",name:"ai_base_url","data-testid":"ai-base-url",placeholder:"optional, OpenAI-compatible",defaultValue:String(((Hn=I.ai)==null?void 0:Hn.base_url)||"")}),p.jsx("button",{className:"btn primary",type:"submit","data-testid":"btn-save-settings",children:"Save"})]})]})]})]}),pe?p.jsx(rE,{initialPath:o,onClose:()=>_e(!1),onSelect:L=>{Je(L),_e(!1)}}):null]})}function uE({review:t,findings:r,aiNote:o,busy:l,tourIndex:a,onTour:u,onAskAi:d,onCopy:f,onPost:g}){var m,x,v,_,S,j,N,k,T,E,b,$,O,H;const y=[...new Set(t.confidence.reasons||[])];return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:`merge-box ${t.confidence.level}`,children:[p.jsxs("div",{className:`level ${t.confidence.level}`,children:[t.confidence.level.toUpperCase()," — ",t.title]}),y.length?p.jsx("ul",{className:"reasons",children:y.map(I=>p.jsx("li",{children:I},I))}):null,t.low_risk?p.jsx("span",{className:"chip",children:"low-risk"}):null,t.change_kinds.map(I=>p.jsx("span",{className:"chip",children:No(I)},I)),(m=t.contract_break)!=null&&m.kind&&t.contract_break.kind!=="none"?p.jsxs("span",{className:`chip ${t.contract_break.kind==="breaking"?"blocker":""}`,"data-testid":"contract-kind",children:["contract ",t.contract_break.kind]}):null]}),p.jsxs("div",{className:"metrics",children:[p.jsxs("div",{className:"metric",children:[p.jsxs("div",{className:"n",children:[t.confidence.covered_sinks,"/",t.confidence.sinks]}),p.jsx("div",{className:"l",children:"Sinks tested"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:r.length}),p.jsx("div",{className:"l",children:"Findings"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:t.residuals.length}),p.jsx("div",{className:"l",children:"Residuals"})]})]}),p.jsx("pre",{className:"headline",children:t.headline}),t.index?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Index ",p.jsx("span",{className:"count",children:t.index.counts.nodes})]}),p.jsxs("div",{className:"muted",children:["Walked ",t.index.counts.nodes," nodes / ",t.index.counts.edges," edges",t.index.reindex_skipped?" from an unchanged index":t.index.reindexed?" after an incremental refresh":" from the existing index",t.index.django_boot&&t.index.django_boot!=="off"?` · Django boot ${t.index.django_boot}`:"",(x=t.workspace)!=null&&x.three_dot?" · three-dot range":""]})]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Read this ",p.jsx("span",{className:"count",children:t.read_order.length})]}),t.read_order.map((I,q)=>p.jsxs("div",{className:q===a?"read-item tour-current":"read-item",children:[p.jsxs("span",{className:"file",children:[q+1,". ",I.path]}),p.jsx("div",{className:"why",children:I.why})]},I.path)),t.read_order.length>0?p.jsxs("div",{className:"btn-row tour-row",children:[p.jsx("button",{type:"button",className:"btn","data-testid":"btn-tour-prev",disabled:a<=0,onClick:()=>u(Math.max(0,a-1)),children:"Previous"}),p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-tour-next",disabled:a>=t.read_order.length-1,onClick:()=>u(Math.min(t.read_order.length-1,a+1)),children:"Next in read order"}),p.jsxs("span",{className:"muted",children:[a+1,"/",t.read_order.length]})]}):null]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Clusters ",p.jsx("span",{className:"count",children:t.clusters.length})]}),t.clusters.map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:I.title})," — ",I.files.join(", ")]},I.id))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Architecture ",p.jsx("span",{className:"count",children:r.length})]}),r.length===0?p.jsx("div",{className:"muted",children:t.architecture_note}):r.map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${I.severity}`,children:I.severity}),I.message]},I.rule+I.message))]}),p.jsx(ym,{cards:t.deepening}),(_=(v=t.contract_break)==null?void 0:v.reasons)!=null&&_.length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Contract ",p.jsx("span",{className:"count",children:t.contract_break.kind})]}),t.contract_break.reasons.map(I=>p.jsx("div",{className:"muted",children:I},I))]}):null,(S=t.auth)!=null&&S.note?p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Auth"}),p.jsx("div",{className:"muted",children:t.auth.note}),(t.auth.missing_permissions||[]).map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:"chip warning",children:"missing"}),I.name]},I.id))]}):null,(t.suggested_tests||[]).length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Suggested tests ",p.jsx("span",{className:"count",children:(j=t.suggested_tests)==null?void 0:j.length})]}),(t.suggested_tests||[]).map(I=>p.jsxs("div",{className:"residual",children:[p.jsx("strong",{children:I.title}),p.jsx("pre",{className:"headline",children:I.body})]},I.title))]}):null,(N=t.trend)!=null&&N.note?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Confidence trend"}),p.jsx("div",{className:"muted",children:t.trend.note}),(t.trend.points||[]).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[I.level," · ",_p(I.created_at),I.sinks!=null?` · ${I.sinks} sinks`:""]},I.id))]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Residual ",p.jsx("span",{className:"count",children:t.residuals.length})]}),p.jsx("p",{className:"muted",children:"AI is only used here, on what the graph could not close."}),t.residuals.map(I=>p.jsx("div",{className:"residual muted",children:I},I))]}),(T=(k=t.evolution)==null?void 0:k.notes)!=null&&T.length||(b=(E=t.evolution)==null?void 0:E.hotspots)!=null&&b.some(I=>I.commits)?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Churn & coupling"}),((($=t.evolution)==null?void 0:$.notes)||[]).map(I=>p.jsx("div",{className:"muted",children:I},I)),(((O=t.evolution)==null?void 0:O.hotspots)||[]).filter(I=>I.commits).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("span",{className:"file",children:I.path})," — ",I.commits," commits, bus factor ",I.bus_factor]},I.path))]}):null,p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:l,onClick:d,children:"Ask configured model"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-copy-markdown",onClick:f,children:"Copy markdown"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-post-comment",onClick:g,children:"Post to PR"})]}),o?p.jsx("pre",{className:"headline",children:o}):null,p.jsx("div",{className:"kicker",children:"Reviewers"}),p.jsx("div",{className:"muted",children:t.suggested_reviewers.join(", ")||"—"}),(H=t.knowledge_owners)!=null&&H.length?p.jsxs("div",{className:"muted",children:["Knowledge: ",t.knowledge_owners.join(", ")]}):null]})}function cE({architecture:t,busy:r,onReindex:o,onReview:l}){const a=t.findings.filter(u=>!u.waived);return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"merge-box high",children:[p.jsxs("div",{className:"level high",children:["INDEXED — ",t.counts.nodes," nodes"]}),p.jsxs("div",{className:"muted",style:{marginTop:8},children:[t.indexed_at?`Last index ${_p(t.indexed_at)}`:"Indexed",t.incremental?" · incremental":" · full",t.stale?" · stale":"",t.django_boot&&t.django_boot!=="off"?` · Django boot ${t.django_boot}`:""]}),p.jsxs("span",{className:"chip",children:[t.counts.edges," edges"]}),t.has_config?p.jsx("span",{className:"chip",children:"loadpath.yml"}):null]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Bounded contexts"}),Object.values(t.contexts).map(u=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:u.name})," — ",(u.django_apps||[]).join(", ")||"no apps"," ·"," ",(u.owners||[]).join(", ")||"unowned"]},u.name))]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Rules ",p.jsx("span",{className:"count",children:(t.rules||[]).length})]}),(t.rules||[]).map(u=>p.jsx("div",{className:"muted",children:u},u))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Findings ",p.jsx("span",{className:"count",children:a.length})]}),a.length===0?p.jsx("div",{className:"muted",children:"No architecture rule hits on the full graph."}):a.map(u=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${u.severity}`,children:u.severity}),u.message]},u.rule+u.message))]}),p.jsx(ym,{cards:t.deepening}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Types"}),p.jsx("table",{className:"type-table",children:p.jsx("tbody",{children:Object.entries(t.type_counts||{}).sort((u,d)=>d[1]-u[1]).slice(0,12).map(([u,d])=>p.jsxs("tr",{children:[p.jsx("td",{children:_l(u)}),p.jsx("td",{children:d})]},u))})})]}),p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:r,onClick:o,"data-testid":"btn-full-reindex",children:"Full reindex"}),p.jsx("button",{type:"button",className:"btn primary",disabled:r,onClick:l,children:"Review against this index"})]})]})}function ym({cards:t}){const r=t||[];return r.length?p.jsxs("details",{className:"section",open:!0,"data-testid":"deepening-list",children:[p.jsxs("summary",{children:["Depth ",p.jsx("span",{className:"count",children:r.length})]}),p.jsx("p",{className:"muted",children:"Deepening opportunities: more behaviour behind a smaller interface, at a real seam."}),r.map(o=>p.jsxs("div",{className:"finding","data-testid":"deepening-card",children:[p.jsx("span",{className:`chip ${o.strength}`,children:l0(o.strength)}),o.top?p.jsx("span",{className:"chip",children:"top"}):null,p.jsx("strong",{children:o.title}),p.jsx("div",{className:"why",children:o.message}),o.deletion_test?p.jsxs("div",{className:"muted",children:["Deletion test: ",o.deletion_test]}):null,o.before&&o.after?p.jsxs("div",{className:"muted",children:[o.before," → ",o.after]}):null]},o.rule+o.title))]}):null}mm(gm());i0.createRoot(document.getElementById("root")).render(p.jsx(F.StrictMode,{children:p.jsx(aE,{})}));export{Ik as L,hE as a,dE as c,p as j,fE as l,F as r,_l as t}; diff --git a/src/loadpath/static/assets/index-B5eCWnJO.css b/src/loadpath/static/assets/index-p-RF8Le9.css similarity index 65% rename from src/loadpath/static/assets/index-B5eCWnJO.css rename to src/loadpath/static/assets/index-p-RF8Le9.css index 6420f3a..9e66c73 100644 --- a/src/loadpath/static/assets/index-B5eCWnJO.css +++ b/src/loadpath/static/assets/index-p-RF8Le9.css @@ -1 +1 @@ -.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}:root,[data-theme=obsidian]{--bg: #070b10;--bg-2: #0d141c;--surface: #121a24;--line: #1e2c3c;--ink: #e7eef6;--muted: #8b9bb0;--high: #2a9d8f;--medium: #e9c46a;--low: #e76f51;--critical: #e85d04;--accent: #4cc9f0;--rail-from: #0b1219;--rail-to: #070b10;--rail-active: #15202c;--btn: #173044;--btn-line: #24506c;--btn-primary: #134e4a;--btn-primary-line: #2a9d8f;--node-bg: #101822;--node-line: #2a3d52;--graph-bg: #070b10;--graph-grid: rgba(42, 80, 120, .09);--edge-cheap: #4a5568;--edge-expensive: #f4a261;--edge-critical: #e85d04;--shadow: rgba(76, 201, 240, .08)}[data-theme=nord]{--bg: #2e3440;--bg-2: #3b4252;--surface: #434c5e;--line: #4c566a;--ink: #eceff4;--muted: #d8dee9;--high: #a3be8c;--medium: #ebcb8b;--low: #bf616a;--critical: #d08770;--accent: #88c0d0;--rail-from: #3b4252;--rail-to: #2e3440;--rail-active: #4c566a;--btn: #434c5e;--btn-line: #81a1c1;--btn-primary: #5e81ac;--btn-primary-line: #88c0d0;--node-bg: #3b4252;--node-line: #81a1c1;--graph-bg: #2e3440;--graph-grid: rgba(136, 192, 208, .12);--edge-cheap: #4c566a;--edge-expensive: #d08770;--edge-critical: #bf616a;--shadow: rgba(136, 192, 208, .12)}[data-theme=solarized-dark]{--bg: #002b36;--bg-2: #073642;--surface: #0a3944;--line: #16444f;--ink: #eee8d5;--muted: #93a1a1;--high: #859900;--medium: #b58900;--low: #dc322f;--critical: #cb4b16;--accent: #2aa198;--rail-from: #073642;--rail-to: #002b36;--rail-active: #16444f;--btn: #073642;--btn-line: #268bd2;--btn-primary: #0a4a42;--btn-primary-line: #2aa198;--node-bg: #073642;--node-line: #268bd2;--graph-bg: #002b36;--graph-grid: rgba(42, 161, 152, .12);--edge-cheap: #586e75;--edge-expensive: #cb4b16;--edge-critical: #dc322f;--shadow: rgba(42, 161, 152, .12)}[data-theme=forest]{--bg: #0e1510;--bg-2: #152019;--surface: #1b2a20;--line: #2c4334;--ink: #e4f0e6;--muted: #8eaa96;--high: #6ab04c;--medium: #c8a951;--low: #e17055;--critical: #d35400;--accent: #7bed9f;--rail-from: #152019;--rail-to: #0e1510;--rail-active: #1f3326;--btn: #1f3326;--btn-line: #3d6b4f;--btn-primary: #1e4d32;--btn-primary-line: #6ab04c;--node-bg: #16241b;--node-line: #3d6b4f;--graph-bg: #0e1510;--graph-grid: rgba(123, 237, 159, .1);--edge-cheap: #3d6b4f;--edge-expensive: #c8a951;--edge-critical: #d35400;--shadow: rgba(123, 237, 159, .1)}[data-theme=rose]{--bg: #191724;--bg-2: #1f1d2e;--surface: #26233a;--line: #403d52;--ink: #e0def4;--muted: #908caa;--high: #9ccfd8;--medium: #f6c177;--low: #eb6f92;--critical: #eb6f92;--accent: #c4a7e7;--rail-from: #1f1d2e;--rail-to: #191724;--rail-active: #26233a;--btn: #26233a;--btn-line: #c4a7e7;--btn-primary: #3a2f4d;--btn-primary-line: #c4a7e7;--node-bg: #1f1d2e;--node-line: #524f67;--graph-bg: #191724;--graph-grid: rgba(196, 167, 231, .12);--edge-cheap: #524f67;--edge-expensive: #f6c177;--edge-critical: #eb6f92;--shadow: rgba(196, 167, 231, .12)}[data-theme=amber]{--bg: #120e0a;--bg-2: #1c1610;--surface: #261e16;--line: #3d2f22;--ink: #f4e6d0;--muted: #b59a78;--high: #c4d6a0;--medium: #e9b44c;--low: #d8572a;--critical: #c0392b;--accent: #f0a05a;--rail-from: #1c1610;--rail-to: #120e0a;--rail-active: #2b2218;--btn: #2b2218;--btn-line: #8a5a2b;--btn-primary: #4a3418;--btn-primary-line: #f0a05a;--node-bg: #1c1610;--node-line: #8a5a2b;--graph-bg: #120e0a;--graph-grid: rgba(240, 160, 90, .12);--edge-cheap: #5c4a38;--edge-expensive: #e9b44c;--edge-critical: #d8572a;--shadow: rgba(240, 160, 90, .12)}[data-theme=volcano]{--bg: #14090a;--bg-2: #1e0e10;--surface: #2a1416;--line: #4a2226;--ink: #fde8e4;--muted: #c48b86;--high: #7bed9f;--medium: #f6c90e;--low: #ff6b6b;--critical: #ff3b3b;--accent: #ff7b54;--rail-from: #1e0e10;--rail-to: #14090a;--rail-active: #32181b;--btn: #32181b;--btn-line: #ff7b54;--btn-primary: #5a1f18;--btn-primary-line: #ff7b54;--node-bg: #1e0e10;--node-line: #7a3330;--graph-bg: #14090a;--graph-grid: rgba(255, 123, 84, .12);--edge-cheap: #5a3330;--edge-expensive: #ff7b54;--edge-critical: #ff3b3b;--shadow: rgba(255, 123, 84, .14)}[data-theme=lavender]{--bg: #12101c;--bg-2: #1a1730;--surface: #221e3c;--line: #3b3560;--ink: #efeaff;--muted: #b3a7d6;--high: #80ffdb;--medium: #ffd166;--low: #ff6b9d;--critical: #ff4d6d;--accent: #c77dff;--rail-from: #1a1730;--rail-to: #12101c;--rail-active: #2a2550;--btn: #2a2550;--btn-line: #c77dff;--btn-primary: #3d2a66;--btn-primary-line: #c77dff;--node-bg: #1a1730;--node-line: #5a4d8a;--graph-bg: #12101c;--graph-grid: rgba(199, 125, 255, .12);--edge-cheap: #5a4d8a;--edge-expensive: #ffd166;--edge-critical: #ff4d6d;--shadow: rgba(199, 125, 255, .14)}[data-theme=neon-noir]{--bg: #05060a;--bg-2: #0a0c14;--surface: #10131c;--line: #1e2436;--ink: #f0f4ff;--muted: #8b93b0;--high: #39ff88;--medium: #ffe66d;--low: #ff2d95;--critical: #ff3d5a;--accent: #00f0ff;--rail-from: #0a0c14;--rail-to: #05060a;--rail-active: #151a2a;--btn: #151a2a;--btn-line: #00f0ff;--btn-primary: #063a40;--btn-primary-line: #00f0ff;--node-bg: #0a0c14;--node-line: #2a3550;--graph-bg: #05060a;--graph-grid: rgba(0, 240, 255, .12);--edge-cheap: #3a4560;--edge-expensive: #ff2d95;--edge-critical: #ff3d5a;--shadow: rgba(0, 240, 255, .22)}[data-theme=synthwave]{--bg: #1a0a2e;--bg-2: #240b3d;--surface: #2d1250;--line: #4a1d7a;--ink: #ffe6fb;--muted: #c49ad8;--high: #00f5d4;--medium: #ffd60a;--low: #ff6b9d;--critical: #ff006e;--accent: #ff2bd6;--rail-from: #240b3d;--rail-to: #1a0a2e;--rail-active: #3a1570;--btn: #3a1570;--btn-line: #ff2bd6;--btn-primary: #5a0a4a;--btn-primary-line: #ff2bd6;--node-bg: #240b3d;--node-line: #7b2cbf;--graph-bg: #1a0a2e;--graph-grid: rgba(255, 43, 214, .16);--edge-cheap: #5a3a80;--edge-expensive: #ff9e00;--edge-critical: #ff006e;--shadow: rgba(255, 43, 214, .24)}[data-theme=phosphor]{--bg: #020804;--bg-2: #061208;--surface: #0a1a0e;--line: #163c1e;--ink: #c8ffc8;--muted: #5aaa5a;--high: #39ff14;--medium: #c8f542;--low: #ffb000;--critical: #ff5e00;--accent: #00ff66;--rail-from: #061208;--rail-to: #020804;--rail-active: #0e2414;--btn: #0e2414;--btn-line: #00ff66;--btn-primary: #0a3a18;--btn-primary-line: #00ff66;--node-bg: #061208;--node-line: #1e6a32;--graph-bg: #020804;--graph-grid: rgba(0, 255, 102, .12);--edge-cheap: #1e5a2a;--edge-expensive: #c8f542;--edge-critical: #ff5e00;--shadow: rgba(0, 255, 102, .2)}[data-theme=aurora]{--bg: #071018;--bg-2: #0c1c28;--surface: #122636;--line: #1e3d52;--ink: #e8fff6;--muted: #7eb8a8;--high: #5fffcf;--medium: #ffe566;--low: #ff7eb6;--critical: #ff4d6d;--accent: #7cffb2;--rail-from: #0c1c28;--rail-to: #071018;--rail-active: #163044;--btn: #163044;--btn-line: #7cffb2;--btn-primary: #0e3d3a;--btn-primary-line: #7cffb2;--node-bg: #0c1c28;--node-line: #2a6a78;--graph-bg: #071018;--graph-grid: rgba(124, 255, 178, .12);--edge-cheap: #2a5a68;--edge-expensive: #c9a0ff;--edge-critical: #ff4d6d;--shadow: rgba(124, 255, 178, .18)}[data-theme=biolume]{--bg: #02141c;--bg-2: #042430;--surface: #073040;--line: #0a4a5c;--ink: #e6fffb;--muted: #6eb8b0;--high: #5dffb0;--medium: #ffe066;--low: #ff79c6;--critical: #ff4d6d;--accent: #18e7d4;--rail-from: #042430;--rail-to: #02141c;--rail-active: #0a3848;--btn: #0a3848;--btn-line: #18e7d4;--btn-primary: #0a4a48;--btn-primary-line: #18e7d4;--node-bg: #042430;--node-line: #1a7080;--graph-bg: #02141c;--graph-grid: rgba(24, 231, 212, .12);--edge-cheap: #1a5a68;--edge-expensive: #ff79c6;--edge-critical: #ff4d6d;--shadow: rgba(24, 231, 212, .2)}[data-theme=carbon]{--bg: #0d0d0f;--bg-2: #16161a;--surface: #1e1e24;--line: #33333c;--ink: #f2f2f4;--muted: #9a9aa8;--high: #3dd68c;--medium: #f0c040;--low: #ff5a5a;--critical: #ff2a2a;--accent: #ff2a2a;--rail-from: #16161a;--rail-to: #0d0d0f;--rail-active: #24242c;--btn: #24242c;--btn-line: #ff2a2a;--btn-primary: #4a1212;--btn-primary-line: #ff2a2a;--node-bg: #16161a;--node-line: #4a4a55;--graph-bg: #0d0d0f;--graph-grid: rgba(255, 42, 42, .1);--edge-cheap: #4a4a55;--edge-expensive: #ff8a3d;--edge-critical: #ff2a2a;--shadow: rgba(255, 42, 42, .18)}[data-theme=paper]{--bg: #f6f1e8;--bg-2: #efe6d6;--surface: #fffaf2;--line: #d9cbb6;--ink: #2b241c;--muted: #6f6456;--high: #2a7a4b;--medium: #b5811a;--low: #c0392b;--critical: #a93226;--accent: #1d6a7a;--rail-from: #efe6d6;--rail-to: #e7dcc8;--rail-active: #e2d3bb;--btn: #fffaf2;--btn-line: #c9b79a;--btn-primary: #d7eee0;--btn-primary-line: #2a7a4b;--node-bg: #fffaf2;--node-line: #c9b79a;--graph-bg: #f6f1e8;--graph-grid: rgba(29, 106, 122, .1);--edge-cheap: #b7a48c;--edge-expensive: #c0392b;--edge-critical: #a93226;--shadow: rgba(43, 36, 28, .08)}[data-theme=solarized-light]{--bg: #fdf6e3;--bg-2: #eee8d5;--surface: #f5efdc;--line: #d6cba9;--ink: #657b83;--muted: #93a1a1;--high: #859900;--medium: #b58900;--low: #dc322f;--critical: #cb4b16;--accent: #268bd2;--rail-from: #eee8d5;--rail-to: #e6dfc8;--rail-active: #e0d9c0;--btn: #fdf6e3;--btn-line: #93a1a1;--btn-primary: #e8efc8;--btn-primary-line: #859900;--node-bg: #fdf6e3;--node-line: #93a1a1;--graph-bg: #fdf6e3;--graph-grid: rgba(38, 139, 210, .12);--edge-cheap: #93a1a1;--edge-expensive: #cb4b16;--edge-critical: #dc322f;--shadow: rgba(101, 123, 131, .1)}[data-theme=seafoam]{--bg: #eef7f4;--bg-2: #dff0ea;--surface: #ffffff;--line: #b7d5cc;--ink: #17332c;--muted: #4d7268;--high: #1b8a5a;--medium: #c48a14;--low: #c44536;--critical: #9b2d22;--accent: #1d9a8a;--rail-from: #dff0ea;--rail-to: #cfe6de;--rail-active: #c4ddd4;--btn: #ffffff;--btn-line: #8fbfb2;--btn-primary: #d4f0e4;--btn-primary-line: #1b8a5a;--node-bg: #ffffff;--node-line: #8fbfb2;--graph-bg: #eef7f4;--graph-grid: rgba(29, 154, 138, .12);--edge-cheap: #8fbfb2;--edge-expensive: #c48a14;--edge-critical: #c44536;--shadow: rgba(23, 51, 44, .08)}[data-theme=high-contrast]{--bg: #ffffff;--bg-2: #f2f2f2;--surface: #ffffff;--line: #111111;--ink: #000000;--muted: #222222;--high: #007a33;--medium: #8a5a00;--low: #b00000;--critical: #9b0000;--accent: #0033cc;--rail-from: #f2f2f2;--rail-to: #e6e6e6;--rail-active: #d9d9d9;--btn: #ffffff;--btn-line: #000000;--btn-primary: #d9f2e3;--btn-primary-line: #007a33;--node-bg: #ffffff;--node-line: #000000;--graph-bg: #ffffff;--graph-grid: rgba(0, 0, 0, .12);--edge-cheap: #444444;--edge-expensive: #8a5a00;--edge-critical: #b00000;--shadow: rgba(0, 0, 0, .12)}[data-theme=sakura]{--bg: #fff0f5;--bg-2: #ffe4ee;--surface: #fff7fa;--line: #f5b8cc;--ink: #4a1830;--muted: #a05a78;--high: #1a8a5c;--medium: #c48a14;--low: #d63d6e;--critical: #b01040;--accent: #e84a8a;--rail-from: #ffe4ee;--rail-to: #f8d4e0;--rail-active: #f5c8d8;--btn: #fff7fa;--btn-line: #e89ab0;--btn-primary: #ffd6e6;--btn-primary-line: #e84a8a;--node-bg: #fff7fa;--node-line: #e89ab0;--graph-bg: #fff0f5;--graph-grid: rgba(232, 74, 138, .12);--edge-cheap: #d4a0b0;--edge-expensive: #d63d6e;--edge-critical: #b01040;--shadow: rgba(74, 24, 48, .1)}[data-theme=citrus]{--bg: #fffce8;--bg-2: #fff3b0;--surface: #fffef5;--line: #e8d44a;--ink: #2a2a08;--muted: #6a6a20;--high: #2a8a20;--medium: #d4a000;--low: #e85d04;--critical: #c0392b;--accent: #5aad14;--rail-from: #fff3b0;--rail-to: #ffe98a;--rail-active: #ffe066;--btn: #fffef5;--btn-line: #d4c030;--btn-primary: #e8f5b8;--btn-primary-line: #5aad14;--node-bg: #fffef5;--node-line: #d4c030;--graph-bg: #fffce8;--graph-grid: rgba(90, 173, 20, .14);--edge-cheap: #c4b040;--edge-expensive: #e85d04;--edge-critical: #c0392b;--shadow: rgba(42, 42, 8, .1)}[data-theme=peach]{--bg: #fff3eb;--bg-2: #ffe0cc;--surface: #fffaf6;--line: #f0c4a8;--ink: #3a2218;--muted: #8a5a48;--high: #2a8a5c;--medium: #d48a14;--low: #e85d3a;--critical: #c0392b;--accent: #ff6b35;--rail-from: #ffe0cc;--rail-to: #ffd4b8;--rail-active: #ffc8a8;--btn: #fffaf6;--btn-line: #e8a888;--btn-primary: #ffe0cc;--btn-primary-line: #ff6b35;--node-bg: #fffaf6;--node-line: #e8a888;--graph-bg: #fff3eb;--graph-grid: rgba(255, 107, 53, .12);--edge-cheap: #d4a088;--edge-expensive: #e85d3a;--edge-critical: #c0392b;--shadow: rgba(58, 34, 24, .1)}[data-theme=candy]{--bg: #f4f0ff;--bg-2: #e8dcff;--surface: #fbf8ff;--line: #d4c0f0;--ink: #2a1848;--muted: #6a5890;--high: #1a8a6a;--medium: #c48a14;--low: #e84a8a;--critical: #c01060;--accent: #ff5eb1;--rail-from: #e8dcff;--rail-to: #ddd0ff;--rail-active: #d4c4ff;--btn: #fbf8ff;--btn-line: #c4a8e8;--btn-primary: #ffd6ec;--btn-primary-line: #ff5eb1;--node-bg: #fbf8ff;--node-line: #c4a8e8;--graph-bg: #f4f0ff;--graph-grid: rgba(255, 94, 177, .14);--edge-cheap: #b0a0d0;--edge-expensive: #e84a8a;--edge-critical: #c01060;--shadow: rgba(42, 24, 72, .1)}[data-theme=sky]{--bg: #e8f4ff;--bg-2: #cfe8ff;--surface: #f5faff;--line: #90c8f0;--ink: #0a2848;--muted: #3a6080;--high: #0a8a4a;--medium: #c48a14;--low: #e85d3a;--critical: #c0392b;--accent: #0077ff;--rail-from: #cfe8ff;--rail-to: #b8dcff;--rail-active: #a8d4ff;--btn: #f5faff;--btn-line: #70b0e0;--btn-primary: #cfe8ff;--btn-primary-line: #0077ff;--node-bg: #f5faff;--node-line: #70b0e0;--graph-bg: #e8f4ff;--graph-grid: rgba(0, 119, 255, .12);--edge-cheap: #80b0d0;--edge-expensive: #e85d3a;--edge-critical: #c0392b;--shadow: rgba(10, 40, 72, .1)}[data-theme=coral]{--bg: #fff1ee;--bg-2: #ffddd6;--surface: #fff8f6;--line: #f0b0a4;--ink: #3a1814;--muted: #8a5048;--high: #0d9488;--medium: #d48a14;--low: #e85d4a;--critical: #c0392b;--accent: #0d9488;--rail-from: #ffddd6;--rail-to: #ffd0c6;--rail-active: #ffc4b8;--btn: #fff8f6;--btn-line: #e89888;--btn-primary: #d4f4ee;--btn-primary-line: #0d9488;--node-bg: #fff8f6;--node-line: #e89888;--graph-bg: #fff1ee;--graph-grid: rgba(13, 148, 136, .14);--edge-cheap: #d4a098;--edge-expensive: #e85d4a;--edge-critical: #c0392b;--shadow: rgba(58, 24, 20, .1)}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}:root{--radius: 6px;--radius-lg: 10px;--control-h: 32px;--font: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;--focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--space: 8px}body{background:var(--bg);color:var(--ink);font-family:var(--font);font-size:13px;line-height:1.45;-webkit-font-smoothing:antialiased}button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,a:focus-visible,summary:focus-visible{outline:none;box-shadow:var(--focus-ring)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.skip{position:absolute;left:12px;top:-40px;z-index:50;background:var(--surface);color:var(--ink);border:1px solid var(--accent);border-radius:var(--radius);padding:8px 12px}.skip:focus{top:12px}.app{display:grid;grid-template-columns:232px 1fr;height:100%}.rail{border-right:1px solid var(--line);background:linear-gradient(180deg,var(--rail-from),var(--rail-to));padding:16px 12px;display:flex;flex-direction:column;gap:2px;min-width:0}.brand{display:flex;flex-direction:column;gap:2px;padding:4px 8px 16px}.brand-mark{font-family:var(--mono);letter-spacing:.16em;font-size:11px;text-transform:uppercase;color:var(--accent);font-weight:600}.brand-sub{font-size:11px;color:var(--muted)}.nav-item{display:flex;align-items:center;gap:10px;background:transparent;border:0;text-align:left;padding:8px 10px;border-radius:var(--radius);color:var(--muted);cursor:pointer;width:100%}.nav-item:hover{background:color-mix(in srgb,var(--rail-active) 70%,transparent);color:var(--ink)}.nav-item.active{background:var(--rail-active);color:var(--ink);font-weight:500}.nav-item svg{flex-shrink:0}.theme-pick{margin-top:14px;display:grid;gap:4px;padding:0 2px}.theme-pick label{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:500}.theme-pick select,.field select,.field input,.topbar input,.topbar select,.settings input,.settings select,.explorer-path input{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:0 10px;height:var(--control-h);width:100%}.rail-foot{margin-top:auto;padding:12px 8px 4px;border-top:1px solid var(--line);display:grid;gap:6px}.kbd-hint{font-size:11px;color:var(--muted)}kbd{font-family:var(--mono);font-size:10px;border:1px solid var(--line);border-radius:4px;padding:0 4px;background:var(--surface)}.main{display:flex;flex-direction:column;min-width:0;min-height:0;position:relative;background:var(--bg)}.progress{position:absolute;top:0;left:0;right:0;height:2px;overflow:hidden;z-index:30;background:color-mix(in srgb,var(--accent) 20%,transparent)}.progress i{display:block;height:100%;width:32%;background:var(--accent);animation:indeterminate 1.1s ease-in-out infinite}@keyframes indeterminate{0%{transform:translate(-120%)}to{transform:translate(400%)}}.topbar{display:flex;gap:10px;align-items:flex-end;padding:10px 16px;border-bottom:1px solid var(--line);background:var(--bg-2);flex-wrap:wrap}.field{display:grid;gap:4px;min-width:0}.field>span{font-size:11px;color:var(--muted);font-weight:500}.field.path{flex:1;min-width:180px}.field.ref{width:188px;flex:0 0 188px}.field.workspace{width:180px;flex:0 0 180px}.path-row,.combo-row{display:flex;min-width:0}.path-row input,.combo-row input{flex:1;min-width:0}.combo{position:relative;min-width:0}.combo-row input{border-top-right-radius:0;border-bottom-right-radius:0}.topbar .icon-btn{width:var(--control-h);padding:0;flex:0 0 var(--control-h)}.combo-toggle{border-top-left-radius:0;border-bottom-left-radius:0;border-left:0}.combo-menu{position:absolute;top:calc(100% + 4px);right:0;left:auto;min-width:340px;max-width:min(480px,70vw);max-height:360px;overflow:auto;z-index:40;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:0 12px 32px var(--shadow);padding:6px 0}.combo-heading{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:600;padding:8px 12px 4px}.combo-menu .combo-option{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;text-align:left;background:transparent;border:0;border-radius:0;height:auto;padding:6px 12px;color:var(--ink);cursor:pointer}.combo-menu .combo-option:hover,.combo-menu .combo-option.active{background:var(--rail-active)}.combo-label{font-family:var(--mono);font-size:12px}.combo-detail{color:var(--muted);font-size:12px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.combo-empty{padding:10px 12px}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:color-mix(in srgb,var(--bg) 72%,transparent);display:grid;place-items:center;padding:24px}.modal{width:min(720px,100%);max-height:min(640px,90vh);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius-lg);box-shadow:0 16px 48px var(--shadow);display:flex;flex-direction:column;overflow:hidden}.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px 10px;border-bottom:1px solid var(--line)}.modal-head h2{font-size:15px}.modal-head .muted{margin:4px 0 0}.explorer-path{display:flex;gap:8px;padding:12px 16px;border-bottom:1px solid var(--line)}.explorer-path input{flex:1;min-width:0}.explorer-list{flex:1;overflow:auto;padding:8px;min-height:220px}.explorer-row{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:transparent;border:0;border-radius:var(--radius);padding:8px 10px;color:var(--ink);cursor:pointer;height:auto}.explorer-row:hover,.explorer-row.active{background:var(--rail-active)}.explorer-name{min-width:0;overflow:hidden;text-overflow:ellipsis}.git-badge{margin-left:auto;margin-bottom:0}.explorer-empty{padding:18px 10px}.modal-foot{display:flex;align-items:center;gap:12px;padding:12px 16px;border-top:1px solid var(--line)}.explorer-current{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:12px}.topbar input,.topbar select{min-width:0}.topbar-actions{display:flex;gap:8px;margin-left:auto;align-items:center;padding-bottom:0}.btn,.topbar button{background:var(--btn);border:1px solid var(--btn-line);border-radius:var(--radius);height:var(--control-h);padding:0 12px;cursor:pointer;font-weight:500;display:inline-flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap}.btn:hover,.topbar button:hover{filter:brightness(1.08)}.btn:disabled,.topbar button:disabled{opacity:.55;cursor:not-allowed;filter:none}.btn.primary{background:var(--btn-primary);border-color:var(--btn-primary-line)}.btn.ghost{background:transparent}.alerts{display:grid;gap:8px;padding:10px 16px 0}.alerts:empty{display:none;padding:0}.stage{flex:1;min-height:0;display:flex;flex-direction:column}.content{flex:1;min-height:0;display:grid;grid-template-columns:minmax(340px,420px) 1fr}.brief{overflow:auto;border-right:1px solid var(--line);padding:16px 18px 24px;background:radial-gradient(circle at 0 0,color-mix(in srgb,var(--accent) 8%,transparent),transparent 42%),var(--bg)}.graph-wrap{position:relative;min-height:0;display:flex;flex-direction:column}.impact-graph{flex:1;min-height:0;position:relative;display:flex;flex-direction:column}.graph-toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--bg-2)}.graph-count{margin-left:auto;font-size:11px}.chip-btn{background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:4px 12px;color:var(--muted);cursor:pointer;height:26px}.chip-btn:hover{color:var(--ink)}.chip-btn.active{background:var(--rail-active);color:var(--ink)}.chip-btn:disabled{opacity:.45;cursor:not-allowed}.graph-stage{flex:1;min-height:0;position:relative;display:flex;flex-direction:column}.graph-stage .react-flow,.graph-3d,.graph-3d-host,.graph-3d-canvas-host{flex:1;width:100%;height:100%;min-height:280px}.graph-3d{position:relative;background:var(--graph-bg);display:flex;flex-direction:column}.graph-3d-host{position:relative;min-height:0;display:flex;flex-direction:column}.graph-3d-canvas-host{position:relative;min-height:0}.graph-3d canvas{display:block;width:100%;height:100%}.graph-3d-tip{position:absolute;pointer-events:none;z-index:2;max-width:320px;padding:6px 8px;border-radius:var(--radius);background:var(--surface);border:1px solid var(--line);color:var(--ink);font-size:11px;line-height:1.35;box-shadow:0 8px 24px var(--shadow)}.graph-3d-tip .t{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.graph-3d-tip .n{font-weight:600}.graph-3d-hint{position:absolute;left:10px;bottom:10px;z-index:2;margin:0;font-size:11px;color:var(--muted);max-width:min(420px,calc(100% - 24px));pointer-events:none}.graph-wrap .react-flow{background-color:var(--graph-bg);background-image:linear-gradient(var(--graph-grid) 1px,transparent 1px),linear-gradient(90deg,var(--graph-grid) 1px,transparent 1px);background-size:24px 24px}.react-flow__minimap{background:var(--graph-bg)!important;border:1px solid var(--line)!important;border-radius:var(--radius);overflow:hidden;box-shadow:0 8px 24px var(--shadow)}.react-flow__minimap-node{fill:var(--muted);stroke:none}.react-flow__minimap-node.selected{fill:var(--accent)}.react-flow__minimap-mask{fill:#00000073!important;stroke:var(--accent)!important}.react-flow__controls{box-shadow:none!important}.react-flow__controls-button{background:var(--surface)!important;border-bottom:1px solid var(--line)!important;fill:var(--ink)!important}h1{font-size:18px;margin:0 0 6px;font-weight:600}h2{font-size:13px;margin:0;font-weight:600}.merge-box{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-lg);padding:12px 14px;margin-bottom:12px}.merge-box.high{border-color:color-mix(in srgb,var(--high) 55%,var(--line))}.merge-box.medium{border-color:color-mix(in srgb,var(--medium) 55%,var(--line))}.merge-box.low{border-color:color-mix(in srgb,var(--low) 55%,var(--line))}.level{font-family:var(--mono);font-weight:600;font-size:14px}.level.high{color:var(--high)}.level.medium{color:var(--medium)}.level.low{color:var(--low)}.merge-title{margin-top:4px;font-size:13px;color:var(--ink)}.reasons{margin:10px 0 0;padding:0 0 0 18px;color:var(--muted)}.reasons li{margin:0 0 4px}.metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:0 0 14px}.metric{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);padding:8px 10px}.metric .n{font-family:var(--mono);font-size:16px;font-weight:600;font-variant-numeric:tabular-nums}.metric .l{font-size:11px;color:var(--muted);margin-top:2px}.section{border-top:1px solid var(--line);padding:8px 0 4px}.section>summary{cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.07em;font-weight:600;padding:6px 0}.section>summary::-webkit-details-marker{display:none}.section>summary .count{font-family:var(--mono);letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:999px;padding:0 7px;height:18px;display:inline-flex;align-items:center;font-size:11px}.kicker{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.08em;margin:16px 0 6px;font-weight:600}.chip{display:inline-flex;align-items:center;font-size:11px;padding:2px 8px;border-radius:999px;border:1px solid var(--line);margin:0 6px 6px 0;color:var(--muted);background:var(--surface)}.chip.blocker{color:var(--low);border-color:var(--low)}.chip.warning{color:var(--medium);border-color:var(--medium)}.chip.strong{color:var(--low);border-color:var(--low)}.chip.worth_exploring{color:var(--medium);border-color:var(--medium)}.chip.speculative{color:var(--muted);border-color:var(--line)}.chip.open{color:var(--high);border-color:color-mix(in srgb,var(--high) 50%,var(--line))}.file{font-family:var(--mono);font-size:12px;color:var(--accent)}.read-item,.finding,.residual{padding:8px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 70%,transparent)}.read-item:last-child,.finding:last-child{border-bottom:0}.read-item .why{color:var(--muted);font-size:12px;margin-top:2px}.muted{color:var(--muted);font-size:13px;line-height:1.45}.error{color:var(--low);padding:8px 12px;border:1px solid var(--low);background:color-mix(in srgb,var(--low) 10%,var(--surface));border-radius:var(--radius);display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.banner{padding:8px 12px;border-radius:var(--radius);border:1px solid var(--line);background:var(--surface);font-size:13px;line-height:1.45;display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.banner.warn{border-color:var(--medium);color:var(--medium)}.banner.stale{border-color:var(--low);color:var(--low)}.banner .dismiss{background:transparent;border:0;color:inherit;cursor:pointer;height:auto;padding:0 2px;opacity:.7}.empty{padding:24px 8px;color:var(--muted);font-size:13px;line-height:1.55}.empty h2{font-size:16px;color:var(--ink);margin-bottom:8px}.empty ol{margin:12px 0 0 18px;padding:0}.empty code,code{font-family:var(--mono);font-size:12px;color:var(--accent)}.btn-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.pr-list{padding:16px;overflow:auto}.pr-toolbar{display:flex;gap:8px;align-items:flex-end;margin-bottom:14px}.pr-toolbar .field{flex:1}.pr-toolbar .field.provider{flex:0 0 140px}.scm-count{margin:0 0 12px;font-size:12px}.scm-login{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:10px 0;border-top:1px solid var(--line)}.scm-login:first-of-type{border-top:0;padding-top:0}.scm-login .btn-row{margin-top:0}.scm-login p{margin:2px 0 0}.oauth-code{font-size:13px;margin:0}.oauth-code code{font-size:14px;letter-spacing:.08em}.pr{border:1px solid var(--line);background:var(--surface);padding:12px 14px;border-radius:var(--radius-lg);margin-bottom:10px}.pr h3{margin:0 0 4px;font-size:14px;font-weight:600}.pr-meta{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center;margin:6px 0 10px}.pr-actions{display:flex;gap:8px;align-items:center}.settings{padding:24px;max-width:760px;overflow:auto;display:grid;gap:16px}.settings-card{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-lg);padding:16px;display:grid;gap:8px}.settings-card h2{font-size:14px;margin-bottom:2px}.settings label{font-size:12px;color:var(--muted);font-weight:500}.theme-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px}.theme-swatch{border:1px solid var(--line);background:var(--bg);color:var(--ink);border-radius:var(--radius);padding:10px;text-align:left;cursor:pointer;height:auto;box-shadow:0 1px 8px var(--shadow)}.theme-swatch.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),0 1px 8px var(--shadow)}.theme-swatch .swatch-bar{height:6px;border-radius:3px;margin-bottom:8px;background:linear-gradient(90deg,var(--accent),var(--high),var(--medium),var(--low))}.theme-swatch .name{font-size:13px;font-weight:600}.theme-swatch .group{font-size:11px;color:var(--muted)}.headline{white-space:pre-wrap;font-family:var(--mono);font-size:12px;color:var(--muted);margin:8px 0 0}.graph-modes{display:flex;gap:8px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--bg-2)}.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;padding:2px;background:var(--surface)}.seg button,.graph-modes button{background:transparent;border:0;border-radius:999px;padding:4px 12px;color:var(--muted);cursor:pointer;height:26px}.seg button.active,.graph-modes button.active{background:var(--rail-active);color:var(--ink)}.legend{margin-left:auto;display:flex;gap:12px;color:var(--muted);font-size:11px}.legend i{display:inline-block;width:14px;height:2px;margin-right:6px;vertical-align:middle;background:var(--edge-cheap)}.legend i.exp{background:var(--edge-expensive)}.legend i.crit{background:var(--edge-critical);height:3px}.legend i.dash{border-top:2px dashed var(--muted);background:none;height:0}.inspector{position:absolute;top:12px;right:12px;z-index:5;width:300px;max-width:calc(100% - 24px);max-height:calc(100% - 24px);overflow-x:hidden;overflow-y:auto;overflow-wrap:break-word;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);padding:10px 12px;box-shadow:0 8px 24px var(--shadow);font-size:12px}.inspector .t{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}.inspector .n,.inspector .file,.inspector .muted{overflow-wrap:break-word}.inspector .n{font-weight:600;margin:4px 0}.inspector-head{display:flex;align-items:flex-start;gap:8px}.inspector-roles{display:flex;flex-wrap:wrap;justify-content:flex-end;flex:1;gap:4px}.inspector-chip{font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:1px 6px;border-radius:999px;border:1px solid var(--line);color:var(--muted);white-space:nowrap}.inspector-close{flex:0 0 auto;width:24px;height:24px;padding:0;border:1px solid var(--line);border-radius:var(--radius);background:transparent;color:var(--muted);font-size:16px;line-height:1;cursor:pointer}.inspector-close:hover{color:var(--ink)}.inspector-purpose{margin:6px 0 8px;color:var(--ink);font-size:12px;line-height:1.4}.inspector-layer{margin-top:4px;font-size:11px}.inspector-facts{margin:10px 0 0;padding-top:8px;border-top:1px solid var(--line)}.inspector-fact{display:grid;grid-template-columns:minmax(64px,92px) minmax(0,1fr);gap:8px;padding:3px 0;align-items:start}.inspector-fact dt{color:var(--muted);font-size:11px;margin:0}.inspector-fact dd{margin:0;overflow-wrap:break-word}.inspector-section{margin-top:10px;padding-top:8px;border-top:1px solid var(--line)}.inspector-section h3{margin:0 0 6px;display:flex;align-items:center;justify-content:space-between;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.07em;font-weight:600}.inspector-section .count{font-family:var(--mono);letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:999px;padding:0 7px;height:18px;display:inline-flex;align-items:center;font-size:11px}.inspector-section ul{list-style:none;margin:0;padding:0}.inspector-section li{padding:4px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 70%,transparent)}.inspector-section li:last-child{border-bottom:0}.inspector-link-name{display:block;font-weight:600;overflow-wrap:break-word}.inspector-link-meta{display:block;color:var(--muted);font-size:11px}.lp-node{padding:8px 10px;border-radius:var(--radius);border:1px solid var(--node-line);background:var(--node-bg);width:180px;max-width:100%;height:56px;box-sizing:border-box;box-shadow:0 0 0 1px var(--shadow);overflow:visible;position:relative}.lp-node .t{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.lp-node .n{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lp-node.selected{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.react-flow__node-load .react-flow__handle{width:8px;height:8px;border:none;background:transparent;opacity:0}.type-table{width:100%;border-collapse:collapse;font-size:12px}.type-table td{padding:3px 0}.type-table td:last-child{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--muted)}@media(prefers-reduced-motion:reduce){.progress i{animation:none;width:100%}*{scroll-behavior:auto!important}}@media(max-width:960px){.app{grid-template-columns:56px 1fr}.brand-sub,.nav-item span,.theme-pick,.kbd-hint,.rail-foot .muted{display:none}.nav-item{justify-content:center;padding:10px}.content{grid-template-columns:1fr}.brief{border-right:0;border-bottom:1px solid var(--line);max-height:42vh}} +.react-flow{direction:ltr;--xy-edge-stroke-default: #b1b1b7;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #555;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(255, 255, 255, .5);--xy-minimap-background-color-default: #fff;--xy-minimap-mask-background-color-default: rgba(240, 240, 240, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #e2e2e2;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: transparent;--xy-background-pattern-dots-color-default: #91919a;--xy-background-pattern-lines-color-default: #eee;--xy-background-pattern-cross-color-default: #e2e2e2;background-color:var(--xy-background-color, var(--xy-background-color-default));--xy-node-color-default: inherit;--xy-node-border-default: 1px solid #1a192b;--xy-node-background-color-default: #fff;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(0, 0, 0, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #1a192b;--xy-node-border-radius-default: 3px;--xy-handle-background-color-default: #1a192b;--xy-handle-border-color-default: #fff;--xy-selection-background-color-default: rgba(0, 89, 220, .08);--xy-selection-border-default: 1px dotted rgba(0, 89, 220, .8);--xy-controls-button-background-color-default: #fefefe;--xy-controls-button-background-color-hover-default: #f4f4f4;--xy-controls-button-color-default: inherit;--xy-controls-button-color-hover-default: inherit;--xy-controls-button-border-color-default: #eee;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #ffffff;--xy-edge-label-color-default: inherit;--xy-resize-background-color-default: #3367d9}.react-flow.dark{--xy-edge-stroke-default: #3e3e3e;--xy-edge-stroke-width-default: 1;--xy-edge-stroke-selected-default: #727272;--xy-connectionline-stroke-default: #b1b1b7;--xy-connectionline-stroke-width-default: 1;--xy-attribution-background-color-default: rgba(150, 150, 150, .25);--xy-minimap-background-color-default: #141414;--xy-minimap-mask-background-color-default: rgba(60, 60, 60, .6);--xy-minimap-mask-stroke-color-default: transparent;--xy-minimap-mask-stroke-width-default: 1;--xy-minimap-node-background-color-default: #2b2b2b;--xy-minimap-node-stroke-color-default: transparent;--xy-minimap-node-stroke-width-default: 2;--xy-background-color-default: #141414;--xy-background-pattern-dots-color-default: #555;--xy-background-pattern-lines-color-default: #333;--xy-background-pattern-cross-color-default: #333;--xy-node-color-default: #f8f8f8;--xy-node-border-default: 1px solid #3c3c3c;--xy-node-background-color-default: #1e1e1e;--xy-node-group-background-color-default: rgba(240, 240, 240, .25);--xy-node-boxshadow-hover-default: 0 1px 4px 1px rgba(255, 255, 255, .08);--xy-node-boxshadow-selected-default: 0 0 0 .5px #999;--xy-handle-background-color-default: #bebebe;--xy-handle-border-color-default: #1e1e1e;--xy-selection-background-color-default: rgba(200, 200, 220, .08);--xy-selection-border-default: 1px dotted rgba(200, 200, 220, .8);--xy-controls-button-background-color-default: #2b2b2b;--xy-controls-button-background-color-hover-default: #3e3e3e;--xy-controls-button-color-default: #f8f8f8;--xy-controls-button-color-hover-default: #fff;--xy-controls-button-border-color-default: #5b5b5b;--xy-controls-box-shadow-default: 0 0 2px 1px rgba(0, 0, 0, .08);--xy-edge-label-background-color-default: #141414;--xy-edge-label-color-default: #f8f8f8}.react-flow__background{background-color:var(--xy-background-color-props, var(--xy-background-color, var(--xy-background-color-default)));pointer-events:none;z-index:-1}.react-flow__container{position:absolute;width:100%;height:100%;top:0;left:0}.react-flow__pane{z-index:1;touch-action:none}.react-flow__pane.draggable{cursor:grab}.react-flow__pane.dragging{cursor:grabbing}.react-flow__pane.selection{cursor:pointer}.react-flow__viewport{transform-origin:0 0;z-index:2;pointer-events:none}.react-flow__renderer{z-index:4}.react-flow__selection{z-index:6}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible{outline:none}.react-flow__edge-path{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default));stroke-width:var(--xy-edge-stroke-width, var(--xy-edge-stroke-width-default));fill:none}.react-flow__connection-path{stroke:var(--xy-connectionline-stroke, var(--xy-connectionline-stroke-default));stroke-width:var(--xy-connectionline-stroke-width, var(--xy-connectionline-stroke-width-default));fill:none}.react-flow .react-flow__edges{position:absolute}.react-flow .react-flow__edges svg{overflow:visible;position:absolute;pointer-events:none}.react-flow__edge{pointer-events:visibleStroke}.react-flow__edge.selectable{cursor:pointer}.react-flow__edge.animated path{stroke-dasharray:5;animation:dashdraw .5s linear infinite}.react-flow__edge.animated path.react-flow__edge-interaction{stroke-dasharray:none;animation:none}.react-flow__edge.inactive{pointer-events:none}.react-flow__edge.selected,.react-flow__edge:focus,.react-flow__edge:focus-visible{outline:none}.react-flow__edge.selected .react-flow__edge-path,.react-flow__edge.selectable:focus .react-flow__edge-path,.react-flow__edge.selectable:focus-visible .react-flow__edge-path{stroke:var(--xy-edge-stroke-selected, var(--xy-edge-stroke-selected-default))}.react-flow__edge-textwrapper{pointer-events:all}.react-flow__edge .react-flow__edge-text{pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__arrowhead polyline{stroke:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__arrowhead polyline.arrowclosed{fill:var(--xy-edge-stroke, var(--xy-edge-stroke-default))}.react-flow__connection{pointer-events:none}.react-flow__connection .animated{stroke-dasharray:5;animation:dashdraw .5s linear infinite}svg.react-flow__connectionline{z-index:1001;overflow:visible;position:absolute}.react-flow__nodes{pointer-events:none;transform-origin:0 0}.react-flow__node{position:absolute;-webkit-user-select:none;-moz-user-select:none;user-select:none;pointer-events:all;transform-origin:0 0;box-sizing:border-box;cursor:default}.react-flow__node.selectable{cursor:pointer}.react-flow__node.draggable{cursor:grab;pointer-events:all}.react-flow__node.draggable.dragging{cursor:grabbing}.react-flow__nodesselection{z-index:3;transform-origin:left top;pointer-events:none}.react-flow__nodesselection-rect{position:absolute;pointer-events:all;cursor:grab}.react-flow__handle{position:absolute;pointer-events:none;min-width:5px;min-height:5px;width:6px;height:6px;background-color:var(--xy-handle-background-color, var(--xy-handle-background-color-default));border:1px solid var(--xy-handle-border-color, var(--xy-handle-border-color-default));border-radius:100%}.react-flow__handle.connectingfrom{pointer-events:all}.react-flow__handle.connectionindicator{pointer-events:all;cursor:crosshair}.react-flow__handle-bottom{top:auto;left:50%;bottom:0;transform:translate(-50%,50%)}.react-flow__handle-top{top:0;left:50%;transform:translate(-50%,-50%)}.react-flow__handle-left{top:50%;left:0;transform:translate(-50%,-50%)}.react-flow__handle-right{top:50%;right:0;transform:translate(50%,-50%)}.react-flow__edgeupdater{cursor:move;pointer-events:all}.react-flow__pane.selection .react-flow__panel{pointer-events:none}.react-flow__panel{position:absolute;z-index:5;margin:15px}.react-flow__panel.top{top:0}.react-flow__panel.bottom{bottom:0}.react-flow__panel.top.center,.react-flow__panel.bottom.center{left:50%;transform:translate(-15px) translate(-50%)}.react-flow__panel.left{left:0}.react-flow__panel.right{right:0}.react-flow__panel.left.center,.react-flow__panel.right.center{top:50%;transform:translateY(-15px) translateY(-50%)}.react-flow__attribution{font-size:10px;background:var(--xy-attribution-background-color, var(--xy-attribution-background-color-default));padding:2px 3px;margin:0}.react-flow__attribution a{text-decoration:none;color:#999}@keyframes dashdraw{0%{stroke-dashoffset:10}}.react-flow__edgelabel-renderer{position:absolute;width:100%;height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;user-select:none;left:0;top:0}.react-flow__viewport-portal{position:absolute;width:100%;height:100%;left:0;top:0;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__minimap{background:var( --xy-minimap-background-color-props, var(--xy-minimap-background-color, var(--xy-minimap-background-color-default)) )}.react-flow__minimap-svg{display:block}.react-flow__minimap-mask{fill:var( --xy-minimap-mask-background-color-props, var(--xy-minimap-mask-background-color, var(--xy-minimap-mask-background-color-default)) );stroke:var( --xy-minimap-mask-stroke-color-props, var(--xy-minimap-mask-stroke-color, var(--xy-minimap-mask-stroke-color-default)) );stroke-width:var( --xy-minimap-mask-stroke-width-props, var(--xy-minimap-mask-stroke-width, var(--xy-minimap-mask-stroke-width-default)) )}.react-flow__minimap-node{fill:var( --xy-minimap-node-background-color-props, var(--xy-minimap-node-background-color, var(--xy-minimap-node-background-color-default)) );stroke:var( --xy-minimap-node-stroke-color-props, var(--xy-minimap-node-stroke-color, var(--xy-minimap-node-stroke-color-default)) );stroke-width:var( --xy-minimap-node-stroke-width-props, var(--xy-minimap-node-stroke-width, var(--xy-minimap-node-stroke-width-default)) )}.react-flow__background-pattern.dots{fill:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-dots-color-default)) )}.react-flow__background-pattern.lines{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-lines-color-default)) )}.react-flow__background-pattern.cross{stroke:var( --xy-background-pattern-color-props, var(--xy-background-pattern-color, var(--xy-background-pattern-cross-color-default)) )}.react-flow__controls{display:flex;flex-direction:column;box-shadow:var(--xy-controls-box-shadow, var(--xy-controls-box-shadow-default))}.react-flow__controls.horizontal{flex-direction:row}.react-flow__controls-button{display:flex;justify-content:center;align-items:center;height:26px;width:26px;padding:4px;border:none;background:var(--xy-controls-button-background-color, var(--xy-controls-button-background-color-default));border-bottom:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) );color:var( --xy-controls-button-color-props, var(--xy-controls-button-color, var(--xy-controls-button-color-default)) );cursor:pointer;-webkit-user-select:none;-moz-user-select:none;user-select:none}.react-flow__controls-button svg{width:100%;max-width:12px;max-height:12px;fill:currentColor}.react-flow__edge.updating .react-flow__edge-path{stroke:#777}.react-flow__edge-text{font-size:10px}.react-flow__node.selectable:focus,.react-flow__node.selectable:focus-visible{outline:none}.react-flow__node-input,.react-flow__node-default,.react-flow__node-output,.react-flow__node-group{padding:10px;border-radius:var(--xy-node-border-radius, var(--xy-node-border-radius-default));width:150px;font-size:12px;color:var(--xy-node-color, var(--xy-node-color-default));text-align:center;border:var(--xy-node-border, var(--xy-node-border-default));background-color:var(--xy-node-background-color, var(--xy-node-background-color-default))}.react-flow__node-input.selectable:hover,.react-flow__node-default.selectable:hover,.react-flow__node-output.selectable:hover,.react-flow__node-group.selectable:hover{box-shadow:var(--xy-node-boxshadow-hover, var(--xy-node-boxshadow-hover-default))}.react-flow__node-input.selectable.selected,.react-flow__node-input.selectable:focus,.react-flow__node-input.selectable:focus-visible,.react-flow__node-default.selectable.selected,.react-flow__node-default.selectable:focus,.react-flow__node-default.selectable:focus-visible,.react-flow__node-output.selectable.selected,.react-flow__node-output.selectable:focus,.react-flow__node-output.selectable:focus-visible,.react-flow__node-group.selectable.selected,.react-flow__node-group.selectable:focus,.react-flow__node-group.selectable:focus-visible{box-shadow:var(--xy-node-boxshadow-selected, var(--xy-node-boxshadow-selected-default))}.react-flow__node-group{background-color:var(--xy-node-group-background-color, var(--xy-node-group-background-color-default))}.react-flow__nodesselection-rect,.react-flow__selection{background:var(--xy-selection-background-color, var(--xy-selection-background-color-default));border:var(--xy-selection-border, var(--xy-selection-border-default))}.react-flow__nodesselection-rect:focus,.react-flow__nodesselection-rect:focus-visible,.react-flow__selection:focus,.react-flow__selection:focus-visible{outline:none}.react-flow__controls-button:hover{background:var( --xy-controls-button-background-color-hover-props, var(--xy-controls-button-background-color-hover, var(--xy-controls-button-background-color-hover-default)) );color:var( --xy-controls-button-color-hover-props, var(--xy-controls-button-color-hover, var(--xy-controls-button-color-hover-default)) )}.react-flow__controls-button:disabled{pointer-events:none}.react-flow__controls-button:disabled svg{fill-opacity:.4}.react-flow__controls-button:last-child{border-bottom:none}.react-flow__controls.horizontal .react-flow__controls-button{border-bottom:none;border-right:1px solid var( --xy-controls-button-border-color-props, var(--xy-controls-button-border-color, var(--xy-controls-button-border-color-default)) )}.react-flow__controls.horizontal .react-flow__controls-button:last-child{border-right:none}.react-flow__resize-control{position:absolute}.react-flow__resize-control.left,.react-flow__resize-control.right{cursor:ew-resize}.react-flow__resize-control.top,.react-flow__resize-control.bottom{cursor:ns-resize}.react-flow__resize-control.top.left,.react-flow__resize-control.bottom.right{cursor:nwse-resize}.react-flow__resize-control.bottom.left,.react-flow__resize-control.top.right{cursor:nesw-resize}.react-flow__resize-control.handle{width:5px;height:5px;border:1px solid #fff;border-radius:1px;background-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));translate:-50% -50%}.react-flow__resize-control.handle.left{left:0;top:50%}.react-flow__resize-control.handle.right{left:100%;top:50%}.react-flow__resize-control.handle.top{left:50%;top:0}.react-flow__resize-control.handle.bottom{left:50%;top:100%}.react-flow__resize-control.handle.top.left,.react-flow__resize-control.handle.bottom.left{left:0}.react-flow__resize-control.handle.top.right,.react-flow__resize-control.handle.bottom.right{left:100%}.react-flow__resize-control.line{border-color:var(--xy-resize-background-color, var(--xy-resize-background-color-default));border-width:0;border-style:solid}.react-flow__resize-control.line.left,.react-flow__resize-control.line.right{width:1px;transform:translate(-50%);top:0;height:100%}.react-flow__resize-control.line.left{left:0;border-left-width:1px}.react-flow__resize-control.line.right{left:100%;border-right-width:1px}.react-flow__resize-control.line.top,.react-flow__resize-control.line.bottom{height:1px;transform:translateY(-50%);left:0;width:100%}.react-flow__resize-control.line.top{top:0;border-top-width:1px}.react-flow__resize-control.line.bottom{border-bottom-width:1px;top:100%}.react-flow__edge-textbg{fill:var(--xy-edge-label-background-color, var(--xy-edge-label-background-color-default))}.react-flow__edge-text{fill:var(--xy-edge-label-color, var(--xy-edge-label-color-default))}:root,[data-theme=obsidian]{--bg: #070b10;--bg-2: #0d141c;--surface: #121a24;--line: #1e2c3c;--ink: #e7eef6;--muted: #8b9bb0;--high: #2a9d8f;--medium: #e9c46a;--low: #e76f51;--critical: #e85d04;--accent: #4cc9f0;--rail-from: #0b1219;--rail-to: #070b10;--rail-active: #15202c;--btn: #173044;--btn-line: #24506c;--btn-primary: #134e4a;--btn-primary-line: #2a9d8f;--node-bg: #101822;--node-line: #2a3d52;--graph-bg: #070b10;--graph-grid: rgba(42, 80, 120, .09);--edge-cheap: #4a5568;--edge-expensive: #f4a261;--edge-critical: #e85d04;--shadow: rgba(76, 201, 240, .08)}[data-theme=nord]{--bg: #2e3440;--bg-2: #3b4252;--surface: #434c5e;--line: #4c566a;--ink: #eceff4;--muted: #d8dee9;--high: #a3be8c;--medium: #ebcb8b;--low: #bf616a;--critical: #d08770;--accent: #88c0d0;--rail-from: #3b4252;--rail-to: #2e3440;--rail-active: #4c566a;--btn: #434c5e;--btn-line: #81a1c1;--btn-primary: #5e81ac;--btn-primary-line: #88c0d0;--node-bg: #3b4252;--node-line: #81a1c1;--graph-bg: #2e3440;--graph-grid: rgba(136, 192, 208, .12);--edge-cheap: #4c566a;--edge-expensive: #d08770;--edge-critical: #bf616a;--shadow: rgba(136, 192, 208, .12)}[data-theme=solarized-dark]{--bg: #002b36;--bg-2: #073642;--surface: #0a3944;--line: #16444f;--ink: #eee8d5;--muted: #93a1a1;--high: #859900;--medium: #b58900;--low: #dc322f;--critical: #cb4b16;--accent: #2aa198;--rail-from: #073642;--rail-to: #002b36;--rail-active: #16444f;--btn: #073642;--btn-line: #268bd2;--btn-primary: #0a4a42;--btn-primary-line: #2aa198;--node-bg: #073642;--node-line: #268bd2;--graph-bg: #002b36;--graph-grid: rgba(42, 161, 152, .12);--edge-cheap: #586e75;--edge-expensive: #cb4b16;--edge-critical: #dc322f;--shadow: rgba(42, 161, 152, .12)}[data-theme=forest]{--bg: #0e1510;--bg-2: #152019;--surface: #1b2a20;--line: #2c4334;--ink: #e4f0e6;--muted: #8eaa96;--high: #6ab04c;--medium: #c8a951;--low: #e17055;--critical: #d35400;--accent: #7bed9f;--rail-from: #152019;--rail-to: #0e1510;--rail-active: #1f3326;--btn: #1f3326;--btn-line: #3d6b4f;--btn-primary: #1e4d32;--btn-primary-line: #6ab04c;--node-bg: #16241b;--node-line: #3d6b4f;--graph-bg: #0e1510;--graph-grid: rgba(123, 237, 159, .1);--edge-cheap: #3d6b4f;--edge-expensive: #c8a951;--edge-critical: #d35400;--shadow: rgba(123, 237, 159, .1)}[data-theme=rose]{--bg: #191724;--bg-2: #1f1d2e;--surface: #26233a;--line: #403d52;--ink: #e0def4;--muted: #908caa;--high: #9ccfd8;--medium: #f6c177;--low: #eb6f92;--critical: #eb6f92;--accent: #c4a7e7;--rail-from: #1f1d2e;--rail-to: #191724;--rail-active: #26233a;--btn: #26233a;--btn-line: #c4a7e7;--btn-primary: #3a2f4d;--btn-primary-line: #c4a7e7;--node-bg: #1f1d2e;--node-line: #524f67;--graph-bg: #191724;--graph-grid: rgba(196, 167, 231, .12);--edge-cheap: #524f67;--edge-expensive: #f6c177;--edge-critical: #eb6f92;--shadow: rgba(196, 167, 231, .12)}[data-theme=amber]{--bg: #120e0a;--bg-2: #1c1610;--surface: #261e16;--line: #3d2f22;--ink: #f4e6d0;--muted: #b59a78;--high: #c4d6a0;--medium: #e9b44c;--low: #d8572a;--critical: #c0392b;--accent: #f0a05a;--rail-from: #1c1610;--rail-to: #120e0a;--rail-active: #2b2218;--btn: #2b2218;--btn-line: #8a5a2b;--btn-primary: #4a3418;--btn-primary-line: #f0a05a;--node-bg: #1c1610;--node-line: #8a5a2b;--graph-bg: #120e0a;--graph-grid: rgba(240, 160, 90, .12);--edge-cheap: #5c4a38;--edge-expensive: #e9b44c;--edge-critical: #d8572a;--shadow: rgba(240, 160, 90, .12)}[data-theme=volcano]{--bg: #14090a;--bg-2: #1e0e10;--surface: #2a1416;--line: #4a2226;--ink: #fde8e4;--muted: #c48b86;--high: #7bed9f;--medium: #f6c90e;--low: #ff6b6b;--critical: #ff3b3b;--accent: #ff7b54;--rail-from: #1e0e10;--rail-to: #14090a;--rail-active: #32181b;--btn: #32181b;--btn-line: #ff7b54;--btn-primary: #5a1f18;--btn-primary-line: #ff7b54;--node-bg: #1e0e10;--node-line: #7a3330;--graph-bg: #14090a;--graph-grid: rgba(255, 123, 84, .12);--edge-cheap: #5a3330;--edge-expensive: #ff7b54;--edge-critical: #ff3b3b;--shadow: rgba(255, 123, 84, .14)}[data-theme=lavender]{--bg: #12101c;--bg-2: #1a1730;--surface: #221e3c;--line: #3b3560;--ink: #efeaff;--muted: #b3a7d6;--high: #80ffdb;--medium: #ffd166;--low: #ff6b9d;--critical: #ff4d6d;--accent: #c77dff;--rail-from: #1a1730;--rail-to: #12101c;--rail-active: #2a2550;--btn: #2a2550;--btn-line: #c77dff;--btn-primary: #3d2a66;--btn-primary-line: #c77dff;--node-bg: #1a1730;--node-line: #5a4d8a;--graph-bg: #12101c;--graph-grid: rgba(199, 125, 255, .12);--edge-cheap: #5a4d8a;--edge-expensive: #ffd166;--edge-critical: #ff4d6d;--shadow: rgba(199, 125, 255, .14)}[data-theme=neon-noir]{--bg: #05060a;--bg-2: #0a0c14;--surface: #10131c;--line: #1e2436;--ink: #f0f4ff;--muted: #8b93b0;--high: #39ff88;--medium: #ffe66d;--low: #ff2d95;--critical: #ff3d5a;--accent: #00f0ff;--rail-from: #0a0c14;--rail-to: #05060a;--rail-active: #151a2a;--btn: #151a2a;--btn-line: #00f0ff;--btn-primary: #063a40;--btn-primary-line: #00f0ff;--node-bg: #0a0c14;--node-line: #2a3550;--graph-bg: #05060a;--graph-grid: rgba(0, 240, 255, .12);--edge-cheap: #3a4560;--edge-expensive: #ff2d95;--edge-critical: #ff3d5a;--shadow: rgba(0, 240, 255, .22)}[data-theme=synthwave]{--bg: #1a0a2e;--bg-2: #240b3d;--surface: #2d1250;--line: #4a1d7a;--ink: #ffe6fb;--muted: #c49ad8;--high: #00f5d4;--medium: #ffd60a;--low: #ff6b9d;--critical: #ff006e;--accent: #ff2bd6;--rail-from: #240b3d;--rail-to: #1a0a2e;--rail-active: #3a1570;--btn: #3a1570;--btn-line: #ff2bd6;--btn-primary: #5a0a4a;--btn-primary-line: #ff2bd6;--node-bg: #240b3d;--node-line: #7b2cbf;--graph-bg: #1a0a2e;--graph-grid: rgba(255, 43, 214, .16);--edge-cheap: #5a3a80;--edge-expensive: #ff9e00;--edge-critical: #ff006e;--shadow: rgba(255, 43, 214, .24)}[data-theme=phosphor]{--bg: #020804;--bg-2: #061208;--surface: #0a1a0e;--line: #163c1e;--ink: #c8ffc8;--muted: #5aaa5a;--high: #39ff14;--medium: #c8f542;--low: #ffb000;--critical: #ff5e00;--accent: #00ff66;--rail-from: #061208;--rail-to: #020804;--rail-active: #0e2414;--btn: #0e2414;--btn-line: #00ff66;--btn-primary: #0a3a18;--btn-primary-line: #00ff66;--node-bg: #061208;--node-line: #1e6a32;--graph-bg: #020804;--graph-grid: rgba(0, 255, 102, .12);--edge-cheap: #1e5a2a;--edge-expensive: #c8f542;--edge-critical: #ff5e00;--shadow: rgba(0, 255, 102, .2)}[data-theme=aurora]{--bg: #071018;--bg-2: #0c1c28;--surface: #122636;--line: #1e3d52;--ink: #e8fff6;--muted: #7eb8a8;--high: #5fffcf;--medium: #ffe566;--low: #ff7eb6;--critical: #ff4d6d;--accent: #7cffb2;--rail-from: #0c1c28;--rail-to: #071018;--rail-active: #163044;--btn: #163044;--btn-line: #7cffb2;--btn-primary: #0e3d3a;--btn-primary-line: #7cffb2;--node-bg: #0c1c28;--node-line: #2a6a78;--graph-bg: #071018;--graph-grid: rgba(124, 255, 178, .12);--edge-cheap: #2a5a68;--edge-expensive: #c9a0ff;--edge-critical: #ff4d6d;--shadow: rgba(124, 255, 178, .18)}[data-theme=biolume]{--bg: #02141c;--bg-2: #042430;--surface: #073040;--line: #0a4a5c;--ink: #e6fffb;--muted: #6eb8b0;--high: #5dffb0;--medium: #ffe066;--low: #ff79c6;--critical: #ff4d6d;--accent: #18e7d4;--rail-from: #042430;--rail-to: #02141c;--rail-active: #0a3848;--btn: #0a3848;--btn-line: #18e7d4;--btn-primary: #0a4a48;--btn-primary-line: #18e7d4;--node-bg: #042430;--node-line: #1a7080;--graph-bg: #02141c;--graph-grid: rgba(24, 231, 212, .12);--edge-cheap: #1a5a68;--edge-expensive: #ff79c6;--edge-critical: #ff4d6d;--shadow: rgba(24, 231, 212, .2)}[data-theme=carbon]{--bg: #0d0d0f;--bg-2: #16161a;--surface: #1e1e24;--line: #33333c;--ink: #f2f2f4;--muted: #9a9aa8;--high: #3dd68c;--medium: #f0c040;--low: #ff5a5a;--critical: #ff2a2a;--accent: #ff2a2a;--rail-from: #16161a;--rail-to: #0d0d0f;--rail-active: #24242c;--btn: #24242c;--btn-line: #ff2a2a;--btn-primary: #4a1212;--btn-primary-line: #ff2a2a;--node-bg: #16161a;--node-line: #4a4a55;--graph-bg: #0d0d0f;--graph-grid: rgba(255, 42, 42, .1);--edge-cheap: #4a4a55;--edge-expensive: #ff8a3d;--edge-critical: #ff2a2a;--shadow: rgba(255, 42, 42, .18)}[data-theme=paper]{--bg: #f6f1e8;--bg-2: #efe6d6;--surface: #fffaf2;--line: #d9cbb6;--ink: #2b241c;--muted: #6f6456;--high: #2a7a4b;--medium: #b5811a;--low: #c0392b;--critical: #a93226;--accent: #1d6a7a;--rail-from: #efe6d6;--rail-to: #e7dcc8;--rail-active: #e2d3bb;--btn: #fffaf2;--btn-line: #c9b79a;--btn-primary: #d7eee0;--btn-primary-line: #2a7a4b;--node-bg: #fffaf2;--node-line: #c9b79a;--graph-bg: #f6f1e8;--graph-grid: rgba(29, 106, 122, .1);--edge-cheap: #b7a48c;--edge-expensive: #c0392b;--edge-critical: #a93226;--shadow: rgba(43, 36, 28, .08)}[data-theme=solarized-light]{--bg: #fdf6e3;--bg-2: #eee8d5;--surface: #f5efdc;--line: #d6cba9;--ink: #657b83;--muted: #93a1a1;--high: #859900;--medium: #b58900;--low: #dc322f;--critical: #cb4b16;--accent: #268bd2;--rail-from: #eee8d5;--rail-to: #e6dfc8;--rail-active: #e0d9c0;--btn: #fdf6e3;--btn-line: #93a1a1;--btn-primary: #e8efc8;--btn-primary-line: #859900;--node-bg: #fdf6e3;--node-line: #93a1a1;--graph-bg: #fdf6e3;--graph-grid: rgba(38, 139, 210, .12);--edge-cheap: #93a1a1;--edge-expensive: #cb4b16;--edge-critical: #dc322f;--shadow: rgba(101, 123, 131, .1)}[data-theme=seafoam]{--bg: #eef7f4;--bg-2: #dff0ea;--surface: #ffffff;--line: #b7d5cc;--ink: #17332c;--muted: #4d7268;--high: #1b8a5a;--medium: #c48a14;--low: #c44536;--critical: #9b2d22;--accent: #1d9a8a;--rail-from: #dff0ea;--rail-to: #cfe6de;--rail-active: #c4ddd4;--btn: #ffffff;--btn-line: #8fbfb2;--btn-primary: #d4f0e4;--btn-primary-line: #1b8a5a;--node-bg: #ffffff;--node-line: #8fbfb2;--graph-bg: #eef7f4;--graph-grid: rgba(29, 154, 138, .12);--edge-cheap: #8fbfb2;--edge-expensive: #c48a14;--edge-critical: #c44536;--shadow: rgba(23, 51, 44, .08)}[data-theme=high-contrast]{--bg: #ffffff;--bg-2: #f2f2f2;--surface: #ffffff;--line: #111111;--ink: #000000;--muted: #222222;--high: #007a33;--medium: #8a5a00;--low: #b00000;--critical: #9b0000;--accent: #0033cc;--rail-from: #f2f2f2;--rail-to: #e6e6e6;--rail-active: #d9d9d9;--btn: #ffffff;--btn-line: #000000;--btn-primary: #d9f2e3;--btn-primary-line: #007a33;--node-bg: #ffffff;--node-line: #000000;--graph-bg: #ffffff;--graph-grid: rgba(0, 0, 0, .12);--edge-cheap: #444444;--edge-expensive: #8a5a00;--edge-critical: #b00000;--shadow: rgba(0, 0, 0, .12)}[data-theme=sakura]{--bg: #fff0f5;--bg-2: #ffe4ee;--surface: #fff7fa;--line: #f5b8cc;--ink: #4a1830;--muted: #a05a78;--high: #1a8a5c;--medium: #c48a14;--low: #d63d6e;--critical: #b01040;--accent: #e84a8a;--rail-from: #ffe4ee;--rail-to: #f8d4e0;--rail-active: #f5c8d8;--btn: #fff7fa;--btn-line: #e89ab0;--btn-primary: #ffd6e6;--btn-primary-line: #e84a8a;--node-bg: #fff7fa;--node-line: #e89ab0;--graph-bg: #fff0f5;--graph-grid: rgba(232, 74, 138, .12);--edge-cheap: #d4a0b0;--edge-expensive: #d63d6e;--edge-critical: #b01040;--shadow: rgba(74, 24, 48, .1)}[data-theme=citrus]{--bg: #fffce8;--bg-2: #fff3b0;--surface: #fffef5;--line: #e8d44a;--ink: #2a2a08;--muted: #6a6a20;--high: #2a8a20;--medium: #d4a000;--low: #e85d04;--critical: #c0392b;--accent: #5aad14;--rail-from: #fff3b0;--rail-to: #ffe98a;--rail-active: #ffe066;--btn: #fffef5;--btn-line: #d4c030;--btn-primary: #e8f5b8;--btn-primary-line: #5aad14;--node-bg: #fffef5;--node-line: #d4c030;--graph-bg: #fffce8;--graph-grid: rgba(90, 173, 20, .14);--edge-cheap: #c4b040;--edge-expensive: #e85d04;--edge-critical: #c0392b;--shadow: rgba(42, 42, 8, .1)}[data-theme=peach]{--bg: #fff3eb;--bg-2: #ffe0cc;--surface: #fffaf6;--line: #f0c4a8;--ink: #3a2218;--muted: #8a5a48;--high: #2a8a5c;--medium: #d48a14;--low: #e85d3a;--critical: #c0392b;--accent: #ff6b35;--rail-from: #ffe0cc;--rail-to: #ffd4b8;--rail-active: #ffc8a8;--btn: #fffaf6;--btn-line: #e8a888;--btn-primary: #ffe0cc;--btn-primary-line: #ff6b35;--node-bg: #fffaf6;--node-line: #e8a888;--graph-bg: #fff3eb;--graph-grid: rgba(255, 107, 53, .12);--edge-cheap: #d4a088;--edge-expensive: #e85d3a;--edge-critical: #c0392b;--shadow: rgba(58, 34, 24, .1)}[data-theme=candy]{--bg: #f4f0ff;--bg-2: #e8dcff;--surface: #fbf8ff;--line: #d4c0f0;--ink: #2a1848;--muted: #6a5890;--high: #1a8a6a;--medium: #c48a14;--low: #e84a8a;--critical: #c01060;--accent: #ff5eb1;--rail-from: #e8dcff;--rail-to: #ddd0ff;--rail-active: #d4c4ff;--btn: #fbf8ff;--btn-line: #c4a8e8;--btn-primary: #ffd6ec;--btn-primary-line: #ff5eb1;--node-bg: #fbf8ff;--node-line: #c4a8e8;--graph-bg: #f4f0ff;--graph-grid: rgba(255, 94, 177, .14);--edge-cheap: #b0a0d0;--edge-expensive: #e84a8a;--edge-critical: #c01060;--shadow: rgba(42, 24, 72, .1)}[data-theme=sky]{--bg: #e8f4ff;--bg-2: #cfe8ff;--surface: #f5faff;--line: #90c8f0;--ink: #0a2848;--muted: #3a6080;--high: #0a8a4a;--medium: #c48a14;--low: #e85d3a;--critical: #c0392b;--accent: #0077ff;--rail-from: #cfe8ff;--rail-to: #b8dcff;--rail-active: #a8d4ff;--btn: #f5faff;--btn-line: #70b0e0;--btn-primary: #cfe8ff;--btn-primary-line: #0077ff;--node-bg: #f5faff;--node-line: #70b0e0;--graph-bg: #e8f4ff;--graph-grid: rgba(0, 119, 255, .12);--edge-cheap: #80b0d0;--edge-expensive: #e85d3a;--edge-critical: #c0392b;--shadow: rgba(10, 40, 72, .1)}[data-theme=coral]{--bg: #fff1ee;--bg-2: #ffddd6;--surface: #fff8f6;--line: #f0b0a4;--ink: #3a1814;--muted: #8a5048;--high: #0d9488;--medium: #d48a14;--low: #e85d4a;--critical: #c0392b;--accent: #0d9488;--rail-from: #ffddd6;--rail-to: #ffd0c6;--rail-active: #ffc4b8;--btn: #fff8f6;--btn-line: #e89888;--btn-primary: #d4f4ee;--btn-primary-line: #0d9488;--node-bg: #fff8f6;--node-line: #e89888;--graph-bg: #fff1ee;--graph-grid: rgba(13, 148, 136, .14);--edge-cheap: #d4a098;--edge-expensive: #e85d4a;--edge-critical: #c0392b;--shadow: rgba(58, 24, 20, .1)}*{box-sizing:border-box}html,body,#root{height:100%;margin:0}:root{--radius: 6px;--radius-lg: 10px;--control-h: 32px;--font: "IBM Plex Sans", ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;--mono: "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;--focus-ring: 0 0 0 2px var(--bg), 0 0 0 4px var(--accent);--space: 8px}body{background:var(--bg);color:var(--ink);font-family:var(--font);font-size:13px;line-height:1.45;-webkit-font-smoothing:antialiased}button,input,select,textarea{font-family:inherit;font-size:inherit;color:inherit}button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible,a:focus-visible,summary:focus-visible{outline:none;box-shadow:var(--focus-ring)}.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;border:0}.skip{position:absolute;left:12px;top:-40px;z-index:50;background:var(--surface);color:var(--ink);border:1px solid var(--accent);border-radius:var(--radius);padding:8px 12px}.skip:focus{top:12px}.app{display:grid;grid-template-columns:232px 1fr;height:100%}.rail{border-right:1px solid var(--line);background:linear-gradient(180deg,var(--rail-from),var(--rail-to));padding:16px 12px;display:flex;flex-direction:column;gap:2px;min-width:0}.brand{display:flex;flex-direction:column;gap:2px;padding:4px 8px 16px}.brand-mark{font-family:var(--mono);letter-spacing:.16em;font-size:11px;text-transform:uppercase;color:var(--accent);font-weight:600}.brand-sub{font-size:11px;color:var(--muted)}.nav-item{display:flex;align-items:center;gap:10px;background:transparent;border:0;text-align:left;padding:8px 10px;border-radius:var(--radius);color:var(--muted);cursor:pointer;width:100%}.nav-item:hover{background:color-mix(in srgb,var(--rail-active) 70%,transparent);color:var(--ink)}.nav-item.active{background:var(--rail-active);color:var(--ink);font-weight:500}.nav-item svg{flex-shrink:0}.theme-pick{margin-top:14px;display:grid;gap:4px;padding:0 2px}.theme-pick label{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--muted);font-weight:500}.theme-pick select,.field select,.field input,.topbar input,.topbar select,.settings input,.settings select,.explorer-path input{background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);padding:0 10px;height:var(--control-h);width:100%}.rail-foot{margin-top:auto;padding:12px 8px 4px;border-top:1px solid var(--line);display:grid;gap:6px}.kbd-hint{font-size:11px;color:var(--muted)}kbd{font-family:var(--mono);font-size:10px;border:1px solid var(--line);border-radius:4px;padding:0 4px;background:var(--surface)}.main{display:flex;flex-direction:column;min-width:0;min-height:0;position:relative;background:var(--bg)}.progress{position:absolute;top:0;left:0;right:0;height:2px;overflow:hidden;z-index:30;background:color-mix(in srgb,var(--accent) 20%,transparent)}.progress i{display:block;height:100%;width:32%;background:var(--accent);animation:indeterminate 1.1s ease-in-out infinite}.progress.determinate i{width:0;animation:none;transform:none;transition:width .2s ease-out}@keyframes indeterminate{0%{transform:translate(-120%)}to{transform:translate(400%)}}.topbar{display:flex;gap:10px;align-items:flex-end;padding:10px 16px;border-bottom:1px solid var(--line);background:var(--bg-2);flex-wrap:wrap}.field{display:grid;gap:4px;min-width:0}.field>span{font-size:11px;color:var(--muted);font-weight:500}.field.path{flex:1;min-width:180px}.field.ref{width:188px;flex:0 0 188px}.field.workspace{width:180px;flex:0 0 180px}.path-row,.combo-row{display:flex;min-width:0}.path-row input,.combo-row input{flex:1;min-width:0}.combo{position:relative;min-width:0}.combo-row input{border-top-right-radius:0;border-bottom-right-radius:0}.topbar .icon-btn{width:var(--control-h);padding:0;flex:0 0 var(--control-h)}.combo-toggle{border-top-left-radius:0;border-bottom-left-radius:0;border-left:0}.combo-menu{position:absolute;top:calc(100% + 4px);right:0;left:auto;min-width:340px;max-width:min(480px,70vw);max-height:360px;overflow:auto;z-index:40;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius);box-shadow:0 12px 32px var(--shadow);padding:6px 0}.combo-heading{font-size:10px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);font-weight:600;padding:8px 12px 4px}.combo-menu .combo-option{display:flex;flex-direction:column;align-items:flex-start;gap:2px;width:100%;text-align:left;background:transparent;border:0;border-radius:0;height:auto;padding:6px 12px;color:var(--ink);cursor:pointer}.combo-menu .combo-option:hover,.combo-menu .combo-option.active{background:var(--rail-active)}.combo-label{font-family:var(--mono);font-size:12px}.combo-detail{color:var(--muted);font-size:12px;line-height:1.35;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-width:100%}.combo-empty{padding:10px 12px}.modal-backdrop{position:fixed;top:0;right:0;bottom:0;left:0;z-index:50;background:color-mix(in srgb,var(--bg) 72%,transparent);display:grid;place-items:center;padding:24px}.modal{width:min(720px,100%);max-height:min(640px,90vh);background:var(--bg-2);border:1px solid var(--line);border-radius:var(--radius-lg);box-shadow:0 16px 48px var(--shadow);display:flex;flex-direction:column;overflow:hidden}.modal-head{display:flex;align-items:flex-start;justify-content:space-between;gap:12px;padding:14px 16px 10px;border-bottom:1px solid var(--line)}.modal-head h2{font-size:15px}.modal-head .muted{margin:4px 0 0}.explorer-path{display:flex;gap:8px;padding:12px 16px;border-bottom:1px solid var(--line)}.explorer-path input{flex:1;min-width:0}.explorer-list{flex:1;overflow:auto;padding:8px;min-height:220px}.explorer-row{display:flex;align-items:center;gap:8px;width:100%;text-align:left;background:transparent;border:0;border-radius:var(--radius);padding:8px 10px;color:var(--ink);cursor:pointer;height:auto}.explorer-row:hover,.explorer-row.active{background:var(--rail-active)}.explorer-name{min-width:0;overflow:hidden;text-overflow:ellipsis}.git-badge{margin-left:auto;margin-bottom:0}.explorer-empty{padding:18px 10px}.modal-foot{display:flex;align-items:center;gap:12px;padding:12px 16px;border-top:1px solid var(--line)}.explorer-current{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-family:var(--mono);font-size:12px}.topbar input,.topbar select{min-width:0}.topbar-actions{display:flex;gap:8px;margin-left:auto;align-items:center;padding-bottom:0}.btn,.topbar button{background:var(--btn);border:1px solid var(--btn-line);border-radius:var(--radius);height:var(--control-h);padding:0 12px;cursor:pointer;font-weight:500;display:inline-flex;align-items:center;justify-content:center;gap:6px;white-space:nowrap}.btn:hover,.topbar button:hover{filter:brightness(1.08)}.btn:disabled,.topbar button:disabled{opacity:.55;cursor:not-allowed;filter:none}.btn.primary{background:var(--btn-primary);border-color:var(--btn-primary-line)}.btn.ghost{background:transparent}.alerts{display:grid;gap:8px;padding:10px 16px 0}.alerts:empty{display:none;padding:0}.stage{flex:1;min-height:0;display:flex;flex-direction:column}.content{flex:1;min-height:0;display:grid;grid-template-columns:minmax(340px,420px) 1fr}.brief{overflow:auto;border-right:1px solid var(--line);padding:16px 18px 24px;background:radial-gradient(circle at 0 0,color-mix(in srgb,var(--accent) 8%,transparent),transparent 42%),var(--bg)}.graph-wrap{position:relative;min-height:0;display:flex;flex-direction:column}.impact-graph{flex:1;min-height:0;position:relative;display:flex;flex-direction:column}.graph-toolbar{display:flex;flex-wrap:wrap;gap:8px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--bg-2)}.graph-count{margin-left:auto;font-size:11px}.chip-btn{background:var(--surface);border:1px solid var(--line);border-radius:999px;padding:4px 12px;color:var(--muted);cursor:pointer;height:26px}.chip-btn:hover{color:var(--ink)}.chip-btn.active{background:var(--rail-active);color:var(--ink)}.chip-btn:disabled{opacity:.45;cursor:not-allowed}.graph-stage{flex:1;min-height:0;position:relative;display:flex;flex-direction:column}.graph-stage .react-flow,.graph-3d,.graph-3d-host,.graph-3d-canvas-host{flex:1;width:100%;height:100%;min-height:280px}.graph-3d{position:relative;background:var(--graph-bg);display:flex;flex-direction:column}.graph-3d-host{position:relative;min-height:0;display:flex;flex-direction:column}.graph-3d-canvas-host{position:relative;min-height:0}.graph-3d canvas{display:block;width:100%;height:100%}.graph-3d-tip{position:absolute;pointer-events:none;z-index:2;max-width:320px;padding:6px 8px;border-radius:var(--radius);background:var(--surface);border:1px solid var(--line);color:var(--ink);font-size:11px;line-height:1.35;box-shadow:0 8px 24px var(--shadow)}.graph-3d-tip .t{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.graph-3d-tip .n{font-weight:600}.graph-3d-hint{position:absolute;left:10px;bottom:10px;z-index:2;margin:0;font-size:11px;color:var(--muted);max-width:min(420px,calc(100% - 24px));pointer-events:none}.graph-wrap .react-flow{background-color:var(--graph-bg);background-image:linear-gradient(var(--graph-grid) 1px,transparent 1px),linear-gradient(90deg,var(--graph-grid) 1px,transparent 1px);background-size:24px 24px}.react-flow__minimap{background:var(--graph-bg)!important;border:1px solid var(--line)!important;border-radius:var(--radius);overflow:hidden;box-shadow:0 8px 24px var(--shadow)}.react-flow__minimap-node{fill:var(--muted);stroke:none}.react-flow__minimap-node.selected{fill:var(--accent)}.react-flow__minimap-mask{fill:#00000073!important;stroke:var(--accent)!important}.react-flow__controls{box-shadow:none!important}.react-flow__controls-button{background:var(--surface)!important;border-bottom:1px solid var(--line)!important;fill:var(--ink)!important}h1{font-size:18px;margin:0 0 6px;font-weight:600}h2{font-size:13px;margin:0;font-weight:600}.merge-box{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-lg);padding:12px 14px;margin-bottom:12px}.merge-box.high{border-color:color-mix(in srgb,var(--high) 55%,var(--line))}.merge-box.medium{border-color:color-mix(in srgb,var(--medium) 55%,var(--line))}.merge-box.low{border-color:color-mix(in srgb,var(--low) 55%,var(--line))}.level{font-family:var(--mono);font-weight:600;font-size:14px}.level.high{color:var(--high)}.level.medium{color:var(--medium)}.level.low{color:var(--low)}.merge-title{margin-top:4px;font-size:13px;color:var(--ink)}.reasons{margin:10px 0 0;padding:0 0 0 18px;color:var(--muted)}.reasons li{margin:0 0 4px}.metrics{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;margin:0 0 14px}.metric{border:1px solid var(--line);border-radius:var(--radius);background:var(--surface);padding:8px 10px}.metric .n{font-family:var(--mono);font-size:16px;font-weight:600;font-variant-numeric:tabular-nums}.metric .l{font-size:11px;color:var(--muted);margin-top:2px}.section{border-top:1px solid var(--line);padding:8px 0 4px}.section>summary{cursor:pointer;list-style:none;display:flex;align-items:center;justify-content:space-between;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.07em;font-weight:600;padding:6px 0}.section>summary::-webkit-details-marker{display:none}.section>summary .count{font-family:var(--mono);letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:999px;padding:0 7px;height:18px;display:inline-flex;align-items:center;font-size:11px}.kicker{color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.08em;margin:16px 0 6px;font-weight:600}.chip{display:inline-flex;align-items:center;font-size:11px;padding:2px 8px;border-radius:999px;border:1px solid var(--line);margin:0 6px 6px 0;color:var(--muted);background:var(--surface)}.chip.blocker{color:var(--low);border-color:var(--low)}.chip.warning{color:var(--medium);border-color:var(--medium)}.chip.strong{color:var(--low);border-color:var(--low)}.chip.worth_exploring{color:var(--medium);border-color:var(--medium)}.chip.speculative{color:var(--muted);border-color:var(--line)}.chip.open{color:var(--high);border-color:color-mix(in srgb,var(--high) 50%,var(--line))}.file{font-family:var(--mono);font-size:12px;color:var(--accent)}.read-item,.finding,.residual{padding:8px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 70%,transparent)}.read-item:last-child,.finding:last-child{border-bottom:0}.read-item.tour-current{background:color-mix(in srgb,var(--accent) 12%,var(--surface));border-color:var(--accent)}.tour-row{margin-top:8px;align-items:center}.field.dirty .chip-btn{height:32px}.muted{color:var(--muted);font-size:13px;line-height:1.45}.error{color:var(--low);padding:8px 12px;border:1px solid var(--low);background:color-mix(in srgb,var(--low) 10%,var(--surface));border-radius:var(--radius);display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.banner{padding:8px 12px;border-radius:var(--radius);border:1px solid var(--line);background:var(--surface);font-size:13px;line-height:1.45;display:flex;justify-content:space-between;gap:12px;align-items:flex-start}.banner.warn{border-color:var(--medium);color:var(--medium)}.banner.stale{border-color:var(--low);color:var(--low)}.banner .dismiss{background:transparent;border:0;color:inherit;cursor:pointer;height:auto;padding:0 2px;opacity:.7}.empty{padding:24px 8px;color:var(--muted);font-size:13px;line-height:1.55}.empty h2{font-size:16px;color:var(--ink);margin-bottom:8px}.empty ol{margin:12px 0 0 18px;padding:0}.empty code,code{font-family:var(--mono);font-size:12px;color:var(--accent)}.btn-row{display:flex;flex-wrap:wrap;gap:8px;margin-top:12px}.pr-list{padding:16px;overflow:auto}.pr-toolbar{display:flex;gap:8px;align-items:flex-end;margin-bottom:14px}.pr-toolbar .field{flex:1}.pr-toolbar .field.provider{flex:0 0 140px}.scm-count{margin:0 0 12px;font-size:12px}.scm-login{display:flex;justify-content:space-between;gap:12px;align-items:center;padding:10px 0;border-top:1px solid var(--line)}.scm-login:first-of-type{border-top:0;padding-top:0}.scm-login .btn-row{margin-top:0}.scm-login p{margin:2px 0 0}.oauth-code{font-size:13px;margin:0}.oauth-code code{font-size:14px;letter-spacing:.08em}.pr{border:1px solid var(--line);background:var(--surface);padding:12px 14px;border-radius:var(--radius-lg);margin-bottom:10px}.pr h3{margin:0 0 4px;font-size:14px;font-weight:600}.pr-meta{display:flex;flex-wrap:wrap;gap:8px 12px;align-items:center;margin:6px 0 10px}.pr-actions{display:flex;gap:8px;align-items:center}.settings{padding:24px;max-width:760px;overflow:auto;display:grid;gap:16px}.settings-card{border:1px solid var(--line);background:var(--surface);border-radius:var(--radius-lg);padding:16px;display:grid;gap:8px}.settings-card h2{font-size:14px;margin-bottom:2px}.settings label{font-size:12px;color:var(--muted);font-weight:500}.theme-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(140px,1fr));gap:8px}.theme-swatch{border:1px solid var(--line);background:var(--bg);color:var(--ink);border-radius:var(--radius);padding:10px;text-align:left;cursor:pointer;height:auto;box-shadow:0 1px 8px var(--shadow)}.theme-swatch.active{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent),0 1px 8px var(--shadow)}.theme-swatch .swatch-bar{height:6px;border-radius:3px;margin-bottom:8px;background:linear-gradient(90deg,var(--accent),var(--high),var(--medium),var(--low))}.theme-swatch .name{font-size:13px;font-weight:600}.theme-swatch .group{font-size:11px;color:var(--muted)}.headline{white-space:pre-wrap;font-family:var(--mono);font-size:12px;color:var(--muted);margin:8px 0 0}.graph-modes{display:flex;gap:8px;align-items:center;padding:8px 14px;border-bottom:1px solid var(--line);background:var(--bg-2)}.seg{display:inline-flex;border:1px solid var(--line);border-radius:999px;padding:2px;background:var(--surface)}.seg button,.graph-modes button{background:transparent;border:0;border-radius:999px;padding:4px 12px;color:var(--muted);cursor:pointer;height:26px}.seg button.active,.graph-modes button.active{background:var(--rail-active);color:var(--ink)}.legend{margin-left:auto;display:flex;gap:12px;color:var(--muted);font-size:11px}.legend i{display:inline-block;width:14px;height:2px;margin-right:6px;vertical-align:middle;background:var(--edge-cheap)}.legend i.exp{background:var(--edge-expensive)}.legend i.crit{background:var(--edge-critical);height:3px}.legend i.dash{border-top:2px dashed var(--muted);background:none;height:0}.inspector{position:absolute;top:12px;right:12px;z-index:5;width:300px;max-width:calc(100% - 24px);max-height:calc(100% - 24px);overflow-x:hidden;overflow-y:auto;overflow-wrap:break-word;background:var(--surface);border:1px solid var(--line);border-radius:var(--radius-lg);padding:10px 12px;box-shadow:0 8px 24px var(--shadow);font-size:12px}.inspector .t{font-size:11px;color:var(--muted);text-transform:uppercase;letter-spacing:.06em}.inspector .n,.inspector .file,.inspector .muted{overflow-wrap:break-word}.inspector .n{font-weight:600;margin:4px 0}.inspector-head{display:flex;align-items:flex-start;gap:8px}.inspector-roles{display:flex;flex-wrap:wrap;justify-content:flex-end;flex:1;gap:4px}.inspector-chip{font-size:10px;text-transform:uppercase;letter-spacing:.04em;padding:1px 6px;border-radius:999px;border:1px solid var(--line);color:var(--muted);white-space:nowrap}.inspector-close{flex:0 0 auto;width:24px;height:24px;padding:0;border:1px solid var(--line);border-radius:var(--radius);background:transparent;color:var(--muted);font-size:16px;line-height:1;cursor:pointer}.inspector-close:hover{color:var(--ink)}.inspector-purpose{margin:6px 0 8px;color:var(--ink);font-size:12px;line-height:1.4}.inspector-layer{margin-top:4px;font-size:11px}.inspector-facts{margin:10px 0 0;padding-top:8px;border-top:1px solid var(--line)}.inspector-fact{display:grid;grid-template-columns:minmax(64px,92px) minmax(0,1fr);gap:8px;padding:3px 0;align-items:start}.inspector-fact dt{color:var(--muted);font-size:11px;margin:0}.inspector-fact dd{margin:0;overflow-wrap:break-word}.inspector-section{margin-top:10px;padding-top:8px;border-top:1px solid var(--line)}.inspector-section h3{margin:0 0 6px;display:flex;align-items:center;justify-content:space-between;color:var(--muted);font-size:11px;text-transform:uppercase;letter-spacing:.07em;font-weight:600}.inspector-section .count{font-family:var(--mono);letter-spacing:0;text-transform:none;border:1px solid var(--line);border-radius:999px;padding:0 7px;height:18px;display:inline-flex;align-items:center;font-size:11px}.inspector-section ul{list-style:none;margin:0;padding:0}.inspector-section li{padding:4px 0;border-bottom:1px solid color-mix(in srgb,var(--line) 70%,transparent)}.inspector-section li:last-child{border-bottom:0}.inspector-link-name{display:block;font-weight:600;overflow-wrap:break-word}.inspector-link-meta{display:block;color:var(--muted);font-size:11px}.lp-node{padding:8px 10px;border-radius:var(--radius);border:1px solid var(--node-line);background:var(--node-bg);width:180px;max-width:100%;height:56px;box-sizing:border-box;box-shadow:0 0 0 1px var(--shadow);overflow:visible;position:relative}.lp-node .t{font-size:10px;color:var(--muted);text-transform:uppercase;letter-spacing:.08em}.lp-node .n{font-size:13px;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.lp-node.selected{border-color:var(--accent);box-shadow:0 0 0 1px var(--accent)}.react-flow__node-load .react-flow__handle{width:8px;height:8px;border:none;background:transparent;opacity:0}.type-table{width:100%;border-collapse:collapse;font-size:12px}.type-table td{padding:3px 0}.type-table td:last-child{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;color:var(--muted)}@media(prefers-reduced-motion:reduce){.progress i{animation:none;width:100%}.progress.determinate i{width:var(--progress, 100%)}*{scroll-behavior:auto!important}}@media(max-width:960px){.app{grid-template-columns:56px 1fr}.brand-sub,.nav-item span,.theme-pick,.kbd-hint,.rail-foot .muted{display:none}.nav-item{justify-content:center;padding:10px}.content{grid-template-columns:1fr}.brief{border-right:0;border-bottom:1px solid var(--line);max-height:42vh}} diff --git a/src/loadpath/static/index.html b/src/loadpath/static/index.html index ea5fecf..18dfb64 100644 --- a/src/loadpath/static/index.html +++ b/src/loadpath/static/index.html @@ -17,8 +17,8 @@ - - + +
diff --git a/tests/unit/test_index_progress.py b/tests/unit/test_index_progress.py new file mode 100644 index 0000000..e799d98 --- /dev/null +++ b/tests/unit/test_index_progress.py @@ -0,0 +1,91 @@ +from __future__ import annotations + +from pathlib import Path + +from fastapi.testclient import TestClient + +from loadpath.index import index_repo +from loadpath.server.app import create_app +from tests.conftest import FIXTURE_ROOT as FIXTURE, prepare_review_repo + + +def test_index_emits_granular_progress(tmp_path: Path): + events: list[dict] = [] + store = index_repo( + FIXTURE, + db_path=tmp_path / "g.sqlite3", + incremental=False, + workers=1, + progress=events.append, + ) + phases = [e["phase"] for e in events] + assert phases[0] == "scan" + assert "extract" in phases + assert "stitch" in phases + assert phases[-1] == "done" + extracts = [e for e in events if e["phase"] == "extract" and e.get("current")] + assert extracts, "expected per-file extract events" + last_extract = [e for e in events if e["phase"] == "extract"][-1] + assert last_extract["total"] >= last_extract["done"] > 0 + assert any("/" in (e.get("current") or "") for e in extracts) + assert store.get_meta("index_workers") == "1" + assert int(store.get_meta("index_elapsed_ms") or "0") >= 0 + store.close() + + +def test_parallel_extract_matches_sequential_graph(tmp_path: Path): + one = index_repo(FIXTURE, db_path=tmp_path / "one.sqlite3", incremental=False, workers=1) + two = index_repo(FIXTURE, db_path=tmp_path / "two.sqlite3", incremental=False, workers=2) + assert two.get_meta("index_workers") == "2" + assert {n["id"] for n in one.nodes()} == {n["id"] for n in two.nodes()} + assert {e["id"] for e in one.edges()} == {e["id"] for e in two.edges()} + one.close() + two.close() + + +def test_incremental_skip_emits_skipped_progress(tmp_path: Path): + db = tmp_path / "g.sqlite3" + first = index_repo(FIXTURE, db_path=db, incremental=False, workers=1) + first.close() + events: list[dict] = [] + store = index_repo(FIXTURE, db_path=db, incremental=True, workers=1, progress=events.append) + assert store.get_meta("reindex_skipped") == "1" + assert store.get_meta("files_extracted") == "0" + assert events[-1]["phase"] == "skipped" + store.close() + + +def test_extract_error_becomes_residual(tmp_path: Path, monkeypatch): + from loadpath import index as index_mod + + def boom(rel, source, config): + raise RuntimeError("extractor exploded") + + monkeypatch.setattr(index_mod, "extract_django_file", boom) + root = tmp_path / "repo" + root.mkdir() + (root / "backend").mkdir() + (root / "backend" / "views.py").write_text("def hello():\n return 1\n") + store = index_repo(root, db_path=tmp_path / "g.sqlite3", incremental=False, workers=1) + residuals = store.get_meta("residuals") or "" + assert "Failed to extract" in residuals + assert "extractor exploded" in residuals + store.close() + + +def test_api_index_progress_idle_then_done(tmp_path, monkeypatch): + monkeypatch.setenv("HOME", str(tmp_path / "home")) + (tmp_path / "home").mkdir() + repo = prepare_review_repo(tmp_path) + client = TestClient(create_app()) + idle = client.get("/api/index/progress", params={"repo_path": str(repo)}) + assert idle.status_code == 200 + assert idle.json()["phase"] == "idle" + indexed = client.post("/api/index", json={"repo_path": str(repo), "incremental": False, "jobs": 1}) + assert indexed.status_code == 200, indexed.text + done = client.get("/api/index/progress", params={"repo_path": str(repo)}) + assert done.status_code == 200 + body = done.json() + assert body["phase"] == "done" + assert body["message"] + assert "elapsed_ms" in body diff --git a/ui/src/App.tsx b/ui/src/App.tsx index 6d74b18..d15eb5b 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -6,7 +6,7 @@ import { ImpactGraph } from "./ImpactGraph"; import { RefCombobox } from "./RefCombobox"; import { RepoExplorer } from "./RepoExplorer"; import { THEMES, applyTheme, readTheme, type ThemeId } from "./themes"; -import type { ArchitectureReport, DeepeningCandidate, GitRefs, IndexedRepo, PullRequest, RemoteRepo, Review } from "./types"; +import type { ArchitectureReport, DeepeningCandidate, GitRefs, IndexedRepo, IndexProgress, PullRequest, RemoteRepo, Review } from "./types"; type Tab = "review" | "architecture" | "graph" | "prs" | "settings"; type GraphMode = "review" | "architecture"; @@ -19,6 +19,12 @@ const TABS: { id: Tab; label: string; testId: string; shortcut: string; icon: ty { id: "settings", label: "Settings", testId: "tab-settings", shortcut: "5", icon: IconSettings }, ]; +function progressPercent(p: IndexProgress): number | null { + const total = p.total || 0; + if (total <= 0) return null; + return Math.min(100, Math.round((100 * (p.done || 0)) / total)); +} + function openOAuthUrl(url: string, host: string, pathPrefix: string) { let parsed: URL; try { @@ -44,6 +50,7 @@ export function App() { const [graphMode, setGraphMode] = useState("review"); const [error, setError] = useState(""); const [busy, setBusy] = useState(""); + const [indexPct, setIndexPct] = useState(null); const [copied, setCopied] = useState(""); const [settings, setSettings] = useState>({}); const [prs, setPrs] = useState([]); @@ -82,6 +89,24 @@ export function App() { busyRef.current = msg; setBusy(msg); }; + const watchIndex = (repoPath: string) => { + const tick = () => { + api + .indexProgress(repoPath) + .then((p) => { + if (!busyRef.current) return; + if (p.message) markBusy(p.message); + setIndexPct(progressPercent(p)); + }) + .catch(() => undefined); + }; + tick(); + const id = window.setInterval(tick, 250); + return () => { + window.clearInterval(id); + setIndexPct(null); + }; + }; useEffect(() => { api @@ -320,6 +345,7 @@ export function App() { markBusy("Tracing load path…"); persistRepo(repo); persistRefs(base, head); + const stopWatch = watchIndex(repo); try { const r = await api.review(repo, base, head, true, dirty); setReview(r); @@ -331,6 +357,7 @@ export function App() { } catch (e) { setError(e instanceof Error ? e.message : String(e)); } finally { + stopWatch(); markBusy(""); } }; @@ -342,6 +369,7 @@ export function App() { setCopied(""); markBusy(incremental ? "Indexing…" : "Full reindex…"); persistRepo(repo); + const stopWatch = watchIndex(repo); try { await api.index(repo, incremental); const report = await loadArchitecture(repo); @@ -353,6 +381,7 @@ export function App() { } catch (e) { setError(e instanceof Error ? e.message : String(e)); } finally { + stopWatch(); markBusy(""); } }; @@ -483,6 +512,8 @@ export function App() { if (match?.local_path) persistRepo(match.local_path); setError(""); markBusy(`Fetching ${item.provider} #${item.number}…`); + const watchPath = match?.local_path || repo; + const stopWatch = watchPath ? watchIndex(watchPath) : () => undefined; try { const r = await api.reviewPr(item.provider, item.repo, item.number, match?.local_path || repo || undefined); setReview(r); @@ -496,6 +527,7 @@ export function App() { setTab("review"); setError(e instanceof Error ? e.message : String(e)); } finally { + stopWatch(); markBusy(""); } }; @@ -667,8 +699,14 @@ export function App() {
{busy ? ( -
- +
+ {busy}
) : null} diff --git a/ui/src/api.ts b/ui/src/api.ts index 7677ffe..eb7fd88 100644 --- a/ui/src/api.ts +++ b/ui/src/api.ts @@ -1,4 +1,4 @@ -import type { ArchitectureReport, FsListing, GitRefs, GraphNode, IndexedRepo, PullRequest, RemoteRepo, Review } from "./types"; +import type { ArchitectureReport, FsListing, GitRefs, GraphNode, IndexedRepo, IndexProgress, PullRequest, RemoteRepo, Review } from "./types"; export function formatApiError(text: string, fallback = "Request failed"): string { const trimmed = (text || "").trim(); @@ -70,6 +70,8 @@ export const api = { }), indexStatus: (repo_path: string) => req(`/api/index?repo_path=${encodeURIComponent(repo_path)}`), + indexProgress: (repo_path: string) => + req(`/api/index/progress?repo_path=${encodeURIComponent(repo_path)}`), architecture: (repo_path: string) => req(`/api/architecture?repo_path=${encodeURIComponent(repo_path)}`), review: (repo_path: string, base: string, head?: string, reindex = true, dirty = false) => diff --git a/ui/src/styles.css b/ui/src/styles.css index 95c4779..628c92e 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -874,6 +874,12 @@ kbd { background: var(--accent); animation: indeterminate 1.1s ease-in-out infinite; } +.progress.determinate i { + width: 0; + animation: none; + transform: none; + transition: width 0.2s ease-out; +} @keyframes indeterminate { 0% { transform: translateX(-120%); } 100% { transform: translateX(400%); } @@ -1691,6 +1697,7 @@ h2 { font-size: 13px; margin: 0; font-weight: 600; } } @media (prefers-reduced-motion: reduce) { .progress i { animation: none; width: 100%; } + .progress.determinate i { width: var(--progress, 100%); } * { scroll-behavior: auto !important; } } @media (max-width: 960px) { diff --git a/ui/src/types.ts b/ui/src/types.ts index 54599b4..b075515 100644 --- a/ui/src/types.ts +++ b/ui/src/types.ts @@ -48,6 +48,8 @@ export type Review = { id: string; title: string; headline: string; + base?: string; + head?: string; change_kinds: string[]; confidence: { level: "high" | "medium" | "low"; @@ -113,6 +115,19 @@ export type Review = { }; }; +export type IndexProgress = { + phase: string; + done?: number; + total?: number; + current?: string; + workers?: number; + skipped?: number; + elapsed_ms?: number; + errors?: number; + message?: string; + repo_path?: string; +}; + export type ArchitectureReport = { ok: boolean; indexed: boolean; From e0fcd231452f8e77ecc51b4b2d441c0fff2a5f69 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Sat, 15 Aug 2026 14:28:00 +0000 Subject: [PATCH 4/4] Keep small repos sequential and show live index phases in the UI. Spawn overhead dominates tiny trees, so default extract workers stay at 1 below 80 files (--jobs / LOADPATH_INDEX_JOBS still force a pool). Worker spawn failures fall back to sequential extract instead of writing an empty graph. The UI ignores idle progress polls so the rail shows the current phase, not "No index in progress". Co-authored-by: zord.lack.net --- src/loadpath/index.py | 12 +++-- ...CNVAazxv.js => LayeredGraph3D-bMz3wlDF.js} | 2 +- .../{index-D9L1hiqG.js => index-CT7t7rTi.js} | 12 ++--- src/loadpath/static/index.html | 2 +- tests/e2e/test_ui_flows.py | 45 +++++++++++++++++++ tests/unit/test_index_progress.py | 9 ++++ ui/src/App.tsx | 4 +- 7 files changed, 73 insertions(+), 13 deletions(-) rename src/loadpath/static/assets/{LayeredGraph3D-CNVAazxv.js => LayeredGraph3D-bMz3wlDF.js} (99%) rename src/loadpath/static/assets/{index-D9L1hiqG.js => index-CT7t7rTi.js} (89%) diff --git a/src/loadpath/index.py b/src/loadpath/index.py index 135a6ce..7eaaa9a 100644 --- a/src/loadpath/index.py +++ b/src/loadpath/index.py @@ -138,7 +138,7 @@ def default_workers(n_files: int) -> int: return max(1, int(env)) if getattr(sys, "frozen", False): return 1 - if n_files < 6: + if n_files < 80: return 1 cpu = os.cpu_count() or 2 return max(1, min(8, cpu, n_files)) @@ -350,6 +350,7 @@ def _extract_parallel( graph, err = None, f"{type(exc).__name__}: {exc}" found[rel] = (graph, err) done += 1 + status = "Extracted" if graph is not None else "Failed" _emit( progress, { @@ -359,7 +360,7 @@ def _extract_parallel( "current": rel, "workers": workers, "elapsed_ms": _elapsed_ms(started), - "message": f"Extracted {rel} ({done}/{total})", + "message": f"{status} {rel} ({done}/{total})", }, ) return [(src, found[src.rel][0], found[src.rel][1]) for src in files] @@ -467,7 +468,12 @@ def index_repo( progress=progress, ) used_workers = n_cpu - except (BrokenProcessPool, OSError, PermissionError): + if results and all(graph is None for _, graph, _err in results): + results = _extract_sequential( + to_extract, config, started=started, progress=progress, workers=1 + ) + used_workers = 1 + except (BrokenProcessPool, OSError, PermissionError, RuntimeError): results = _extract_sequential( to_extract, config, started=started, progress=progress, workers=1 ) diff --git a/src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js b/src/loadpath/static/assets/LayeredGraph3D-bMz3wlDF.js similarity index 99% rename from src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js rename to src/loadpath/static/assets/LayeredGraph3D-bMz3wlDF.js index 08abd43..fdb2e5f 100644 --- a/src/loadpath/static/assets/LayeredGraph3D-CNVAazxv.js +++ b/src/loadpath/static/assets/LayeredGraph3D-bMz3wlDF.js @@ -1,4 +1,4 @@ -import{r as bn,l as tc,c as nc,a as ic,L as sc,j as jn,t as rc}from"./index-D9L1hiqG.js";/** +import{r as bn,l as tc,c as nc,a as ic,L as sc,j as jn,t as rc}from"./index-CT7t7rTi.js";/** * @license * Copyright 2010-2026 Three.js Authors * SPDX-License-Identifier: MIT diff --git a/src/loadpath/static/assets/index-D9L1hiqG.js b/src/loadpath/static/assets/index-CT7t7rTi.js similarity index 89% rename from src/loadpath/static/assets/index-D9L1hiqG.js rename to src/loadpath/static/assets/index-CT7t7rTi.js index edd309e..b8c90fc 100644 --- a/src/loadpath/static/assets/index-D9L1hiqG.js +++ b/src/loadpath/static/assets/index-CT7t7rTi.js @@ -1,4 +1,4 @@ -(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))l(a);new MutationObserver(a=>{for(const u of a)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function o(a){const u={};return a.integrity&&(u.integrity=a.integrity),a.referrerPolicy&&(u.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?u.credentials="include":a.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(a){if(a.ep)return;a.ep=!0;const u=o(a);fetch(a.href,u)}})();function xp(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var wu={exports:{}},vo={},_u={exports:{}},Ie={};/** +(function(){const r=document.createElement("link").relList;if(r&&r.supports&&r.supports("modulepreload"))return;for(const a of document.querySelectorAll('link[rel="modulepreload"]'))l(a);new MutationObserver(a=>{for(const u of a)if(u.type==="childList")for(const d of u.addedNodes)d.tagName==="LINK"&&d.rel==="modulepreload"&&l(d)}).observe(document,{childList:!0,subtree:!0});function o(a){const u={};return a.integrity&&(u.integrity=a.integrity),a.referrerPolicy&&(u.referrerPolicy=a.referrerPolicy),a.crossOrigin==="use-credentials"?u.credentials="include":a.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(a){if(a.ep)return;a.ep=!0;const u=o(a);fetch(a.href,u)}})();function xp(t){return t&&t.__esModule&&Object.prototype.hasOwnProperty.call(t,"default")?t.default:t}var wu={exports:{}},vo={},_u={exports:{}},Te={};/** * @license React * react.production.min.js * @@ -6,7 +6,7 @@ * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. - */var Bf;function Qy(){if(Bf)return Ie;Bf=1;var t=Symbol.for("react.element"),r=Symbol.for("react.portal"),o=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),a=Symbol.for("react.profiler"),u=Symbol.for("react.provider"),d=Symbol.for("react.context"),f=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),y=Symbol.for("react.memo"),m=Symbol.for("react.lazy"),x=Symbol.iterator;function v(M){return M===null||typeof M!="object"?null:(M=x&&M[x]||M["@@iterator"],typeof M=="function"?M:null)}var _={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},S=Object.assign,j={};function N(M,R,re){this.props=M,this.context=R,this.refs=j,this.updater=re||_}N.prototype.isReactComponent={},N.prototype.setState=function(M,R){if(typeof M!="object"&&typeof M!="function"&&M!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,M,R,"setState")},N.prototype.forceUpdate=function(M){this.updater.enqueueForceUpdate(this,M,"forceUpdate")};function k(){}k.prototype=N.prototype;function T(M,R,re){this.props=M,this.context=R,this.refs=j,this.updater=re||_}var E=T.prototype=new k;E.constructor=T,S(E,N.prototype),E.isPureReactComponent=!0;var b=Array.isArray,$=Object.prototype.hasOwnProperty,O={current:null},H={key:!0,ref:!0,__self:!0,__source:!0};function I(M,R,re){var ie,ce={},fe=null,de=null;if(R!=null)for(ie in R.ref!==void 0&&(de=R.ref),R.key!==void 0&&(fe=""+R.key),R)$.call(R,ie)&&!H.hasOwnProperty(ie)&&(ce[ie]=R[ie]);var K=arguments.length-2;if(K===1)ce.children=re;else if(1P||c[w]!==h[P]){var A=` -`+c[w].replace(" at new "," at ");return e.displayName&&A.includes("")&&(A=A.replace("",e.displayName)),A}while(1<=w&&0<=P);break}}}finally{re=!1,Error.prepareStackTrace=i}return(e=e?e.displayName||e.name:"")?R(e):""}function ce(e){switch(e.tag){case 5:return R(e.type);case 16:return R("Lazy");case 13:return R("Suspense");case 19:return R("SuspenseList");case 0:case 2:case 15:return e=ie(e.type,!1),e;case 11:return e=ie(e.type.render,!1),e;case 1:return e=ie(e.type,!0),e;default:return""}}function fe(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case H:return"Fragment";case O:return"Portal";case q:return"Profiler";case I:return"StrictMode";case J:return"Suspense";case C:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case G:return(e.displayName||"Context")+".Consumer";case ne:return(e._context.displayName||"Context")+".Provider";case ee:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Y:return n=e.displayName||null,n!==null?n:fe(e.type)||"Memo";case V:n=e._payload,e=e._init;try{return fe(e(n))}catch{}}return null}function de(e){var n=e.type;switch(e.tag){case 24:return"Cache";case 9:return(n.displayName||"Context")+".Consumer";case 10:return(n._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=n.render,e=e.displayName||e.name||"",n.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return n;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return fe(n);case 8:return n===I?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n}return null}function K(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function le(e){var n=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function pe(e){var n=le(e)?"checked":"value",i=Object.getOwnPropertyDescriptor(e.constructor.prototype,n),s=""+e[n];if(!e.hasOwnProperty(n)&&typeof i<"u"&&typeof i.get=="function"&&typeof i.set=="function"){var c=i.get,h=i.set;return Object.defineProperty(e,n,{configurable:!0,get:function(){return c.call(this)},set:function(w){s=""+w,h.call(this,w)}}),Object.defineProperty(e,n,{enumerable:i.enumerable}),{getValue:function(){return s},setValue:function(w){s=""+w},stopTracking:function(){e._valueTracker=null,delete e[n]}}}}function _e(e){e._valueTracker||(e._valueTracker=pe(e))}function xe(e){if(!e)return!1;var n=e._valueTracker;if(!n)return!0;var i=n.getValue(),s="";return e&&(s=le(e)?e.checked?"true":"false":e.value),e=s,e!==i?(n.setValue(e),!0):!1}function ge(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function je(e,n){var i=n.checked;return W({},n,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:i??e._wrapperState.initialChecked})}function Me(e,n){var i=n.defaultValue==null?"":n.defaultValue,s=n.checked!=null?n.checked:n.defaultChecked;i=K(n.value!=null?n.value:i),e._wrapperState={initialChecked:s,initialValue:i,controlled:n.type==="checkbox"||n.type==="radio"?n.checked!=null:n.value!=null}}function Pe(e,n){n=n.checked,n!=null&&E(e,"checked",n,!1)}function Re(e,n){Pe(e,n);var i=K(n.value),s=n.type;if(i!=null)s==="number"?(i===0&&e.value===""||e.value!=i)&&(e.value=""+i):e.value!==""+i&&(e.value=""+i);else if(s==="submit"||s==="reset"){e.removeAttribute("value");return}n.hasOwnProperty("value")?nt(e,n.type,i):n.hasOwnProperty("defaultValue")&&nt(e,n.type,K(n.defaultValue)),n.checked==null&&n.defaultChecked!=null&&(e.defaultChecked=!!n.defaultChecked)}function tt(e,n,i){if(n.hasOwnProperty("value")||n.hasOwnProperty("defaultValue")){var s=n.type;if(!(s!=="submit"&&s!=="reset"||n.value!==void 0&&n.value!==null))return;n=""+e._wrapperState.initialValue,i||n===e.value||(e.value=n),e.defaultValue=n}i=e.name,i!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,i!==""&&(e.name=i)}function nt(e,n,i){(n!=="number"||ge(e.ownerDocument)!==e)&&(i==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+i&&(e.defaultValue=""+i))}var Qe=Array.isArray;function ot(e,n,i,s){if(e=e.options,n){n={};for(var c=0;c"+n.valueOf().toString()+"",n=Je.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;n.firstChild;)e.appendChild(n.firstChild)}});function wt(e,n){if(n){var i=e.firstChild;if(i&&i===e.lastChild&&i.nodeType===3){i.nodeValue=n;return}}e.textContent=n}var Gt={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},zi=["Webkit","ms","Moz","O"];Object.keys(Gt).forEach(function(e){zi.forEach(function(n){n=n+e.charAt(0).toUpperCase()+e.substring(1),Gt[n]=Gt[e]})});function kt(e,n,i){return n==null||typeof n=="boolean"||n===""?"":i||typeof n!="number"||n===0||Gt.hasOwnProperty(e)&&Gt[e]?(""+n).trim():n+"px"}function hr(e,n){e=e.style;for(var i in n)if(n.hasOwnProperty(i)){var s=i.indexOf("--")===0,c=kt(i,n[i],s);i==="float"&&(i="cssFloat"),s?e.setProperty(i,c):e[i]=c}}var An=W({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function zn(e,n){if(n){if(An[e]&&(n.children!=null||n.dangerouslySetInnerHTML!=null))throw Error(o(137,e));if(n.dangerouslySetInnerHTML!=null){if(n.children!=null)throw Error(o(60));if(typeof n.dangerouslySetInnerHTML!="object"||!("__html"in n.dangerouslySetInnerHTML))throw Error(o(61))}if(n.style!=null&&typeof n.style!="object")throw Error(o(62))}}function pr(e,n){if(e.indexOf("-")===-1)return typeof n.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var gr=null;function mr(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var yr=null,un=null,cn=null;function Ur(e){if(e=no(e)){if(typeof yr!="function")throw Error(o(280));var n=e.stateNode;n&&(n=us(n),yr(e.stateNode,e.type,n))}}function Dn(e){un?cn?cn.push(e):cn=[e]:un=e}function Yr(){if(un){var e=un,n=cn;if(cn=un=null,Ur(e),n)for(e=0;e>>=0,e===0?32:31-(Ol(e)/Fl|0)|0}var Jr=64,ei=4194304;function wr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function kn(e,n){var i=e.pendingLanes;if(i===0)return 0;var s=0,c=e.suspendedLanes,h=e.pingedLanes,w=i&268435455;if(w!==0){var P=w&~c;P!==0?s=wr(P):(h&=w,h!==0&&(s=wr(h)))}else w=i&~c,w!==0?s=wr(w):h!==0&&(s=wr(h));if(s===0)return 0;if(n!==0&&n!==s&&(n&c)===0&&(c=s&-s,h=n&-n,c>=h||c===16&&(h&4194240)!==0))return n;if((s&4)!==0&&(s|=i&16),n=e.entangledLanes,n!==0)for(e=e.entanglements,n&=s;0i;i++)n.push(e);return n}function Sr(e,n,i){e.pendingLanes|=n,n!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,n=31-Lt(n),e[n]=i}function Vl(e,n){var i=e.pendingLanes&~n;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=n,e.mutableReadLanes&=n,e.entangledLanes&=n,n=e.entanglements;var s=e.eventTimes;for(e=e.expirationTimes;0=Gi),Lc=" ",Ac=!1;function zc(e,n){switch(e){case"keyup":return Um.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Dc(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ii=!1;function Gm(e,n){switch(e){case"compositionend":return Dc(n);case"keypress":return n.which!==32?null:(Ac=!0,Lc);case"textInput":return e=n.data,e===Lc&&Ac?null:e;default:return null}}function Xm(e,n){if(ii)return e==="compositionend"||!ea&&zc(e,n)?(e=Cc(),Zo=Xl=Gn=null,ii=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:i,offset:n-e};e=s}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=Wc(i)}}function Yc(e,n){return e&&n?e===n?!0:e&&e.nodeType===3?!1:n&&n.nodeType===3?Yc(e,n.parentNode):"contains"in e?e.contains(n):e.compareDocumentPosition?!!(e.compareDocumentPosition(n)&16):!1:!1}function Gc(){for(var e=window,n=ge();n instanceof e.HTMLIFrameElement;){try{var i=typeof n.contentWindow.location.href=="string"}catch{i=!1}if(i)e=n.contentWindow;else break;n=ge(e.document)}return n}function ra(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n&&(n==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||n==="textarea"||e.contentEditable==="true")}function ry(e){var n=Gc(),i=e.focusedElem,s=e.selectionRange;if(n!==i&&i&&i.ownerDocument&&Yc(i.ownerDocument.documentElement,i)){if(s!==null&&ra(i)){if(n=s.start,e=s.end,e===void 0&&(e=n),"selectionStart"in i)i.selectionStart=n,i.selectionEnd=Math.min(e,i.value.length);else if(e=(n=i.ownerDocument||document)&&n.defaultView||window,e.getSelection){e=e.getSelection();var c=i.textContent.length,h=Math.min(s.start,c);s=s.end===void 0?h:Math.min(s.end,c),!e.extend&&h>s&&(c=s,s=h,h=c),c=Uc(i,h);var w=Uc(i,s);c&&w&&(e.rangeCount!==1||e.anchorNode!==c.node||e.anchorOffset!==c.offset||e.focusNode!==w.node||e.focusOffset!==w.offset)&&(n=n.createRange(),n.setStart(c.node,c.offset),e.removeAllRanges(),h>s?(e.addRange(n),e.extend(w.node,w.offset)):(n.setEnd(w.node,w.offset),e.addRange(n)))}}for(n=[],e=i;e=e.parentNode;)e.nodeType===1&&n.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof i.focus=="function"&&i.focus(),i=0;i=document.documentMode,oi=null,ia=null,Ki=null,oa=!1;function Xc(e,n,i){var s=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;oa||oi==null||oi!==ge(s)||(s=oi,"selectionStart"in s&&ra(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),Ki&&Qi(Ki,s)||(Ki=s,s=ss(ia,"onSelect"),0")&&(A=A.replace("",e.displayName)),A}while(1<=w&&0<=P);break}}}finally{re=!1,Error.prepareStackTrace=i}return(e=e?e.displayName||e.name:"")?R(e):""}function ce(e){switch(e.tag){case 5:return R(e.type);case 16:return R("Lazy");case 13:return R("Suspense");case 19:return R("SuspenseList");case 0:case 2:case 15:return e=ie(e.type,!1),e;case 11:return e=ie(e.type.render,!1),e;case 1:return e=ie(e.type,!0),e;default:return""}}function fe(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case H:return"Fragment";case O:return"Portal";case q:return"Profiler";case I:return"StrictMode";case J:return"Suspense";case C:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case G:return(e.displayName||"Context")+".Consumer";case ne:return(e._context.displayName||"Context")+".Provider";case ee:var n=e.render;return e=e.displayName,e||(e=n.displayName||n.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case Y:return n=e.displayName||null,n!==null?n:fe(e.type)||"Memo";case V:n=e._payload,e=e._init;try{return fe(e(n))}catch{}}return null}function de(e){var n=e.type;switch(e.tag){case 24:return"Cache";case 9:return(n.displayName||"Context")+".Consumer";case 10:return(n._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=n.render,e=e.displayName||e.name||"",n.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return n;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return fe(n);case 8:return n===I?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof n=="function")return n.displayName||n.name||null;if(typeof n=="string")return n}return null}function K(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function le(e){var n=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(n==="checkbox"||n==="radio")}function pe(e){var n=le(e)?"checked":"value",i=Object.getOwnPropertyDescriptor(e.constructor.prototype,n),s=""+e[n];if(!e.hasOwnProperty(n)&&typeof i<"u"&&typeof i.get=="function"&&typeof i.set=="function"){var c=i.get,h=i.set;return Object.defineProperty(e,n,{configurable:!0,get:function(){return c.call(this)},set:function(w){s=""+w,h.call(this,w)}}),Object.defineProperty(e,n,{enumerable:i.enumerable}),{getValue:function(){return s},setValue:function(w){s=""+w},stopTracking:function(){e._valueTracker=null,delete e[n]}}}}function _e(e){e._valueTracker||(e._valueTracker=pe(e))}function xe(e){if(!e)return!1;var n=e._valueTracker;if(!n)return!0;var i=n.getValue(),s="";return e&&(s=le(e)?e.checked?"true":"false":e.value),e=s,e!==i?(n.setValue(e),!0):!1}function ge(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function je(e,n){var i=n.checked;return W({},n,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:i??e._wrapperState.initialChecked})}function Pe(e,n){var i=n.defaultValue==null?"":n.defaultValue,s=n.checked!=null?n.checked:n.defaultChecked;i=K(n.value!=null?n.value:i),e._wrapperState={initialChecked:s,initialValue:i,controlled:n.type==="checkbox"||n.type==="radio"?n.checked!=null:n.value!=null}}function Ie(e,n){n=n.checked,n!=null&&E(e,"checked",n,!1)}function Re(e,n){Ie(e,n);var i=K(n.value),s=n.type;if(i!=null)s==="number"?(i===0&&e.value===""||e.value!=i)&&(e.value=""+i):e.value!==""+i&&(e.value=""+i);else if(s==="submit"||s==="reset"){e.removeAttribute("value");return}n.hasOwnProperty("value")?nt(e,n.type,i):n.hasOwnProperty("defaultValue")&&nt(e,n.type,K(n.defaultValue)),n.checked==null&&n.defaultChecked!=null&&(e.defaultChecked=!!n.defaultChecked)}function tt(e,n,i){if(n.hasOwnProperty("value")||n.hasOwnProperty("defaultValue")){var s=n.type;if(!(s!=="submit"&&s!=="reset"||n.value!==void 0&&n.value!==null))return;n=""+e._wrapperState.initialValue,i||n===e.value||(e.value=n),e.defaultValue=n}i=e.name,i!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,i!==""&&(e.name=i)}function nt(e,n,i){(n!=="number"||ge(e.ownerDocument)!==e)&&(i==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+i&&(e.defaultValue=""+i))}var Qe=Array.isArray;function ot(e,n,i,s){if(e=e.options,n){n={};for(var c=0;c"+n.valueOf().toString()+"",n=Je.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;n.firstChild;)e.appendChild(n.firstChild)}});function wt(e,n){if(n){var i=e.firstChild;if(i&&i===e.lastChild&&i.nodeType===3){i.nodeValue=n;return}}e.textContent=n}var Gt={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},zi=["Webkit","ms","Moz","O"];Object.keys(Gt).forEach(function(e){zi.forEach(function(n){n=n+e.charAt(0).toUpperCase()+e.substring(1),Gt[n]=Gt[e]})});function kt(e,n,i){return n==null||typeof n=="boolean"||n===""?"":i||typeof n!="number"||n===0||Gt.hasOwnProperty(e)&&Gt[e]?(""+n).trim():n+"px"}function hr(e,n){e=e.style;for(var i in n)if(n.hasOwnProperty(i)){var s=i.indexOf("--")===0,c=kt(i,n[i],s);i==="float"&&(i="cssFloat"),s?e.setProperty(i,c):e[i]=c}}var An=W({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function zn(e,n){if(n){if(An[e]&&(n.children!=null||n.dangerouslySetInnerHTML!=null))throw Error(o(137,e));if(n.dangerouslySetInnerHTML!=null){if(n.children!=null)throw Error(o(60));if(typeof n.dangerouslySetInnerHTML!="object"||!("__html"in n.dangerouslySetInnerHTML))throw Error(o(61))}if(n.style!=null&&typeof n.style!="object")throw Error(o(62))}}function pr(e,n){if(e.indexOf("-")===-1)return typeof n.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var gr=null;function mr(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var yr=null,un=null,cn=null;function Ur(e){if(e=no(e)){if(typeof yr!="function")throw Error(o(280));var n=e.stateNode;n&&(n=us(n),yr(e.stateNode,e.type,n))}}function Dn(e){un?cn?cn.push(e):cn=[e]:un=e}function Yr(){if(un){var e=un,n=cn;if(cn=un=null,Ur(e),n)for(e=0;e>>=0,e===0?32:31-(Ol(e)/Fl|0)|0}var Jr=64,ei=4194304;function wr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function kn(e,n){var i=e.pendingLanes;if(i===0)return 0;var s=0,c=e.suspendedLanes,h=e.pingedLanes,w=i&268435455;if(w!==0){var P=w&~c;P!==0?s=wr(P):(h&=w,h!==0&&(s=wr(h)))}else w=i&~c,w!==0?s=wr(w):h!==0&&(s=wr(h));if(s===0)return 0;if(n!==0&&n!==s&&(n&c)===0&&(c=s&-s,h=n&-n,c>=h||c===16&&(h&4194240)!==0))return n;if((s&4)!==0&&(s|=i&16),n=e.entangledLanes,n!==0)for(e=e.entanglements,n&=s;0i;i++)n.push(e);return n}function Sr(e,n,i){e.pendingLanes|=n,n!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,n=31-Lt(n),e[n]=i}function Vl(e,n){var i=e.pendingLanes&~n;e.pendingLanes=n,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=n,e.mutableReadLanes&=n,e.entangledLanes&=n,n=e.entanglements;var s=e.eventTimes;for(e=e.expirationTimes;0=Gi),Lc=" ",Ac=!1;function zc(e,n){switch(e){case"keyup":return Um.indexOf(n.keyCode)!==-1;case"keydown":return n.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Dc(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var ii=!1;function Gm(e,n){switch(e){case"compositionend":return Dc(n);case"keypress":return n.which!==32?null:(Ac=!0,Lc);case"textInput":return e=n.data,e===Lc&&Ac?null:e;default:return null}}function Xm(e,n){if(ii)return e==="compositionend"||!ea&&zc(e,n)?(e=Cc(),Zo=Xl=Gn=null,ii=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(n.ctrlKey||n.altKey||n.metaKey)||n.ctrlKey&&n.altKey){if(n.char&&1=n)return{node:i,offset:n-e};e=s}e:{for(;i;){if(i.nextSibling){i=i.nextSibling;break e}i=i.parentNode}i=void 0}i=Wc(i)}}function Yc(e,n){return e&&n?e===n?!0:e&&e.nodeType===3?!1:n&&n.nodeType===3?Yc(e,n.parentNode):"contains"in e?e.contains(n):e.compareDocumentPosition?!!(e.compareDocumentPosition(n)&16):!1:!1}function Gc(){for(var e=window,n=ge();n instanceof e.HTMLIFrameElement;){try{var i=typeof n.contentWindow.location.href=="string"}catch{i=!1}if(i)e=n.contentWindow;else break;n=ge(e.document)}return n}function ra(e){var n=e&&e.nodeName&&e.nodeName.toLowerCase();return n&&(n==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||n==="textarea"||e.contentEditable==="true")}function ry(e){var n=Gc(),i=e.focusedElem,s=e.selectionRange;if(n!==i&&i&&i.ownerDocument&&Yc(i.ownerDocument.documentElement,i)){if(s!==null&&ra(i)){if(n=s.start,e=s.end,e===void 0&&(e=n),"selectionStart"in i)i.selectionStart=n,i.selectionEnd=Math.min(e,i.value.length);else if(e=(n=i.ownerDocument||document)&&n.defaultView||window,e.getSelection){e=e.getSelection();var c=i.textContent.length,h=Math.min(s.start,c);s=s.end===void 0?h:Math.min(s.end,c),!e.extend&&h>s&&(c=s,s=h,h=c),c=Uc(i,h);var w=Uc(i,s);c&&w&&(e.rangeCount!==1||e.anchorNode!==c.node||e.anchorOffset!==c.offset||e.focusNode!==w.node||e.focusOffset!==w.offset)&&(n=n.createRange(),n.setStart(c.node,c.offset),e.removeAllRanges(),h>s?(e.addRange(n),e.extend(w.node,w.offset)):(n.setEnd(w.node,w.offset),e.addRange(n)))}}for(n=[],e=i;e=e.parentNode;)e.nodeType===1&&n.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof i.focus=="function"&&i.focus(),i=0;i=document.documentMode,oi=null,ia=null,Ki=null,oa=!1;function Xc(e,n,i){var s=i.window===i?i.document:i.nodeType===9?i:i.ownerDocument;oa||oi==null||oi!==ge(s)||(s=oi,"selectionStart"in s&&ra(s)?s={start:s.selectionStart,end:s.selectionEnd}:(s=(s.ownerDocument&&s.ownerDocument.defaultView||window).getSelection(),s={anchorNode:s.anchorNode,anchorOffset:s.anchorOffset,focusNode:s.focusNode,focusOffset:s.focusOffset}),Ki&&Qi(Ki,s)||(Ki=s,s=ss(ia,"onSelect"),0ci||(e.current=ya[ci],ya[ci]=null,ci--)}function Fe(e,n){ci++,ya[ci]=e.current,e.current=n}var Kn={},mt=Qn(Kn),Et=Qn(!1),Er=Kn;function di(e,n){var i=e.type.contextTypes;if(!i)return Kn;var s=e.stateNode;if(s&&s.__reactInternalMemoizedUnmaskedChildContext===n)return s.__reactInternalMemoizedMaskedChildContext;var c={},h;for(h in i)c[h]=n[h];return s&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=n,e.__reactInternalMemoizedMaskedChildContext=c),c}function Nt(e){return e=e.childContextTypes,e!=null}function cs(){Be(Et),Be(mt)}function ud(e,n,i){if(mt.current!==Kn)throw Error(o(168));Fe(mt,n),Fe(Et,i)}function cd(e,n,i){var s=e.stateNode;if(n=n.childContextTypes,typeof s.getChildContext!="function")return i;s=s.getChildContext();for(var c in s)if(!(c in n))throw Error(o(108,de(e)||"Unknown",c));return W({},i,s)}function ds(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||Kn,Er=mt.current,Fe(mt,e),Fe(Et,Et.current),!0}function dd(e,n,i){var s=e.stateNode;if(!s)throw Error(o(169));i?(e=cd(e,n,Er),s.__reactInternalMemoizedMergedChildContext=e,Be(Et),Be(mt),Fe(mt,e)):Be(Et),Fe(Et,i)}var Nn=null,fs=!1,va=!1;function fd(e){Nn===null?Nn=[e]:Nn.push(e)}function gy(e){fs=!0,fd(e)}function Zn(){if(!va&&Nn!==null){va=!0;var e=0,n=Oe;try{var i=Nn;for(Oe=1;e>=w,c-=w,jn=1<<32-Lt(n)+c|i<be?(dt=Ne,Ne=null):dt=Ne.sibling;var De=oe(X,Ne,Q[be],ue);if(De===null){Ne===null&&(Ne=dt);break}e&&Ne&&De.alternate===null&&n(X,Ne),B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De,Ne=dt}if(be===Q.length)return i(X,Ne),Ue&&jr(X,be),we;if(Ne===null){for(;bebe?(dt=Ne,Ne=null):dt=Ne.sibling;var lr=oe(X,Ne,De.value,ue);if(lr===null){Ne===null&&(Ne=dt);break}e&&Ne&&lr.alternate===null&&n(X,Ne),B=h(lr,B,be),Ee===null?we=lr:Ee.sibling=lr,Ee=lr,Ne=dt}if(De.done)return i(X,Ne),Ue&&jr(X,be),we;if(Ne===null){for(;!De.done;be++,De=Q.next())De=ae(X,De.value,ue),De!==null&&(B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De);return Ue&&jr(X,be),we}for(Ne=s(X,Ne);!De.done;be++,De=Q.next())De=he(Ne,X,be,De.value,ue),De!==null&&(e&&De.alternate!==null&&Ne.delete(De.key===null?be:De.key),B=h(De,B,be),Ee===null?we=De:Ee.sibling=De,Ee=De);return e&&Ne.forEach(function(qy){return n(X,qy)}),Ue&&jr(X,be),we}function et(X,B,Q,ue){if(typeof Q=="object"&&Q!==null&&Q.type===H&&Q.key===null&&(Q=Q.props.children),typeof Q=="object"&&Q!==null){switch(Q.$$typeof){case $:e:{for(var we=Q.key,Ee=B;Ee!==null;){if(Ee.key===we){if(we=Q.type,we===H){if(Ee.tag===7){i(X,Ee.sibling),B=c(Ee,Q.props.children),B.return=X,X=B;break e}}else if(Ee.elementType===we||typeof we=="object"&&we!==null&&we.$$typeof===V&&vd(we)===Ee.type){i(X,Ee.sibling),B=c(Ee,Q.props),B.ref=ro(X,Ee,Q),B.return=X,X=B;break e}i(X,Ee);break}else n(X,Ee);Ee=Ee.sibling}Q.type===H?(B=Lr(Q.props.children,X.mode,ue,Q.key),B.return=X,X=B):(ue=Fs(Q.type,Q.key,Q.props,null,X.mode,ue),ue.ref=ro(X,B,Q),ue.return=X,X=ue)}return w(X);case O:e:{for(Ee=Q.key;B!==null;){if(B.key===Ee)if(B.tag===4&&B.stateNode.containerInfo===Q.containerInfo&&B.stateNode.implementation===Q.implementation){i(X,B.sibling),B=c(B,Q.children||[]),B.return=X,X=B;break e}else{i(X,B);break}else n(X,B);B=B.sibling}B=gu(Q,X.mode,ue),B.return=X,X=B}return w(X);case V:return Ee=Q._init,et(X,B,Ee(Q._payload),ue)}if(Qe(Q))return ye(X,B,Q,ue);if(D(Q))return ve(X,B,Q,ue);ms(X,Q)}return typeof Q=="string"&&Q!==""||typeof Q=="number"?(Q=""+Q,B!==null&&B.tag===6?(i(X,B.sibling),B=c(B,Q),B.return=X,X=B):(i(X,B),B=pu(Q,X.mode,ue),B.return=X,X=B),w(X)):i(X,B)}return et}var gi=xd(!0),wd=xd(!1),ys=Qn(null),vs=null,mi=null,Ea=null;function Na(){Ea=mi=vs=null}function ja(e){var n=ys.current;Be(ys),e._currentValue=n}function ba(e,n,i){for(;e!==null;){var s=e.alternate;if((e.childLanes&n)!==n?(e.childLanes|=n,s!==null&&(s.childLanes|=n)):s!==null&&(s.childLanes&n)!==n&&(s.childLanes|=n),e===i)break;e=e.return}}function yi(e,n){vs=e,Ea=mi=null,e=e.dependencies,e!==null&&e.firstContext!==null&&((e.lanes&n)!==0&&(jt=!0),e.firstContext=null)}function Vt(e){var n=e._currentValue;if(Ea!==e)if(e={context:e,memoizedValue:n,next:null},mi===null){if(vs===null)throw Error(o(308));mi=e,vs.dependencies={lanes:0,firstContext:e}}else mi=mi.next=e;return n}var br=null;function Ca(e){br===null?br=[e]:br.push(e)}function _d(e,n,i,s){var c=n.interleaved;return c===null?(i.next=i,Ca(n)):(i.next=c.next,c.next=i),n.interleaved=i,Cn(e,s)}function Cn(e,n){e.lanes|=n;var i=e.alternate;for(i!==null&&(i.lanes|=n),i=e,e=e.return;e!==null;)e.childLanes|=n,i=e.alternate,i!==null&&(i.childLanes|=n),i=e,e=e.return;return i.tag===3?i.stateNode:null}var Jn=!1;function Ma(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function Sd(e,n){e=e.updateQueue,n.updateQueue===e&&(n.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function Mn(e,n){return{eventTime:e,lane:n,tag:0,payload:null,callback:null,next:null}}function er(e,n,i){var s=e.updateQueue;if(s===null)return null;if(s=s.shared,(Le&2)!==0){var c=s.pending;return c===null?n.next=n:(n.next=c.next,c.next=n),s.pending=n,Cn(e,i)}return c=s.interleaved,c===null?(n.next=n,Ca(s)):(n.next=c.next,c.next=n),s.interleaved=n,Cn(e,i)}function xs(e,n,i){if(n=n.updateQueue,n!==null&&(n=n.shared,(i&4194240)!==0)){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,ti(e,i)}}function kd(e,n){var i=e.updateQueue,s=e.alternate;if(s!==null&&(s=s.updateQueue,i===s)){var c=null,h=null;if(i=i.firstBaseUpdate,i!==null){do{var w={eventTime:i.eventTime,lane:i.lane,tag:i.tag,payload:i.payload,callback:i.callback,next:null};h===null?c=h=w:h=h.next=w,i=i.next}while(i!==null);h===null?c=h=n:h=h.next=n}else c=h=n;i={baseState:s.baseState,firstBaseUpdate:c,lastBaseUpdate:h,shared:s.shared,effects:s.effects},e.updateQueue=i;return}e=i.lastBaseUpdate,e===null?i.firstBaseUpdate=n:e.next=n,i.lastBaseUpdate=n}function ws(e,n,i,s){var c=e.updateQueue;Jn=!1;var h=c.firstBaseUpdate,w=c.lastBaseUpdate,P=c.shared.pending;if(P!==null){c.shared.pending=null;var A=P,Z=A.next;A.next=null,w===null?h=Z:w.next=Z,w=A;var se=e.alternate;se!==null&&(se=se.updateQueue,P=se.lastBaseUpdate,P!==w&&(P===null?se.firstBaseUpdate=Z:P.next=Z,se.lastBaseUpdate=A))}if(h!==null){var ae=c.baseState;w=0,se=Z=A=null,P=h;do{var oe=P.lane,he=P.eventTime;if((s&oe)===oe){se!==null&&(se=se.next={eventTime:he,lane:0,tag:P.tag,payload:P.payload,callback:P.callback,next:null});e:{var ye=e,ve=P;switch(oe=n,he=i,ve.tag){case 1:if(ye=ve.payload,typeof ye=="function"){ae=ye.call(he,ae,oe);break e}ae=ye;break e;case 3:ye.flags=ye.flags&-65537|128;case 0:if(ye=ve.payload,oe=typeof ye=="function"?ye.call(he,ae,oe):ye,oe==null)break e;ae=W({},ae,oe);break e;case 2:Jn=!0}}P.callback!==null&&P.lane!==0&&(e.flags|=64,oe=c.effects,oe===null?c.effects=[P]:oe.push(P))}else he={eventTime:he,lane:oe,tag:P.tag,payload:P.payload,callback:P.callback,next:null},se===null?(Z=se=he,A=ae):se=se.next=he,w|=oe;if(P=P.next,P===null){if(P=c.shared.pending,P===null)break;oe=P,P=oe.next,oe.next=null,c.lastBaseUpdate=oe,c.shared.pending=null}}while(!0);if(se===null&&(A=ae),c.baseState=A,c.firstBaseUpdate=Z,c.lastBaseUpdate=se,n=c.shared.interleaved,n!==null){c=n;do w|=c.lane,c=c.next;while(c!==n)}else h===null&&(c.shared.lanes=0);Pr|=w,e.lanes=w,e.memoizedState=ae}}function Ed(e,n,i){if(e=n.effects,n.effects=null,e!==null)for(n=0;ni?i:4,e(!0);var s=La.transition;La.transition={};try{e(!1),n()}finally{Oe=i,La.transition=s}}function Vd(){return Wt().memoizedState}function xy(e,n,i){var s=ir(e);if(i={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null},Wd(e))Ud(n,i);else if(i=_d(e,n,i,s),i!==null){var c=St();en(i,e,s,c),Yd(i,n,s)}}function wy(e,n,i){var s=ir(e),c={lane:s,action:i,hasEagerState:!1,eagerState:null,next:null};if(Wd(e))Ud(n,c);else{var h=e.alternate;if(e.lanes===0&&(h===null||h.lanes===0)&&(h=n.lastRenderedReducer,h!==null))try{var w=n.lastRenderedState,P=h(w,i);if(c.hasEagerState=!0,c.eagerState=P,qt(P,w)){var A=n.interleaved;A===null?(c.next=c,Ca(n)):(c.next=A.next,A.next=c),n.interleaved=c;return}}catch{}finally{}i=_d(e,n,c,s),i!==null&&(c=St(),en(i,e,s,c),Yd(i,n,s))}}function Wd(e){var n=e.alternate;return e===Xe||n!==null&&n===Xe}function Ud(e,n){lo=ks=!0;var i=e.pending;i===null?n.next=n:(n.next=i.next,i.next=n),e.pending=n}function Yd(e,n,i){if((i&4194240)!==0){var s=n.lanes;s&=e.pendingLanes,i|=s,n.lanes=i,ti(e,i)}}var js={readContext:Vt,useCallback:yt,useContext:yt,useEffect:yt,useImperativeHandle:yt,useInsertionEffect:yt,useLayoutEffect:yt,useMemo:yt,useReducer:yt,useRef:yt,useState:yt,useDebugValue:yt,useDeferredValue:yt,useTransition:yt,useMutableSource:yt,useSyncExternalStore:yt,useId:yt,unstable_isNewReconciler:!1},_y={readContext:Vt,useCallback:function(e,n){return hn().memoizedState=[e,n===void 0?null:n],e},useContext:Vt,useEffect:Ad,useImperativeHandle:function(e,n,i){return i=i!=null?i.concat([e]):null,Es(4194308,4,$d.bind(null,n,e),i)},useLayoutEffect:function(e,n){return Es(4194308,4,e,n)},useInsertionEffect:function(e,n){return Es(4,2,e,n)},useMemo:function(e,n){var i=hn();return n=n===void 0?null:n,e=e(),i.memoizedState=[e,n],e},useReducer:function(e,n,i){var s=hn();return n=i!==void 0?i(n):n,s.memoizedState=s.baseState=n,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:n},s.queue=e,e=e.dispatch=xy.bind(null,Xe,e),[s.memoizedState,e]},useRef:function(e){var n=hn();return e={current:e},n.memoizedState=e},useState:Rd,useDebugValue:Ha,useDeferredValue:function(e){return hn().memoizedState=e},useTransition:function(){var e=Rd(!1),n=e[0];return e=vy.bind(null,e[1]),hn().memoizedState=e,[n,e]},useMutableSource:function(){},useSyncExternalStore:function(e,n,i){var s=Xe,c=hn();if(Ue){if(i===void 0)throw Error(o(407));i=i()}else{if(i=n(),ct===null)throw Error(o(349));(Mr&30)!==0||Cd(s,n,i)}c.memoizedState=i;var h={value:i,getSnapshot:n};return c.queue=h,Ad(Pd.bind(null,s,h,e),[e]),s.flags|=2048,co(9,Md.bind(null,s,h,i,n),void 0,null),i},useId:function(){var e=hn(),n=ct.identifierPrefix;if(Ue){var i=bn,s=jn;i=(s&~(1<<32-Lt(s)-1)).toString(32)+i,n=":"+n+"R"+i,i=ao++,0<\/script>",e=e.removeChild(e.firstChild)):typeof s.is=="string"?e=w.createElement(i,{is:s.is}):(e=w.createElement(i),i==="select"&&(w=e,s.multiple?w.multiple=!0:s.size&&(w.size=s.size))):e=w.createElementNS(e,i),e[dn]=n,e[to]=s,hf(e,n,!1,!1),n.stateNode=e;e:{switch(w=pr(i,s),i){case"dialog":He("cancel",e),He("close",e),c=s;break;case"iframe":case"object":case"embed":He("load",e),c=s;break;case"video":case"audio":for(c=0;cSi&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304)}else{if(!s)if(e=_s(w),e!==null){if(n.flags|=128,s=!0,i=e.updateQueue,i!==null&&(n.updateQueue=i,n.flags|=4),fo(h,!0),h.tail===null&&h.tailMode==="hidden"&&!w.alternate&&!Ue)return vt(n),null}else 2*Ye()-h.renderingStartTime>Si&&i!==1073741824&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304);h.isBackwards?(w.sibling=n.child,n.child=w):(i=h.last,i!==null?i.sibling=w:n.child=w,h.last=w)}return h.tail!==null?(n=h.tail,h.rendering=n,h.tail=n.sibling,h.renderingStartTime=Ye(),n.sibling=null,i=Ge.current,Fe(Ge,s?i&1|2:i&1),n):(vt(n),null);case 22:case 23:return du(),s=n.memoizedState!==null,e!==null&&e.memoizedState!==null!==s&&(n.flags|=8192),s&&(n.mode&1)!==0?($t&1073741824)!==0&&(vt(n),n.subtreeFlags&6&&(n.flags|=8192)):vt(n),null;case 24:return null;case 25:return null}throw Error(o(156,n.tag))}function My(e,n){switch(wa(n),n.tag){case 1:return Nt(n.type)&&cs(),e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 3:return vi(),Be(Et),Be(mt),Ra(),e=n.flags,(e&65536)!==0&&(e&128)===0?(n.flags=e&-65537|128,n):null;case 5:return Ia(n),null;case 13:if(Be(Ge),e=n.memoizedState,e!==null&&e.dehydrated!==null){if(n.alternate===null)throw Error(o(340));pi()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 19:return Be(Ge),null;case 4:return vi(),null;case 10:return ja(n.type._context),null;case 22:case 23:return du(),null;case 24:return null;default:return null}}var Ps=!1,xt=!1,Py=typeof WeakSet=="function"?WeakSet:Set,me=null;function wi(e,n){var i=e.ref;if(i!==null)if(typeof i=="function")try{i(null)}catch(s){Ze(e,n,s)}else i.current=null}function Ja(e,n,i){try{i()}catch(s){Ze(e,n,s)}}var mf=!1;function Iy(e,n){if(da=Qo,e=Gc(),ra(e)){if("selectionStart"in e)var i={start:e.selectionStart,end:e.selectionEnd};else e:{i=(i=e.ownerDocument)&&i.defaultView||window;var s=i.getSelection&&i.getSelection();if(s&&s.rangeCount!==0){i=s.anchorNode;var c=s.anchorOffset,h=s.focusNode;s=s.focusOffset;try{i.nodeType,h.nodeType}catch{i=null;break e}var w=0,P=-1,A=-1,Z=0,se=0,ae=e,oe=null;t:for(;;){for(var he;ae!==i||c!==0&&ae.nodeType!==3||(P=w+c),ae!==h||s!==0&&ae.nodeType!==3||(A=w+s),ae.nodeType===3&&(w+=ae.nodeValue.length),(he=ae.firstChild)!==null;)oe=ae,ae=he;for(;;){if(ae===e)break t;if(oe===i&&++Z===c&&(P=w),oe===h&&++se===s&&(A=w),(he=ae.nextSibling)!==null)break;ae=oe,oe=ae.parentNode}ae=he}i=P===-1||A===-1?null:{start:P,end:A}}else i=null}i=i||{start:0,end:0}}else i=null;for(fa={focusedElem:e,selectionRange:i},Qo=!1,me=n;me!==null;)if(n=me,e=n.child,(n.subtreeFlags&1028)!==0&&e!==null)e.return=n,me=e;else for(;me!==null;){n=me;try{var ye=n.alternate;if((n.flags&1024)!==0)switch(n.tag){case 0:case 11:case 15:break;case 1:if(ye!==null){var ve=ye.memoizedProps,et=ye.memoizedState,X=n.stateNode,B=X.getSnapshotBeforeUpdate(n.elementType===n.type?ve:Kt(n.type,ve),et);X.__reactInternalSnapshotBeforeUpdate=B}break;case 3:var Q=n.stateNode.containerInfo;Q.nodeType===1?Q.textContent="":Q.nodeType===9&&Q.documentElement&&Q.removeChild(Q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(ue){Ze(n,n.return,ue)}if(e=n.sibling,e!==null){e.return=n.return,me=e;break}me=n.return}return ye=mf,mf=!1,ye}function ho(e,n,i){var s=n.updateQueue;if(s=s!==null?s.lastEffect:null,s!==null){var c=s=s.next;do{if((c.tag&e)===e){var h=c.destroy;c.destroy=void 0,h!==void 0&&Ja(n,i,h)}c=c.next}while(c!==s)}}function Is(e,n){if(n=n.updateQueue,n=n!==null?n.lastEffect:null,n!==null){var i=n=n.next;do{if((i.tag&e)===e){var s=i.create;i.destroy=s()}i=i.next}while(i!==n)}}function eu(e){var n=e.ref;if(n!==null){var i=e.stateNode;switch(e.tag){case 5:e=i;break;default:e=i}typeof n=="function"?n(e):n.current=e}}function yf(e){var n=e.alternate;n!==null&&(e.alternate=null,yf(n)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(n=e.stateNode,n!==null&&(delete n[dn],delete n[to],delete n[ma],delete n[hy],delete n[py])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function vf(e){return e.tag===5||e.tag===3||e.tag===4}function xf(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||vf(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.nodeType===8?i.parentNode.insertBefore(e,n):i.insertBefore(e,n):(i.nodeType===8?(n=i.parentNode,n.insertBefore(e,i)):(n=i,n.appendChild(e)),i=i._reactRootContainer,i!=null||n.onclick!==null||(n.onclick=as));else if(s!==4&&(e=e.child,e!==null))for(tu(e,n,i),e=e.sibling;e!==null;)tu(e,n,i),e=e.sibling}function nu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.insertBefore(e,n):i.appendChild(e);else if(s!==4&&(e=e.child,e!==null))for(nu(e,n,i),e=e.sibling;e!==null;)nu(e,n,i),e=e.sibling}var ht=null,Zt=!1;function tr(e,n,i){for(i=i.child;i!==null;)wf(e,n,i),i=i.sibling}function wf(e,n,i){if(Rt&&typeof Rt.onCommitFiberUnmount=="function")try{Rt.onCommitFiberUnmount(Zr,i)}catch{}switch(i.tag){case 5:xt||wi(i,n);case 6:var s=ht,c=Zt;ht=null,tr(e,n,i),ht=s,Zt=c,ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?e.parentNode.removeChild(i):e.removeChild(i)):ht.removeChild(i.stateNode));break;case 18:ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?ga(e.parentNode,i):e.nodeType===1&&ga(e,i),Wi(e)):ga(ht,i.stateNode));break;case 4:s=ht,c=Zt,ht=i.stateNode.containerInfo,Zt=!0,tr(e,n,i),ht=s,Zt=c;break;case 0:case 11:case 14:case 15:if(!xt&&(s=i.updateQueue,s!==null&&(s=s.lastEffect,s!==null))){c=s=s.next;do{var h=c,w=h.destroy;h=h.tag,w!==void 0&&((h&2)!==0||(h&4)!==0)&&Ja(i,n,w),c=c.next}while(c!==s)}tr(e,n,i);break;case 1:if(!xt&&(wi(i,n),s=i.stateNode,typeof s.componentWillUnmount=="function"))try{s.props=i.memoizedProps,s.state=i.memoizedState,s.componentWillUnmount()}catch(P){Ze(i,n,P)}tr(e,n,i);break;case 21:tr(e,n,i);break;case 22:i.mode&1?(xt=(s=xt)||i.memoizedState!==null,tr(e,n,i),xt=s):tr(e,n,i);break;default:tr(e,n,i)}}function _f(e){var n=e.updateQueue;if(n!==null){e.updateQueue=null;var i=e.stateNode;i===null&&(i=e.stateNode=new Py),n.forEach(function(s){var c=Fy.bind(null,e,s);i.has(s)||(i.add(s),s.then(c,c))})}}function Jt(e,n){var i=n.deletions;if(i!==null)for(var s=0;sc&&(c=w),s&=~h}if(s=c,s=Ye()-s,s=(120>s?120:480>s?480:1080>s?1080:1920>s?1920:3e3>s?3e3:4320>s?4320:1960*Ry(s/1960))-s,10e?16:e,rr===null)var s=!1;else{if(e=rr,rr=null,zs=0,(Le&6)!==0)throw Error(o(331));var c=Le;for(Le|=4,me=e.current;me!==null;){var h=me,w=h.child;if((me.flags&16)!==0){var P=h.deletions;if(P!==null){for(var A=0;AYe()-ou?Tr(e,0):iu|=i),Ct(e,n)}function Lf(e,n){n===0&&((e.mode&1)===0?n=1:(n=ei,ei<<=1,(ei&130023424)===0&&(ei=4194304)));var i=St();e=Cn(e,n),e!==null&&(Sr(e,n,i),Ct(e,i))}function Oy(e){var n=e.memoizedState,i=0;n!==null&&(i=n.retryLane),Lf(e,i)}function Fy(e,n){var i=0;switch(e.tag){case 13:var s=e.stateNode,c=e.memoizedState;c!==null&&(i=c.retryLane);break;case 19:s=e.stateNode;break;default:throw Error(o(314))}s!==null&&s.delete(n),Lf(e,i)}var Af;Af=function(e,n,i){if(e!==null)if(e.memoizedProps!==n.pendingProps||Et.current)jt=!0;else{if((e.lanes&i)===0&&(n.flags&128)===0)return jt=!1,by(e,n,i);jt=(e.flags&131072)!==0}else jt=!1,Ue&&(n.flags&1048576)!==0&&hd(n,ps,n.index);switch(n.lanes=0,n.tag){case 2:var s=n.type;Ms(e,n),e=n.pendingProps;var c=di(n,mt.current);yi(n,i),c=za(null,n,s,e,c,i);var h=Da();return n.flags|=1,typeof c=="object"&&c!==null&&typeof c.render=="function"&&c.$$typeof===void 0?(n.tag=1,n.memoizedState=null,n.updateQueue=null,Nt(s)?(h=!0,ds(n)):h=!1,n.memoizedState=c.state!==null&&c.state!==void 0?c.state:null,Ma(n),c.updater=bs,n.stateNode=c,c._reactInternals=n,Va(n,s,e,i),n=Ga(null,n,s,!0,h,i)):(n.tag=0,Ue&&h&&xa(n),_t(null,n,c,i),n=n.child),n;case 16:s=n.elementType;e:{switch(Ms(e,n),e=n.pendingProps,c=s._init,s=c(s._payload),n.type=s,c=n.tag=By(s),e=Kt(s,e),c){case 0:n=Ya(null,n,s,e,i);break e;case 1:n=lf(null,n,s,e,i);break e;case 11:n=tf(null,n,s,e,i);break e;case 14:n=nf(null,n,s,Kt(s.type,e),i);break e}throw Error(o(306,s,""))}return n;case 0:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ya(e,n,s,c,i);case 1:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),lf(e,n,s,c,i);case 3:e:{if(af(n),e===null)throw Error(o(387));s=n.pendingProps,h=n.memoizedState,c=h.element,Sd(e,n),ws(n,s,null,i);var w=n.memoizedState;if(s=w.element,h.isDehydrated)if(h={element:s,isDehydrated:!1,cache:w.cache,pendingSuspenseBoundaries:w.pendingSuspenseBoundaries,transitions:w.transitions},n.updateQueue.baseState=h,n.memoizedState=h,n.flags&256){c=xi(Error(o(423)),n),n=uf(e,n,s,i,c);break e}else if(s!==c){c=xi(Error(o(424)),n),n=uf(e,n,s,i,c);break e}else for(Dt=qn(n.stateNode.containerInfo.firstChild),zt=n,Ue=!0,Qt=null,i=wd(n,null,s,i),n.child=i;i;)i.flags=i.flags&-3|4096,i=i.sibling;else{if(pi(),s===c){n=Pn(e,n,i);break e}_t(e,n,s,i)}n=n.child}return n;case 5:return Nd(n),e===null&&Sa(n),s=n.type,c=n.pendingProps,h=e!==null?e.memoizedProps:null,w=c.children,ha(s,c)?w=null:h!==null&&ha(s,h)&&(n.flags|=32),sf(e,n),_t(e,n,w,i),n.child;case 6:return e===null&&Sa(n),null;case 13:return cf(e,n,i);case 4:return Pa(n,n.stateNode.containerInfo),s=n.pendingProps,e===null?n.child=gi(n,null,s,i):_t(e,n,s,i),n.child;case 11:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),tf(e,n,s,c,i);case 7:return _t(e,n,n.pendingProps,i),n.child;case 8:return _t(e,n,n.pendingProps.children,i),n.child;case 12:return _t(e,n,n.pendingProps.children,i),n.child;case 10:e:{if(s=n.type._context,c=n.pendingProps,h=n.memoizedProps,w=c.value,Fe(ys,s._currentValue),s._currentValue=w,h!==null)if(qt(h.value,w)){if(h.children===c.children&&!Et.current){n=Pn(e,n,i);break e}}else for(h=n.child,h!==null&&(h.return=n);h!==null;){var P=h.dependencies;if(P!==null){w=h.child;for(var A=P.firstContext;A!==null;){if(A.context===s){if(h.tag===1){A=Mn(-1,i&-i),A.tag=2;var Z=h.updateQueue;if(Z!==null){Z=Z.shared;var se=Z.pending;se===null?A.next=A:(A.next=se.next,se.next=A),Z.pending=A}}h.lanes|=i,A=h.alternate,A!==null&&(A.lanes|=i),ba(h.return,i,n),P.lanes|=i;break}A=A.next}}else if(h.tag===10)w=h.type===n.type?null:h.child;else if(h.tag===18){if(w=h.return,w===null)throw Error(o(341));w.lanes|=i,P=w.alternate,P!==null&&(P.lanes|=i),ba(w,i,n),w=h.sibling}else w=h.child;if(w!==null)w.return=h;else for(w=h;w!==null;){if(w===n){w=null;break}if(h=w.sibling,h!==null){h.return=w.return,w=h;break}w=w.return}h=w}_t(e,n,c.children,i),n=n.child}return n;case 9:return c=n.type,s=n.pendingProps.children,yi(n,i),c=Vt(c),s=s(c),n.flags|=1,_t(e,n,s,i),n.child;case 14:return s=n.type,c=Kt(s,n.pendingProps),c=Kt(s.type,c),nf(e,n,s,c,i);case 15:return rf(e,n,n.type,n.pendingProps,i);case 17:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ms(e,n),n.tag=1,Nt(s)?(e=!0,ds(n)):e=!1,yi(n,i),Xd(n,s,c),Va(n,s,c,i),Ga(null,n,s,!0,e,i);case 19:return ff(e,n,i);case 22:return of(e,n,i)}throw Error(o(156,n.tag))};function zf(e,n){return Ce(e,n)}function Hy(e,n,i,s){this.tag=e,this.key=i,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=s,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Yt(e,n,i,s){return new Hy(e,n,i,s)}function hu(e){return e=e.prototype,!(!e||!e.isReactComponent)}function By(e){if(typeof e=="function")return hu(e)?1:0;if(e!=null){if(e=e.$$typeof,e===ee)return 11;if(e===Y)return 14}return 2}function sr(e,n){var i=e.alternate;return i===null?(i=Yt(e.tag,n,e.key,e.mode),i.elementType=e.elementType,i.type=e.type,i.stateNode=e.stateNode,i.alternate=e,e.alternate=i):(i.pendingProps=n,i.type=e.type,i.flags=0,i.subtreeFlags=0,i.deletions=null),i.flags=e.flags&14680064,i.childLanes=e.childLanes,i.lanes=e.lanes,i.child=e.child,i.memoizedProps=e.memoizedProps,i.memoizedState=e.memoizedState,i.updateQueue=e.updateQueue,n=e.dependencies,i.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext},i.sibling=e.sibling,i.index=e.index,i.ref=e.ref,i}function Fs(e,n,i,s,c,h){var w=2;if(s=e,typeof e=="function")hu(e)&&(w=1);else if(typeof e=="string")w=5;else e:switch(e){case H:return Lr(i.children,c,h,n);case I:w=8,c|=8;break;case q:return e=Yt(12,i,n,c|2),e.elementType=q,e.lanes=h,e;case J:return e=Yt(13,i,n,c),e.elementType=J,e.lanes=h,e;case C:return e=Yt(19,i,n,c),e.elementType=C,e.lanes=h,e;case U:return Hs(i,c,h,n);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case ne:w=10;break e;case G:w=9;break e;case ee:w=11;break e;case Y:w=14;break e;case V:w=16,s=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return n=Yt(w,i,n,c),n.elementType=e,n.type=s,n.lanes=h,n}function Lr(e,n,i,s){return e=Yt(7,e,s,n),e.lanes=i,e}function Hs(e,n,i,s){return e=Yt(22,e,s,n),e.elementType=U,e.lanes=i,e.stateNode={isHidden:!1},e}function pu(e,n,i){return e=Yt(6,e,null,n),e.lanes=i,e}function gu(e,n,i){return n=Yt(4,e.children!==null?e.children:[],e.key,n),n.lanes=i,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}function Vy(e,n,i,s,c){this.tag=n,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=_r(0),this.expirationTimes=_r(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=_r(0),this.identifierPrefix=s,this.onRecoverableError=c,this.mutableSourceEagerHydrationData=null}function mu(e,n,i,s,c,h,w,P,A){return e=new Vy(e,n,i,P,A),n===1?(n=1,h===!0&&(n|=8)):n=0,h=Yt(3,null,null,n),e.current=h,h.stateNode=e,h.memoizedState={element:s,isDehydrated:i,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(h),e}function Wy(e,n,i){var s=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Su.exports=n0(),Su.exports}var Qf;function r0(){if(Qf)return Xs;Qf=1;var t=wp();return Xs.createRoot=t.createRoot,Xs.hydrateRoot=t.hydrateRoot,Xs}var i0=r0();function o0(t,r="Request failed"){const o=(t||"").trim();if(!o)return r;try{const a=JSON.parse(o).detail;if(typeof a=="string"&&a.trim())return a;if(Array.isArray(a)){const u=a.map(d=>typeof d=="string"?d:d&&typeof d=="object"&&"msg"in d?String(d.msg):"").filter(Boolean);if(u.length)return u.join("; ")}}catch{}return o}async function Ve(t,r){const o=await fetch(t,{...r,headers:{"Content-Type":"application/json",...(r==null?void 0:r.headers)||{}}});if(!o.ok){const l=await o.text();throw new Error(o0(l,o.statusText||"Request failed"))}return o.json()}const s0=["github_token","gitlab_token","gitlab_oauth_client_secret","bitbucket_token","bitbucket_oauth_client_secret","ai_api_key","ai_model","ai_base_url"],$e={health:()=>Ve("/api/health"),settings:()=>Ve("/api/settings"),saveSettings:t=>{const r={...t};for(const o of s0)r[o]===""&&delete r[o];return Ve("/api/settings",{method:"PUT",body:JSON.stringify(r)})},repos:()=>Ve("/api/repos"),browse:t=>Ve(`/api/fs${t?`?path=${encodeURIComponent(t)}`:""}`),gitRefs:(t,r=50)=>Ve(`/api/git/refs?repo_path=${encodeURIComponent(t)}&limit=${r}`),index:(t,r=!0)=>Ve("/api/index",{method:"POST",body:JSON.stringify({repo_path:t,incremental:r})}),indexStatus:t=>Ve(`/api/index?repo_path=${encodeURIComponent(t)}`),indexProgress:t=>Ve(`/api/index/progress?repo_path=${encodeURIComponent(t)}`),architecture:t=>Ve(`/api/architecture?repo_path=${encodeURIComponent(t)}`),review:(t,r,o,l=!0,a=!1)=>Ve("/api/review",{method:"POST",body:JSON.stringify({repo_path:t,base:r,head:o||null,reindex:l,incremental:!0,three_dot:!0,dirty:a})}),whatIf:(t,r)=>Ve("/api/whatif",{method:"POST",body:JSON.stringify({repo_path:t,node_id:r})}),reviewPr:(t,r,o,l)=>Ve("/api/prs/review",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,repo_path:l||null})}),init:(t,r=!1)=>Ve("/api/init",{method:"POST",body:JSON.stringify({repo_path:t,overwrite:r})}),postComment:(t,r,o,l)=>Ve("/api/prs/comment",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,markdown:l})}),graph:(t,r="full")=>Ve(`/api/graph?repo_path=${encodeURIComponent(t)}&scope=${r}`),prs:(t,r,o="open")=>Ve("/api/prs",{method:"POST",body:JSON.stringify({provider:t,repo:r,state:o})}),scmRepos:t=>Ve(`/api/scm/repos?provider=${encodeURIComponent(t)}`),oauthStatus:()=>Ve("/api/oauth/status"),githubOAuthStart:()=>Ve("/api/oauth/github/start",{method:"POST",body:"{}"}),githubOAuthPoll:t=>Ve("/api/oauth/github/poll",{method:"POST",body:JSON.stringify({flow_id:t})}),bitbucketOAuthStart:()=>Ve("/api/oauth/bitbucket/start"),gitlabOAuthStart:()=>Ve("/api/oauth/gitlab/start"),oauthDisconnect:t=>Ve("/api/oauth/disconnect",{method:"POST",body:JSON.stringify({provider:t})}),residual:t=>Ve("/api/ai/residual",{method:"POST",body:JSON.stringify({review:t})})};function No(t){return t.replaceAll("_"," ")}function l0(t){return t.replaceAll("_"," ")}function _l(t){return t.split(".").pop()||t}function _p(t){if(!t)return"";const r=new Date(t);return Number.isNaN(r.getTime())?t:r.toLocaleString()}function Ni(t){return t.replace(/([/\\._:@-])/g,"$1​")}function Wr({className:t,children:r}){return p.jsx("svg",{className:t,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:r})}function a0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("path",{d:"M3 3.5h6.5L13 7v5.5H3z"}),p.jsx("path",{d:"M9.5 3.5V7H13"}),p.jsx("path",{d:"M5.5 9.5h5M5.5 11.5h3.5"})]})}function u0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("rect",{x:"2.5",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"2.5",y:"9",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"9",width:"4.5",height:"4.5",rx:"0.8"})]})}function c0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4",cy:"8",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"4",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"12",r:"1.6"}),p.jsx("path",{d:"M5.5 7.2 10.4 4.8M5.5 8.8 10.4 11.2"})]})}function d0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4.5",cy:"4",r:"1.4"}),p.jsx("circle",{cx:"4.5",cy:"12",r:"1.4"}),p.jsx("circle",{cx:"11.5",cy:"12",r:"1.4"}),p.jsx("path",{d:"M4.5 5.5v5M4.5 8h4.2a3 3 0 0 1 3 3"})]})}function f0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"8",cy:"8",r:"2.1"}),p.jsx("path",{d:"M8 2.5v1.6M8 11.9v1.6M2.5 8h1.6M11.9 8h1.6M4.1 4.1l1.1 1.1M10.8 10.8l1.1 1.1M11.9 4.1l-1.1 1.1M5.2 10.8l-1.1 1.1"})]})}function Sp({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M2.5 4.5h4L8 6h5.5v6.5h-11z"})})}function h0({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M4 6.5 8 10.5 12 6.5"})})}const p0="modulepreload",g0=function(t,r){return new URL(t,r).href},Kf={},m0=function(r,o,l){let a=Promise.resolve();if(o&&o.length>0){let d=function(m){return Promise.all(m.map(x=>Promise.resolve(x).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};const f=document.getElementsByTagName("link"),g=document.querySelector("meta[property=csp-nonce]"),y=(g==null?void 0:g.nonce)||(g==null?void 0:g.getAttribute("nonce"));a=d(o.map(m=>{if(m=g0(m,l),m in Kf)return;Kf[m]=!0;const x=m.endsWith(".css"),v=x?'[rel="stylesheet"]':"";if(!!l)for(let j=f.length-1;j>=0;j--){const N=f[j];if(N.href===m&&(!x||N.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${m}"]${v}`))return;const S=document.createElement("link");if(S.rel=x?"stylesheet":p0,x||(S.as="script"),S.crossOrigin="",S.href=m,y&&S.setAttribute("nonce",y),document.head.appendChild(S),x)return new Promise((j,N)=>{S.addEventListener("load",j),S.addEventListener("error",()=>N(new Error(`Unable to preload CSS for ${m}`)))})}))}function u(d){const f=new Event("vite:preloadError",{cancelable:!0});if(f.payload=d,window.dispatchEvent(f),!f.defaultPrevented)throw d}return a.then(d=>{for(const f of d||[])f.status==="rejected"&&u(f.reason);return r().catch(u)})};function it(t){if(typeof t=="string"||typeof t=="number")return""+t;let r="";if(Array.isArray(t))for(let o=0,l;o{}};function Sl(){for(var t=0,r=arguments.length,o={},l;t=0&&(l=o.slice(a+1),o=o.slice(0,a)),o&&!r.hasOwnProperty(o))throw new Error("unknown type: "+o);return{type:o,name:l}})}ol.prototype=Sl.prototype={constructor:ol,on:function(t,r){var o=this._,l=v0(t+"",o),a,u=-1,d=l.length;if(arguments.length<2){for(;++u0)for(var o=new Array(a),l=0,a,u;l=0&&(r=t.slice(0,o))!=="xmlns"&&(t=t.slice(o+1)),Jf.hasOwnProperty(r)?{space:Jf[r],local:t}:t}function w0(t){return function(){var r=this.ownerDocument,o=this.namespaceURI;return o===Fu&&r.documentElement.namespaceURI===Fu?r.createElement(t):r.createElementNS(o,t)}}function _0(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function kp(t){var r=kl(t);return(r.local?_0:w0)(r)}function S0(){}function ec(t){return t==null?S0:function(){return this.querySelector(t)}}function k0(t){typeof t!="function"&&(t=ec(t));for(var r=this._groups,o=r.length,l=new Array(o),a=0;a=E&&(E=T+1);!($=N[E])&&++E=0;)(d=l[a])&&(u&&d.compareDocumentPosition(u)^4&&u.parentNode.insertBefore(d,u),u=d);return this}function X0(t){t||(t=q0);function r(x,v){return x&&v?t(x.__data__,v.__data__):!x-!v}for(var o=this._groups,l=o.length,a=new Array(l),u=0;ur?1:t>=r?0:NaN}function Q0(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function K0(){return Array.from(this)}function Z0(){for(var t=this._groups,r=0,o=t.length;r1?this.each((r==null?uv:typeof r=="function"?dv:cv)(t,r,o??"")):Mi(this.node(),t)}function Mi(t,r){return t.style.getPropertyValue(r)||Cp(t).getComputedStyle(t,null).getPropertyValue(r)}function hv(t){return function(){delete this[t]}}function pv(t,r){return function(){this[t]=r}}function gv(t,r){return function(){var o=r.apply(this,arguments);o==null?delete this[t]:this[t]=o}}function mv(t,r){return arguments.length>1?this.each((r==null?hv:typeof r=="function"?gv:pv)(t,r)):this.node()[t]}function Mp(t){return t.trim().split(/^|\s+/)}function tc(t){return t.classList||new Pp(t)}function Pp(t){this._node=t,this._names=Mp(t.getAttribute("class")||"")}Pp.prototype={add:function(t){var r=this._names.indexOf(t);r<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var r=this._names.indexOf(t);r>=0&&(this._names.splice(r,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Ip(t,r){for(var o=tc(t),l=-1,a=r.length;++l=0&&(o=r.slice(l+1),r=r.slice(0,l)),{type:r,name:o}})}function Wv(t){return function(){var r=this.__on;if(r){for(var o=0,l=-1,a=r.length,u;o()=>t;function Hu(t,{sourceEvent:r,subject:o,target:l,identifier:a,active:u,x:d,y:f,dx:g,dy:y,dispatch:m}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},subject:{value:o,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},identifier:{value:a,enumerable:!0,configurable:!0},active:{value:u,enumerable:!0,configurable:!0},x:{value:d,enumerable:!0,configurable:!0},y:{value:f,enumerable:!0,configurable:!0},dx:{value:g,enumerable:!0,configurable:!0},dy:{value:y,enumerable:!0,configurable:!0},_:{value:m}})}Hu.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};function ex(t){return!t.ctrlKey&&!t.button}function tx(){return this.parentNode}function nx(t,r){return r??{x:t.x,y:t.y}}function rx(){return navigator.maxTouchPoints||"ontouchstart"in this}function Dp(){var t=ex,r=tx,o=nx,l=rx,a={},u=Sl("start","drag","end"),d=0,f,g,y,m,x=0;function v(b){b.on("mousedown.drag",_).filter(l).on("touchstart.drag",N).on("touchmove.drag",k,Jv).on("touchend.drag touchcancel.drag",T).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(b,$){if(!(m||!t.call(this,b,$))){var O=E(this,r.call(this,b,$),b,$,"mouse");O&&(Ot(b.view).on("mousemove.drag",S,jo).on("mouseup.drag",j,jo),Ap(b.view),Nu(b),y=!1,f=b.clientX,g=b.clientY,O("start",b))}}function S(b){if(bi(b),!y){var $=b.clientX-f,O=b.clientY-g;y=$*$+O*O>x}a.mouse("drag",b)}function j(b){Ot(b.view).on("mousemove.drag mouseup.drag",null),zp(b.view,y),bi(b),a.mouse("end",b)}function N(b,$){if(t.call(this,b,$)){var O=b.changedTouches,H=r.call(this,b,$),I=O.length,q,ne;for(q=0;q>8&15|r>>4&240,r>>4&15|r&240,(r&15)<<4|r&15,1):o===8?Qs(r>>24&255,r>>16&255,r>>8&255,(r&255)/255):o===4?Qs(r>>12&15|r>>8&240,r>>8&15|r>>4&240,r>>4&15|r&240,((r&15)<<4|r&15)/255):null):(r=ox.exec(t))?new Pt(r[1],r[2],r[3],1):(r=sx.exec(t))?new Pt(r[1]*255/100,r[2]*255/100,r[3]*255/100,1):(r=lx.exec(t))?Qs(r[1],r[2],r[3],r[4]):(r=ax.exec(t))?Qs(r[1]*255/100,r[2]*255/100,r[3]*255/100,r[4]):(r=ux.exec(t))?sh(r[1],r[2]/100,r[3]/100,1):(r=cx.exec(t))?sh(r[1],r[2]/100,r[3]/100,r[4]):eh.hasOwnProperty(t)?rh(eh[t]):t==="transparent"?new Pt(NaN,NaN,NaN,0):null}function rh(t){return new Pt(t>>16&255,t>>8&255,t&255,1)}function Qs(t,r,o,l){return l<=0&&(t=r=o=NaN),new Pt(t,r,o,l)}function hx(t){return t instanceof $o||(t=Or(t)),t?(t=t.rgb(),new Pt(t.r,t.g,t.b,t.opacity)):new Pt}function Bu(t,r,o,l){return arguments.length===1?hx(t):new Pt(t,r,o,l??1)}function Pt(t,r,o,l){this.r=+t,this.g=+r,this.b=+o,this.opacity=+l}nc(Pt,Bu,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new Pt(Dr(this.r),Dr(this.g),Dr(this.b),fl(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:ih,formatHex:ih,formatHex8:px,formatRgb:oh,toString:oh}));function ih(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}`}function px(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}${zr((isNaN(this.opacity)?1:this.opacity)*255)}`}function oh(){const t=fl(this.opacity);return`${t===1?"rgb(":"rgba("}${Dr(this.r)}, ${Dr(this.g)}, ${Dr(this.b)}${t===1?")":`, ${t})`}`}function fl(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Dr(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function zr(t){return t=Dr(t),(t<16?"0":"")+t.toString(16)}function sh(t,r,o,l){return l<=0?t=r=o=NaN:o<=0||o>=1?t=r=NaN:r<=0&&(t=NaN),new nn(t,r,o,l)}function Op(t){if(t instanceof nn)return new nn(t.h,t.s,t.l,t.opacity);if(t instanceof $o||(t=Or(t)),!t)return new nn;if(t instanceof nn)return t;t=t.rgb();var r=t.r/255,o=t.g/255,l=t.b/255,a=Math.min(r,o,l),u=Math.max(r,o,l),d=NaN,f=u-a,g=(u+a)/2;return f?(r===u?d=(o-l)/f+(o0&&g<1?0:d,new nn(d,f,g,t.opacity)}function gx(t,r,o,l){return arguments.length===1?Op(t):new nn(t,r,o,l??1)}function nn(t,r,o,l){this.h=+t,this.s=+r,this.l=+o,this.opacity=+l}nc(nn,gx,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new nn(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new nn(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,r=isNaN(t)||isNaN(this.s)?0:this.s,o=this.l,l=o+(o<.5?o:1-o)*r,a=2*o-l;return new Pt(ju(t>=240?t-240:t+120,a,l),ju(t,a,l),ju(t<120?t+240:t-120,a,l),this.opacity)},clamp(){return new nn(lh(this.h),Ks(this.s),Ks(this.l),fl(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=fl(this.opacity);return`${t===1?"hsl(":"hsla("}${lh(this.h)}, ${Ks(this.s)*100}%, ${Ks(this.l)*100}%${t===1?")":`, ${t})`}`}}));function lh(t){return t=(t||0)%360,t<0?t+360:t}function Ks(t){return Math.max(0,Math.min(1,t||0))}function ju(t,r,o){return(t<60?r+(o-r)*t/60:t<180?o:t<240?r+(o-r)*(240-t)/60:r)*255}const rc=t=>()=>t;function mx(t,r){return function(o){return t+o*r}}function yx(t,r,o){return t=Math.pow(t,o),r=Math.pow(r,o)-t,o=1/o,function(l){return Math.pow(t+l*r,o)}}function vx(t){return(t=+t)==1?Fp:function(r,o){return o-r?yx(r,o,t):rc(isNaN(r)?o:r)}}function Fp(t,r){var o=r-t;return o?mx(t,o):rc(isNaN(t)?r:t)}const hl=(function t(r){var o=vx(r);function l(a,u){var d=o((a=Bu(a)).r,(u=Bu(u)).r),f=o(a.g,u.g),g=o(a.b,u.b),y=Fp(a.opacity,u.opacity);return function(m){return a.r=d(m),a.g=f(m),a.b=g(m),a.opacity=y(m),a+""}}return l.gamma=t,l})(1);function xx(t,r){r||(r=[]);var o=t?Math.min(r.length,t.length):0,l=r.slice(),a;return function(u){for(a=0;ao&&(u=r.slice(o,u),f[d]?f[d]+=u:f[++d]=u),(l=l[0])===(a=a[0])?f[d]?f[d]+=a:f[++d]=a:(f[++d]=null,g.push({i:d,x:gn(l,a)})),o=bu.lastIndex;return o180?m+=360:m-y>180&&(y+=360),v.push({i:x.push(a(x)+"rotate(",null,l)-2,x:gn(y,m)})):m&&x.push(a(x)+"rotate("+m+l)}function f(y,m,x,v){y!==m?v.push({i:x.push(a(x)+"skewX(",null,l)-2,x:gn(y,m)}):m&&x.push(a(x)+"skewX("+m+l)}function g(y,m,x,v,_,S){if(y!==x||m!==v){var j=_.push(a(_)+"scale(",null,",",null,")");S.push({i:j-4,x:gn(y,x)},{i:j-2,x:gn(m,v)})}else(x!==1||v!==1)&&_.push(a(_)+"scale("+x+","+v+")")}return function(y,m){var x=[],v=[];return y=t(y),m=t(m),u(y.translateX,y.translateY,m.translateX,m.translateY,x,v),d(y.rotate,m.rotate,x,v),f(y.skewX,m.skewX,x,v),g(y.scaleX,y.scaleY,m.scaleX,m.scaleY,x,v),y=m=null,function(_){for(var S=-1,j=v.length,N;++S=0&&t._call.call(void 0,r),t=t._next;--Pi}function ch(){Fr=(gl=Mo.now())+El,Pi=_o=0;try{Lx()}finally{Pi=0,zx(),Fr=0}}function Ax(){var t=Mo.now(),r=t-gl;r>Wp&&(El-=r,gl=t)}function zx(){for(var t,r=pl,o,l=1/0;r;)r._call?(l>r._time&&(l=r._time),t=r,r=r._next):(o=r._next,r._next=null,r=t?t._next=o:pl=o);So=t,Uu(l)}function Uu(t){if(!Pi){_o&&(_o=clearTimeout(_o));var r=t-Fr;r>24?(t<1/0&&(_o=setTimeout(ch,t-Mo.now()-El)),xo&&(xo=clearInterval(xo))):(xo||(gl=Mo.now(),xo=setInterval(Ax,Wp)),Pi=1,Up(ch))}}function dh(t,r,o){var l=new ml;return r=r==null?0:+r,l.restart(a=>{l.stop(),t(a+r)},r,o),l}var Dx=Sl("start","end","cancel","interrupt"),$x=[],Gp=0,fh=1,Yu=2,ll=3,hh=4,Gu=5,al=6;function Nl(t,r,o,l,a,u){var d=t.__transition;if(!d)t.__transition={};else if(o in d)return;Ox(t,o,{name:r,index:l,group:a,on:Dx,tween:$x,time:u.time,delay:u.delay,duration:u.duration,ease:u.ease,timer:null,state:Gp})}function oc(t,r){var o=ln(t,r);if(o.state>Gp)throw new Error("too late; already scheduled");return o}function yn(t,r){var o=ln(t,r);if(o.state>ll)throw new Error("too late; already running");return o}function ln(t,r){var o=t.__transition;if(!o||!(o=o[r]))throw new Error("transition not found");return o}function Ox(t,r,o){var l=t.__transition,a;l[r]=o,o.timer=Yp(u,0,o.time);function u(y){o.state=fh,o.timer.restart(d,o.delay,o.time),o.delay<=y&&d(y-o.delay)}function d(y){var m,x,v,_;if(o.state!==fh)return g();for(m in l)if(_=l[m],_.name===o.name){if(_.state===ll)return dh(d);_.state===hh?(_.state=al,_.timer.stop(),_.on.call("interrupt",t,t.__data__,_.index,_.group),delete l[m]):+mYu&&l.state=0&&(r=r.slice(0,o)),!r||r==="start"})}function gw(t,r,o){var l,a,u=pw(r)?oc:yn;return function(){var d=u(this,t),f=d.on;f!==l&&(a=(l=f).copy()).on(r,o),d.on=a}}function mw(t,r){var o=this._id;return arguments.length<2?ln(this.node(),o).on.on(t):this.each(gw(o,t,r))}function yw(t){return function(){var r=this.parentNode;for(var o in this.__transition)if(+o!==t)return;r&&r.removeChild(this)}}function vw(){return this.on("end.remove",yw(this._id))}function xw(t){var r=this._name,o=this._id;typeof t!="function"&&(t=ec(t));for(var l=this._groups,a=l.length,u=new Array(a),d=0;d()=>t;function Ww(t,{sourceEvent:r,target:o,transform:l,dispatch:a}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},transform:{value:l,enumerable:!0,configurable:!0},_:{value:a}})}function Rn(t,r,o){this.k=t,this.x=r,this.y=o}Rn.prototype={constructor:Rn,scale:function(t){return t===1?this:new Rn(this.k*t,this.x,this.y)},translate:function(t,r){return t===0&r===0?this:new Rn(this.k,this.x+this.k*t,this.y+this.k*r)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var jl=new Rn(1,0,0);Kp.prototype=Rn.prototype;function Kp(t){for(;!t.__zoom;)if(!(t=t.parentNode))return jl;return t.__zoom}function Cu(t){t.stopImmediatePropagation()}function wo(t){t.preventDefault(),t.stopImmediatePropagation()}function Uw(t){return(!t.ctrlKey||t.type==="wheel")&&!t.button}function Yw(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t,t.hasAttribute("viewBox")?(t=t.viewBox.baseVal,[[t.x,t.y],[t.x+t.width,t.y+t.height]]):[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]):[[0,0],[t.clientWidth,t.clientHeight]]}function ph(){return this.__zoom||jl}function Gw(t){return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Xw(){return navigator.maxTouchPoints||"ontouchstart"in this}function qw(t,r,o){var l=t.invertX(r[0][0])-o[0][0],a=t.invertX(r[1][0])-o[1][0],u=t.invertY(r[0][1])-o[0][1],d=t.invertY(r[1][1])-o[1][1];return t.translate(a>l?(l+a)/2:Math.min(0,l)||Math.max(0,a),d>u?(u+d)/2:Math.min(0,u)||Math.max(0,d))}function Zp(){var t=Uw,r=Yw,o=qw,l=Gw,a=Xw,u=[0,1/0],d=[[-1/0,-1/0],[1/0,1/0]],f=250,g=sl,y=Sl("start","zoom","end"),m,x,v,_=500,S=150,j=0,N=10;function k(C){C.property("__zoom",ph).on("wheel.zoom",I,{passive:!1}).on("mousedown.zoom",q).on("dblclick.zoom",ne).filter(a).on("touchstart.zoom",G).on("touchmove.zoom",ee).on("touchend.zoom touchcancel.zoom",J).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}k.transform=function(C,Y,V,U){var z=C.selection?C.selection():C;z.property("__zoom",ph),C!==z?$(C,Y,V,U):z.interrupt().each(function(){O(this,arguments).event(U).start().zoom(null,typeof Y=="function"?Y.apply(this,arguments):Y).end()})},k.scaleBy=function(C,Y,V,U){k.scaleTo(C,function(){var z=this.__zoom.k,D=typeof Y=="function"?Y.apply(this,arguments):Y;return z*D},V,U)},k.scaleTo=function(C,Y,V,U){k.transform(C,function(){var z=r.apply(this,arguments),D=this.__zoom,W=V==null?b(z):typeof V=="function"?V.apply(this,arguments):V,M=D.invert(W),R=typeof Y=="function"?Y.apply(this,arguments):Y;return o(E(T(D,R),W,M),z,d)},V,U)},k.translateBy=function(C,Y,V,U){k.transform(C,function(){return o(this.__zoom.translate(typeof Y=="function"?Y.apply(this,arguments):Y,typeof V=="function"?V.apply(this,arguments):V),r.apply(this,arguments),d)},null,U)},k.translateTo=function(C,Y,V,U,z){k.transform(C,function(){var D=r.apply(this,arguments),W=this.__zoom,M=U==null?b(D):typeof U=="function"?U.apply(this,arguments):U;return o(jl.translate(M[0],M[1]).scale(W.k).translate(typeof Y=="function"?-Y.apply(this,arguments):-Y,typeof V=="function"?-V.apply(this,arguments):-V),D,d)},U,z)};function T(C,Y){return Y=Math.max(u[0],Math.min(u[1],Y)),Y===C.k?C:new Rn(Y,C.x,C.y)}function E(C,Y,V){var U=Y[0]-V[0]*C.k,z=Y[1]-V[1]*C.k;return U===C.x&&z===C.y?C:new Rn(C.k,U,z)}function b(C){return[(+C[0][0]+ +C[1][0])/2,(+C[0][1]+ +C[1][1])/2]}function $(C,Y,V,U){C.on("start.zoom",function(){O(this,arguments).event(U).start()}).on("interrupt.zoom end.zoom",function(){O(this,arguments).event(U).end()}).tween("zoom",function(){var z=this,D=arguments,W=O(z,D).event(U),M=r.apply(z,D),R=V==null?b(M):typeof V=="function"?V.apply(z,D):V,re=Math.max(M[1][0]-M[0][0],M[1][1]-M[0][1]),ie=z.__zoom,ce=typeof Y=="function"?Y.apply(z,D):Y,fe=g(ie.invert(R).concat(re/ie.k),ce.invert(R).concat(re/ce.k));return function(de){if(de===1)de=ce;else{var K=fe(de),le=re/K[2];de=new Rn(le,R[0]-K[0]*le,R[1]-K[1]*le)}W.zoom(null,de)}})}function O(C,Y,V){return!V&&C.__zooming||new H(C,Y)}function H(C,Y){this.that=C,this.args=Y,this.active=0,this.sourceEvent=null,this.extent=r.apply(C,Y),this.taps=0}H.prototype={event:function(C){return C&&(this.sourceEvent=C),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(C,Y){return this.mouse&&C!=="mouse"&&(this.mouse[1]=Y.invert(this.mouse[0])),this.touch0&&C!=="touch"&&(this.touch0[1]=Y.invert(this.touch0[0])),this.touch1&&C!=="touch"&&(this.touch1[1]=Y.invert(this.touch1[0])),this.that.__zoom=Y,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(C){var Y=Ot(this.that).datum();y.call(C,this.that,new Ww(C,{sourceEvent:this.sourceEvent,target:k,transform:this.that.__zoom,dispatch:y}),Y)}};function I(C,...Y){if(!t.apply(this,arguments))return;var V=O(this,Y).event(C),U=this.__zoom,z=Math.max(u[0],Math.min(u[1],U.k*Math.pow(2,l.apply(this,arguments)))),D=tn(C);if(V.wheel)(V.mouse[0][0]!==D[0]||V.mouse[0][1]!==D[1])&&(V.mouse[1]=U.invert(V.mouse[0]=D)),clearTimeout(V.wheel);else{if(U.k===z)return;V.mouse=[D,U.invert(D)],ul(this),V.start()}wo(C),V.wheel=setTimeout(W,S),V.zoom("mouse",o(E(T(U,z),V.mouse[0],V.mouse[1]),V.extent,d));function W(){V.wheel=null,V.end()}}function q(C,...Y){if(v||!t.apply(this,arguments))return;var V=C.currentTarget,U=O(this,Y,!0).event(C),z=Ot(C.view).on("mousemove.zoom",R,!0).on("mouseup.zoom",re,!0),D=tn(C,V),W=C.clientX,M=C.clientY;Ap(C.view),Cu(C),U.mouse=[D,this.__zoom.invert(D)],ul(this),U.start();function R(ie){if(wo(ie),!U.moved){var ce=ie.clientX-W,fe=ie.clientY-M;U.moved=ce*ce+fe*fe>j}U.event(ie).zoom("mouse",o(E(U.that.__zoom,U.mouse[0]=tn(ie,V),U.mouse[1]),U.extent,d))}function re(ie){z.on("mousemove.zoom mouseup.zoom",null),zp(ie.view,U.moved),wo(ie),U.event(ie).end()}}function ne(C,...Y){if(t.apply(this,arguments)){var V=this.__zoom,U=tn(C.changedTouches?C.changedTouches[0]:C,this),z=V.invert(U),D=V.k*(C.shiftKey?.5:2),W=o(E(T(V,D),U,z),r.apply(this,Y),d);wo(C),f>0?Ot(this).transition().duration(f).call($,W,U,C):Ot(this).call(k.transform,W,U,C)}}function G(C,...Y){if(t.apply(this,arguments)){var V=C.touches,U=V.length,z=O(this,Y,C.changedTouches.length===U).event(C),D,W,M,R;for(Cu(C),W=0;W`Seems like you have not used ${t==="svelte"?"SvelteFlowProvider":"ReactFlowProvider"} as an ancestor. Help: https://${t}flow.dev/error#001`,error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:t=>`Node type "${t}" not found. Using fallback type "default".`,error004:()=>"The parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:t=>`The old edge with id=${t} does not exist.`,error009:t=>`Marker type "${t}" doesn't exist.`,error008:(t,{id:r,sourceHandle:o,targetHandle:l})=>`Couldn't create edge for ${t} handle id: "${t==="source"?o:l}", edge id: ${r}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:t=>`Edge type "${t}" not found. Using fallback type "default".`,error012:t=>`Node with id "${t}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(t="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${t}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs.",error016:t=>`Edge with id "${t}" does not exist, it may have been removed. This can happen when an edge is deleted before the "onEdgeClick" handler is called.`},Po=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Jp=["Enter"," ","Escape"],eg={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:t,x:r,y:o})=>`Moved selected node ${t}. New position, x: ${r}, y: ${o}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"};var Ii;(function(t){t.Strict="strict",t.Loose="loose"})(Ii||(Ii={}));var $r;(function(t){t.Free="free",t.Vertical="vertical",t.Horizontal="horizontal"})($r||($r={}));var Io;(function(t){t.Partial="partial",t.Full="full"})(Io||(Io={}));const tg={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};var dr;(function(t){t.Bezier="default",t.Straight="straight",t.Step="step",t.SmoothStep="smoothstep",t.SimpleBezier="simplebezier"})(dr||(dr={}));var To;(function(t){t.Arrow="arrow",t.ArrowClosed="arrowclosed"})(To||(To={}));var Se;(function(t){t.Left="left",t.Top="top",t.Right="right",t.Bottom="bottom"})(Se||(Se={}));const gh={[Se.Left]:Se.Right,[Se.Right]:Se.Left,[Se.Top]:Se.Bottom,[Se.Bottom]:Se.Top};function ng(t){return t===null?null:t?"valid":"invalid"}const rg=t=>!!t&&typeof t=="object"&&"id"in t&&"source"in t&&"target"in t,Qw=t=>!!t&&typeof t=="object"&&"id"in t&&"position"in t&&!("source"in t)&&!("target"in t),lc=t=>!!t&&typeof t=="object"&&"id"in t&&"internals"in t&&!("source"in t)&&!("target"in t),Oo=(t,r=[0,0])=>{const{width:o,height:l}=an(t),a=t.origin??r,u=o*a[0],d=l*a[1];return{x:t.position.x-u,y:t.position.y-d}},Kw=(t,r={nodeOrigin:[0,0]})=>{if(t.length===0)return{x:0,y:0,width:0,height:0};let o=!1;const l=t.reduce((a,u)=>{const d=typeof u=="string";let f=!r.nodeLookup&&!d?u:void 0;return r.nodeLookup&&(f=d?r.nodeLookup.get(u):lc(u)?u:r.nodeLookup.get(u.id)),f?(o=!0,bl(a,yl(f,r.nodeOrigin))):a},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return o?Cl(l):{x:0,y:0,width:0,height:0}},Fo=(t,r={})=>{let o={x:1/0,y:1/0,x2:-1/0,y2:-1/0},l=!1;return t.forEach(a=>{(r.filter===void 0||r.filter(a))&&(o=bl(o,yl(a)),l=!0)}),l?Cl(o):{x:0,y:0,width:0,height:0}},ac=(t,r,[o,l,a]=[0,0,1],u=!1,d=!1)=>{const f=(r.x-o)/a,g=(r.y-l)/a,y=r.width/a,m=r.height/a,x=[];for(const v of t.values()){const{measured:_,selectable:S=!0,hidden:j=!1}=v;if(d&&!S||j)continue;const N=_.width??v.width??v.initialWidth??0,k=_.height??v.height??v.initialHeight??0,{x:T,y:E}=v.internals.positionAbsolute,b=lg(f,g,y,m,T,E,N,k),$=N*k,O=u&&b>0;(!v.internals.handleBounds||O||b>=$||v.dragging)&&x.push(v)}return x},Zw=(t,r)=>{const o=new Set;return t.forEach(l=>{o.add(l.id)}),r.filter(l=>o.has(l.source)||o.has(l.target))};function Jw(t,r){const o=new Map,l=r!=null&&r.nodes?new Set(r.nodes.map(a=>a.id)):null;return t.forEach(a=>{let u;if(r!=null&&r.includeHiddenNodes){const{width:d,height:f}=an(a);u=d>0&&f>0}else u=!!(a.measured.width&&a.measured.height&&!a.hidden);u&&(!l||l.has(a.id))&&o.set(a.id,a)}),o}async function e1({nodes:t,width:r,height:o,panZoom:l,minZoom:a,maxZoom:u},d){if(t.size===0)return!0;const f=Jw(t,d),g=Fo(f),y=cc(g,r,o,(d==null?void 0:d.minZoom)??a,(d==null?void 0:d.maxZoom)??u,(d==null?void 0:d.padding)??.1);return await l.setViewport(y,{duration:d==null?void 0:d.duration,ease:d==null?void 0:d.ease,interpolate:d==null?void 0:d.interpolate}),!0}function ig({nodeId:t,nextPosition:r,nodeLookup:o,nodeOrigin:l=[0,0],nodeExtent:a,onError:u}){const d=o.get(t),f=d.parentId?o.get(d.parentId):void 0,{x:g,y}=f?f.internals.positionAbsolute:{x:0,y:0},m=d.origin??l;let x=d.extent||a;if(d.extent==="parent"&&!d.expandParent)if(!f)u==null||u("005",sn.error005());else{const{width:_,height:S}=an(f);_&&S&&(x=[[g,y],[g+_,y+S]])}else f&&Br(d.extent)&&(x=[[d.extent[0][0]+g,d.extent[0][1]+y],[d.extent[1][0]+g,d.extent[1][1]+y]]);const v=Br(x)?Hr(r,x,d.measured):r;return(d.measured.width===void 0||d.measured.height===void 0)&&(u==null||u("015",sn.error015())),{position:{x:v.x-g+(d.measured.width??0)*m[0],y:v.y-y+(d.measured.height??0)*m[1]},positionAbsolute:v}}async function t1({nodesToRemove:t=[],edgesToRemove:r=[],nodes:o,edges:l,onBeforeDelete:a}){const u=new Set(t.map(v=>v.id)),d=[];for(const v of o){if(v.deletable===!1)continue;const _=u.has(v.id),S=!_&&v.parentId&&d.find(j=>j.id===v.parentId);(_||S)&&d.push(v)}const f=new Set(r.map(v=>v.id)),g=l.filter(v=>v.deletable!==!1),m=Zw(d,g);for(const v of g)f.has(v.id)&&!m.find(S=>S.id===v.id)&&m.push(v);if(!a)return{edges:m,nodes:d};const x=await a({nodes:d,edges:m});return typeof x=="boolean"?x?{edges:m,nodes:d}:{edges:[],nodes:[]}:x}const Ti=(t,r=0,o=1)=>Math.min(Math.max(t,r),o),Hr=(t={x:0,y:0},r,o)=>({x:Ti(t.x,r[0][0],r[1][0]-((o==null?void 0:o.width)??0)),y:Ti(t.y,r[0][1],r[1][1]-((o==null?void 0:o.height)??0))});function og(t,r,o){const{width:l,height:a}=an(o),{x:u,y:d}=o.internals.positionAbsolute;return Hr(t,[[u,d],[u+l,d+a]],r)}const mh=(t,r,o)=>to?-Ti(Math.abs(t-o),1,r)/r:0,uc=(t,r,o=15,l=40)=>{const a=mh(t.x,l,r.width-l)*o,u=mh(t.y,l,r.height-l)*o;return[a,u]},bl=(t,r)=>({x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),x2:Math.max(t.x2,r.x2),y2:Math.max(t.y2,r.y2)}),Xu=({x:t,y:r,width:o,height:l})=>({x:t,y:r,x2:t+o,y2:r+l}),Cl=({x:t,y:r,x2:o,y2:l})=>({x:t,y:r,width:o-t,height:l-r}),Ro=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,width:((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0,height:((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0}},yl=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,x2:o+(((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0),y2:l+(((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0)}},sg=(t,r)=>Cl(bl(Xu(t),Xu(r))),lg=(t,r,o,l,a,u,d,f)=>{const g=Math.max(0,Math.min(t+o,a+d)-Math.max(t,a)),y=Math.max(0,Math.min(r+l,u+f)-Math.max(r,u));return Math.ceil(g*y)},vl=(t,r)=>lg(t.x,t.y,t.width,t.height,r.x,r.y,r.width,r.height),yh=t=>rn(t.width)&&rn(t.height)&&rn(t.x)&&rn(t.y),rn=t=>!isNaN(t)&&isFinite(t),ag=(t,r)=>(o,l)=>{},Ho=(t,r=[1,1])=>({x:r[0]*Math.round(t.x/r[0]),y:r[1]*Math.round(t.y/r[1])}),Bo=({x:t,y:r},[o,l,a],u=!1,d=[1,1])=>{const f={x:(t-o)/a,y:(r-l)/a};return u?Ho(f,d):f},Ri=({x:t,y:r},[o,l,a])=>({x:t*a+o,y:r*a+l});function Ei(t,r){if(typeof t=="number")return Math.floor((r-r/(1+t))*.5);if(typeof t=="string"&&t.endsWith("px")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(o)}if(typeof t=="string"&&t.endsWith("%")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(r*o*.01)}return console.error(`The padding value "${t}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function n1(t,r,o){if(typeof t=="string"||typeof t=="number"){const l=Ei(t,o),a=Ei(t,r);return{top:l,right:a,bottom:l,left:a,x:a*2,y:l*2}}if(typeof t=="object"){const l=Ei(t.top??t.y??0,o),a=Ei(t.bottom??t.y??0,o),u=Ei(t.left??t.x??0,r),d=Ei(t.right??t.x??0,r);return{top:l,right:d,bottom:a,left:u,x:u+d,y:l+a}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function r1(t,r,o,l,a,u){const{x:d,y:f}=Ri(t,[r,o,l]),{x:g,y}=Ri({x:t.x+t.width,y:t.y+t.height},[r,o,l]),m=a-g,x=u-y;return{left:Math.floor(d),top:Math.floor(f),right:Math.floor(m),bottom:Math.floor(x)}}const cc=(t,r,o,l,a,u)=>{const d=n1(u,r,o),f=(r-d.x)/t.width,g=(o-d.y)/t.height,y=Math.min(f,g),m=Ti(y,l,a),x=t.x+t.width/2,v=t.y+t.height/2,_=r/2-x*m,S=o/2-v*m,j=r1(t,_,S,m,r,o),N={left:Math.min(j.left-d.left,0),top:Math.min(j.top-d.top,0),right:Math.min(j.right-d.right,0),bottom:Math.min(j.bottom-d.bottom,0)};return{x:_-N.left+N.right,y:S-N.top+N.bottom,zoom:m}},Lo=()=>{var t;return typeof navigator<"u"&&((t=navigator==null?void 0:navigator.userAgent)==null?void 0:t.indexOf("Mac"))>=0};function Br(t){return t!=null&&t!=="parent"}function an(t){var r,o;return{width:((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth??0,height:((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight??0}}function ug(t){var r,o;return(((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth)!==void 0&&(((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight)!==void 0}function cg(t,r={width:0,height:0},o,l,a){const u={...t},d=l.get(o);if(d){const f=d.origin||a;u.x+=d.internals.positionAbsolute.x-(r.width??0)*f[0],u.y+=d.internals.positionAbsolute.y-(r.height??0)*f[1]}return u}function vh(t,r){if(t.size!==r.size)return!1;for(const o of t)if(!r.has(o))return!1;return!0}function i1(){let t,r;return{promise:new Promise((l,a)=>{t=l,r=a}),resolve:t,reject:r}}function o1(t){return{...eg,...t||{}}}function Eo(t,{snapGrid:r=[0,0],snapToGrid:o=!1,transform:l,containerBounds:a}){const{x:u,y:d}=on(t),f=Bo({x:u-((a==null?void 0:a.left)??0),y:d-((a==null?void 0:a.top)??0)},l),{x:g,y}=o?Ho(f,r):f;return{xSnapped:g,ySnapped:y,...f}}const dc=t=>({width:t.offsetWidth,height:t.offsetHeight}),dg=t=>{var r;return((r=t==null?void 0:t.getRootNode)==null?void 0:r.call(t))||(window==null?void 0:window.document)},s1=["INPUT","SELECT","TEXTAREA"];function fg(t){var l,a;const r=((a=(l=t.composedPath)==null?void 0:l.call(t))==null?void 0:a[0])||t.target;return(r==null?void 0:r.nodeType)!==1?!1:s1.includes(r.nodeName)||r.hasAttribute("contenteditable")||!!r.closest(".nokey")}const hg=t=>"clientX"in t,on=(t,r)=>{var u,d;const o=hg(t),l=o?t.clientX:(u=t.touches)==null?void 0:u[0].clientX,a=o?t.clientY:(d=t.touches)==null?void 0:d[0].clientY;return{x:l-((r==null?void 0:r.left)??0),y:a-((r==null?void 0:r.top)??0)}},xh=(t,r,o,l,a)=>{const u=r.querySelectorAll(`.${t}`);return!u||!u.length?null:Array.from(u).map(d=>{const f=d.getBoundingClientRect();return{id:d.getAttribute("data-handleid"),type:t,nodeId:a,position:d.getAttribute("data-handlepos"),x:(f.left-o.left)/l,y:(f.top-o.top)/l,...dc(d)}})};function pg({sourceX:t,sourceY:r,targetX:o,targetY:l,sourceControlX:a,sourceControlY:u,targetControlX:d,targetControlY:f}){const g=t*.125+a*.375+d*.375+o*.125,y=r*.125+u*.375+f*.375+l*.125,m=Math.abs(g-t),x=Math.abs(y-r);return[g,y,m,x]}function el(t,r){return t>=0?.5*t:r*25*Math.sqrt(-t)}function wh({pos:t,x1:r,y1:o,x2:l,y2:a,c:u}){switch(t){case Se.Left:return[r-el(r-l,u),o];case Se.Right:return[r+el(l-r,u),o];case Se.Top:return[r,o-el(o-a,u)];case Se.Bottom:return[r,o+el(a-o,u)]}}function gg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top,curvature:d=.25}){const[f,g]=wh({pos:o,x1:t,y1:r,x2:l,y2:a,c:d}),[y,m]=wh({pos:u,x1:l,y1:a,x2:t,y2:r,c:d}),[x,v,_,S]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:f,sourceControlY:g,targetControlX:y,targetControlY:m});return[`M${t},${r} C${f},${g} ${y},${m} ${l},${a}`,x,v,_,S]}function mg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const a=Math.abs(o-t)/2,u=o0}const u1=({source:t,sourceHandle:r,target:o,targetHandle:l})=>`xy-edge__${t}${r||""}-${o}${l||""}`,c1=(t,r)=>r.some(o=>o.source===t.source&&o.target===t.target&&(o.sourceHandle===t.sourceHandle||!o.sourceHandle&&!t.sourceHandle)&&(o.targetHandle===t.targetHandle||!o.targetHandle&&!t.targetHandle)),d1=(t,r,o={})=>{var u;if(!t.source||!t.target)return(u=o.onError)==null||u.call(o,"006",sn.error006()),r;const l=o.getEdgeId||u1;let a;return rg(t)?a={...t}:a={...t,id:l(t)},c1(a,r)?r:(a.sourceHandle===null&&delete a.sourceHandle,a.targetHandle===null&&delete a.targetHandle,r.concat(a))};function yg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const[a,u,d,f]=mg({sourceX:t,sourceY:r,targetX:o,targetY:l});return[`M ${t},${r}L ${o},${l}`,a,u,d,f]}const _h={[Se.Left]:{x:-1,y:0},[Se.Right]:{x:1,y:0},[Se.Top]:{x:0,y:-1},[Se.Bottom]:{x:0,y:1}},f1=({source:t,sourcePosition:r=Se.Bottom,target:o})=>r===Se.Left||r===Se.Right?t.xMath.sqrt(Math.pow(r.x-t.x,2)+Math.pow(r.y-t.y,2));function h1({source:t,sourcePosition:r=Se.Bottom,target:o,targetPosition:l=Se.Top,center:a,offset:u,stepPosition:d}){const f=_h[r],g=_h[l],y={x:t.x+f.x*u,y:t.y+f.y*u},m={x:o.x+g.x*u,y:o.y+g.y*u},x=f1({source:y,sourcePosition:r,target:m}),v=x.x!==0?"x":"y",_=x[v];let S=[],j,N;const k={x:0,y:0},T={x:0,y:0},[,,E,b]=mg({sourceX:t.x,sourceY:t.y,targetX:o.x,targetY:o.y});if(f[v]*g[v]===-1){v==="x"?(j=a.x??y.x+(m.x-y.x)*d,N=a.y??(y.y+m.y)/2):(j=a.x??(y.x+m.x)/2,N=a.y??y.y+(m.y-y.y)*d);const I=[{x:j,y:y.y},{x:j,y:m.y}],q=[{x:y.x,y:N},{x:m.x,y:N}];f[v]===_?S=v==="x"?I:q:S=v==="x"?q:I}else{const I=[{x:y.x,y:m.y}],q=[{x:m.x,y:y.y}];if(v==="x"?S=f.x===_?q:I:S=f.y===_?I:q,r===l){const C=Math.abs(t[v]-o[v]);if(C<=u){const Y=Math.min(u-1,u-C);f[v]===_?k[v]=(y[v]>t[v]?-1:1)*Y:T[v]=(m[v]>o[v]?-1:1)*Y}}if(r!==l){const C=v==="x"?"y":"x",Y=f[v]===g[C],V=y[C]>m[C],U=y[C]=J?(j=(ne.x+G.x)/2,N=S[0].y):(j=S[0].x,N=(ne.y+G.y)/2)}const $={x:y.x+k.x,y:y.y+k.y},O={x:m.x+T.x,y:m.y+T.y};return[[t,...$.x!==S[0].x||$.y!==S[0].y?[$]:[],...S,...O.x!==S[S.length-1].x||O.y!==S[S.length-1].y?[O]:[],o],j,N,E,b]}function p1(t,r,o,l){const a=Math.min(Sh(t,r)/2,Sh(r,o)/2,l),{x:u,y:d}=r;if(t.x===u&&u===o.x||t.y===d&&d===o.y)return`L${u} ${d}`;if(t.y===d){const y=t.xo.id===r):t[0])||null}function Qu(t,r){return t?typeof t=="string"?t:`${r?`${r}__`:""}${Object.keys(t).sort().map(l=>`${l}=${t[l]}`).join("&")}`:""}function m1(t,{id:r,defaultColor:o,defaultMarkerStart:l,defaultMarkerEnd:a}){const u=new Set;return t.reduce((d,f)=>([f.markerStart||l,f.markerEnd||a].forEach(g=>{if(g&&typeof g=="object"){const y=Qu(g,r);u.has(y)||(d.push({id:y,color:g.color||o,...g}),u.add(y))}}),d),[]).sort((d,f)=>d.id.localeCompare(f.id))}const vg=1e3,y1=10,fc={nodeOrigin:[0,0],nodeExtent:Po,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},v1={...fc,checkEquality:!0};function hc(t,r){const o={...t};for(const l in r)r[l]!==void 0&&(o[l]=r[l]);return o}function x1(t,r,o){const l=hc(fc,o);for(const a of t.values())if(a.parentId)gc(a,t,r,l);else{const u=Oo(a,l.nodeOrigin),d=Br(a.extent)?a.extent:l.nodeExtent,f=Hr(u,d,an(a));a.internals.positionAbsolute=f}}function w1(t,r){if(!t.handles)return t.measured?r==null?void 0:r.internals.handleBounds:void 0;const o=[],l=[];for(const a of t.handles){const u={id:a.id,width:a.width??1,height:a.height??1,nodeId:t.id,x:a.x,y:a.y,position:a.position,type:a.type};a.type==="source"?o.push(u):a.type==="target"&&l.push(u)}return{source:o,target:l}}function pc(t){return t==="manual"}function Ku(t,r,o,l={}){var m,x;const a=hc(v1,l),u={i:0},d=new Map(r),f=a!=null&&a.elevateNodesOnSelect&&!pc(a.zIndexMode)?vg:0;let g=t.length>0,y=!1;r.clear(),o.clear();for(const v of t){let _=d.get(v.id);if(a.checkEquality&&v===(_==null?void 0:_.internals.userNode))r.set(v.id,_);else{const S=Oo(v,a.nodeOrigin),j=Br(v.extent)?v.extent:a.nodeExtent,N=Hr(S,j,an(v));_={...a.defaults,...v,measured:{width:(m=v.measured)==null?void 0:m.width,height:(x=v.measured)==null?void 0:x.height},internals:{positionAbsolute:N,handleBounds:w1(v,_),z:xg(v,f,a.zIndexMode),userNode:v}},r.set(v.id,_)}(_.measured===void 0||_.measured.width===void 0||_.measured.height===void 0)&&!_.hidden&&(g=!1),v.parentId&&gc(_,r,o,l,u),y||(y=v.selected??!1)}return{nodesInitialized:g,hasSelectedNodes:y}}function _1(t,r){if(!t.parentId)return;const o=r.get(t.parentId);o?o.set(t.id,t):r.set(t.parentId,new Map([[t.id,t]]))}function gc(t,r,o,l,a){const{elevateNodesOnSelect:u,nodeOrigin:d,nodeExtent:f,zIndexMode:g}=hc(fc,l),y=t.parentId,m=r.get(y);if(!m){console.warn(`Parent node ${y} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}_1(t,o),a&&!m.parentId&&m.internals.rootParentIndex===void 0&&g==="auto"&&(m.internals.rootParentIndex=++a.i,m.internals.z=m.internals.z+a.i*y1),a&&m.internals.rootParentIndex!==void 0&&(a.i=m.internals.rootParentIndex);const x=u&&!pc(g)?vg:0,{x:v,y:_,z:S}=S1(t,m,d,f,x,g),{positionAbsolute:j}=t.internals,N=v!==j.x||_!==j.y;(N||S!==t.internals.z)&&r.set(t.id,{...t,internals:{...t.internals,positionAbsolute:N?{x:v,y:_}:j,z:S}})}function xg(t,r,o){const l=rn(t.zIndex)?t.zIndex:0;return pc(o)?l:l+(t.selected?r:0)}function S1(t,r,o,l,a,u){const{x:d,y:f}=r.internals.positionAbsolute,g=an(t),y=Oo(t,o),m=Br(t.extent)?Hr(y,t.extent,g):y;let x=Hr({x:d+m.x,y:f+m.y},l,g);t.extent==="parent"&&(x=og(x,g,r));const v=xg(t,a,u),_=r.internals.z??0;return{x:x.x,y:x.y,z:_>=v?_+1:v}}function mc(t,r,o,l=[0,0]){var d;const a=[],u=new Map;for(const f of t){const g=r.get(f.parentId);if(!g)continue;const y=((d=u.get(f.parentId))==null?void 0:d.expandedRect)??Ro(g),m=sg(y,f.rect);u.set(f.parentId,{expandedRect:m,parent:g})}return u.size>0&&u.forEach(({expandedRect:f,parent:g},y)=>{var E;const m=g.internals.positionAbsolute,x=an(g),v=g.origin??l,_=f.x0||S>0||k||T)&&(a.push({id:y,type:"position",position:{x:g.position.x-_+k,y:g.position.y-S+T}}),(E=o.get(y))==null||E.forEach(b=>{t.some($=>$.id===b.id)||a.push({id:b.id,type:"position",position:{x:b.position.x+_,y:b.position.y+S}})})),(x.width0){const _=mc(v,r,o,a);y.push(..._)}return{changes:y,updatedInternals:g}}async function E1({delta:t,panZoom:r,transform:o,translateExtent:l,width:a,height:u}){if(!r||!t.x&&!t.y)return!1;const d=await r.setViewportConstrained({x:o[0]+t.x,y:o[1]+t.y,zoom:o[2]},[[0,0],[a,u]],l);return!!d&&(d.x!==o[0]||d.y!==o[1]||d.k!==o[2])}function jh(t,r,o,l,a,u){let d=a;const f=l.get(d)||new Map;l.set(d,f.set(o,r)),d=`${a}-${t}`;const g=l.get(d)||new Map;if(l.set(d,g.set(o,r)),u){d=`${a}-${t}-${u}`;const y=l.get(d)||new Map;l.set(d,y.set(o,r))}}function wg(t,r,o){t.clear(),r.clear();for(const l of o){const{source:a,target:u,sourceHandle:d=null,targetHandle:f=null}=l,g={edgeId:l.id,source:a,target:u,sourceHandle:d,targetHandle:f},y=`${a}-${d}--${u}-${f}`,m=`${u}-${f}--${a}-${d}`;jh("source",g,m,t,a,d),jh("target",g,y,t,u,f),r.set(l.id,l)}}function _g(t,r){if(!t.parentId)return!1;const o=r.get(t.parentId);return o?o.selected?!0:_g(o,r):!1}function bh(t,r,o){var a;let l=t;do{if((a=l==null?void 0:l.matches)!=null&&a.call(l,r))return!0;if(l===o)return!1;l=l==null?void 0:l.parentElement}while(l);return!1}function N1(t,r,o,l){const a=new Map;for(const[u,d]of t)if((d.selected||d.id===l)&&(!d.parentId||!_g(d,t))&&(d.draggable||r&&typeof d.draggable>"u")){const f=t.get(u);f&&a.set(u,{id:u,position:f.position||{x:0,y:0},distance:{x:o.x-f.internals.positionAbsolute.x,y:o.y-f.internals.positionAbsolute.y},extent:f.extent,parentId:f.parentId,origin:f.origin,expandParent:f.expandParent,internals:{positionAbsolute:f.internals.positionAbsolute||{x:0,y:0}},measured:{width:f.measured.width??0,height:f.measured.height??0}})}return a}function Mu({nodeId:t,dragItems:r,nodeLookup:o,dragging:l=!0}){var d,f,g;const a=[];for(const[y,m]of r){const x=(d=o.get(y))==null?void 0:d.internals.userNode;x&&a.push({...x,position:m.position,dragging:l})}if(!t)return[a[0],a];const u=(f=o.get(t))==null?void 0:f.internals.userNode;return[u?{...u,position:((g=r.get(t))==null?void 0:g.position)||u.position,dragging:l}:a[0],a]}function j1({dragItems:t,snapGrid:r,x:o,y:l}){const a=t.values().next().value;if(!a)return null;const u={x:o-a.distance.x,y:l-a.distance.y},d=Ho(u,r);return{x:d.x-u.x,y:d.y-u.y}}function b1({onNodeMouseDown:t,getStoreItems:r,onDragStart:o,onDrag:l,onDragStop:a}){let u={x:null,y:null},d=0,f=new Map,g=!1,y={x:0,y:0},m=null,x=!1,v=null,_=!1,S=!1,j=null;function N({noDragClassName:T,handleSelector:E,domNode:b,isSelectable:$,nodeId:O,nodeClickDistance:H=0}){v=Ot(b);function I({x:ee,y:J}){const{nodeLookup:C,nodeExtent:Y,snapGrid:V,snapToGrid:U,nodeOrigin:z,onNodeDrag:D,onSelectionDrag:W,onError:M,updateNodePositions:R}=r();u={x:ee,y:J};let re=!1;const ie=f.size>1,ce=ie&&Y?Xu(Fo(f)):null,fe=ie&&U?j1({dragItems:f,snapGrid:V,x:ee,y:J}):null;for(const[de,K]of f){if(!C.has(de))continue;let le={x:ee-K.distance.x,y:J-K.distance.y};U&&(le=fe?{x:Math.round(le.x+fe.x),y:Math.round(le.y+fe.y)}:Ho(le,V));let pe=null;if(ie&&Y&&!K.extent&&ce){const{positionAbsolute:ge}=K.internals,je=ge.x-ce.x+Y[0][0],Me=ge.x+K.measured.width-ce.x2+Y[1][0],Pe=ge.y-ce.y+Y[0][1],Re=ge.y+K.measured.height-ce.y2+Y[1][1];pe=[[je,Pe],[Me,Re]]}const{position:_e,positionAbsolute:xe}=ig({nodeId:de,nextPosition:le,nodeLookup:C,nodeExtent:pe||Y,nodeOrigin:z,onError:M});re=re||K.position.x!==_e.x||K.position.y!==_e.y,K.position=_e,K.internals.positionAbsolute=xe}if(S=S||re,!!re&&(R(f,!0),j&&(l||D||!O&&W))){const[de,K]=Mu({nodeId:O,dragItems:f,nodeLookup:C});l==null||l(j,f,de,K),D==null||D(j,de,K),O||W==null||W(j,K)}}async function q(){if(!m)return;const{transform:ee,panBy:J,autoPanSpeed:C,autoPanOnNodeDrag:Y}=r();if(!Y){g=!1,cancelAnimationFrame(d);return}const[V,U]=uc(y,m,C);(V!==0||U!==0)&&(u.x=(u.x??0)-V/ee[2],u.y=(u.y??0)-U/ee[2],await J({x:V,y:U})&&I(u)),d=requestAnimationFrame(q)}function ne(ee){var ie;const{nodeLookup:J,multiSelectionActive:C,nodesDraggable:Y,transform:V,snapGrid:U,snapToGrid:z,selectNodesOnDrag:D,onNodeDragStart:W,onSelectionDragStart:M,unselectNodesAndEdges:R}=r();x=!0,(!D||!$)&&!C&&O&&((ie=J.get(O))!=null&&ie.selected||R()),$&&D&&O&&(t==null||t(O));const re=Eo(ee.sourceEvent,{transform:V,snapGrid:U,snapToGrid:z,containerBounds:m});if(u=re,f=N1(J,Y,re,O),f.size>0&&(o||W||!O&&M)){const[ce,fe]=Mu({nodeId:O,dragItems:f,nodeLookup:J});o==null||o(ee.sourceEvent,f,ce,fe),W==null||W(ee.sourceEvent,ce,fe),O||M==null||M(ee.sourceEvent,fe)}}const G=Dp().clickDistance(H).on("start",ee=>{const{domNode:J,nodeDragThreshold:C,transform:Y,snapGrid:V,snapToGrid:U}=r();m=(J==null?void 0:J.getBoundingClientRect())||null,_=!1,S=!1,j=ee.sourceEvent,C===0&&ne(ee),u=Eo(ee.sourceEvent,{transform:Y,snapGrid:V,snapToGrid:U,containerBounds:m}),y=on(ee.sourceEvent,m)}).on("drag",ee=>{const{autoPanOnNodeDrag:J,transform:C,snapGrid:Y,snapToGrid:V,nodeDragThreshold:U,nodeLookup:z}=r(),D=Eo(ee.sourceEvent,{transform:C,snapGrid:Y,snapToGrid:V,containerBounds:m});if(j=ee.sourceEvent,(ee.sourceEvent.type==="touchmove"&&ee.sourceEvent.touches.length>1||O&&!z.has(O))&&(_=!0),!_){if(!g&&J&&x&&(g=!0,q()),!x){const W=on(ee.sourceEvent,m),M=W.x-y.x,R=W.y-y.y;Math.sqrt(M*M+R*R)>U&&ne(ee)}(u.x!==D.xSnapped||u.y!==D.ySnapped)&&f&&x&&(y=on(ee.sourceEvent,m),I(D))}}).on("end",ee=>{if(!x||_){_&&f.size>0&&r().updateNodePositions(f,!1);return}if(g=!1,x=!1,cancelAnimationFrame(d),f.size>0){const{nodeLookup:J,updateNodePositions:C,onNodeDragStop:Y,onSelectionDragStop:V}=r();if(S&&(C(f,!1),S=!1),a||Y||!O&&V){const[U,z]=Mu({nodeId:O,dragItems:f,nodeLookup:J,dragging:!1});a==null||a(ee.sourceEvent,f,U,z),Y==null||Y(ee.sourceEvent,U,z),O||V==null||V(ee.sourceEvent,z)}}}).filter(ee=>{const J=ee.target;return!ee.button&&(!T||!bh(J,`.${T}`,b))&&(!E||bh(J,E,b))});v.call(G)}function k(){v==null||v.on(".drag",null)}return{update:N,destroy:k}}function C1(t,r,o){const l=[],a={x:t.x-o,y:t.y-o,width:o*2,height:o*2};for(const u of r.values())vl(a,Ro(u))>0&&l.push(u);return l}const M1=250;function P1(t,r,o,l){var f,g;let a=[],u=1/0;const d=C1(t,o,r+M1);for(const y of d){const m=[...((f=y.internals.handleBounds)==null?void 0:f.source)??[],...((g=y.internals.handleBounds)==null?void 0:g.target)??[]];for(const x of m){if(l.nodeId===x.nodeId&&l.type===x.type&&l.id===x.id)continue;const{x:v,y:_}=Vr(y,x,x.position,!0),S=Math.sqrt(Math.pow(v-t.x,2)+Math.pow(_-t.y,2));S>r||(S1){const y=l.type==="source"?"target":"source";return a.find(m=>m.type===y)??a[0]}return a[0]}function Sg(t,r,o,l,a,u=!1){var y,m,x;const d=l.get(t);if(!d)return null;const f=a==="strict"?(y=d.internals.handleBounds)==null?void 0:y[r]:[...((m=d.internals.handleBounds)==null?void 0:m.source)??[],...((x=d.internals.handleBounds)==null?void 0:x.target)??[]],g=(o?f==null?void 0:f.find(v=>v.id===o):f==null?void 0:f[0])??null;return g&&u?{...g,...Vr(d,g,g.position,!0)}:g}function kg(t,r){return t||(r!=null&&r.classList.contains("target")?"target":r!=null&&r.classList.contains("source")?"source":null)}function I1(t,r){let o=null;return r?o=!0:t&&!r&&(o=!1),o}const Eg=()=>!0;function T1(t,{connectionMode:r,connectionRadius:o,handleId:l,nodeId:a,edgeUpdaterType:u,isTarget:d,domNode:f,nodeLookup:g,lib:y,autoPanOnConnect:m,flowId:x,panBy:v,cancelConnection:_,onConnectStart:S,onConnect:j,onConnectEnd:N,isValidConnection:k=Eg,onReconnectEnd:T,updateConnection:E,getTransform:b,getFromHandle:$,autoPanSpeed:O,dragThreshold:H=1,handleDomNode:I}){const q=dg(t.target);let ne=0,G;const{x:ee,y:J}=on(t),C=kg(u,I),Y=f==null?void 0:f.getBoundingClientRect();let V=!1;if(!Y||!C)return;const U=Sg(a,C,l,g,r);if(!U)return;let z=on(t,Y),D=!1,W=null,M=!1,R=null;function re(){if(!m||!Y)return;const[_e,xe]=uc(z,Y,O);v({x:_e,y:xe}),ne=requestAnimationFrame(re)}const ie={...U,nodeId:a,type:C,position:U.position},ce=g.get(a);let de={inProgress:!0,isValid:null,from:Vr(ce,ie,Se.Left,!0),fromHandle:ie,fromPosition:ie.position,fromNode:ce,to:z,toHandle:null,toPosition:gh[ie.position],toNode:null,pointer:z};function K(){V=!0,E(de),S==null||S(t,{nodeId:a,handleId:l,handleType:C})}H===0&&K();function le(_e){if(!V){const{x:Re,y:tt}=on(_e),nt=Re-ee,Qe=tt-J;if(!(nt*nt+Qe*Qe>H*H))return;K()}if(!$()||!ie){pe(_e);return}const xe=b();z=on(_e,Y),G=P1(Bo(z,xe,!1,[1,1]),o,g,ie),D||(re(),D=!0);const ge=Ng(_e,{handle:G,connectionMode:r,fromNodeId:a,fromHandleId:l,fromType:d?"target":"source",isValidConnection:k,doc:q,lib:y,flowId:x,nodeLookup:g});R=ge.handleDomNode,W=ge.connection,M=I1(!!G,ge.isValid);const je=g.get(a),Me=je?Vr(je,ie,Se.Left,!0):de.from,Pe={...de,from:Me,isValid:M,to:ge.toHandle&&M?Ri({x:ge.toHandle.x,y:ge.toHandle.y},xe):z,toHandle:ge.toHandle,toPosition:M&&ge.toHandle?ge.toHandle.position:gh[ie.position],toNode:ge.toHandle?g.get(ge.toHandle.nodeId):null,pointer:z};E(Pe),de=Pe}function pe(_e){if(!("touches"in _e&&_e.touches.length>0)){if(V){(G||R)&&W&&M&&(j==null||j(W));const{inProgress:xe,...ge}=de,je={...ge,toPosition:de.toHandle?de.toPosition:null};N==null||N(_e,je),u&&(T==null||T(_e,je))}_(),cancelAnimationFrame(ne),D=!1,M=!1,W=null,R=null,q.removeEventListener("mousemove",le),q.removeEventListener("mouseup",pe),q.removeEventListener("touchmove",le),q.removeEventListener("touchend",pe)}}q.addEventListener("mousemove",le),q.addEventListener("mouseup",pe),q.addEventListener("touchmove",le),q.addEventListener("touchend",pe)}function Ng(t,{handle:r,connectionMode:o,fromNodeId:l,fromHandleId:a,fromType:u,doc:d,lib:f,flowId:g,isValidConnection:y=Eg,nodeLookup:m}){const x=u==="target",v=r?d.querySelector(`.${f}-flow__handle[data-id="${g}-${r==null?void 0:r.nodeId}-${r==null?void 0:r.id}-${r==null?void 0:r.type}"]`):null,{x:_,y:S}=on(t),j=d.elementFromPoint(_,S),N=j!=null&&j.classList.contains(`${f}-flow__handle`)?j:v,k={handleDomNode:N,isValid:!1,connection:null,toHandle:null};if(N){const T=kg(void 0,N),E=N.getAttribute("data-nodeid"),b=N.getAttribute("data-handleid"),$=N.classList.contains("connectable"),O=N.classList.contains("connectableend");if(!E||!T)return k;const H={source:x?E:l,sourceHandle:x?b:a,target:x?l:E,targetHandle:x?a:b};k.connection=H;const q=$&&O&&(o===Ii.Strict?x&&T==="source"||!x&&T==="target":E!==l||b!==a);k.isValid=q&&y(H),k.toHandle=Sg(E,T,b,m,o,!0)}return k}const Zu={onPointerDown:T1,isValid:Ng};function R1({domNode:t,panZoom:r,getTransform:o,getViewScale:l}){const a=Ot(t);function u({translateExtent:f,width:g,height:y,zoomStep:m=1,pannable:x=!0,zoomable:v=!0,inversePan:_=!1}){const S=E=>{if(E.sourceEvent.type!=="wheel"||!r)return;const b=o(),$=E.sourceEvent.ctrlKey&&Lo()?10:1,O=-E.sourceEvent.deltaY*(E.sourceEvent.deltaMode===1?.05:E.sourceEvent.deltaMode?1:.002)*m,H=b[2]*Math.pow(2,O*$);r.scaleTo(H)};let j=[0,0];const N=E=>{(E.sourceEvent.type==="mousedown"||E.sourceEvent.type==="touchstart")&&(j=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY])},k=E=>{const b=o();if(E.sourceEvent.type!=="mousemove"&&E.sourceEvent.type!=="touchmove"||!r)return;const $=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY],O=[$[0]-j[0],$[1]-j[1]];j=$;const H=l()*Math.max(b[2],Math.log(b[2]))*(_?-1:1),I={x:b[0]-O[0]*H,y:b[1]-O[1]*H},q=[[0,0],[g,y]];r.setViewportConstrained({x:I.x,y:I.y,zoom:b[2]},q,f)},T=Zp().on("start",N).on("zoom",x?k:null).on("zoom.wheel",v?S:null);a.call(T,{})}function d(){a.on("zoom",null)}return{update:u,destroy:d,pointer:tn}}const Ml=t=>({x:t.x,y:t.y,zoom:t.k}),Pu=({x:t,y:r,zoom:o})=>jl.translate(t,r).scale(o),cr=(t,r)=>t.target.closest(`.${r}`),jg=(t,r)=>r===2&&Array.isArray(t)&&t.includes(2),L1=t=>((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2,Iu=(t,r=0,o=L1,l=()=>{})=>{const a=typeof r=="number"&&r>0;return a||l(),a?t.transition().duration(r).ease(o).on("end",l):t},bg=t=>{const r=t.ctrlKey&&Lo()?10:1;return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*r};function A1({zoomPanValues:t,noWheelClassName:r,d3Selection:o,d3Zoom:l,panOnScrollMode:a,panOnScrollSpeed:u,zoomOnPinch:d,onPanZoomStart:f,onPanZoom:g,onPanZoomEnd:y}){return m=>{if(cr(m,r))return m.ctrlKey&&m.preventDefault(),!1;m.preventDefault(),m.stopImmediatePropagation();const x=o.property("__zoom").k||1;if(m.ctrlKey&&d){const N=tn(m),k=bg(m),T=x*Math.pow(2,k);l.scaleTo(o,T,N,m);return}const v=m.deltaMode===1?20:1;let _=a===$r.Vertical?0:m.deltaX*v,S=a===$r.Horizontal?0:m.deltaY*v;!Lo()&&m.shiftKey&&a!==$r.Vertical&&(_=m.deltaY*v,S=0),l.translateBy(o,-(_/x)*u,-(S/x)*u,{internal:!0});const j=Ml(o.property("__zoom"));clearTimeout(t.panScrollTimeout),t.isPanScrolling?g==null||g(m,j):(t.isPanScrolling=!0,f==null||f(m,j)),t.panScrollTimeout=setTimeout(()=>{y==null||y(m,j),t.isPanScrolling=!1},150)}}function z1({noWheelClassName:t,preventScrolling:r,d3ZoomHandler:o}){return function(l,a){const u=l.type==="wheel",d=!r&&u&&!l.ctrlKey,f=cr(l,t);if(l.ctrlKey&&u&&f&&l.preventDefault(),d||f)return null;l.preventDefault(),o.call(this,l,a)}}function D1({zoomPanValues:t,onDraggingChange:r,onPanZoomStart:o}){return l=>{var u,d,f;if((u=l.sourceEvent)!=null&&u.internal)return;const a=Ml(l.transform);t.mouseButton=((d=l.sourceEvent)==null?void 0:d.button)||0,t.isZoomingOrPanning=!0,t.prevViewport=a,((f=l.sourceEvent)==null?void 0:f.type)==="mousedown"&&r(!0),o&&(o==null||o(l.sourceEvent,a))}}function $1({zoomPanValues:t,panOnDrag:r,onPaneContextMenu:o,onTransformChange:l,onPanZoom:a}){return u=>{var d,f;t.usedRightMouseButton=!!(o&&jg(r,t.mouseButton??0)),(d=u.sourceEvent)!=null&&d.sync||l([u.transform.x,u.transform.y,u.transform.k]),a&&!((f=u.sourceEvent)!=null&&f.internal)&&(a==null||a(u.sourceEvent,Ml(u.transform)))}}function O1({zoomPanValues:t,panOnDrag:r,panOnScroll:o,onDraggingChange:l,onPanZoomEnd:a,onPaneContextMenu:u}){return d=>{var f;if(!((f=d.sourceEvent)!=null&&f.internal)&&(t.isZoomingOrPanning=!1,u&&jg(r,t.mouseButton??0)&&!t.usedRightMouseButton&&d.sourceEvent&&u(d.sourceEvent),t.usedRightMouseButton=!1,l(!1),a)){const g=Ml(d.transform);t.prevViewport=g,clearTimeout(t.timerId),t.timerId=setTimeout(()=>{a==null||a(d.sourceEvent,g)},o?150:0)}}}function F1({panActivationKeyPressed:t,zoomActivationKeyPressed:r,zoomOnScroll:o,zoomOnPinch:l,panOnDrag:a,panOnScroll:u,zoomOnDoubleClick:d,userSelectionActive:f,noWheelClassName:g,noPanClassName:y,lib:m,connectionInProgress:x}){return v=>{var k;const _=r||o,S=l&&v.ctrlKey,j=v.type==="wheel";if(v.button===1&&v.type==="mousedown"&&(cr(v,`${m}-flow__node`)||cr(v,`${m}-flow__edge`)||cr(v,`${m}-flow__selection`)||cr(v,`${m}-flow__nodesselection`)))return!0;if(!a&&!_&&!u&&!d&&!l||f||x&&!j||cr(v,g)&&j||cr(v,y)&&(!j||u&&j&&!r)||!l&&v.ctrlKey&&j)return!1;if(!l&&v.type==="touchstart"&&((k=v.touches)==null?void 0:k.length)>1)return v.preventDefault(),!1;if(!_&&!u&&!S&&j||!a&&(v.type==="mousedown"||v.type==="touchstart")||Array.isArray(a)&&!a.includes(v.button)&&v.type==="mousedown")return!1;const N=Array.isArray(a)&&a.includes(v.button)||!v.button||v.button<=1;return(!v.ctrlKey||j||t)&&N}}function H1({domNode:t,minZoom:r,maxZoom:o,translateExtent:l,viewport:a,onPanZoom:u,onPanZoomStart:d,onPanZoomEnd:f,onDraggingChange:g}){const y={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},m=t.getBoundingClientRect();let x=[[0,0],[m.width,m.height]];const v=typeof ResizeObserver<"u"?new ResizeObserver(J=>{const C=J[0];C&&(x=[[0,0],[C.contentRect.width,C.contentRect.height]])}):null;v==null||v.observe(t);const _=Zp().extent(()=>x).scaleExtent([r,o]).translateExtent(l),S=Ot(t).call(_);b({x:a.x,y:a.y,zoom:Ti(a.zoom,r,o)},[[0,0],[m.width,m.height]],l);const j=S.on("wheel.zoom"),N=S.on("dblclick.zoom");_.wheelDelta(bg);async function k(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).transform(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function T({noWheelClassName:J,noPanClassName:C,onPaneContextMenu:Y,userSelectionActive:V,panOnScroll:U,panOnDrag:z,panOnScrollMode:D,panOnScrollSpeed:W,preventScrolling:M,zoomOnPinch:R,zoomOnScroll:re,zoomOnDoubleClick:ie,panActivationKeyPressed:ce=!1,zoomActivationKeyPressed:fe,lib:de,onTransformChange:K,connectionInProgress:le,paneClickDistance:pe,selectionOnDrag:_e}){V&&!y.isZoomingOrPanning&&E();const xe=U&&!fe&&!V;_.clickDistance(_e?1/0:!rn(pe)||pe<0?0:pe);const ge=xe?A1({zoomPanValues:y,noWheelClassName:J,d3Selection:S,d3Zoom:_,panOnScrollMode:D,panOnScrollSpeed:W,zoomOnPinch:R,onPanZoomStart:d,onPanZoom:u,onPanZoomEnd:f}):z1({noWheelClassName:J,preventScrolling:M,d3ZoomHandler:j});S.on("wheel.zoom",ge,{passive:!1});const je=D1({zoomPanValues:y,onDraggingChange:g,onPanZoomStart:d});_.on("start",je);const Me=$1({zoomPanValues:y,panOnDrag:z,onPaneContextMenu:!!Y,onPanZoom:u,onTransformChange:K});_.on("zoom",Me);const Pe=O1({zoomPanValues:y,panOnDrag:z,panOnScroll:U,onPaneContextMenu:Y,onPanZoomEnd:f,onDraggingChange:g});_.on("end",Pe);const Re=F1({panActivationKeyPressed:ce,zoomActivationKeyPressed:fe,panOnDrag:z,zoomOnScroll:re,panOnScroll:U,zoomOnDoubleClick:ie,zoomOnPinch:R,userSelectionActive:V,noPanClassName:C,noWheelClassName:J,lib:de,connectionInProgress:le});_.filter(Re),ie?S.on("dblclick.zoom",N):S.on("dblclick.zoom",null)}function E(){_.on("zoom",null)}async function b(J,C,Y){const V=Pu(J),U=_==null?void 0:_.constrain()(V,C,Y);return U&&await k(U),U}async function $(J,C){const Y=Pu(J);return await k(Y,C),Y}function O(J){if(S){const C=Pu(J),Y=S.property("__zoom");(Y.k!==J.zoom||Y.x!==J.x||Y.y!==J.y)&&(_==null||_.transform(S,C,null,{sync:!0}))}}function H(){const J=S?Kp(S.node()):{x:0,y:0,k:1};return{x:J.x,y:J.y,zoom:J.k}}async function I(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleTo(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}async function q(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleBy(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function ne(J){_==null||_.scaleExtent(J)}function G(J){_==null||_.translateExtent(J)}function ee(J){const C=!rn(J)||J<0?0:J;_==null||_.clickDistance(C)}return{update:T,destroy:E,setViewport:$,setViewportConstrained:b,getViewport:H,scaleTo:I,scaleBy:q,setScaleExtent:ne,setTranslateExtent:G,syncViewport:O,setClickDistance:ee}}var Li;(function(t){t.Line="line",t.Handle="handle"})(Li||(Li={}));function B1({width:t,prevWidth:r,height:o,prevHeight:l,affectsX:a,affectsY:u}){const d=t-r,f=o-l,g=[d>0?1:d<0?-1:0,f>0?1:f<0?-1:0];return d&&a&&(g[0]=g[0]*-1),f&&u&&(g[1]=g[1]*-1),g}function Ch(t){const r=t.includes("right")||t.includes("left"),o=t.includes("bottom")||t.includes("top"),l=t.includes("left"),a=t.includes("top");return{isHorizontal:r,isVertical:o,affectsX:l,affectsY:a}}function ar(t,r){return Math.max(0,r-t)}function ur(t,r){return Math.max(0,t-r)}function tl(t,r,o){return Math.max(0,r-t,t-o)}function Mh(t,r){return t?!r:r}function V1(t,r,o,l,a,u,d,f){let{affectsX:g,affectsY:y}=r;const{isHorizontal:m,isVertical:x}=r,v=m&&x,{xSnapped:_,ySnapped:S}=o,{minWidth:j,maxWidth:N,minHeight:k,maxHeight:T}=l,{x:E,y:b,width:$,height:O,aspectRatio:H}=t;let I=Math.floor(m?_-t.pointerX:0),q=Math.floor(x?S-t.pointerY:0);const ne=$+(g?-I:I),G=O+(y?-q:q),ee=-u[0]*$,J=-u[1]*O;let C=tl(ne,j,N),Y=tl(G,k,T);if(d){let z=0,D=0;g&&I<0?z=ar(E+I+ee,d[0][0]):!g&&I>0&&(z=ur(E+ne+ee,d[1][0])),y&&q<0?D=ar(b+q+J,d[0][1]):!y&&q>0&&(D=ur(b+G+J,d[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(f){let z=0,D=0;g&&I>0?z=ur(E+I,f[0][0]):!g&&I<0&&(z=ar(E+ne,f[1][0])),y&&q>0?D=ur(b+q,f[0][1]):!y&&q<0&&(D=ar(b+G,f[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(a){if(m){const z=tl(ne/H,k,T)*H;if(C=Math.max(C,z),d){let D=0;!g&&!y||g&&!y&&v?D=ur(b+J+ne/H,d[1][1])*H:D=ar(b+J+(g?I:-I)/H,d[0][1])*H,C=Math.max(C,D)}if(f){let D=0;!g&&!y||g&&!y&&v?D=ar(b+ne/H,f[1][1])*H:D=ur(b+(g?I:-I)/H,f[0][1])*H,C=Math.max(C,D)}}if(x){const z=tl(G*H,j,N)/H;if(Y=Math.max(Y,z),d){let D=0;!g&&!y||y&&!g&&v?D=ur(E+G*H+ee,d[1][0])/H:D=ar(E+(y?q:-q)*H+ee,d[0][0])/H,Y=Math.max(Y,D)}if(f){let D=0;!g&&!y||y&&!g&&v?D=ar(E+G*H,f[1][0])/H:D=ur(E+(y?q:-q)*H,f[0][0])/H,Y=Math.max(Y,D)}}}q=q+(q<0?Y:-Y),I=I+(I<0?C:-C),a&&(v?ne>G*H?q=(Mh(g,y)?-I:I)/H:I=(Mh(g,y)?-q:q)*H:m?(q=I/H,y=g):(I=q*H,g=y));const V=g?E+I:E,U=y?b+q:b;return{width:$+(g?-I:I),height:O+(y?-q:q),x:u[0]*I*(g?-1:1)+V,y:u[1]*q*(y?-1:1)+U}}const Cg={width:0,height:0,x:0,y:0},W1={...Cg,pointerX:0,pointerY:0,aspectRatio:1};function U1(t,r,o){const l=r.position.x+t.position.x,a=r.position.y+t.position.y,u=t.measured.width??0,d=t.measured.height??0,f=o[0]*u,g=o[1]*d;return[[l-f,a-g],[l+u-f,a+d-g]]}function Y1({domNode:t,nodeId:r,getStoreItems:o,onChange:l,onEnd:a}){const u=Ot(t);let d={controlDirection:Ch("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function f({controlPosition:y,boundaries:m,keepAspectRatio:x,resizeDirection:v,onResizeStart:_,onResize:S,onResizeEnd:j,shouldResize:N}){let k={...Cg},T={...W1};d={boundaries:m,resizeDirection:v,keepAspectRatio:x,controlDirection:Ch(y)};let E,b=null,$=[],O,H,I,q=!1;const ne=Dp().on("start",G=>{const{nodeLookup:ee,transform:J,snapGrid:C,snapToGrid:Y,nodeOrigin:V,paneDomNode:U}=o();if(E=ee.get(r),!E)return;b=(U==null?void 0:U.getBoundingClientRect())??null;const{xSnapped:z,ySnapped:D}=Eo(G.sourceEvent,{transform:J,snapGrid:C,snapToGrid:Y,containerBounds:b});k={width:E.measured.width??0,height:E.measured.height??0,x:E.position.x??0,y:E.position.y??0},T={...k,pointerX:z,pointerY:D,aspectRatio:k.width/k.height},O=void 0,H=Br(E.extent)?E.extent:void 0,E.parentId&&(E.extent==="parent"||E.expandParent)&&(O=ee.get(E.parentId)),O&&E.extent==="parent"&&(H=[[0,0],[O.measured.width,O.measured.height]]),$=[],I=void 0;for(const[W,M]of ee)if(M.parentId===r&&($.push({id:W,position:{...M.position},extent:M.extent}),M.extent==="parent"||M.expandParent)){const R=U1(M,E,M.origin??V);I?I=[[Math.min(R[0][0],I[0][0]),Math.min(R[0][1],I[0][1])],[Math.max(R[1][0],I[1][0]),Math.max(R[1][1],I[1][1])]]:I=R}_==null||_(G,{...k})}).on("drag",G=>{const{transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y}=o(),V=Eo(G.sourceEvent,{transform:ee,snapGrid:J,snapToGrid:C,containerBounds:b}),U=[];if(!E)return;const{x:z,y:D,width:W,height:M}=k,R={},re=E.origin??Y,{width:ie,height:ce,x:fe,y:de}=V1(T,d.controlDirection,V,d.boundaries,d.keepAspectRatio,re,H,I),K=ie!==W,le=ce!==M,pe=fe!==z&&K,_e=de!==D&≤if(!pe&&!_e&&!K&&!le)return;if((pe||_e||re[0]===1||re[1]===1)&&(R.x=pe?fe:k.x,R.y=_e?de:k.y,k.x=R.x,k.y=R.y,$.length>0)){const Me=fe-z,Pe=de-D;for(const Re of $)Re.position={x:Re.position.x-Me+re[0]*(ie-W),y:Re.position.y-Pe+re[1]*(ce-M)},U.push(Re)}if((K||le)&&(R.width=K&&(!d.resizeDirection||d.resizeDirection==="horizontal")?ie:k.width,R.height=le&&(!d.resizeDirection||d.resizeDirection==="vertical")?ce:k.height,k.width=R.width,k.height=R.height),O&&E.expandParent){const Me=re[0]*(R.width??0);R.x&&R.x{q&&(j==null||j(G,{...k}),a==null||a({...k}),q=!1)});u.call(ne)}function g(){u.on(".drag",null)}return{update:f,destroy:g}}var Tu={exports:{}},Ru={},Lu={exports:{}},Au={};/** +`+h.stack}return{value:e,source:n,stack:c,digest:null}}function Wa(e,n,i){return{value:e,source:null,stack:i??null,digest:n??null}}function Ua(e,n){try{console.error(n.value)}catch(i){setTimeout(function(){throw i})}}var Ey=typeof WeakMap=="function"?WeakMap:Map;function Qd(e,n,i){i=Mn(-1,i),i.tag=3,i.payload={element:null};var s=n.value;return i.callback=function(){Ls||(Ls=!0,su=s),Ua(e,n)},i}function Kd(e,n,i){i=Mn(-1,i),i.tag=3;var s=e.type.getDerivedStateFromError;if(typeof s=="function"){var c=n.value;i.payload=function(){return s(c)},i.callback=function(){Ua(e,n)}}var h=e.stateNode;return h!==null&&typeof h.componentDidCatch=="function"&&(i.callback=function(){Ua(e,n),typeof s!="function"&&(nr===null?nr=new Set([this]):nr.add(this));var w=n.stack;this.componentDidCatch(n.value,{componentStack:w!==null?w:""})}),i}function Zd(e,n,i){var s=e.pingCache;if(s===null){s=e.pingCache=new Ey;var c=new Set;s.set(n,c)}else c=s.get(n),c===void 0&&(c=new Set,s.set(n,c));c.has(i)||(c.add(i),e=$y.bind(null,e,n,i),n.then(e,e))}function Jd(e){do{var n;if((n=e.tag===13)&&(n=e.memoizedState,n=n!==null?n.dehydrated!==null:!0),n)return e;e=e.return}while(e!==null);return null}function ef(e,n,i,s,c){return(e.mode&1)===0?(e===n?e.flags|=65536:(e.flags|=128,i.flags|=131072,i.flags&=-52805,i.tag===1&&(i.alternate===null?i.tag=17:(n=Mn(-1,1),n.tag=2,er(i,n,1))),i.lanes|=1),e):(e.flags|=65536,e.lanes=c,e)}var Ny=b.ReactCurrentOwner,jt=!1;function _t(e,n,i,s){n.child=e===null?wd(n,null,i,s):gi(n,e.child,i,s)}function tf(e,n,i,s,c){i=i.render;var h=n.ref;return yi(n,c),s=za(e,n,i,s,h,c),i=Da(),e!==null&&!jt?(n.updateQueue=e.updateQueue,n.flags&=-2053,e.lanes&=~c,Pn(e,n,c)):(Ue&&i&&xa(n),n.flags|=1,_t(e,n,s,c),n.child)}function nf(e,n,i,s,c){if(e===null){var h=i.type;return typeof h=="function"&&!hu(h)&&h.defaultProps===void 0&&i.compare===null&&i.defaultProps===void 0?(n.tag=15,n.type=h,rf(e,n,h,s,c)):(e=Fs(i.type,null,s,n,n.mode,c),e.ref=n.ref,e.return=n,n.child=e)}if(h=e.child,(e.lanes&c)===0){var w=h.memoizedProps;if(i=i.compare,i=i!==null?i:Qi,i(w,s)&&e.ref===n.ref)return Pn(e,n,c)}return n.flags|=1,e=sr(h,s),e.ref=n.ref,e.return=n,n.child=e}function rf(e,n,i,s,c){if(e!==null){var h=e.memoizedProps;if(Qi(h,s)&&e.ref===n.ref)if(jt=!1,n.pendingProps=s=h,(e.lanes&c)!==0)(e.flags&131072)!==0&&(jt=!0);else return n.lanes=e.lanes,Pn(e,n,c)}return Ya(e,n,i,s,c)}function of(e,n,i){var s=n.pendingProps,c=s.children,h=e!==null?e.memoizedState:null;if(s.mode==="hidden")if((n.mode&1)===0)n.memoizedState={baseLanes:0,cachePool:null,transitions:null},Fe(_i,$t),$t|=i;else{if((i&1073741824)===0)return e=h!==null?h.baseLanes|i:i,n.lanes=n.childLanes=1073741824,n.memoizedState={baseLanes:e,cachePool:null,transitions:null},n.updateQueue=null,Fe(_i,$t),$t|=e,null;n.memoizedState={baseLanes:0,cachePool:null,transitions:null},s=h!==null?h.baseLanes:i,Fe(_i,$t),$t|=s}else h!==null?(s=h.baseLanes|i,n.memoizedState=null):s=i,Fe(_i,$t),$t|=s;return _t(e,n,c,i),n.child}function sf(e,n){var i=n.ref;(e===null&&i!==null||e!==null&&e.ref!==i)&&(n.flags|=512,n.flags|=2097152)}function Ya(e,n,i,s,c){var h=Nt(i)?Er:mt.current;return h=di(n,h),yi(n,c),i=za(e,n,i,s,h,c),s=Da(),e!==null&&!jt?(n.updateQueue=e.updateQueue,n.flags&=-2053,e.lanes&=~c,Pn(e,n,c)):(Ue&&s&&xa(n),n.flags|=1,_t(e,n,i,c),n.child)}function lf(e,n,i,s,c){if(Nt(i)){var h=!0;ds(n)}else h=!1;if(yi(n,c),n.stateNode===null)Ms(e,n),Xd(n,i,s),Va(n,i,s,c),s=!0;else if(e===null){var w=n.stateNode,P=n.memoizedProps;w.props=P;var A=w.context,Z=i.contextType;typeof Z=="object"&&Z!==null?Z=Vt(Z):(Z=Nt(i)?Er:mt.current,Z=di(n,Z));var se=i.getDerivedStateFromProps,ae=typeof se=="function"||typeof w.getSnapshotBeforeUpdate=="function";ae||typeof w.UNSAFE_componentWillReceiveProps!="function"&&typeof w.componentWillReceiveProps!="function"||(P!==s||A!==Z)&&qd(n,w,s,Z),Jn=!1;var oe=n.memoizedState;w.state=oe,ws(n,s,w,c),A=n.memoizedState,P!==s||oe!==A||Et.current||Jn?(typeof se=="function"&&(Ba(n,i,se,s),A=n.memoizedState),(P=Jn||Gd(n,i,P,s,oe,A,Z))?(ae||typeof w.UNSAFE_componentWillMount!="function"&&typeof w.componentWillMount!="function"||(typeof w.componentWillMount=="function"&&w.componentWillMount(),typeof w.UNSAFE_componentWillMount=="function"&&w.UNSAFE_componentWillMount()),typeof w.componentDidMount=="function"&&(n.flags|=4194308)):(typeof w.componentDidMount=="function"&&(n.flags|=4194308),n.memoizedProps=s,n.memoizedState=A),w.props=s,w.state=A,w.context=Z,s=P):(typeof w.componentDidMount=="function"&&(n.flags|=4194308),s=!1)}else{w=n.stateNode,Sd(e,n),P=n.memoizedProps,Z=n.type===n.elementType?P:Kt(n.type,P),w.props=Z,ae=n.pendingProps,oe=w.context,A=i.contextType,typeof A=="object"&&A!==null?A=Vt(A):(A=Nt(i)?Er:mt.current,A=di(n,A));var he=i.getDerivedStateFromProps;(se=typeof he=="function"||typeof w.getSnapshotBeforeUpdate=="function")||typeof w.UNSAFE_componentWillReceiveProps!="function"&&typeof w.componentWillReceiveProps!="function"||(P!==ae||oe!==A)&&qd(n,w,s,A),Jn=!1,oe=n.memoizedState,w.state=oe,ws(n,s,w,c);var ye=n.memoizedState;P!==ae||oe!==ye||Et.current||Jn?(typeof he=="function"&&(Ba(n,i,he,s),ye=n.memoizedState),(Z=Jn||Gd(n,i,Z,s,oe,ye,A)||!1)?(se||typeof w.UNSAFE_componentWillUpdate!="function"&&typeof w.componentWillUpdate!="function"||(typeof w.componentWillUpdate=="function"&&w.componentWillUpdate(s,ye,A),typeof w.UNSAFE_componentWillUpdate=="function"&&w.UNSAFE_componentWillUpdate(s,ye,A)),typeof w.componentDidUpdate=="function"&&(n.flags|=4),typeof w.getSnapshotBeforeUpdate=="function"&&(n.flags|=1024)):(typeof w.componentDidUpdate!="function"||P===e.memoizedProps&&oe===e.memoizedState||(n.flags|=4),typeof w.getSnapshotBeforeUpdate!="function"||P===e.memoizedProps&&oe===e.memoizedState||(n.flags|=1024),n.memoizedProps=s,n.memoizedState=ye),w.props=s,w.state=ye,w.context=A,s=Z):(typeof w.componentDidUpdate!="function"||P===e.memoizedProps&&oe===e.memoizedState||(n.flags|=4),typeof w.getSnapshotBeforeUpdate!="function"||P===e.memoizedProps&&oe===e.memoizedState||(n.flags|=1024),s=!1)}return Ga(e,n,i,s,h,c)}function Ga(e,n,i,s,c,h){sf(e,n);var w=(n.flags&128)!==0;if(!s&&!w)return c&&dd(n,i,!1),Pn(e,n,h);s=n.stateNode,Ny.current=n;var P=w&&typeof i.getDerivedStateFromError!="function"?null:s.render();return n.flags|=1,e!==null&&w?(n.child=gi(n,e.child,null,h),n.child=gi(n,null,P,h)):_t(e,n,P,h),n.memoizedState=s.state,c&&dd(n,i,!0),n.child}function af(e){var n=e.stateNode;n.pendingContext?ud(e,n.pendingContext,n.pendingContext!==n.context):n.context&&ud(e,n.context,!1),Pa(e,n.containerInfo)}function uf(e,n,i,s,c){return pi(),ka(c),n.flags|=256,_t(e,n,i,s),n.child}var Xa={dehydrated:null,treeContext:null,retryLane:0};function qa(e){return{baseLanes:e,cachePool:null,transitions:null}}function cf(e,n,i){var s=n.pendingProps,c=Ge.current,h=!1,w=(n.flags&128)!==0,P;if((P=w)||(P=e!==null&&e.memoizedState===null?!1:(c&2)!==0),P?(h=!0,n.flags&=-129):(e===null||e.memoizedState!==null)&&(c|=1),Fe(Ge,c&1),e===null)return Sa(n),e=n.memoizedState,e!==null&&(e=e.dehydrated,e!==null)?((n.mode&1)===0?n.lanes=1:e.data==="$!"?n.lanes=8:n.lanes=1073741824,null):(w=s.children,e=s.fallback,h?(s=n.mode,h=n.child,w={mode:"hidden",children:w},(s&1)===0&&h!==null?(h.childLanes=0,h.pendingProps=w):h=Hs(w,s,0,null),e=Lr(e,s,i,null),h.return=n,e.return=n,h.sibling=e,n.child=h,n.child.memoizedState=qa(i),n.memoizedState=Xa,e):Qa(n,w));if(c=e.memoizedState,c!==null&&(P=c.dehydrated,P!==null))return jy(e,n,w,s,P,c,i);if(h){h=s.fallback,w=n.mode,c=e.child,P=c.sibling;var A={mode:"hidden",children:s.children};return(w&1)===0&&n.child!==c?(s=n.child,s.childLanes=0,s.pendingProps=A,n.deletions=null):(s=sr(c,A),s.subtreeFlags=c.subtreeFlags&14680064),P!==null?h=sr(P,h):(h=Lr(h,w,i,null),h.flags|=2),h.return=n,s.return=n,s.sibling=h,n.child=s,s=h,h=n.child,w=e.child.memoizedState,w=w===null?qa(i):{baseLanes:w.baseLanes|i,cachePool:null,transitions:w.transitions},h.memoizedState=w,h.childLanes=e.childLanes&~i,n.memoizedState=Xa,s}return h=e.child,e=h.sibling,s=sr(h,{mode:"visible",children:s.children}),(n.mode&1)===0&&(s.lanes=i),s.return=n,s.sibling=null,e!==null&&(i=n.deletions,i===null?(n.deletions=[e],n.flags|=16):i.push(e)),n.child=s,n.memoizedState=null,s}function Qa(e,n){return n=Hs({mode:"visible",children:n},e.mode,0,null),n.return=e,e.child=n}function Cs(e,n,i,s){return s!==null&&ka(s),gi(n,e.child,null,i),e=Qa(n,n.pendingProps.children),e.flags|=2,n.memoizedState=null,e}function jy(e,n,i,s,c,h,w){if(i)return n.flags&256?(n.flags&=-257,s=Wa(Error(o(422))),Cs(e,n,w,s)):n.memoizedState!==null?(n.child=e.child,n.flags|=128,null):(h=s.fallback,c=n.mode,s=Hs({mode:"visible",children:s.children},c,0,null),h=Lr(h,c,w,null),h.flags|=2,s.return=n,h.return=n,s.sibling=h,n.child=s,(n.mode&1)!==0&&gi(n,e.child,null,w),n.child.memoizedState=qa(w),n.memoizedState=Xa,h);if((n.mode&1)===0)return Cs(e,n,w,null);if(c.data==="$!"){if(s=c.nextSibling&&c.nextSibling.dataset,s)var P=s.dgst;return s=P,h=Error(o(419)),s=Wa(h,s,void 0),Cs(e,n,w,s)}if(P=(w&e.childLanes)!==0,jt||P){if(s=ct,s!==null){switch(w&-w){case 4:c=2;break;case 16:c=8;break;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:c=32;break;case 536870912:c=268435456;break;default:c=0}c=(c&(s.suspendedLanes|w))!==0?0:c,c!==0&&c!==h.retryLane&&(h.retryLane=c,Cn(e,c),en(s,e,c,-1))}return fu(),s=Wa(Error(o(421))),Cs(e,n,w,s)}return c.data==="$?"?(n.flags|=128,n.child=e.child,n=Oy.bind(null,e),c._reactRetry=n,null):(e=h.treeContext,Dt=qn(c.nextSibling),zt=n,Ue=!0,Qt=null,e!==null&&(Ht[Bt++]=jn,Ht[Bt++]=bn,Ht[Bt++]=Nr,jn=e.id,bn=e.overflow,Nr=n),n=Qa(n,s.children),n.flags|=4096,n)}function df(e,n,i){e.lanes|=n;var s=e.alternate;s!==null&&(s.lanes|=n),ba(e.return,n,i)}function Ka(e,n,i,s,c){var h=e.memoizedState;h===null?e.memoizedState={isBackwards:n,rendering:null,renderingStartTime:0,last:s,tail:i,tailMode:c}:(h.isBackwards=n,h.rendering=null,h.renderingStartTime=0,h.last=s,h.tail=i,h.tailMode=c)}function ff(e,n,i){var s=n.pendingProps,c=s.revealOrder,h=s.tail;if(_t(e,n,s.children,i),s=Ge.current,(s&2)!==0)s=s&1|2,n.flags|=128;else{if(e!==null&&(e.flags&128)!==0)e:for(e=n.child;e!==null;){if(e.tag===13)e.memoizedState!==null&&df(e,i,n);else if(e.tag===19)df(e,i,n);else if(e.child!==null){e.child.return=e,e=e.child;continue}if(e===n)break e;for(;e.sibling===null;){if(e.return===null||e.return===n)break e;e=e.return}e.sibling.return=e.return,e=e.sibling}s&=1}if(Fe(Ge,s),(n.mode&1)===0)n.memoizedState=null;else switch(c){case"forwards":for(i=n.child,c=null;i!==null;)e=i.alternate,e!==null&&_s(e)===null&&(c=i),i=i.sibling;i=c,i===null?(c=n.child,n.child=null):(c=i.sibling,i.sibling=null),Ka(n,!1,c,i,h);break;case"backwards":for(i=null,c=n.child,n.child=null;c!==null;){if(e=c.alternate,e!==null&&_s(e)===null){n.child=c;break}e=c.sibling,c.sibling=i,i=c,c=e}Ka(n,!0,i,null,h);break;case"together":Ka(n,!1,null,null,void 0);break;default:n.memoizedState=null}return n.child}function Ms(e,n){(n.mode&1)===0&&e!==null&&(e.alternate=null,n.alternate=null,n.flags|=2)}function Pn(e,n,i){if(e!==null&&(n.dependencies=e.dependencies),Pr|=n.lanes,(i&n.childLanes)===0)return null;if(e!==null&&n.child!==e.child)throw Error(o(153));if(n.child!==null){for(e=n.child,i=sr(e,e.pendingProps),n.child=i,i.return=n;e.sibling!==null;)e=e.sibling,i=i.sibling=sr(e,e.pendingProps),i.return=n;i.sibling=null}return n.child}function by(e,n,i){switch(n.tag){case 3:af(n),pi();break;case 5:Nd(n);break;case 1:Nt(n.type)&&ds(n);break;case 4:Pa(n,n.stateNode.containerInfo);break;case 10:var s=n.type._context,c=n.memoizedProps.value;Fe(ys,s._currentValue),s._currentValue=c;break;case 13:if(s=n.memoizedState,s!==null)return s.dehydrated!==null?(Fe(Ge,Ge.current&1),n.flags|=128,null):(i&n.child.childLanes)!==0?cf(e,n,i):(Fe(Ge,Ge.current&1),e=Pn(e,n,i),e!==null?e.sibling:null);Fe(Ge,Ge.current&1);break;case 19:if(s=(i&n.childLanes)!==0,(e.flags&128)!==0){if(s)return ff(e,n,i);n.flags|=128}if(c=n.memoizedState,c!==null&&(c.rendering=null,c.tail=null,c.lastEffect=null),Fe(Ge,Ge.current),s)break;return null;case 22:case 23:return n.lanes=0,of(e,n,i)}return Pn(e,n,i)}var hf,Za,pf,gf;hf=function(e,n){for(var i=n.child;i!==null;){if(i.tag===5||i.tag===6)e.appendChild(i.stateNode);else if(i.tag!==4&&i.child!==null){i.child.return=i,i=i.child;continue}if(i===n)break;for(;i.sibling===null;){if(i.return===null||i.return===n)return;i=i.return}i.sibling.return=i.return,i=i.sibling}},Za=function(){},pf=function(e,n,i,s){var c=e.memoizedProps;if(c!==s){e=n.stateNode,Cr(fn.current);var h=null;switch(i){case"input":c=je(e,c),s=je(e,s),h=[];break;case"select":c=W({},c,{value:void 0}),s=W({},s,{value:void 0}),h=[];break;case"textarea":c=at(e,c),s=at(e,s),h=[];break;default:typeof c.onClick!="function"&&typeof s.onClick=="function"&&(e.onclick=as)}zn(i,s);var w;i=null;for(Z in c)if(!s.hasOwnProperty(Z)&&c.hasOwnProperty(Z)&&c[Z]!=null)if(Z==="style"){var P=c[Z];for(w in P)P.hasOwnProperty(w)&&(i||(i={}),i[w]="")}else Z!=="dangerouslySetInnerHTML"&&Z!=="children"&&Z!=="suppressContentEditableWarning"&&Z!=="suppressHydrationWarning"&&Z!=="autoFocus"&&(a.hasOwnProperty(Z)?h||(h=[]):(h=h||[]).push(Z,null));for(Z in s){var A=s[Z];if(P=c!=null?c[Z]:void 0,s.hasOwnProperty(Z)&&A!==P&&(A!=null||P!=null))if(Z==="style")if(P){for(w in P)!P.hasOwnProperty(w)||A&&A.hasOwnProperty(w)||(i||(i={}),i[w]="");for(w in A)A.hasOwnProperty(w)&&P[w]!==A[w]&&(i||(i={}),i[w]=A[w])}else i||(h||(h=[]),h.push(Z,i)),i=A;else Z==="dangerouslySetInnerHTML"?(A=A?A.__html:void 0,P=P?P.__html:void 0,A!=null&&P!==A&&(h=h||[]).push(Z,A)):Z==="children"?typeof A!="string"&&typeof A!="number"||(h=h||[]).push(Z,""+A):Z!=="suppressContentEditableWarning"&&Z!=="suppressHydrationWarning"&&(a.hasOwnProperty(Z)?(A!=null&&Z==="onScroll"&&He("scroll",e),h||P===A||(h=[])):(h=h||[]).push(Z,A))}i&&(h=h||[]).push("style",i);var Z=h;(n.updateQueue=Z)&&(n.flags|=4)}},gf=function(e,n,i,s){i!==s&&(n.flags|=4)};function fo(e,n){if(!Ue)switch(e.tailMode){case"hidden":n=e.tail;for(var i=null;n!==null;)n.alternate!==null&&(i=n),n=n.sibling;i===null?e.tail=null:i.sibling=null;break;case"collapsed":i=e.tail;for(var s=null;i!==null;)i.alternate!==null&&(s=i),i=i.sibling;s===null?n||e.tail===null?e.tail=null:e.tail.sibling=null:s.sibling=null}}function vt(e){var n=e.alternate!==null&&e.alternate.child===e.child,i=0,s=0;if(n)for(var c=e.child;c!==null;)i|=c.lanes|c.childLanes,s|=c.subtreeFlags&14680064,s|=c.flags&14680064,c.return=e,c=c.sibling;else for(c=e.child;c!==null;)i|=c.lanes|c.childLanes,s|=c.subtreeFlags,s|=c.flags,c.return=e,c=c.sibling;return e.subtreeFlags|=s,e.childLanes=i,n}function Cy(e,n,i){var s=n.pendingProps;switch(wa(n),n.tag){case 2:case 16:case 15:case 0:case 11:case 7:case 8:case 12:case 9:case 14:return vt(n),null;case 1:return Nt(n.type)&&cs(),vt(n),null;case 3:return s=n.stateNode,vi(),Be(Et),Be(mt),Ra(),s.pendingContext&&(s.context=s.pendingContext,s.pendingContext=null),(e===null||e.child===null)&&(gs(n)?n.flags|=4:e===null||e.memoizedState.isDehydrated&&(n.flags&256)===0||(n.flags|=1024,Qt!==null&&(uu(Qt),Qt=null))),Za(e,n),vt(n),null;case 5:Ia(n);var c=Cr(so.current);if(i=n.type,e!==null&&n.stateNode!=null)pf(e,n,i,s,c),e.ref!==n.ref&&(n.flags|=512,n.flags|=2097152);else{if(!s){if(n.stateNode===null)throw Error(o(166));return vt(n),null}if(e=Cr(fn.current),gs(n)){s=n.stateNode,i=n.type;var h=n.memoizedProps;switch(s[dn]=n,s[to]=h,e=(n.mode&1)!==0,i){case"dialog":He("cancel",s),He("close",s);break;case"iframe":case"object":case"embed":He("load",s);break;case"video":case"audio":for(c=0;c<\/script>",e=e.removeChild(e.firstChild)):typeof s.is=="string"?e=w.createElement(i,{is:s.is}):(e=w.createElement(i),i==="select"&&(w=e,s.multiple?w.multiple=!0:s.size&&(w.size=s.size))):e=w.createElementNS(e,i),e[dn]=n,e[to]=s,hf(e,n,!1,!1),n.stateNode=e;e:{switch(w=pr(i,s),i){case"dialog":He("cancel",e),He("close",e),c=s;break;case"iframe":case"object":case"embed":He("load",e),c=s;break;case"video":case"audio":for(c=0;cSi&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304)}else{if(!s)if(e=_s(w),e!==null){if(n.flags|=128,s=!0,i=e.updateQueue,i!==null&&(n.updateQueue=i,n.flags|=4),fo(h,!0),h.tail===null&&h.tailMode==="hidden"&&!w.alternate&&!Ue)return vt(n),null}else 2*Ye()-h.renderingStartTime>Si&&i!==1073741824&&(n.flags|=128,s=!0,fo(h,!1),n.lanes=4194304);h.isBackwards?(w.sibling=n.child,n.child=w):(i=h.last,i!==null?i.sibling=w:n.child=w,h.last=w)}return h.tail!==null?(n=h.tail,h.rendering=n,h.tail=n.sibling,h.renderingStartTime=Ye(),n.sibling=null,i=Ge.current,Fe(Ge,s?i&1|2:i&1),n):(vt(n),null);case 22:case 23:return du(),s=n.memoizedState!==null,e!==null&&e.memoizedState!==null!==s&&(n.flags|=8192),s&&(n.mode&1)!==0?($t&1073741824)!==0&&(vt(n),n.subtreeFlags&6&&(n.flags|=8192)):vt(n),null;case 24:return null;case 25:return null}throw Error(o(156,n.tag))}function My(e,n){switch(wa(n),n.tag){case 1:return Nt(n.type)&&cs(),e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 3:return vi(),Be(Et),Be(mt),Ra(),e=n.flags,(e&65536)!==0&&(e&128)===0?(n.flags=e&-65537|128,n):null;case 5:return Ia(n),null;case 13:if(Be(Ge),e=n.memoizedState,e!==null&&e.dehydrated!==null){if(n.alternate===null)throw Error(o(340));pi()}return e=n.flags,e&65536?(n.flags=e&-65537|128,n):null;case 19:return Be(Ge),null;case 4:return vi(),null;case 10:return ja(n.type._context),null;case 22:case 23:return du(),null;case 24:return null;default:return null}}var Ps=!1,xt=!1,Py=typeof WeakSet=="function"?WeakSet:Set,me=null;function wi(e,n){var i=e.ref;if(i!==null)if(typeof i=="function")try{i(null)}catch(s){Ze(e,n,s)}else i.current=null}function Ja(e,n,i){try{i()}catch(s){Ze(e,n,s)}}var mf=!1;function Iy(e,n){if(da=Qo,e=Gc(),ra(e)){if("selectionStart"in e)var i={start:e.selectionStart,end:e.selectionEnd};else e:{i=(i=e.ownerDocument)&&i.defaultView||window;var s=i.getSelection&&i.getSelection();if(s&&s.rangeCount!==0){i=s.anchorNode;var c=s.anchorOffset,h=s.focusNode;s=s.focusOffset;try{i.nodeType,h.nodeType}catch{i=null;break e}var w=0,P=-1,A=-1,Z=0,se=0,ae=e,oe=null;t:for(;;){for(var he;ae!==i||c!==0&&ae.nodeType!==3||(P=w+c),ae!==h||s!==0&&ae.nodeType!==3||(A=w+s),ae.nodeType===3&&(w+=ae.nodeValue.length),(he=ae.firstChild)!==null;)oe=ae,ae=he;for(;;){if(ae===e)break t;if(oe===i&&++Z===c&&(P=w),oe===h&&++se===s&&(A=w),(he=ae.nextSibling)!==null)break;ae=oe,oe=ae.parentNode}ae=he}i=P===-1||A===-1?null:{start:P,end:A}}else i=null}i=i||{start:0,end:0}}else i=null;for(fa={focusedElem:e,selectionRange:i},Qo=!1,me=n;me!==null;)if(n=me,e=n.child,(n.subtreeFlags&1028)!==0&&e!==null)e.return=n,me=e;else for(;me!==null;){n=me;try{var ye=n.alternate;if((n.flags&1024)!==0)switch(n.tag){case 0:case 11:case 15:break;case 1:if(ye!==null){var ve=ye.memoizedProps,et=ye.memoizedState,X=n.stateNode,B=X.getSnapshotBeforeUpdate(n.elementType===n.type?ve:Kt(n.type,ve),et);X.__reactInternalSnapshotBeforeUpdate=B}break;case 3:var Q=n.stateNode.containerInfo;Q.nodeType===1?Q.textContent="":Q.nodeType===9&&Q.documentElement&&Q.removeChild(Q.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(o(163))}}catch(ue){Ze(n,n.return,ue)}if(e=n.sibling,e!==null){e.return=n.return,me=e;break}me=n.return}return ye=mf,mf=!1,ye}function ho(e,n,i){var s=n.updateQueue;if(s=s!==null?s.lastEffect:null,s!==null){var c=s=s.next;do{if((c.tag&e)===e){var h=c.destroy;c.destroy=void 0,h!==void 0&&Ja(n,i,h)}c=c.next}while(c!==s)}}function Is(e,n){if(n=n.updateQueue,n=n!==null?n.lastEffect:null,n!==null){var i=n=n.next;do{if((i.tag&e)===e){var s=i.create;i.destroy=s()}i=i.next}while(i!==n)}}function eu(e){var n=e.ref;if(n!==null){var i=e.stateNode;switch(e.tag){case 5:e=i;break;default:e=i}typeof n=="function"?n(e):n.current=e}}function yf(e){var n=e.alternate;n!==null&&(e.alternate=null,yf(n)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(n=e.stateNode,n!==null&&(delete n[dn],delete n[to],delete n[ma],delete n[hy],delete n[py])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function vf(e){return e.tag===5||e.tag===3||e.tag===4}function xf(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||vf(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function tu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.nodeType===8?i.parentNode.insertBefore(e,n):i.insertBefore(e,n):(i.nodeType===8?(n=i.parentNode,n.insertBefore(e,i)):(n=i,n.appendChild(e)),i=i._reactRootContainer,i!=null||n.onclick!==null||(n.onclick=as));else if(s!==4&&(e=e.child,e!==null))for(tu(e,n,i),e=e.sibling;e!==null;)tu(e,n,i),e=e.sibling}function nu(e,n,i){var s=e.tag;if(s===5||s===6)e=e.stateNode,n?i.insertBefore(e,n):i.appendChild(e);else if(s!==4&&(e=e.child,e!==null))for(nu(e,n,i),e=e.sibling;e!==null;)nu(e,n,i),e=e.sibling}var ht=null,Zt=!1;function tr(e,n,i){for(i=i.child;i!==null;)wf(e,n,i),i=i.sibling}function wf(e,n,i){if(Rt&&typeof Rt.onCommitFiberUnmount=="function")try{Rt.onCommitFiberUnmount(Zr,i)}catch{}switch(i.tag){case 5:xt||wi(i,n);case 6:var s=ht,c=Zt;ht=null,tr(e,n,i),ht=s,Zt=c,ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?e.parentNode.removeChild(i):e.removeChild(i)):ht.removeChild(i.stateNode));break;case 18:ht!==null&&(Zt?(e=ht,i=i.stateNode,e.nodeType===8?ga(e.parentNode,i):e.nodeType===1&&ga(e,i),Wi(e)):ga(ht,i.stateNode));break;case 4:s=ht,c=Zt,ht=i.stateNode.containerInfo,Zt=!0,tr(e,n,i),ht=s,Zt=c;break;case 0:case 11:case 14:case 15:if(!xt&&(s=i.updateQueue,s!==null&&(s=s.lastEffect,s!==null))){c=s=s.next;do{var h=c,w=h.destroy;h=h.tag,w!==void 0&&((h&2)!==0||(h&4)!==0)&&Ja(i,n,w),c=c.next}while(c!==s)}tr(e,n,i);break;case 1:if(!xt&&(wi(i,n),s=i.stateNode,typeof s.componentWillUnmount=="function"))try{s.props=i.memoizedProps,s.state=i.memoizedState,s.componentWillUnmount()}catch(P){Ze(i,n,P)}tr(e,n,i);break;case 21:tr(e,n,i);break;case 22:i.mode&1?(xt=(s=xt)||i.memoizedState!==null,tr(e,n,i),xt=s):tr(e,n,i);break;default:tr(e,n,i)}}function _f(e){var n=e.updateQueue;if(n!==null){e.updateQueue=null;var i=e.stateNode;i===null&&(i=e.stateNode=new Py),n.forEach(function(s){var c=Fy.bind(null,e,s);i.has(s)||(i.add(s),s.then(c,c))})}}function Jt(e,n){var i=n.deletions;if(i!==null)for(var s=0;sc&&(c=w),s&=~h}if(s=c,s=Ye()-s,s=(120>s?120:480>s?480:1080>s?1080:1920>s?1920:3e3>s?3e3:4320>s?4320:1960*Ry(s/1960))-s,10e?16:e,rr===null)var s=!1;else{if(e=rr,rr=null,zs=0,(Le&6)!==0)throw Error(o(331));var c=Le;for(Le|=4,me=e.current;me!==null;){var h=me,w=h.child;if((me.flags&16)!==0){var P=h.deletions;if(P!==null){for(var A=0;AYe()-ou?Tr(e,0):iu|=i),Ct(e,n)}function Lf(e,n){n===0&&((e.mode&1)===0?n=1:(n=ei,ei<<=1,(ei&130023424)===0&&(ei=4194304)));var i=St();e=Cn(e,n),e!==null&&(Sr(e,n,i),Ct(e,i))}function Oy(e){var n=e.memoizedState,i=0;n!==null&&(i=n.retryLane),Lf(e,i)}function Fy(e,n){var i=0;switch(e.tag){case 13:var s=e.stateNode,c=e.memoizedState;c!==null&&(i=c.retryLane);break;case 19:s=e.stateNode;break;default:throw Error(o(314))}s!==null&&s.delete(n),Lf(e,i)}var Af;Af=function(e,n,i){if(e!==null)if(e.memoizedProps!==n.pendingProps||Et.current)jt=!0;else{if((e.lanes&i)===0&&(n.flags&128)===0)return jt=!1,by(e,n,i);jt=(e.flags&131072)!==0}else jt=!1,Ue&&(n.flags&1048576)!==0&&hd(n,ps,n.index);switch(n.lanes=0,n.tag){case 2:var s=n.type;Ms(e,n),e=n.pendingProps;var c=di(n,mt.current);yi(n,i),c=za(null,n,s,e,c,i);var h=Da();return n.flags|=1,typeof c=="object"&&c!==null&&typeof c.render=="function"&&c.$$typeof===void 0?(n.tag=1,n.memoizedState=null,n.updateQueue=null,Nt(s)?(h=!0,ds(n)):h=!1,n.memoizedState=c.state!==null&&c.state!==void 0?c.state:null,Ma(n),c.updater=bs,n.stateNode=c,c._reactInternals=n,Va(n,s,e,i),n=Ga(null,n,s,!0,h,i)):(n.tag=0,Ue&&h&&xa(n),_t(null,n,c,i),n=n.child),n;case 16:s=n.elementType;e:{switch(Ms(e,n),e=n.pendingProps,c=s._init,s=c(s._payload),n.type=s,c=n.tag=By(s),e=Kt(s,e),c){case 0:n=Ya(null,n,s,e,i);break e;case 1:n=lf(null,n,s,e,i);break e;case 11:n=tf(null,n,s,e,i);break e;case 14:n=nf(null,n,s,Kt(s.type,e),i);break e}throw Error(o(306,s,""))}return n;case 0:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ya(e,n,s,c,i);case 1:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),lf(e,n,s,c,i);case 3:e:{if(af(n),e===null)throw Error(o(387));s=n.pendingProps,h=n.memoizedState,c=h.element,Sd(e,n),ws(n,s,null,i);var w=n.memoizedState;if(s=w.element,h.isDehydrated)if(h={element:s,isDehydrated:!1,cache:w.cache,pendingSuspenseBoundaries:w.pendingSuspenseBoundaries,transitions:w.transitions},n.updateQueue.baseState=h,n.memoizedState=h,n.flags&256){c=xi(Error(o(423)),n),n=uf(e,n,s,i,c);break e}else if(s!==c){c=xi(Error(o(424)),n),n=uf(e,n,s,i,c);break e}else for(Dt=qn(n.stateNode.containerInfo.firstChild),zt=n,Ue=!0,Qt=null,i=wd(n,null,s,i),n.child=i;i;)i.flags=i.flags&-3|4096,i=i.sibling;else{if(pi(),s===c){n=Pn(e,n,i);break e}_t(e,n,s,i)}n=n.child}return n;case 5:return Nd(n),e===null&&Sa(n),s=n.type,c=n.pendingProps,h=e!==null?e.memoizedProps:null,w=c.children,ha(s,c)?w=null:h!==null&&ha(s,h)&&(n.flags|=32),sf(e,n),_t(e,n,w,i),n.child;case 6:return e===null&&Sa(n),null;case 13:return cf(e,n,i);case 4:return Pa(n,n.stateNode.containerInfo),s=n.pendingProps,e===null?n.child=gi(n,null,s,i):_t(e,n,s,i),n.child;case 11:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),tf(e,n,s,c,i);case 7:return _t(e,n,n.pendingProps,i),n.child;case 8:return _t(e,n,n.pendingProps.children,i),n.child;case 12:return _t(e,n,n.pendingProps.children,i),n.child;case 10:e:{if(s=n.type._context,c=n.pendingProps,h=n.memoizedProps,w=c.value,Fe(ys,s._currentValue),s._currentValue=w,h!==null)if(qt(h.value,w)){if(h.children===c.children&&!Et.current){n=Pn(e,n,i);break e}}else for(h=n.child,h!==null&&(h.return=n);h!==null;){var P=h.dependencies;if(P!==null){w=h.child;for(var A=P.firstContext;A!==null;){if(A.context===s){if(h.tag===1){A=Mn(-1,i&-i),A.tag=2;var Z=h.updateQueue;if(Z!==null){Z=Z.shared;var se=Z.pending;se===null?A.next=A:(A.next=se.next,se.next=A),Z.pending=A}}h.lanes|=i,A=h.alternate,A!==null&&(A.lanes|=i),ba(h.return,i,n),P.lanes|=i;break}A=A.next}}else if(h.tag===10)w=h.type===n.type?null:h.child;else if(h.tag===18){if(w=h.return,w===null)throw Error(o(341));w.lanes|=i,P=w.alternate,P!==null&&(P.lanes|=i),ba(w,i,n),w=h.sibling}else w=h.child;if(w!==null)w.return=h;else for(w=h;w!==null;){if(w===n){w=null;break}if(h=w.sibling,h!==null){h.return=w.return,w=h;break}w=w.return}h=w}_t(e,n,c.children,i),n=n.child}return n;case 9:return c=n.type,s=n.pendingProps.children,yi(n,i),c=Vt(c),s=s(c),n.flags|=1,_t(e,n,s,i),n.child;case 14:return s=n.type,c=Kt(s,n.pendingProps),c=Kt(s.type,c),nf(e,n,s,c,i);case 15:return rf(e,n,n.type,n.pendingProps,i);case 17:return s=n.type,c=n.pendingProps,c=n.elementType===s?c:Kt(s,c),Ms(e,n),n.tag=1,Nt(s)?(e=!0,ds(n)):e=!1,yi(n,i),Xd(n,s,c),Va(n,s,c,i),Ga(null,n,s,!0,e,i);case 19:return ff(e,n,i);case 22:return of(e,n,i)}throw Error(o(156,n.tag))};function zf(e,n){return Ce(e,n)}function Hy(e,n,i,s){this.tag=e,this.key=i,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=n,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=s,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function Yt(e,n,i,s){return new Hy(e,n,i,s)}function hu(e){return e=e.prototype,!(!e||!e.isReactComponent)}function By(e){if(typeof e=="function")return hu(e)?1:0;if(e!=null){if(e=e.$$typeof,e===ee)return 11;if(e===Y)return 14}return 2}function sr(e,n){var i=e.alternate;return i===null?(i=Yt(e.tag,n,e.key,e.mode),i.elementType=e.elementType,i.type=e.type,i.stateNode=e.stateNode,i.alternate=e,e.alternate=i):(i.pendingProps=n,i.type=e.type,i.flags=0,i.subtreeFlags=0,i.deletions=null),i.flags=e.flags&14680064,i.childLanes=e.childLanes,i.lanes=e.lanes,i.child=e.child,i.memoizedProps=e.memoizedProps,i.memoizedState=e.memoizedState,i.updateQueue=e.updateQueue,n=e.dependencies,i.dependencies=n===null?null:{lanes:n.lanes,firstContext:n.firstContext},i.sibling=e.sibling,i.index=e.index,i.ref=e.ref,i}function Fs(e,n,i,s,c,h){var w=2;if(s=e,typeof e=="function")hu(e)&&(w=1);else if(typeof e=="string")w=5;else e:switch(e){case H:return Lr(i.children,c,h,n);case I:w=8,c|=8;break;case q:return e=Yt(12,i,n,c|2),e.elementType=q,e.lanes=h,e;case J:return e=Yt(13,i,n,c),e.elementType=J,e.lanes=h,e;case C:return e=Yt(19,i,n,c),e.elementType=C,e.lanes=h,e;case U:return Hs(i,c,h,n);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case ne:w=10;break e;case G:w=9;break e;case ee:w=11;break e;case Y:w=14;break e;case V:w=16,s=null;break e}throw Error(o(130,e==null?e:typeof e,""))}return n=Yt(w,i,n,c),n.elementType=e,n.type=s,n.lanes=h,n}function Lr(e,n,i,s){return e=Yt(7,e,s,n),e.lanes=i,e}function Hs(e,n,i,s){return e=Yt(22,e,s,n),e.elementType=U,e.lanes=i,e.stateNode={isHidden:!1},e}function pu(e,n,i){return e=Yt(6,e,null,n),e.lanes=i,e}function gu(e,n,i){return n=Yt(4,e.children!==null?e.children:[],e.key,n),n.lanes=i,n.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},n}function Vy(e,n,i,s,c){this.tag=n,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=_r(0),this.expirationTimes=_r(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=_r(0),this.identifierPrefix=s,this.onRecoverableError=c,this.mutableSourceEagerHydrationData=null}function mu(e,n,i,s,c,h,w,P,A){return e=new Vy(e,n,i,P,A),n===1?(n=1,h===!0&&(n|=8)):n=0,h=Yt(3,null,null,n),e.current=h,h.stateNode=e,h.memoizedState={element:s,isDehydrated:i,cache:null,transitions:null,pendingSuspenseBoundaries:null},Ma(h),e}function Wy(e,n,i){var s=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(t)}catch(r){console.error(r)}}return t(),Su.exports=n0(),Su.exports}var Qf;function r0(){if(Qf)return Xs;Qf=1;var t=wp();return Xs.createRoot=t.createRoot,Xs.hydrateRoot=t.hydrateRoot,Xs}var i0=r0();function o0(t,r="Request failed"){const o=(t||"").trim();if(!o)return r;try{const a=JSON.parse(o).detail;if(typeof a=="string"&&a.trim())return a;if(Array.isArray(a)){const u=a.map(d=>typeof d=="string"?d:d&&typeof d=="object"&&"msg"in d?String(d.msg):"").filter(Boolean);if(u.length)return u.join("; ")}}catch{}return o}async function Ve(t,r){const o=await fetch(t,{...r,headers:{"Content-Type":"application/json",...(r==null?void 0:r.headers)||{}}});if(!o.ok){const l=await o.text();throw new Error(o0(l,o.statusText||"Request failed"))}return o.json()}const s0=["github_token","gitlab_token","gitlab_oauth_client_secret","bitbucket_token","bitbucket_oauth_client_secret","ai_api_key","ai_model","ai_base_url"],$e={health:()=>Ve("/api/health"),settings:()=>Ve("/api/settings"),saveSettings:t=>{const r={...t};for(const o of s0)r[o]===""&&delete r[o];return Ve("/api/settings",{method:"PUT",body:JSON.stringify(r)})},repos:()=>Ve("/api/repos"),browse:t=>Ve(`/api/fs${t?`?path=${encodeURIComponent(t)}`:""}`),gitRefs:(t,r=50)=>Ve(`/api/git/refs?repo_path=${encodeURIComponent(t)}&limit=${r}`),index:(t,r=!0)=>Ve("/api/index",{method:"POST",body:JSON.stringify({repo_path:t,incremental:r})}),indexStatus:t=>Ve(`/api/index?repo_path=${encodeURIComponent(t)}`),indexProgress:t=>Ve(`/api/index/progress?repo_path=${encodeURIComponent(t)}`),architecture:t=>Ve(`/api/architecture?repo_path=${encodeURIComponent(t)}`),review:(t,r,o,l=!0,a=!1)=>Ve("/api/review",{method:"POST",body:JSON.stringify({repo_path:t,base:r,head:o||null,reindex:l,incremental:!0,three_dot:!0,dirty:a})}),whatIf:(t,r)=>Ve("/api/whatif",{method:"POST",body:JSON.stringify({repo_path:t,node_id:r})}),reviewPr:(t,r,o,l)=>Ve("/api/prs/review",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,repo_path:l||null})}),init:(t,r=!1)=>Ve("/api/init",{method:"POST",body:JSON.stringify({repo_path:t,overwrite:r})}),postComment:(t,r,o,l)=>Ve("/api/prs/comment",{method:"POST",body:JSON.stringify({provider:t,repo:r,number:o,markdown:l})}),graph:(t,r="full")=>Ve(`/api/graph?repo_path=${encodeURIComponent(t)}&scope=${r}`),prs:(t,r,o="open")=>Ve("/api/prs",{method:"POST",body:JSON.stringify({provider:t,repo:r,state:o})}),scmRepos:t=>Ve(`/api/scm/repos?provider=${encodeURIComponent(t)}`),oauthStatus:()=>Ve("/api/oauth/status"),githubOAuthStart:()=>Ve("/api/oauth/github/start",{method:"POST",body:"{}"}),githubOAuthPoll:t=>Ve("/api/oauth/github/poll",{method:"POST",body:JSON.stringify({flow_id:t})}),bitbucketOAuthStart:()=>Ve("/api/oauth/bitbucket/start"),gitlabOAuthStart:()=>Ve("/api/oauth/gitlab/start"),oauthDisconnect:t=>Ve("/api/oauth/disconnect",{method:"POST",body:JSON.stringify({provider:t})}),residual:t=>Ve("/api/ai/residual",{method:"POST",body:JSON.stringify({review:t})})};function No(t){return t.replaceAll("_"," ")}function l0(t){return t.replaceAll("_"," ")}function _l(t){return t.split(".").pop()||t}function _p(t){if(!t)return"";const r=new Date(t);return Number.isNaN(r.getTime())?t:r.toLocaleString()}function Ni(t){return t.replace(/([/\\._:@-])/g,"$1​")}function Wr({className:t,children:r}){return p.jsx("svg",{className:t,width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round","aria-hidden":"true",children:r})}function a0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("path",{d:"M3 3.5h6.5L13 7v5.5H3z"}),p.jsx("path",{d:"M9.5 3.5V7H13"}),p.jsx("path",{d:"M5.5 9.5h5M5.5 11.5h3.5"})]})}function u0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("rect",{x:"2.5",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"2.5",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"2.5",y:"9",width:"4.5",height:"4.5",rx:"0.8"}),p.jsx("rect",{x:"9",y:"9",width:"4.5",height:"4.5",rx:"0.8"})]})}function c0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4",cy:"8",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"4",r:"1.6"}),p.jsx("circle",{cx:"12",cy:"12",r:"1.6"}),p.jsx("path",{d:"M5.5 7.2 10.4 4.8M5.5 8.8 10.4 11.2"})]})}function d0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"4.5",cy:"4",r:"1.4"}),p.jsx("circle",{cx:"4.5",cy:"12",r:"1.4"}),p.jsx("circle",{cx:"11.5",cy:"12",r:"1.4"}),p.jsx("path",{d:"M4.5 5.5v5M4.5 8h4.2a3 3 0 0 1 3 3"})]})}function f0({className:t}){return p.jsxs(Wr,{className:t,children:[p.jsx("circle",{cx:"8",cy:"8",r:"2.1"}),p.jsx("path",{d:"M8 2.5v1.6M8 11.9v1.6M2.5 8h1.6M11.9 8h1.6M4.1 4.1l1.1 1.1M10.8 10.8l1.1 1.1M11.9 4.1l-1.1 1.1M5.2 10.8l-1.1 1.1"})]})}function Sp({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M2.5 4.5h4L8 6h5.5v6.5h-11z"})})}function h0({className:t}){return p.jsx(Wr,{className:t,children:p.jsx("path",{d:"M4 6.5 8 10.5 12 6.5"})})}const p0="modulepreload",g0=function(t,r){return new URL(t,r).href},Kf={},m0=function(r,o,l){let a=Promise.resolve();if(o&&o.length>0){let d=function(m){return Promise.all(m.map(x=>Promise.resolve(x).then(v=>({status:"fulfilled",value:v}),v=>({status:"rejected",reason:v}))))};const f=document.getElementsByTagName("link"),g=document.querySelector("meta[property=csp-nonce]"),y=(g==null?void 0:g.nonce)||(g==null?void 0:g.getAttribute("nonce"));a=d(o.map(m=>{if(m=g0(m,l),m in Kf)return;Kf[m]=!0;const x=m.endsWith(".css"),v=x?'[rel="stylesheet"]':"";if(!!l)for(let j=f.length-1;j>=0;j--){const N=f[j];if(N.href===m&&(!x||N.rel==="stylesheet"))return}else if(document.querySelector(`link[href="${m}"]${v}`))return;const S=document.createElement("link");if(S.rel=x?"stylesheet":p0,x||(S.as="script"),S.crossOrigin="",S.href=m,y&&S.setAttribute("nonce",y),document.head.appendChild(S),x)return new Promise((j,N)=>{S.addEventListener("load",j),S.addEventListener("error",()=>N(new Error(`Unable to preload CSS for ${m}`)))})}))}function u(d){const f=new Event("vite:preloadError",{cancelable:!0});if(f.payload=d,window.dispatchEvent(f),!f.defaultPrevented)throw d}return a.then(d=>{for(const f of d||[])f.status==="rejected"&&u(f.reason);return r().catch(u)})};function it(t){if(typeof t=="string"||typeof t=="number")return""+t;let r="";if(Array.isArray(t))for(let o=0,l;o{}};function Sl(){for(var t=0,r=arguments.length,o={},l;t=0&&(l=o.slice(a+1),o=o.slice(0,a)),o&&!r.hasOwnProperty(o))throw new Error("unknown type: "+o);return{type:o,name:l}})}ol.prototype=Sl.prototype={constructor:ol,on:function(t,r){var o=this._,l=v0(t+"",o),a,u=-1,d=l.length;if(arguments.length<2){for(;++u0)for(var o=new Array(a),l=0,a,u;l=0&&(r=t.slice(0,o))!=="xmlns"&&(t=t.slice(o+1)),Jf.hasOwnProperty(r)?{space:Jf[r],local:t}:t}function w0(t){return function(){var r=this.ownerDocument,o=this.namespaceURI;return o===Fu&&r.documentElement.namespaceURI===Fu?r.createElement(t):r.createElementNS(o,t)}}function _0(t){return function(){return this.ownerDocument.createElementNS(t.space,t.local)}}function kp(t){var r=kl(t);return(r.local?_0:w0)(r)}function S0(){}function ec(t){return t==null?S0:function(){return this.querySelector(t)}}function k0(t){typeof t!="function"&&(t=ec(t));for(var r=this._groups,o=r.length,l=new Array(o),a=0;a=E&&(E=T+1);!($=N[E])&&++E=0;)(d=l[a])&&(u&&d.compareDocumentPosition(u)^4&&u.parentNode.insertBefore(d,u),u=d);return this}function X0(t){t||(t=q0);function r(x,v){return x&&v?t(x.__data__,v.__data__):!x-!v}for(var o=this._groups,l=o.length,a=new Array(l),u=0;ur?1:t>=r?0:NaN}function Q0(){var t=arguments[0];return arguments[0]=this,t.apply(null,arguments),this}function K0(){return Array.from(this)}function Z0(){for(var t=this._groups,r=0,o=t.length;r1?this.each((r==null?uv:typeof r=="function"?dv:cv)(t,r,o??"")):Mi(this.node(),t)}function Mi(t,r){return t.style.getPropertyValue(r)||Cp(t).getComputedStyle(t,null).getPropertyValue(r)}function hv(t){return function(){delete this[t]}}function pv(t,r){return function(){this[t]=r}}function gv(t,r){return function(){var o=r.apply(this,arguments);o==null?delete this[t]:this[t]=o}}function mv(t,r){return arguments.length>1?this.each((r==null?hv:typeof r=="function"?gv:pv)(t,r)):this.node()[t]}function Mp(t){return t.trim().split(/^|\s+/)}function tc(t){return t.classList||new Pp(t)}function Pp(t){this._node=t,this._names=Mp(t.getAttribute("class")||"")}Pp.prototype={add:function(t){var r=this._names.indexOf(t);r<0&&(this._names.push(t),this._node.setAttribute("class",this._names.join(" ")))},remove:function(t){var r=this._names.indexOf(t);r>=0&&(this._names.splice(r,1),this._node.setAttribute("class",this._names.join(" ")))},contains:function(t){return this._names.indexOf(t)>=0}};function Ip(t,r){for(var o=tc(t),l=-1,a=r.length;++l=0&&(o=r.slice(l+1),r=r.slice(0,l)),{type:r,name:o}})}function Wv(t){return function(){var r=this.__on;if(r){for(var o=0,l=-1,a=r.length,u;o()=>t;function Hu(t,{sourceEvent:r,subject:o,target:l,identifier:a,active:u,x:d,y:f,dx:g,dy:y,dispatch:m}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},subject:{value:o,enumerable:!0,configurable:!0},target:{value:l,enumerable:!0,configurable:!0},identifier:{value:a,enumerable:!0,configurable:!0},active:{value:u,enumerable:!0,configurable:!0},x:{value:d,enumerable:!0,configurable:!0},y:{value:f,enumerable:!0,configurable:!0},dx:{value:g,enumerable:!0,configurable:!0},dy:{value:y,enumerable:!0,configurable:!0},_:{value:m}})}Hu.prototype.on=function(){var t=this._.on.apply(this._,arguments);return t===this._?this:t};function ex(t){return!t.ctrlKey&&!t.button}function tx(){return this.parentNode}function nx(t,r){return r??{x:t.x,y:t.y}}function rx(){return navigator.maxTouchPoints||"ontouchstart"in this}function Dp(){var t=ex,r=tx,o=nx,l=rx,a={},u=Sl("start","drag","end"),d=0,f,g,y,m,x=0;function v(b){b.on("mousedown.drag",_).filter(l).on("touchstart.drag",N).on("touchmove.drag",k,Jv).on("touchend.drag touchcancel.drag",T).style("touch-action","none").style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}function _(b,$){if(!(m||!t.call(this,b,$))){var O=E(this,r.call(this,b,$),b,$,"mouse");O&&(Ot(b.view).on("mousemove.drag",S,jo).on("mouseup.drag",j,jo),Ap(b.view),Nu(b),y=!1,f=b.clientX,g=b.clientY,O("start",b))}}function S(b){if(bi(b),!y){var $=b.clientX-f,O=b.clientY-g;y=$*$+O*O>x}a.mouse("drag",b)}function j(b){Ot(b.view).on("mousemove.drag mouseup.drag",null),zp(b.view,y),bi(b),a.mouse("end",b)}function N(b,$){if(t.call(this,b,$)){var O=b.changedTouches,H=r.call(this,b,$),I=O.length,q,ne;for(q=0;q>8&15|r>>4&240,r>>4&15|r&240,(r&15)<<4|r&15,1):o===8?Qs(r>>24&255,r>>16&255,r>>8&255,(r&255)/255):o===4?Qs(r>>12&15|r>>8&240,r>>8&15|r>>4&240,r>>4&15|r&240,((r&15)<<4|r&15)/255):null):(r=ox.exec(t))?new Pt(r[1],r[2],r[3],1):(r=sx.exec(t))?new Pt(r[1]*255/100,r[2]*255/100,r[3]*255/100,1):(r=lx.exec(t))?Qs(r[1],r[2],r[3],r[4]):(r=ax.exec(t))?Qs(r[1]*255/100,r[2]*255/100,r[3]*255/100,r[4]):(r=ux.exec(t))?sh(r[1],r[2]/100,r[3]/100,1):(r=cx.exec(t))?sh(r[1],r[2]/100,r[3]/100,r[4]):eh.hasOwnProperty(t)?rh(eh[t]):t==="transparent"?new Pt(NaN,NaN,NaN,0):null}function rh(t){return new Pt(t>>16&255,t>>8&255,t&255,1)}function Qs(t,r,o,l){return l<=0&&(t=r=o=NaN),new Pt(t,r,o,l)}function hx(t){return t instanceof $o||(t=Or(t)),t?(t=t.rgb(),new Pt(t.r,t.g,t.b,t.opacity)):new Pt}function Bu(t,r,o,l){return arguments.length===1?hx(t):new Pt(t,r,o,l??1)}function Pt(t,r,o,l){this.r=+t,this.g=+r,this.b=+o,this.opacity=+l}nc(Pt,Bu,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new Pt(this.r*t,this.g*t,this.b*t,this.opacity)},rgb(){return this},clamp(){return new Pt(Dr(this.r),Dr(this.g),Dr(this.b),fl(this.opacity))},displayable(){return-.5<=this.r&&this.r<255.5&&-.5<=this.g&&this.g<255.5&&-.5<=this.b&&this.b<255.5&&0<=this.opacity&&this.opacity<=1},hex:ih,formatHex:ih,formatHex8:px,formatRgb:oh,toString:oh}));function ih(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}`}function px(){return`#${zr(this.r)}${zr(this.g)}${zr(this.b)}${zr((isNaN(this.opacity)?1:this.opacity)*255)}`}function oh(){const t=fl(this.opacity);return`${t===1?"rgb(":"rgba("}${Dr(this.r)}, ${Dr(this.g)}, ${Dr(this.b)}${t===1?")":`, ${t})`}`}function fl(t){return isNaN(t)?1:Math.max(0,Math.min(1,t))}function Dr(t){return Math.max(0,Math.min(255,Math.round(t)||0))}function zr(t){return t=Dr(t),(t<16?"0":"")+t.toString(16)}function sh(t,r,o,l){return l<=0?t=r=o=NaN:o<=0||o>=1?t=r=NaN:r<=0&&(t=NaN),new nn(t,r,o,l)}function Op(t){if(t instanceof nn)return new nn(t.h,t.s,t.l,t.opacity);if(t instanceof $o||(t=Or(t)),!t)return new nn;if(t instanceof nn)return t;t=t.rgb();var r=t.r/255,o=t.g/255,l=t.b/255,a=Math.min(r,o,l),u=Math.max(r,o,l),d=NaN,f=u-a,g=(u+a)/2;return f?(r===u?d=(o-l)/f+(o0&&g<1?0:d,new nn(d,f,g,t.opacity)}function gx(t,r,o,l){return arguments.length===1?Op(t):new nn(t,r,o,l??1)}function nn(t,r,o,l){this.h=+t,this.s=+r,this.l=+o,this.opacity=+l}nc(nn,gx,$p($o,{brighter(t){return t=t==null?dl:Math.pow(dl,t),new nn(this.h,this.s,this.l*t,this.opacity)},darker(t){return t=t==null?bo:Math.pow(bo,t),new nn(this.h,this.s,this.l*t,this.opacity)},rgb(){var t=this.h%360+(this.h<0)*360,r=isNaN(t)||isNaN(this.s)?0:this.s,o=this.l,l=o+(o<.5?o:1-o)*r,a=2*o-l;return new Pt(ju(t>=240?t-240:t+120,a,l),ju(t,a,l),ju(t<120?t+240:t-120,a,l),this.opacity)},clamp(){return new nn(lh(this.h),Ks(this.s),Ks(this.l),fl(this.opacity))},displayable(){return(0<=this.s&&this.s<=1||isNaN(this.s))&&0<=this.l&&this.l<=1&&0<=this.opacity&&this.opacity<=1},formatHsl(){const t=fl(this.opacity);return`${t===1?"hsl(":"hsla("}${lh(this.h)}, ${Ks(this.s)*100}%, ${Ks(this.l)*100}%${t===1?")":`, ${t})`}`}}));function lh(t){return t=(t||0)%360,t<0?t+360:t}function Ks(t){return Math.max(0,Math.min(1,t||0))}function ju(t,r,o){return(t<60?r+(o-r)*t/60:t<180?o:t<240?r+(o-r)*(240-t)/60:r)*255}const rc=t=>()=>t;function mx(t,r){return function(o){return t+o*r}}function yx(t,r,o){return t=Math.pow(t,o),r=Math.pow(r,o)-t,o=1/o,function(l){return Math.pow(t+l*r,o)}}function vx(t){return(t=+t)==1?Fp:function(r,o){return o-r?yx(r,o,t):rc(isNaN(r)?o:r)}}function Fp(t,r){var o=r-t;return o?mx(t,o):rc(isNaN(t)?r:t)}const hl=(function t(r){var o=vx(r);function l(a,u){var d=o((a=Bu(a)).r,(u=Bu(u)).r),f=o(a.g,u.g),g=o(a.b,u.b),y=Fp(a.opacity,u.opacity);return function(m){return a.r=d(m),a.g=f(m),a.b=g(m),a.opacity=y(m),a+""}}return l.gamma=t,l})(1);function xx(t,r){r||(r=[]);var o=t?Math.min(r.length,t.length):0,l=r.slice(),a;return function(u){for(a=0;ao&&(u=r.slice(o,u),f[d]?f[d]+=u:f[++d]=u),(l=l[0])===(a=a[0])?f[d]?f[d]+=a:f[++d]=a:(f[++d]=null,g.push({i:d,x:gn(l,a)})),o=bu.lastIndex;return o180?m+=360:m-y>180&&(y+=360),v.push({i:x.push(a(x)+"rotate(",null,l)-2,x:gn(y,m)})):m&&x.push(a(x)+"rotate("+m+l)}function f(y,m,x,v){y!==m?v.push({i:x.push(a(x)+"skewX(",null,l)-2,x:gn(y,m)}):m&&x.push(a(x)+"skewX("+m+l)}function g(y,m,x,v,_,S){if(y!==x||m!==v){var j=_.push(a(_)+"scale(",null,",",null,")");S.push({i:j-4,x:gn(y,x)},{i:j-2,x:gn(m,v)})}else(x!==1||v!==1)&&_.push(a(_)+"scale("+x+","+v+")")}return function(y,m){var x=[],v=[];return y=t(y),m=t(m),u(y.translateX,y.translateY,m.translateX,m.translateY,x,v),d(y.rotate,m.rotate,x,v),f(y.skewX,m.skewX,x,v),g(y.scaleX,y.scaleY,m.scaleX,m.scaleY,x,v),y=m=null,function(_){for(var S=-1,j=v.length,N;++S=0&&t._call.call(void 0,r),t=t._next;--Pi}function ch(){Fr=(gl=Mo.now())+El,Pi=_o=0;try{Lx()}finally{Pi=0,zx(),Fr=0}}function Ax(){var t=Mo.now(),r=t-gl;r>Wp&&(El-=r,gl=t)}function zx(){for(var t,r=pl,o,l=1/0;r;)r._call?(l>r._time&&(l=r._time),t=r,r=r._next):(o=r._next,r._next=null,r=t?t._next=o:pl=o);So=t,Uu(l)}function Uu(t){if(!Pi){_o&&(_o=clearTimeout(_o));var r=t-Fr;r>24?(t<1/0&&(_o=setTimeout(ch,t-Mo.now()-El)),xo&&(xo=clearInterval(xo))):(xo||(gl=Mo.now(),xo=setInterval(Ax,Wp)),Pi=1,Up(ch))}}function dh(t,r,o){var l=new ml;return r=r==null?0:+r,l.restart(a=>{l.stop(),t(a+r)},r,o),l}var Dx=Sl("start","end","cancel","interrupt"),$x=[],Gp=0,fh=1,Yu=2,ll=3,hh=4,Gu=5,al=6;function Nl(t,r,o,l,a,u){var d=t.__transition;if(!d)t.__transition={};else if(o in d)return;Ox(t,o,{name:r,index:l,group:a,on:Dx,tween:$x,time:u.time,delay:u.delay,duration:u.duration,ease:u.ease,timer:null,state:Gp})}function oc(t,r){var o=ln(t,r);if(o.state>Gp)throw new Error("too late; already scheduled");return o}function yn(t,r){var o=ln(t,r);if(o.state>ll)throw new Error("too late; already running");return o}function ln(t,r){var o=t.__transition;if(!o||!(o=o[r]))throw new Error("transition not found");return o}function Ox(t,r,o){var l=t.__transition,a;l[r]=o,o.timer=Yp(u,0,o.time);function u(y){o.state=fh,o.timer.restart(d,o.delay,o.time),o.delay<=y&&d(y-o.delay)}function d(y){var m,x,v,_;if(o.state!==fh)return g();for(m in l)if(_=l[m],_.name===o.name){if(_.state===ll)return dh(d);_.state===hh?(_.state=al,_.timer.stop(),_.on.call("interrupt",t,t.__data__,_.index,_.group),delete l[m]):+mYu&&l.state=0&&(r=r.slice(0,o)),!r||r==="start"})}function gw(t,r,o){var l,a,u=pw(r)?oc:yn;return function(){var d=u(this,t),f=d.on;f!==l&&(a=(l=f).copy()).on(r,o),d.on=a}}function mw(t,r){var o=this._id;return arguments.length<2?ln(this.node(),o).on.on(t):this.each(gw(o,t,r))}function yw(t){return function(){var r=this.parentNode;for(var o in this.__transition)if(+o!==t)return;r&&r.removeChild(this)}}function vw(){return this.on("end.remove",yw(this._id))}function xw(t){var r=this._name,o=this._id;typeof t!="function"&&(t=ec(t));for(var l=this._groups,a=l.length,u=new Array(a),d=0;d()=>t;function Ww(t,{sourceEvent:r,target:o,transform:l,dispatch:a}){Object.defineProperties(this,{type:{value:t,enumerable:!0,configurable:!0},sourceEvent:{value:r,enumerable:!0,configurable:!0},target:{value:o,enumerable:!0,configurable:!0},transform:{value:l,enumerable:!0,configurable:!0},_:{value:a}})}function Rn(t,r,o){this.k=t,this.x=r,this.y=o}Rn.prototype={constructor:Rn,scale:function(t){return t===1?this:new Rn(this.k*t,this.x,this.y)},translate:function(t,r){return t===0&r===0?this:new Rn(this.k,this.x+this.k*t,this.y+this.k*r)},apply:function(t){return[t[0]*this.k+this.x,t[1]*this.k+this.y]},applyX:function(t){return t*this.k+this.x},applyY:function(t){return t*this.k+this.y},invert:function(t){return[(t[0]-this.x)/this.k,(t[1]-this.y)/this.k]},invertX:function(t){return(t-this.x)/this.k},invertY:function(t){return(t-this.y)/this.k},rescaleX:function(t){return t.copy().domain(t.range().map(this.invertX,this).map(t.invert,t))},rescaleY:function(t){return t.copy().domain(t.range().map(this.invertY,this).map(t.invert,t))},toString:function(){return"translate("+this.x+","+this.y+") scale("+this.k+")"}};var jl=new Rn(1,0,0);Kp.prototype=Rn.prototype;function Kp(t){for(;!t.__zoom;)if(!(t=t.parentNode))return jl;return t.__zoom}function Cu(t){t.stopImmediatePropagation()}function wo(t){t.preventDefault(),t.stopImmediatePropagation()}function Uw(t){return(!t.ctrlKey||t.type==="wheel")&&!t.button}function Yw(){var t=this;return t instanceof SVGElement?(t=t.ownerSVGElement||t,t.hasAttribute("viewBox")?(t=t.viewBox.baseVal,[[t.x,t.y],[t.x+t.width,t.y+t.height]]):[[0,0],[t.width.baseVal.value,t.height.baseVal.value]]):[[0,0],[t.clientWidth,t.clientHeight]]}function ph(){return this.__zoom||jl}function Gw(t){return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*(t.ctrlKey?10:1)}function Xw(){return navigator.maxTouchPoints||"ontouchstart"in this}function qw(t,r,o){var l=t.invertX(r[0][0])-o[0][0],a=t.invertX(r[1][0])-o[1][0],u=t.invertY(r[0][1])-o[0][1],d=t.invertY(r[1][1])-o[1][1];return t.translate(a>l?(l+a)/2:Math.min(0,l)||Math.max(0,a),d>u?(u+d)/2:Math.min(0,u)||Math.max(0,d))}function Zp(){var t=Uw,r=Yw,o=qw,l=Gw,a=Xw,u=[0,1/0],d=[[-1/0,-1/0],[1/0,1/0]],f=250,g=sl,y=Sl("start","zoom","end"),m,x,v,_=500,S=150,j=0,N=10;function k(C){C.property("__zoom",ph).on("wheel.zoom",I,{passive:!1}).on("mousedown.zoom",q).on("dblclick.zoom",ne).filter(a).on("touchstart.zoom",G).on("touchmove.zoom",ee).on("touchend.zoom touchcancel.zoom",J).style("-webkit-tap-highlight-color","rgba(0,0,0,0)")}k.transform=function(C,Y,V,U){var z=C.selection?C.selection():C;z.property("__zoom",ph),C!==z?$(C,Y,V,U):z.interrupt().each(function(){O(this,arguments).event(U).start().zoom(null,typeof Y=="function"?Y.apply(this,arguments):Y).end()})},k.scaleBy=function(C,Y,V,U){k.scaleTo(C,function(){var z=this.__zoom.k,D=typeof Y=="function"?Y.apply(this,arguments):Y;return z*D},V,U)},k.scaleTo=function(C,Y,V,U){k.transform(C,function(){var z=r.apply(this,arguments),D=this.__zoom,W=V==null?b(z):typeof V=="function"?V.apply(this,arguments):V,M=D.invert(W),R=typeof Y=="function"?Y.apply(this,arguments):Y;return o(E(T(D,R),W,M),z,d)},V,U)},k.translateBy=function(C,Y,V,U){k.transform(C,function(){return o(this.__zoom.translate(typeof Y=="function"?Y.apply(this,arguments):Y,typeof V=="function"?V.apply(this,arguments):V),r.apply(this,arguments),d)},null,U)},k.translateTo=function(C,Y,V,U,z){k.transform(C,function(){var D=r.apply(this,arguments),W=this.__zoom,M=U==null?b(D):typeof U=="function"?U.apply(this,arguments):U;return o(jl.translate(M[0],M[1]).scale(W.k).translate(typeof Y=="function"?-Y.apply(this,arguments):-Y,typeof V=="function"?-V.apply(this,arguments):-V),D,d)},U,z)};function T(C,Y){return Y=Math.max(u[0],Math.min(u[1],Y)),Y===C.k?C:new Rn(Y,C.x,C.y)}function E(C,Y,V){var U=Y[0]-V[0]*C.k,z=Y[1]-V[1]*C.k;return U===C.x&&z===C.y?C:new Rn(C.k,U,z)}function b(C){return[(+C[0][0]+ +C[1][0])/2,(+C[0][1]+ +C[1][1])/2]}function $(C,Y,V,U){C.on("start.zoom",function(){O(this,arguments).event(U).start()}).on("interrupt.zoom end.zoom",function(){O(this,arguments).event(U).end()}).tween("zoom",function(){var z=this,D=arguments,W=O(z,D).event(U),M=r.apply(z,D),R=V==null?b(M):typeof V=="function"?V.apply(z,D):V,re=Math.max(M[1][0]-M[0][0],M[1][1]-M[0][1]),ie=z.__zoom,ce=typeof Y=="function"?Y.apply(z,D):Y,fe=g(ie.invert(R).concat(re/ie.k),ce.invert(R).concat(re/ce.k));return function(de){if(de===1)de=ce;else{var K=fe(de),le=re/K[2];de=new Rn(le,R[0]-K[0]*le,R[1]-K[1]*le)}W.zoom(null,de)}})}function O(C,Y,V){return!V&&C.__zooming||new H(C,Y)}function H(C,Y){this.that=C,this.args=Y,this.active=0,this.sourceEvent=null,this.extent=r.apply(C,Y),this.taps=0}H.prototype={event:function(C){return C&&(this.sourceEvent=C),this},start:function(){return++this.active===1&&(this.that.__zooming=this,this.emit("start")),this},zoom:function(C,Y){return this.mouse&&C!=="mouse"&&(this.mouse[1]=Y.invert(this.mouse[0])),this.touch0&&C!=="touch"&&(this.touch0[1]=Y.invert(this.touch0[0])),this.touch1&&C!=="touch"&&(this.touch1[1]=Y.invert(this.touch1[0])),this.that.__zoom=Y,this.emit("zoom"),this},end:function(){return--this.active===0&&(delete this.that.__zooming,this.emit("end")),this},emit:function(C){var Y=Ot(this.that).datum();y.call(C,this.that,new Ww(C,{sourceEvent:this.sourceEvent,target:k,transform:this.that.__zoom,dispatch:y}),Y)}};function I(C,...Y){if(!t.apply(this,arguments))return;var V=O(this,Y).event(C),U=this.__zoom,z=Math.max(u[0],Math.min(u[1],U.k*Math.pow(2,l.apply(this,arguments)))),D=tn(C);if(V.wheel)(V.mouse[0][0]!==D[0]||V.mouse[0][1]!==D[1])&&(V.mouse[1]=U.invert(V.mouse[0]=D)),clearTimeout(V.wheel);else{if(U.k===z)return;V.mouse=[D,U.invert(D)],ul(this),V.start()}wo(C),V.wheel=setTimeout(W,S),V.zoom("mouse",o(E(T(U,z),V.mouse[0],V.mouse[1]),V.extent,d));function W(){V.wheel=null,V.end()}}function q(C,...Y){if(v||!t.apply(this,arguments))return;var V=C.currentTarget,U=O(this,Y,!0).event(C),z=Ot(C.view).on("mousemove.zoom",R,!0).on("mouseup.zoom",re,!0),D=tn(C,V),W=C.clientX,M=C.clientY;Ap(C.view),Cu(C),U.mouse=[D,this.__zoom.invert(D)],ul(this),U.start();function R(ie){if(wo(ie),!U.moved){var ce=ie.clientX-W,fe=ie.clientY-M;U.moved=ce*ce+fe*fe>j}U.event(ie).zoom("mouse",o(E(U.that.__zoom,U.mouse[0]=tn(ie,V),U.mouse[1]),U.extent,d))}function re(ie){z.on("mousemove.zoom mouseup.zoom",null),zp(ie.view,U.moved),wo(ie),U.event(ie).end()}}function ne(C,...Y){if(t.apply(this,arguments)){var V=this.__zoom,U=tn(C.changedTouches?C.changedTouches[0]:C,this),z=V.invert(U),D=V.k*(C.shiftKey?.5:2),W=o(E(T(V,D),U,z),r.apply(this,Y),d);wo(C),f>0?Ot(this).transition().duration(f).call($,W,U,C):Ot(this).call(k.transform,W,U,C)}}function G(C,...Y){if(t.apply(this,arguments)){var V=C.touches,U=V.length,z=O(this,Y,C.changedTouches.length===U).event(C),D,W,M,R;for(Cu(C),W=0;W`Seems like you have not used ${t==="svelte"?"SvelteFlowProvider":"ReactFlowProvider"} as an ancestor. Help: https://${t}flow.dev/error#001`,error002:()=>"It looks like you've created a new nodeTypes or edgeTypes object. If this wasn't on purpose please define the nodeTypes/edgeTypes outside of the component or memoize them.",error003:t=>`Node type "${t}" not found. Using fallback type "default".`,error004:()=>"The parent container needs a width and a height to render the graph.",error005:()=>"Only child nodes can use a parent extent.",error006:()=>"Can't create edge. An edge needs a source and a target.",error007:t=>`The old edge with id=${t} does not exist.`,error009:t=>`Marker type "${t}" doesn't exist.`,error008:(t,{id:r,sourceHandle:o,targetHandle:l})=>`Couldn't create edge for ${t} handle id: "${t==="source"?o:l}", edge id: ${r}.`,error010:()=>"Handle: No node id found. Make sure to only use a Handle inside a custom Node.",error011:t=>`Edge type "${t}" not found. Using fallback type "default".`,error012:t=>`Node with id "${t}" does not exist, it may have been removed. This can happen when a node is deleted before the "onNodeClick" handler is called.`,error013:(t="react")=>`It seems that you haven't loaded the styles. Please import '@xyflow/${t}/dist/style.css' or base.css to make sure everything is working properly.`,error014:()=>"useNodeConnections: No node ID found. Call useNodeConnections inside a custom Node or provide a node ID.",error015:()=>"It seems that you are trying to drag a node that is not initialized. Please use onNodesChange as explained in the docs.",error016:t=>`Edge with id "${t}" does not exist, it may have been removed. This can happen when an edge is deleted before the "onEdgeClick" handler is called.`},Po=[[Number.NEGATIVE_INFINITY,Number.NEGATIVE_INFINITY],[Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY]],Jp=["Enter"," ","Escape"],eg={"node.a11yDescription.default":"Press enter or space to select a node. Press delete to remove it and escape to cancel.","node.a11yDescription.keyboardDisabled":"Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.","node.a11yDescription.ariaLiveMessage":({direction:t,x:r,y:o})=>`Moved selected node ${t}. New position, x: ${r}, y: ${o}`,"edge.a11yDescription.default":"Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.","controls.ariaLabel":"Control Panel","controls.zoomIn.ariaLabel":"Zoom In","controls.zoomOut.ariaLabel":"Zoom Out","controls.fitView.ariaLabel":"Fit View","controls.interactive.ariaLabel":"Toggle Interactivity","minimap.ariaLabel":"Mini Map","handle.ariaLabel":"Handle"};var Ii;(function(t){t.Strict="strict",t.Loose="loose"})(Ii||(Ii={}));var $r;(function(t){t.Free="free",t.Vertical="vertical",t.Horizontal="horizontal"})($r||($r={}));var Io;(function(t){t.Partial="partial",t.Full="full"})(Io||(Io={}));const tg={inProgress:!1,isValid:null,from:null,fromHandle:null,fromPosition:null,fromNode:null,to:null,toHandle:null,toPosition:null,toNode:null,pointer:null};var dr;(function(t){t.Bezier="default",t.Straight="straight",t.Step="step",t.SmoothStep="smoothstep",t.SimpleBezier="simplebezier"})(dr||(dr={}));var To;(function(t){t.Arrow="arrow",t.ArrowClosed="arrowclosed"})(To||(To={}));var Se;(function(t){t.Left="left",t.Top="top",t.Right="right",t.Bottom="bottom"})(Se||(Se={}));const gh={[Se.Left]:Se.Right,[Se.Right]:Se.Left,[Se.Top]:Se.Bottom,[Se.Bottom]:Se.Top};function ng(t){return t===null?null:t?"valid":"invalid"}const rg=t=>!!t&&typeof t=="object"&&"id"in t&&"source"in t&&"target"in t,Qw=t=>!!t&&typeof t=="object"&&"id"in t&&"position"in t&&!("source"in t)&&!("target"in t),lc=t=>!!t&&typeof t=="object"&&"id"in t&&"internals"in t&&!("source"in t)&&!("target"in t),Oo=(t,r=[0,0])=>{const{width:o,height:l}=an(t),a=t.origin??r,u=o*a[0],d=l*a[1];return{x:t.position.x-u,y:t.position.y-d}},Kw=(t,r={nodeOrigin:[0,0]})=>{if(t.length===0)return{x:0,y:0,width:0,height:0};let o=!1;const l=t.reduce((a,u)=>{const d=typeof u=="string";let f=!r.nodeLookup&&!d?u:void 0;return r.nodeLookup&&(f=d?r.nodeLookup.get(u):lc(u)?u:r.nodeLookup.get(u.id)),f?(o=!0,bl(a,yl(f,r.nodeOrigin))):a},{x:1/0,y:1/0,x2:-1/0,y2:-1/0});return o?Cl(l):{x:0,y:0,width:0,height:0}},Fo=(t,r={})=>{let o={x:1/0,y:1/0,x2:-1/0,y2:-1/0},l=!1;return t.forEach(a=>{(r.filter===void 0||r.filter(a))&&(o=bl(o,yl(a)),l=!0)}),l?Cl(o):{x:0,y:0,width:0,height:0}},ac=(t,r,[o,l,a]=[0,0,1],u=!1,d=!1)=>{const f=(r.x-o)/a,g=(r.y-l)/a,y=r.width/a,m=r.height/a,x=[];for(const v of t.values()){const{measured:_,selectable:S=!0,hidden:j=!1}=v;if(d&&!S||j)continue;const N=_.width??v.width??v.initialWidth??0,k=_.height??v.height??v.initialHeight??0,{x:T,y:E}=v.internals.positionAbsolute,b=lg(f,g,y,m,T,E,N,k),$=N*k,O=u&&b>0;(!v.internals.handleBounds||O||b>=$||v.dragging)&&x.push(v)}return x},Zw=(t,r)=>{const o=new Set;return t.forEach(l=>{o.add(l.id)}),r.filter(l=>o.has(l.source)||o.has(l.target))};function Jw(t,r){const o=new Map,l=r!=null&&r.nodes?new Set(r.nodes.map(a=>a.id)):null;return t.forEach(a=>{let u;if(r!=null&&r.includeHiddenNodes){const{width:d,height:f}=an(a);u=d>0&&f>0}else u=!!(a.measured.width&&a.measured.height&&!a.hidden);u&&(!l||l.has(a.id))&&o.set(a.id,a)}),o}async function e1({nodes:t,width:r,height:o,panZoom:l,minZoom:a,maxZoom:u},d){if(t.size===0)return!0;const f=Jw(t,d),g=Fo(f),y=cc(g,r,o,(d==null?void 0:d.minZoom)??a,(d==null?void 0:d.maxZoom)??u,(d==null?void 0:d.padding)??.1);return await l.setViewport(y,{duration:d==null?void 0:d.duration,ease:d==null?void 0:d.ease,interpolate:d==null?void 0:d.interpolate}),!0}function ig({nodeId:t,nextPosition:r,nodeLookup:o,nodeOrigin:l=[0,0],nodeExtent:a,onError:u}){const d=o.get(t),f=d.parentId?o.get(d.parentId):void 0,{x:g,y}=f?f.internals.positionAbsolute:{x:0,y:0},m=d.origin??l;let x=d.extent||a;if(d.extent==="parent"&&!d.expandParent)if(!f)u==null||u("005",sn.error005());else{const{width:_,height:S}=an(f);_&&S&&(x=[[g,y],[g+_,y+S]])}else f&&Br(d.extent)&&(x=[[d.extent[0][0]+g,d.extent[0][1]+y],[d.extent[1][0]+g,d.extent[1][1]+y]]);const v=Br(x)?Hr(r,x,d.measured):r;return(d.measured.width===void 0||d.measured.height===void 0)&&(u==null||u("015",sn.error015())),{position:{x:v.x-g+(d.measured.width??0)*m[0],y:v.y-y+(d.measured.height??0)*m[1]},positionAbsolute:v}}async function t1({nodesToRemove:t=[],edgesToRemove:r=[],nodes:o,edges:l,onBeforeDelete:a}){const u=new Set(t.map(v=>v.id)),d=[];for(const v of o){if(v.deletable===!1)continue;const _=u.has(v.id),S=!_&&v.parentId&&d.find(j=>j.id===v.parentId);(_||S)&&d.push(v)}const f=new Set(r.map(v=>v.id)),g=l.filter(v=>v.deletable!==!1),m=Zw(d,g);for(const v of g)f.has(v.id)&&!m.find(S=>S.id===v.id)&&m.push(v);if(!a)return{edges:m,nodes:d};const x=await a({nodes:d,edges:m});return typeof x=="boolean"?x?{edges:m,nodes:d}:{edges:[],nodes:[]}:x}const Ti=(t,r=0,o=1)=>Math.min(Math.max(t,r),o),Hr=(t={x:0,y:0},r,o)=>({x:Ti(t.x,r[0][0],r[1][0]-((o==null?void 0:o.width)??0)),y:Ti(t.y,r[0][1],r[1][1]-((o==null?void 0:o.height)??0))});function og(t,r,o){const{width:l,height:a}=an(o),{x:u,y:d}=o.internals.positionAbsolute;return Hr(t,[[u,d],[u+l,d+a]],r)}const mh=(t,r,o)=>to?-Ti(Math.abs(t-o),1,r)/r:0,uc=(t,r,o=15,l=40)=>{const a=mh(t.x,l,r.width-l)*o,u=mh(t.y,l,r.height-l)*o;return[a,u]},bl=(t,r)=>({x:Math.min(t.x,r.x),y:Math.min(t.y,r.y),x2:Math.max(t.x2,r.x2),y2:Math.max(t.y2,r.y2)}),Xu=({x:t,y:r,width:o,height:l})=>({x:t,y:r,x2:t+o,y2:r+l}),Cl=({x:t,y:r,x2:o,y2:l})=>({x:t,y:r,width:o-t,height:l-r}),Ro=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,width:((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0,height:((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0}},yl=(t,r=[0,0])=>{var a,u;const{x:o,y:l}=lc(t)?t.internals.positionAbsolute:Oo(t,r);return{x:o,y:l,x2:o+(((a=t.measured)==null?void 0:a.width)??t.width??t.initialWidth??0),y2:l+(((u=t.measured)==null?void 0:u.height)??t.height??t.initialHeight??0)}},sg=(t,r)=>Cl(bl(Xu(t),Xu(r))),lg=(t,r,o,l,a,u,d,f)=>{const g=Math.max(0,Math.min(t+o,a+d)-Math.max(t,a)),y=Math.max(0,Math.min(r+l,u+f)-Math.max(r,u));return Math.ceil(g*y)},vl=(t,r)=>lg(t.x,t.y,t.width,t.height,r.x,r.y,r.width,r.height),yh=t=>rn(t.width)&&rn(t.height)&&rn(t.x)&&rn(t.y),rn=t=>!isNaN(t)&&isFinite(t),ag=(t,r)=>(o,l)=>{},Ho=(t,r=[1,1])=>({x:r[0]*Math.round(t.x/r[0]),y:r[1]*Math.round(t.y/r[1])}),Bo=({x:t,y:r},[o,l,a],u=!1,d=[1,1])=>{const f={x:(t-o)/a,y:(r-l)/a};return u?Ho(f,d):f},Ri=({x:t,y:r},[o,l,a])=>({x:t*a+o,y:r*a+l});function Ei(t,r){if(typeof t=="number")return Math.floor((r-r/(1+t))*.5);if(typeof t=="string"&&t.endsWith("px")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(o)}if(typeof t=="string"&&t.endsWith("%")){const o=parseFloat(t);if(!Number.isNaN(o))return Math.floor(r*o*.01)}return console.error(`The padding value "${t}" is invalid. Please provide a number or a string with a valid unit (px or %).`),0}function n1(t,r,o){if(typeof t=="string"||typeof t=="number"){const l=Ei(t,o),a=Ei(t,r);return{top:l,right:a,bottom:l,left:a,x:a*2,y:l*2}}if(typeof t=="object"){const l=Ei(t.top??t.y??0,o),a=Ei(t.bottom??t.y??0,o),u=Ei(t.left??t.x??0,r),d=Ei(t.right??t.x??0,r);return{top:l,right:d,bottom:a,left:u,x:u+d,y:l+a}}return{top:0,right:0,bottom:0,left:0,x:0,y:0}}function r1(t,r,o,l,a,u){const{x:d,y:f}=Ri(t,[r,o,l]),{x:g,y}=Ri({x:t.x+t.width,y:t.y+t.height},[r,o,l]),m=a-g,x=u-y;return{left:Math.floor(d),top:Math.floor(f),right:Math.floor(m),bottom:Math.floor(x)}}const cc=(t,r,o,l,a,u)=>{const d=n1(u,r,o),f=(r-d.x)/t.width,g=(o-d.y)/t.height,y=Math.min(f,g),m=Ti(y,l,a),x=t.x+t.width/2,v=t.y+t.height/2,_=r/2-x*m,S=o/2-v*m,j=r1(t,_,S,m,r,o),N={left:Math.min(j.left-d.left,0),top:Math.min(j.top-d.top,0),right:Math.min(j.right-d.right,0),bottom:Math.min(j.bottom-d.bottom,0)};return{x:_-N.left+N.right,y:S-N.top+N.bottom,zoom:m}},Lo=()=>{var t;return typeof navigator<"u"&&((t=navigator==null?void 0:navigator.userAgent)==null?void 0:t.indexOf("Mac"))>=0};function Br(t){return t!=null&&t!=="parent"}function an(t){var r,o;return{width:((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth??0,height:((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight??0}}function ug(t){var r,o;return(((r=t.measured)==null?void 0:r.width)??t.width??t.initialWidth)!==void 0&&(((o=t.measured)==null?void 0:o.height)??t.height??t.initialHeight)!==void 0}function cg(t,r={width:0,height:0},o,l,a){const u={...t},d=l.get(o);if(d){const f=d.origin||a;u.x+=d.internals.positionAbsolute.x-(r.width??0)*f[0],u.y+=d.internals.positionAbsolute.y-(r.height??0)*f[1]}return u}function vh(t,r){if(t.size!==r.size)return!1;for(const o of t)if(!r.has(o))return!1;return!0}function i1(){let t,r;return{promise:new Promise((l,a)=>{t=l,r=a}),resolve:t,reject:r}}function o1(t){return{...eg,...t||{}}}function Eo(t,{snapGrid:r=[0,0],snapToGrid:o=!1,transform:l,containerBounds:a}){const{x:u,y:d}=on(t),f=Bo({x:u-((a==null?void 0:a.left)??0),y:d-((a==null?void 0:a.top)??0)},l),{x:g,y}=o?Ho(f,r):f;return{xSnapped:g,ySnapped:y,...f}}const dc=t=>({width:t.offsetWidth,height:t.offsetHeight}),dg=t=>{var r;return((r=t==null?void 0:t.getRootNode)==null?void 0:r.call(t))||(window==null?void 0:window.document)},s1=["INPUT","SELECT","TEXTAREA"];function fg(t){var l,a;const r=((a=(l=t.composedPath)==null?void 0:l.call(t))==null?void 0:a[0])||t.target;return(r==null?void 0:r.nodeType)!==1?!1:s1.includes(r.nodeName)||r.hasAttribute("contenteditable")||!!r.closest(".nokey")}const hg=t=>"clientX"in t,on=(t,r)=>{var u,d;const o=hg(t),l=o?t.clientX:(u=t.touches)==null?void 0:u[0].clientX,a=o?t.clientY:(d=t.touches)==null?void 0:d[0].clientY;return{x:l-((r==null?void 0:r.left)??0),y:a-((r==null?void 0:r.top)??0)}},xh=(t,r,o,l,a)=>{const u=r.querySelectorAll(`.${t}`);return!u||!u.length?null:Array.from(u).map(d=>{const f=d.getBoundingClientRect();return{id:d.getAttribute("data-handleid"),type:t,nodeId:a,position:d.getAttribute("data-handlepos"),x:(f.left-o.left)/l,y:(f.top-o.top)/l,...dc(d)}})};function pg({sourceX:t,sourceY:r,targetX:o,targetY:l,sourceControlX:a,sourceControlY:u,targetControlX:d,targetControlY:f}){const g=t*.125+a*.375+d*.375+o*.125,y=r*.125+u*.375+f*.375+l*.125,m=Math.abs(g-t),x=Math.abs(y-r);return[g,y,m,x]}function el(t,r){return t>=0?.5*t:r*25*Math.sqrt(-t)}function wh({pos:t,x1:r,y1:o,x2:l,y2:a,c:u}){switch(t){case Se.Left:return[r-el(r-l,u),o];case Se.Right:return[r+el(l-r,u),o];case Se.Top:return[r,o-el(o-a,u)];case Se.Bottom:return[r,o+el(a-o,u)]}}function gg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top,curvature:d=.25}){const[f,g]=wh({pos:o,x1:t,y1:r,x2:l,y2:a,c:d}),[y,m]=wh({pos:u,x1:l,y1:a,x2:t,y2:r,c:d}),[x,v,_,S]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:f,sourceControlY:g,targetControlX:y,targetControlY:m});return[`M${t},${r} C${f},${g} ${y},${m} ${l},${a}`,x,v,_,S]}function mg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const a=Math.abs(o-t)/2,u=o0}const u1=({source:t,sourceHandle:r,target:o,targetHandle:l})=>`xy-edge__${t}${r||""}-${o}${l||""}`,c1=(t,r)=>r.some(o=>o.source===t.source&&o.target===t.target&&(o.sourceHandle===t.sourceHandle||!o.sourceHandle&&!t.sourceHandle)&&(o.targetHandle===t.targetHandle||!o.targetHandle&&!t.targetHandle)),d1=(t,r,o={})=>{var u;if(!t.source||!t.target)return(u=o.onError)==null||u.call(o,"006",sn.error006()),r;const l=o.getEdgeId||u1;let a;return rg(t)?a={...t}:a={...t,id:l(t)},c1(a,r)?r:(a.sourceHandle===null&&delete a.sourceHandle,a.targetHandle===null&&delete a.targetHandle,r.concat(a))};function yg({sourceX:t,sourceY:r,targetX:o,targetY:l}){const[a,u,d,f]=mg({sourceX:t,sourceY:r,targetX:o,targetY:l});return[`M ${t},${r}L ${o},${l}`,a,u,d,f]}const _h={[Se.Left]:{x:-1,y:0},[Se.Right]:{x:1,y:0},[Se.Top]:{x:0,y:-1},[Se.Bottom]:{x:0,y:1}},f1=({source:t,sourcePosition:r=Se.Bottom,target:o})=>r===Se.Left||r===Se.Right?t.xMath.sqrt(Math.pow(r.x-t.x,2)+Math.pow(r.y-t.y,2));function h1({source:t,sourcePosition:r=Se.Bottom,target:o,targetPosition:l=Se.Top,center:a,offset:u,stepPosition:d}){const f=_h[r],g=_h[l],y={x:t.x+f.x*u,y:t.y+f.y*u},m={x:o.x+g.x*u,y:o.y+g.y*u},x=f1({source:y,sourcePosition:r,target:m}),v=x.x!==0?"x":"y",_=x[v];let S=[],j,N;const k={x:0,y:0},T={x:0,y:0},[,,E,b]=mg({sourceX:t.x,sourceY:t.y,targetX:o.x,targetY:o.y});if(f[v]*g[v]===-1){v==="x"?(j=a.x??y.x+(m.x-y.x)*d,N=a.y??(y.y+m.y)/2):(j=a.x??(y.x+m.x)/2,N=a.y??y.y+(m.y-y.y)*d);const I=[{x:j,y:y.y},{x:j,y:m.y}],q=[{x:y.x,y:N},{x:m.x,y:N}];f[v]===_?S=v==="x"?I:q:S=v==="x"?q:I}else{const I=[{x:y.x,y:m.y}],q=[{x:m.x,y:y.y}];if(v==="x"?S=f.x===_?q:I:S=f.y===_?I:q,r===l){const C=Math.abs(t[v]-o[v]);if(C<=u){const Y=Math.min(u-1,u-C);f[v]===_?k[v]=(y[v]>t[v]?-1:1)*Y:T[v]=(m[v]>o[v]?-1:1)*Y}}if(r!==l){const C=v==="x"?"y":"x",Y=f[v]===g[C],V=y[C]>m[C],U=y[C]=J?(j=(ne.x+G.x)/2,N=S[0].y):(j=S[0].x,N=(ne.y+G.y)/2)}const $={x:y.x+k.x,y:y.y+k.y},O={x:m.x+T.x,y:m.y+T.y};return[[t,...$.x!==S[0].x||$.y!==S[0].y?[$]:[],...S,...O.x!==S[S.length-1].x||O.y!==S[S.length-1].y?[O]:[],o],j,N,E,b]}function p1(t,r,o,l){const a=Math.min(Sh(t,r)/2,Sh(r,o)/2,l),{x:u,y:d}=r;if(t.x===u&&u===o.x||t.y===d&&d===o.y)return`L${u} ${d}`;if(t.y===d){const y=t.xo.id===r):t[0])||null}function Qu(t,r){return t?typeof t=="string"?t:`${r?`${r}__`:""}${Object.keys(t).sort().map(l=>`${l}=${t[l]}`).join("&")}`:""}function m1(t,{id:r,defaultColor:o,defaultMarkerStart:l,defaultMarkerEnd:a}){const u=new Set;return t.reduce((d,f)=>([f.markerStart||l,f.markerEnd||a].forEach(g=>{if(g&&typeof g=="object"){const y=Qu(g,r);u.has(y)||(d.push({id:y,color:g.color||o,...g}),u.add(y))}}),d),[]).sort((d,f)=>d.id.localeCompare(f.id))}const vg=1e3,y1=10,fc={nodeOrigin:[0,0],nodeExtent:Po,elevateNodesOnSelect:!0,zIndexMode:"basic",defaults:{}},v1={...fc,checkEquality:!0};function hc(t,r){const o={...t};for(const l in r)r[l]!==void 0&&(o[l]=r[l]);return o}function x1(t,r,o){const l=hc(fc,o);for(const a of t.values())if(a.parentId)gc(a,t,r,l);else{const u=Oo(a,l.nodeOrigin),d=Br(a.extent)?a.extent:l.nodeExtent,f=Hr(u,d,an(a));a.internals.positionAbsolute=f}}function w1(t,r){if(!t.handles)return t.measured?r==null?void 0:r.internals.handleBounds:void 0;const o=[],l=[];for(const a of t.handles){const u={id:a.id,width:a.width??1,height:a.height??1,nodeId:t.id,x:a.x,y:a.y,position:a.position,type:a.type};a.type==="source"?o.push(u):a.type==="target"&&l.push(u)}return{source:o,target:l}}function pc(t){return t==="manual"}function Ku(t,r,o,l={}){var m,x;const a=hc(v1,l),u={i:0},d=new Map(r),f=a!=null&&a.elevateNodesOnSelect&&!pc(a.zIndexMode)?vg:0;let g=t.length>0,y=!1;r.clear(),o.clear();for(const v of t){let _=d.get(v.id);if(a.checkEquality&&v===(_==null?void 0:_.internals.userNode))r.set(v.id,_);else{const S=Oo(v,a.nodeOrigin),j=Br(v.extent)?v.extent:a.nodeExtent,N=Hr(S,j,an(v));_={...a.defaults,...v,measured:{width:(m=v.measured)==null?void 0:m.width,height:(x=v.measured)==null?void 0:x.height},internals:{positionAbsolute:N,handleBounds:w1(v,_),z:xg(v,f,a.zIndexMode),userNode:v}},r.set(v.id,_)}(_.measured===void 0||_.measured.width===void 0||_.measured.height===void 0)&&!_.hidden&&(g=!1),v.parentId&&gc(_,r,o,l,u),y||(y=v.selected??!1)}return{nodesInitialized:g,hasSelectedNodes:y}}function _1(t,r){if(!t.parentId)return;const o=r.get(t.parentId);o?o.set(t.id,t):r.set(t.parentId,new Map([[t.id,t]]))}function gc(t,r,o,l,a){const{elevateNodesOnSelect:u,nodeOrigin:d,nodeExtent:f,zIndexMode:g}=hc(fc,l),y=t.parentId,m=r.get(y);if(!m){console.warn(`Parent node ${y} not found. Please make sure that parent nodes are in front of their child nodes in the nodes array.`);return}_1(t,o),a&&!m.parentId&&m.internals.rootParentIndex===void 0&&g==="auto"&&(m.internals.rootParentIndex=++a.i,m.internals.z=m.internals.z+a.i*y1),a&&m.internals.rootParentIndex!==void 0&&(a.i=m.internals.rootParentIndex);const x=u&&!pc(g)?vg:0,{x:v,y:_,z:S}=S1(t,m,d,f,x,g),{positionAbsolute:j}=t.internals,N=v!==j.x||_!==j.y;(N||S!==t.internals.z)&&r.set(t.id,{...t,internals:{...t.internals,positionAbsolute:N?{x:v,y:_}:j,z:S}})}function xg(t,r,o){const l=rn(t.zIndex)?t.zIndex:0;return pc(o)?l:l+(t.selected?r:0)}function S1(t,r,o,l,a,u){const{x:d,y:f}=r.internals.positionAbsolute,g=an(t),y=Oo(t,o),m=Br(t.extent)?Hr(y,t.extent,g):y;let x=Hr({x:d+m.x,y:f+m.y},l,g);t.extent==="parent"&&(x=og(x,g,r));const v=xg(t,a,u),_=r.internals.z??0;return{x:x.x,y:x.y,z:_>=v?_+1:v}}function mc(t,r,o,l=[0,0]){var d;const a=[],u=new Map;for(const f of t){const g=r.get(f.parentId);if(!g)continue;const y=((d=u.get(f.parentId))==null?void 0:d.expandedRect)??Ro(g),m=sg(y,f.rect);u.set(f.parentId,{expandedRect:m,parent:g})}return u.size>0&&u.forEach(({expandedRect:f,parent:g},y)=>{var E;const m=g.internals.positionAbsolute,x=an(g),v=g.origin??l,_=f.x0||S>0||k||T)&&(a.push({id:y,type:"position",position:{x:g.position.x-_+k,y:g.position.y-S+T}}),(E=o.get(y))==null||E.forEach(b=>{t.some($=>$.id===b.id)||a.push({id:b.id,type:"position",position:{x:b.position.x+_,y:b.position.y+S}})})),(x.width0){const _=mc(v,r,o,a);y.push(..._)}return{changes:y,updatedInternals:g}}async function E1({delta:t,panZoom:r,transform:o,translateExtent:l,width:a,height:u}){if(!r||!t.x&&!t.y)return!1;const d=await r.setViewportConstrained({x:o[0]+t.x,y:o[1]+t.y,zoom:o[2]},[[0,0],[a,u]],l);return!!d&&(d.x!==o[0]||d.y!==o[1]||d.k!==o[2])}function jh(t,r,o,l,a,u){let d=a;const f=l.get(d)||new Map;l.set(d,f.set(o,r)),d=`${a}-${t}`;const g=l.get(d)||new Map;if(l.set(d,g.set(o,r)),u){d=`${a}-${t}-${u}`;const y=l.get(d)||new Map;l.set(d,y.set(o,r))}}function wg(t,r,o){t.clear(),r.clear();for(const l of o){const{source:a,target:u,sourceHandle:d=null,targetHandle:f=null}=l,g={edgeId:l.id,source:a,target:u,sourceHandle:d,targetHandle:f},y=`${a}-${d}--${u}-${f}`,m=`${u}-${f}--${a}-${d}`;jh("source",g,m,t,a,d),jh("target",g,y,t,u,f),r.set(l.id,l)}}function _g(t,r){if(!t.parentId)return!1;const o=r.get(t.parentId);return o?o.selected?!0:_g(o,r):!1}function bh(t,r,o){var a;let l=t;do{if((a=l==null?void 0:l.matches)!=null&&a.call(l,r))return!0;if(l===o)return!1;l=l==null?void 0:l.parentElement}while(l);return!1}function N1(t,r,o,l){const a=new Map;for(const[u,d]of t)if((d.selected||d.id===l)&&(!d.parentId||!_g(d,t))&&(d.draggable||r&&typeof d.draggable>"u")){const f=t.get(u);f&&a.set(u,{id:u,position:f.position||{x:0,y:0},distance:{x:o.x-f.internals.positionAbsolute.x,y:o.y-f.internals.positionAbsolute.y},extent:f.extent,parentId:f.parentId,origin:f.origin,expandParent:f.expandParent,internals:{positionAbsolute:f.internals.positionAbsolute||{x:0,y:0}},measured:{width:f.measured.width??0,height:f.measured.height??0}})}return a}function Mu({nodeId:t,dragItems:r,nodeLookup:o,dragging:l=!0}){var d,f,g;const a=[];for(const[y,m]of r){const x=(d=o.get(y))==null?void 0:d.internals.userNode;x&&a.push({...x,position:m.position,dragging:l})}if(!t)return[a[0],a];const u=(f=o.get(t))==null?void 0:f.internals.userNode;return[u?{...u,position:((g=r.get(t))==null?void 0:g.position)||u.position,dragging:l}:a[0],a]}function j1({dragItems:t,snapGrid:r,x:o,y:l}){const a=t.values().next().value;if(!a)return null;const u={x:o-a.distance.x,y:l-a.distance.y},d=Ho(u,r);return{x:d.x-u.x,y:d.y-u.y}}function b1({onNodeMouseDown:t,getStoreItems:r,onDragStart:o,onDrag:l,onDragStop:a}){let u={x:null,y:null},d=0,f=new Map,g=!1,y={x:0,y:0},m=null,x=!1,v=null,_=!1,S=!1,j=null;function N({noDragClassName:T,handleSelector:E,domNode:b,isSelectable:$,nodeId:O,nodeClickDistance:H=0}){v=Ot(b);function I({x:ee,y:J}){const{nodeLookup:C,nodeExtent:Y,snapGrid:V,snapToGrid:U,nodeOrigin:z,onNodeDrag:D,onSelectionDrag:W,onError:M,updateNodePositions:R}=r();u={x:ee,y:J};let re=!1;const ie=f.size>1,ce=ie&&Y?Xu(Fo(f)):null,fe=ie&&U?j1({dragItems:f,snapGrid:V,x:ee,y:J}):null;for(const[de,K]of f){if(!C.has(de))continue;let le={x:ee-K.distance.x,y:J-K.distance.y};U&&(le=fe?{x:Math.round(le.x+fe.x),y:Math.round(le.y+fe.y)}:Ho(le,V));let pe=null;if(ie&&Y&&!K.extent&&ce){const{positionAbsolute:ge}=K.internals,je=ge.x-ce.x+Y[0][0],Pe=ge.x+K.measured.width-ce.x2+Y[1][0],Ie=ge.y-ce.y+Y[0][1],Re=ge.y+K.measured.height-ce.y2+Y[1][1];pe=[[je,Ie],[Pe,Re]]}const{position:_e,positionAbsolute:xe}=ig({nodeId:de,nextPosition:le,nodeLookup:C,nodeExtent:pe||Y,nodeOrigin:z,onError:M});re=re||K.position.x!==_e.x||K.position.y!==_e.y,K.position=_e,K.internals.positionAbsolute=xe}if(S=S||re,!!re&&(R(f,!0),j&&(l||D||!O&&W))){const[de,K]=Mu({nodeId:O,dragItems:f,nodeLookup:C});l==null||l(j,f,de,K),D==null||D(j,de,K),O||W==null||W(j,K)}}async function q(){if(!m)return;const{transform:ee,panBy:J,autoPanSpeed:C,autoPanOnNodeDrag:Y}=r();if(!Y){g=!1,cancelAnimationFrame(d);return}const[V,U]=uc(y,m,C);(V!==0||U!==0)&&(u.x=(u.x??0)-V/ee[2],u.y=(u.y??0)-U/ee[2],await J({x:V,y:U})&&I(u)),d=requestAnimationFrame(q)}function ne(ee){var ie;const{nodeLookup:J,multiSelectionActive:C,nodesDraggable:Y,transform:V,snapGrid:U,snapToGrid:z,selectNodesOnDrag:D,onNodeDragStart:W,onSelectionDragStart:M,unselectNodesAndEdges:R}=r();x=!0,(!D||!$)&&!C&&O&&((ie=J.get(O))!=null&&ie.selected||R()),$&&D&&O&&(t==null||t(O));const re=Eo(ee.sourceEvent,{transform:V,snapGrid:U,snapToGrid:z,containerBounds:m});if(u=re,f=N1(J,Y,re,O),f.size>0&&(o||W||!O&&M)){const[ce,fe]=Mu({nodeId:O,dragItems:f,nodeLookup:J});o==null||o(ee.sourceEvent,f,ce,fe),W==null||W(ee.sourceEvent,ce,fe),O||M==null||M(ee.sourceEvent,fe)}}const G=Dp().clickDistance(H).on("start",ee=>{const{domNode:J,nodeDragThreshold:C,transform:Y,snapGrid:V,snapToGrid:U}=r();m=(J==null?void 0:J.getBoundingClientRect())||null,_=!1,S=!1,j=ee.sourceEvent,C===0&&ne(ee),u=Eo(ee.sourceEvent,{transform:Y,snapGrid:V,snapToGrid:U,containerBounds:m}),y=on(ee.sourceEvent,m)}).on("drag",ee=>{const{autoPanOnNodeDrag:J,transform:C,snapGrid:Y,snapToGrid:V,nodeDragThreshold:U,nodeLookup:z}=r(),D=Eo(ee.sourceEvent,{transform:C,snapGrid:Y,snapToGrid:V,containerBounds:m});if(j=ee.sourceEvent,(ee.sourceEvent.type==="touchmove"&&ee.sourceEvent.touches.length>1||O&&!z.has(O))&&(_=!0),!_){if(!g&&J&&x&&(g=!0,q()),!x){const W=on(ee.sourceEvent,m),M=W.x-y.x,R=W.y-y.y;Math.sqrt(M*M+R*R)>U&&ne(ee)}(u.x!==D.xSnapped||u.y!==D.ySnapped)&&f&&x&&(y=on(ee.sourceEvent,m),I(D))}}).on("end",ee=>{if(!x||_){_&&f.size>0&&r().updateNodePositions(f,!1);return}if(g=!1,x=!1,cancelAnimationFrame(d),f.size>0){const{nodeLookup:J,updateNodePositions:C,onNodeDragStop:Y,onSelectionDragStop:V}=r();if(S&&(C(f,!1),S=!1),a||Y||!O&&V){const[U,z]=Mu({nodeId:O,dragItems:f,nodeLookup:J,dragging:!1});a==null||a(ee.sourceEvent,f,U,z),Y==null||Y(ee.sourceEvent,U,z),O||V==null||V(ee.sourceEvent,z)}}}).filter(ee=>{const J=ee.target;return!ee.button&&(!T||!bh(J,`.${T}`,b))&&(!E||bh(J,E,b))});v.call(G)}function k(){v==null||v.on(".drag",null)}return{update:N,destroy:k}}function C1(t,r,o){const l=[],a={x:t.x-o,y:t.y-o,width:o*2,height:o*2};for(const u of r.values())vl(a,Ro(u))>0&&l.push(u);return l}const M1=250;function P1(t,r,o,l){var f,g;let a=[],u=1/0;const d=C1(t,o,r+M1);for(const y of d){const m=[...((f=y.internals.handleBounds)==null?void 0:f.source)??[],...((g=y.internals.handleBounds)==null?void 0:g.target)??[]];for(const x of m){if(l.nodeId===x.nodeId&&l.type===x.type&&l.id===x.id)continue;const{x:v,y:_}=Vr(y,x,x.position,!0),S=Math.sqrt(Math.pow(v-t.x,2)+Math.pow(_-t.y,2));S>r||(S1){const y=l.type==="source"?"target":"source";return a.find(m=>m.type===y)??a[0]}return a[0]}function Sg(t,r,o,l,a,u=!1){var y,m,x;const d=l.get(t);if(!d)return null;const f=a==="strict"?(y=d.internals.handleBounds)==null?void 0:y[r]:[...((m=d.internals.handleBounds)==null?void 0:m.source)??[],...((x=d.internals.handleBounds)==null?void 0:x.target)??[]],g=(o?f==null?void 0:f.find(v=>v.id===o):f==null?void 0:f[0])??null;return g&&u?{...g,...Vr(d,g,g.position,!0)}:g}function kg(t,r){return t||(r!=null&&r.classList.contains("target")?"target":r!=null&&r.classList.contains("source")?"source":null)}function I1(t,r){let o=null;return r?o=!0:t&&!r&&(o=!1),o}const Eg=()=>!0;function T1(t,{connectionMode:r,connectionRadius:o,handleId:l,nodeId:a,edgeUpdaterType:u,isTarget:d,domNode:f,nodeLookup:g,lib:y,autoPanOnConnect:m,flowId:x,panBy:v,cancelConnection:_,onConnectStart:S,onConnect:j,onConnectEnd:N,isValidConnection:k=Eg,onReconnectEnd:T,updateConnection:E,getTransform:b,getFromHandle:$,autoPanSpeed:O,dragThreshold:H=1,handleDomNode:I}){const q=dg(t.target);let ne=0,G;const{x:ee,y:J}=on(t),C=kg(u,I),Y=f==null?void 0:f.getBoundingClientRect();let V=!1;if(!Y||!C)return;const U=Sg(a,C,l,g,r);if(!U)return;let z=on(t,Y),D=!1,W=null,M=!1,R=null;function re(){if(!m||!Y)return;const[_e,xe]=uc(z,Y,O);v({x:_e,y:xe}),ne=requestAnimationFrame(re)}const ie={...U,nodeId:a,type:C,position:U.position},ce=g.get(a);let de={inProgress:!0,isValid:null,from:Vr(ce,ie,Se.Left,!0),fromHandle:ie,fromPosition:ie.position,fromNode:ce,to:z,toHandle:null,toPosition:gh[ie.position],toNode:null,pointer:z};function K(){V=!0,E(de),S==null||S(t,{nodeId:a,handleId:l,handleType:C})}H===0&&K();function le(_e){if(!V){const{x:Re,y:tt}=on(_e),nt=Re-ee,Qe=tt-J;if(!(nt*nt+Qe*Qe>H*H))return;K()}if(!$()||!ie){pe(_e);return}const xe=b();z=on(_e,Y),G=P1(Bo(z,xe,!1,[1,1]),o,g,ie),D||(re(),D=!0);const ge=Ng(_e,{handle:G,connectionMode:r,fromNodeId:a,fromHandleId:l,fromType:d?"target":"source",isValidConnection:k,doc:q,lib:y,flowId:x,nodeLookup:g});R=ge.handleDomNode,W=ge.connection,M=I1(!!G,ge.isValid);const je=g.get(a),Pe=je?Vr(je,ie,Se.Left,!0):de.from,Ie={...de,from:Pe,isValid:M,to:ge.toHandle&&M?Ri({x:ge.toHandle.x,y:ge.toHandle.y},xe):z,toHandle:ge.toHandle,toPosition:M&&ge.toHandle?ge.toHandle.position:gh[ie.position],toNode:ge.toHandle?g.get(ge.toHandle.nodeId):null,pointer:z};E(Ie),de=Ie}function pe(_e){if(!("touches"in _e&&_e.touches.length>0)){if(V){(G||R)&&W&&M&&(j==null||j(W));const{inProgress:xe,...ge}=de,je={...ge,toPosition:de.toHandle?de.toPosition:null};N==null||N(_e,je),u&&(T==null||T(_e,je))}_(),cancelAnimationFrame(ne),D=!1,M=!1,W=null,R=null,q.removeEventListener("mousemove",le),q.removeEventListener("mouseup",pe),q.removeEventListener("touchmove",le),q.removeEventListener("touchend",pe)}}q.addEventListener("mousemove",le),q.addEventListener("mouseup",pe),q.addEventListener("touchmove",le),q.addEventListener("touchend",pe)}function Ng(t,{handle:r,connectionMode:o,fromNodeId:l,fromHandleId:a,fromType:u,doc:d,lib:f,flowId:g,isValidConnection:y=Eg,nodeLookup:m}){const x=u==="target",v=r?d.querySelector(`.${f}-flow__handle[data-id="${g}-${r==null?void 0:r.nodeId}-${r==null?void 0:r.id}-${r==null?void 0:r.type}"]`):null,{x:_,y:S}=on(t),j=d.elementFromPoint(_,S),N=j!=null&&j.classList.contains(`${f}-flow__handle`)?j:v,k={handleDomNode:N,isValid:!1,connection:null,toHandle:null};if(N){const T=kg(void 0,N),E=N.getAttribute("data-nodeid"),b=N.getAttribute("data-handleid"),$=N.classList.contains("connectable"),O=N.classList.contains("connectableend");if(!E||!T)return k;const H={source:x?E:l,sourceHandle:x?b:a,target:x?l:E,targetHandle:x?a:b};k.connection=H;const q=$&&O&&(o===Ii.Strict?x&&T==="source"||!x&&T==="target":E!==l||b!==a);k.isValid=q&&y(H),k.toHandle=Sg(E,T,b,m,o,!0)}return k}const Zu={onPointerDown:T1,isValid:Ng};function R1({domNode:t,panZoom:r,getTransform:o,getViewScale:l}){const a=Ot(t);function u({translateExtent:f,width:g,height:y,zoomStep:m=1,pannable:x=!0,zoomable:v=!0,inversePan:_=!1}){const S=E=>{if(E.sourceEvent.type!=="wheel"||!r)return;const b=o(),$=E.sourceEvent.ctrlKey&&Lo()?10:1,O=-E.sourceEvent.deltaY*(E.sourceEvent.deltaMode===1?.05:E.sourceEvent.deltaMode?1:.002)*m,H=b[2]*Math.pow(2,O*$);r.scaleTo(H)};let j=[0,0];const N=E=>{(E.sourceEvent.type==="mousedown"||E.sourceEvent.type==="touchstart")&&(j=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY])},k=E=>{const b=o();if(E.sourceEvent.type!=="mousemove"&&E.sourceEvent.type!=="touchmove"||!r)return;const $=[E.sourceEvent.clientX??E.sourceEvent.touches[0].clientX,E.sourceEvent.clientY??E.sourceEvent.touches[0].clientY],O=[$[0]-j[0],$[1]-j[1]];j=$;const H=l()*Math.max(b[2],Math.log(b[2]))*(_?-1:1),I={x:b[0]-O[0]*H,y:b[1]-O[1]*H},q=[[0,0],[g,y]];r.setViewportConstrained({x:I.x,y:I.y,zoom:b[2]},q,f)},T=Zp().on("start",N).on("zoom",x?k:null).on("zoom.wheel",v?S:null);a.call(T,{})}function d(){a.on("zoom",null)}return{update:u,destroy:d,pointer:tn}}const Ml=t=>({x:t.x,y:t.y,zoom:t.k}),Pu=({x:t,y:r,zoom:o})=>jl.translate(t,r).scale(o),cr=(t,r)=>t.target.closest(`.${r}`),jg=(t,r)=>r===2&&Array.isArray(t)&&t.includes(2),L1=t=>((t*=2)<=1?t*t*t:(t-=2)*t*t+2)/2,Iu=(t,r=0,o=L1,l=()=>{})=>{const a=typeof r=="number"&&r>0;return a||l(),a?t.transition().duration(r).ease(o).on("end",l):t},bg=t=>{const r=t.ctrlKey&&Lo()?10:1;return-t.deltaY*(t.deltaMode===1?.05:t.deltaMode?1:.002)*r};function A1({zoomPanValues:t,noWheelClassName:r,d3Selection:o,d3Zoom:l,panOnScrollMode:a,panOnScrollSpeed:u,zoomOnPinch:d,onPanZoomStart:f,onPanZoom:g,onPanZoomEnd:y}){return m=>{if(cr(m,r))return m.ctrlKey&&m.preventDefault(),!1;m.preventDefault(),m.stopImmediatePropagation();const x=o.property("__zoom").k||1;if(m.ctrlKey&&d){const N=tn(m),k=bg(m),T=x*Math.pow(2,k);l.scaleTo(o,T,N,m);return}const v=m.deltaMode===1?20:1;let _=a===$r.Vertical?0:m.deltaX*v,S=a===$r.Horizontal?0:m.deltaY*v;!Lo()&&m.shiftKey&&a!==$r.Vertical&&(_=m.deltaY*v,S=0),l.translateBy(o,-(_/x)*u,-(S/x)*u,{internal:!0});const j=Ml(o.property("__zoom"));clearTimeout(t.panScrollTimeout),t.isPanScrolling?g==null||g(m,j):(t.isPanScrolling=!0,f==null||f(m,j)),t.panScrollTimeout=setTimeout(()=>{y==null||y(m,j),t.isPanScrolling=!1},150)}}function z1({noWheelClassName:t,preventScrolling:r,d3ZoomHandler:o}){return function(l,a){const u=l.type==="wheel",d=!r&&u&&!l.ctrlKey,f=cr(l,t);if(l.ctrlKey&&u&&f&&l.preventDefault(),d||f)return null;l.preventDefault(),o.call(this,l,a)}}function D1({zoomPanValues:t,onDraggingChange:r,onPanZoomStart:o}){return l=>{var u,d,f;if((u=l.sourceEvent)!=null&&u.internal)return;const a=Ml(l.transform);t.mouseButton=((d=l.sourceEvent)==null?void 0:d.button)||0,t.isZoomingOrPanning=!0,t.prevViewport=a,((f=l.sourceEvent)==null?void 0:f.type)==="mousedown"&&r(!0),o&&(o==null||o(l.sourceEvent,a))}}function $1({zoomPanValues:t,panOnDrag:r,onPaneContextMenu:o,onTransformChange:l,onPanZoom:a}){return u=>{var d,f;t.usedRightMouseButton=!!(o&&jg(r,t.mouseButton??0)),(d=u.sourceEvent)!=null&&d.sync||l([u.transform.x,u.transform.y,u.transform.k]),a&&!((f=u.sourceEvent)!=null&&f.internal)&&(a==null||a(u.sourceEvent,Ml(u.transform)))}}function O1({zoomPanValues:t,panOnDrag:r,panOnScroll:o,onDraggingChange:l,onPanZoomEnd:a,onPaneContextMenu:u}){return d=>{var f;if(!((f=d.sourceEvent)!=null&&f.internal)&&(t.isZoomingOrPanning=!1,u&&jg(r,t.mouseButton??0)&&!t.usedRightMouseButton&&d.sourceEvent&&u(d.sourceEvent),t.usedRightMouseButton=!1,l(!1),a)){const g=Ml(d.transform);t.prevViewport=g,clearTimeout(t.timerId),t.timerId=setTimeout(()=>{a==null||a(d.sourceEvent,g)},o?150:0)}}}function F1({panActivationKeyPressed:t,zoomActivationKeyPressed:r,zoomOnScroll:o,zoomOnPinch:l,panOnDrag:a,panOnScroll:u,zoomOnDoubleClick:d,userSelectionActive:f,noWheelClassName:g,noPanClassName:y,lib:m,connectionInProgress:x}){return v=>{var k;const _=r||o,S=l&&v.ctrlKey,j=v.type==="wheel";if(v.button===1&&v.type==="mousedown"&&(cr(v,`${m}-flow__node`)||cr(v,`${m}-flow__edge`)||cr(v,`${m}-flow__selection`)||cr(v,`${m}-flow__nodesselection`)))return!0;if(!a&&!_&&!u&&!d&&!l||f||x&&!j||cr(v,g)&&j||cr(v,y)&&(!j||u&&j&&!r)||!l&&v.ctrlKey&&j)return!1;if(!l&&v.type==="touchstart"&&((k=v.touches)==null?void 0:k.length)>1)return v.preventDefault(),!1;if(!_&&!u&&!S&&j||!a&&(v.type==="mousedown"||v.type==="touchstart")||Array.isArray(a)&&!a.includes(v.button)&&v.type==="mousedown")return!1;const N=Array.isArray(a)&&a.includes(v.button)||!v.button||v.button<=1;return(!v.ctrlKey||j||t)&&N}}function H1({domNode:t,minZoom:r,maxZoom:o,translateExtent:l,viewport:a,onPanZoom:u,onPanZoomStart:d,onPanZoomEnd:f,onDraggingChange:g}){const y={isZoomingOrPanning:!1,usedRightMouseButton:!1,prevViewport:{},mouseButton:0,timerId:void 0,panScrollTimeout:void 0,isPanScrolling:!1},m=t.getBoundingClientRect();let x=[[0,0],[m.width,m.height]];const v=typeof ResizeObserver<"u"?new ResizeObserver(J=>{const C=J[0];C&&(x=[[0,0],[C.contentRect.width,C.contentRect.height]])}):null;v==null||v.observe(t);const _=Zp().extent(()=>x).scaleExtent([r,o]).translateExtent(l),S=Ot(t).call(_);b({x:a.x,y:a.y,zoom:Ti(a.zoom,r,o)},[[0,0],[m.width,m.height]],l);const j=S.on("wheel.zoom"),N=S.on("dblclick.zoom");_.wheelDelta(bg);async function k(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).transform(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function T({noWheelClassName:J,noPanClassName:C,onPaneContextMenu:Y,userSelectionActive:V,panOnScroll:U,panOnDrag:z,panOnScrollMode:D,panOnScrollSpeed:W,preventScrolling:M,zoomOnPinch:R,zoomOnScroll:re,zoomOnDoubleClick:ie,panActivationKeyPressed:ce=!1,zoomActivationKeyPressed:fe,lib:de,onTransformChange:K,connectionInProgress:le,paneClickDistance:pe,selectionOnDrag:_e}){V&&!y.isZoomingOrPanning&&E();const xe=U&&!fe&&!V;_.clickDistance(_e?1/0:!rn(pe)||pe<0?0:pe);const ge=xe?A1({zoomPanValues:y,noWheelClassName:J,d3Selection:S,d3Zoom:_,panOnScrollMode:D,panOnScrollSpeed:W,zoomOnPinch:R,onPanZoomStart:d,onPanZoom:u,onPanZoomEnd:f}):z1({noWheelClassName:J,preventScrolling:M,d3ZoomHandler:j});S.on("wheel.zoom",ge,{passive:!1});const je=D1({zoomPanValues:y,onDraggingChange:g,onPanZoomStart:d});_.on("start",je);const Pe=$1({zoomPanValues:y,panOnDrag:z,onPaneContextMenu:!!Y,onPanZoom:u,onTransformChange:K});_.on("zoom",Pe);const Ie=O1({zoomPanValues:y,panOnDrag:z,panOnScroll:U,onPaneContextMenu:Y,onPanZoomEnd:f,onDraggingChange:g});_.on("end",Ie);const Re=F1({panActivationKeyPressed:ce,zoomActivationKeyPressed:fe,panOnDrag:z,zoomOnScroll:re,panOnScroll:U,zoomOnDoubleClick:ie,zoomOnPinch:R,userSelectionActive:V,noPanClassName:C,noWheelClassName:J,lib:de,connectionInProgress:le});_.filter(Re),ie?S.on("dblclick.zoom",N):S.on("dblclick.zoom",null)}function E(){_.on("zoom",null)}async function b(J,C,Y){const V=Pu(J),U=_==null?void 0:_.constrain()(V,C,Y);return U&&await k(U),U}async function $(J,C){const Y=Pu(J);return await k(Y,C),Y}function O(J){if(S){const C=Pu(J),Y=S.property("__zoom");(Y.k!==J.zoom||Y.x!==J.x||Y.y!==J.y)&&(_==null||_.transform(S,C,null,{sync:!0}))}}function H(){const J=S?Kp(S.node()):{x:0,y:0,k:1};return{x:J.x,y:J.y,zoom:J.k}}async function I(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleTo(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}async function q(J,C){return S?new Promise(Y=>{_==null||_.interpolate((C==null?void 0:C.interpolate)==="linear"?ko:sl).scaleBy(Iu(S,C==null?void 0:C.duration,C==null?void 0:C.ease,()=>Y(!0)),J)}):!1}function ne(J){_==null||_.scaleExtent(J)}function G(J){_==null||_.translateExtent(J)}function ee(J){const C=!rn(J)||J<0?0:J;_==null||_.clickDistance(C)}return{update:T,destroy:E,setViewport:$,setViewportConstrained:b,getViewport:H,scaleTo:I,scaleBy:q,setScaleExtent:ne,setTranslateExtent:G,syncViewport:O,setClickDistance:ee}}var Li;(function(t){t.Line="line",t.Handle="handle"})(Li||(Li={}));function B1({width:t,prevWidth:r,height:o,prevHeight:l,affectsX:a,affectsY:u}){const d=t-r,f=o-l,g=[d>0?1:d<0?-1:0,f>0?1:f<0?-1:0];return d&&a&&(g[0]=g[0]*-1),f&&u&&(g[1]=g[1]*-1),g}function Ch(t){const r=t.includes("right")||t.includes("left"),o=t.includes("bottom")||t.includes("top"),l=t.includes("left"),a=t.includes("top");return{isHorizontal:r,isVertical:o,affectsX:l,affectsY:a}}function ar(t,r){return Math.max(0,r-t)}function ur(t,r){return Math.max(0,t-r)}function tl(t,r,o){return Math.max(0,r-t,t-o)}function Mh(t,r){return t?!r:r}function V1(t,r,o,l,a,u,d,f){let{affectsX:g,affectsY:y}=r;const{isHorizontal:m,isVertical:x}=r,v=m&&x,{xSnapped:_,ySnapped:S}=o,{minWidth:j,maxWidth:N,minHeight:k,maxHeight:T}=l,{x:E,y:b,width:$,height:O,aspectRatio:H}=t;let I=Math.floor(m?_-t.pointerX:0),q=Math.floor(x?S-t.pointerY:0);const ne=$+(g?-I:I),G=O+(y?-q:q),ee=-u[0]*$,J=-u[1]*O;let C=tl(ne,j,N),Y=tl(G,k,T);if(d){let z=0,D=0;g&&I<0?z=ar(E+I+ee,d[0][0]):!g&&I>0&&(z=ur(E+ne+ee,d[1][0])),y&&q<0?D=ar(b+q+J,d[0][1]):!y&&q>0&&(D=ur(b+G+J,d[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(f){let z=0,D=0;g&&I>0?z=ur(E+I,f[0][0]):!g&&I<0&&(z=ar(E+ne,f[1][0])),y&&q>0?D=ur(b+q,f[0][1]):!y&&q<0&&(D=ar(b+G,f[1][1])),C=Math.max(C,z),Y=Math.max(Y,D)}if(a){if(m){const z=tl(ne/H,k,T)*H;if(C=Math.max(C,z),d){let D=0;!g&&!y||g&&!y&&v?D=ur(b+J+ne/H,d[1][1])*H:D=ar(b+J+(g?I:-I)/H,d[0][1])*H,C=Math.max(C,D)}if(f){let D=0;!g&&!y||g&&!y&&v?D=ar(b+ne/H,f[1][1])*H:D=ur(b+(g?I:-I)/H,f[0][1])*H,C=Math.max(C,D)}}if(x){const z=tl(G*H,j,N)/H;if(Y=Math.max(Y,z),d){let D=0;!g&&!y||y&&!g&&v?D=ur(E+G*H+ee,d[1][0])/H:D=ar(E+(y?q:-q)*H+ee,d[0][0])/H,Y=Math.max(Y,D)}if(f){let D=0;!g&&!y||y&&!g&&v?D=ar(E+G*H,f[1][0])/H:D=ur(E+(y?q:-q)*H,f[0][0])/H,Y=Math.max(Y,D)}}}q=q+(q<0?Y:-Y),I=I+(I<0?C:-C),a&&(v?ne>G*H?q=(Mh(g,y)?-I:I)/H:I=(Mh(g,y)?-q:q)*H:m?(q=I/H,y=g):(I=q*H,g=y));const V=g?E+I:E,U=y?b+q:b;return{width:$+(g?-I:I),height:O+(y?-q:q),x:u[0]*I*(g?-1:1)+V,y:u[1]*q*(y?-1:1)+U}}const Cg={width:0,height:0,x:0,y:0},W1={...Cg,pointerX:0,pointerY:0,aspectRatio:1};function U1(t,r,o){const l=r.position.x+t.position.x,a=r.position.y+t.position.y,u=t.measured.width??0,d=t.measured.height??0,f=o[0]*u,g=o[1]*d;return[[l-f,a-g],[l+u-f,a+d-g]]}function Y1({domNode:t,nodeId:r,getStoreItems:o,onChange:l,onEnd:a}){const u=Ot(t);let d={controlDirection:Ch("bottom-right"),boundaries:{minWidth:0,minHeight:0,maxWidth:Number.MAX_VALUE,maxHeight:Number.MAX_VALUE},resizeDirection:void 0,keepAspectRatio:!1};function f({controlPosition:y,boundaries:m,keepAspectRatio:x,resizeDirection:v,onResizeStart:_,onResize:S,onResizeEnd:j,shouldResize:N}){let k={...Cg},T={...W1};d={boundaries:m,resizeDirection:v,keepAspectRatio:x,controlDirection:Ch(y)};let E,b=null,$=[],O,H,I,q=!1;const ne=Dp().on("start",G=>{const{nodeLookup:ee,transform:J,snapGrid:C,snapToGrid:Y,nodeOrigin:V,paneDomNode:U}=o();if(E=ee.get(r),!E)return;b=(U==null?void 0:U.getBoundingClientRect())??null;const{xSnapped:z,ySnapped:D}=Eo(G.sourceEvent,{transform:J,snapGrid:C,snapToGrid:Y,containerBounds:b});k={width:E.measured.width??0,height:E.measured.height??0,x:E.position.x??0,y:E.position.y??0},T={...k,pointerX:z,pointerY:D,aspectRatio:k.width/k.height},O=void 0,H=Br(E.extent)?E.extent:void 0,E.parentId&&(E.extent==="parent"||E.expandParent)&&(O=ee.get(E.parentId)),O&&E.extent==="parent"&&(H=[[0,0],[O.measured.width,O.measured.height]]),$=[],I=void 0;for(const[W,M]of ee)if(M.parentId===r&&($.push({id:W,position:{...M.position},extent:M.extent}),M.extent==="parent"||M.expandParent)){const R=U1(M,E,M.origin??V);I?I=[[Math.min(R[0][0],I[0][0]),Math.min(R[0][1],I[0][1])],[Math.max(R[1][0],I[1][0]),Math.max(R[1][1],I[1][1])]]:I=R}_==null||_(G,{...k})}).on("drag",G=>{const{transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y}=o(),V=Eo(G.sourceEvent,{transform:ee,snapGrid:J,snapToGrid:C,containerBounds:b}),U=[];if(!E)return;const{x:z,y:D,width:W,height:M}=k,R={},re=E.origin??Y,{width:ie,height:ce,x:fe,y:de}=V1(T,d.controlDirection,V,d.boundaries,d.keepAspectRatio,re,H,I),K=ie!==W,le=ce!==M,pe=fe!==z&&K,_e=de!==D&≤if(!pe&&!_e&&!K&&!le)return;if((pe||_e||re[0]===1||re[1]===1)&&(R.x=pe?fe:k.x,R.y=_e?de:k.y,k.x=R.x,k.y=R.y,$.length>0)){const Pe=fe-z,Ie=de-D;for(const Re of $)Re.position={x:Re.position.x-Pe+re[0]*(ie-W),y:Re.position.y-Ie+re[1]*(ce-M)},U.push(Re)}if((K||le)&&(R.width=K&&(!d.resizeDirection||d.resizeDirection==="horizontal")?ie:k.width,R.height=le&&(!d.resizeDirection||d.resizeDirection==="vertical")?ce:k.height,k.width=R.width,k.height=R.height),O&&E.expandParent){const Pe=re[0]*(R.width??0);R.x&&R.x{q&&(j==null||j(G,{...k}),a==null||a({...k}),q=!1)});u.call(ne)}function g(){u.on(".drag",null)}return{update:f,destroy:g}}var Tu={exports:{}},Ru={},Lu={exports:{}},Au={};/** * @license React * use-sync-external-store-shim.production.js * @@ -58,5 +58,5 @@ Error generating stack: `+h.message+` `,` +`).split(` -`)),m=y.reduce((x,v)=>x.concat(...v),[]);return[y,m]}return[[],[]]},[t]);return F.useEffect(()=>{const g=(r==null?void 0:r.target)??Hh,y=(r==null?void 0:r.actInsideInputWithModifier)??!0;if(t!==null){const m=_=>{var N,k;if(a.current=_.ctrlKey||_.metaKey||_.shiftKey||_.altKey,(!a.current||a.current&&!y)&&fg(_))return!1;const j=Vh(_.code,f);if(u.current.add(_[j]),Bh(d,u.current,!1)){const T=((k=(N=_.composedPath)==null?void 0:N.call(_))==null?void 0:k[0])||_.target,E=(T==null?void 0:T.nodeName)==="BUTTON"||(T==null?void 0:T.nodeName)==="A";r.preventDefault!==!1&&(a.current||!E)&&_.preventDefault(),l(!0)}},x=_=>{const S=Vh(_.code,f);Bh(d,u.current,!0)?(l(!1),u.current.clear()):u.current.delete(_[S]),_.key==="Meta"&&u.current.clear(),a.current=!1},v=()=>{u.current.clear(),l(!1)};return g==null||g.addEventListener("keydown",m),g==null||g.addEventListener("keyup",x),window.addEventListener("blur",v),window.addEventListener("contextmenu",v),()=>{g==null||g.removeEventListener("keydown",m),g==null||g.removeEventListener("keyup",x),window.removeEventListener("blur",v),window.removeEventListener("contextmenu",v)}}},[t,l]),o}function Bh(t,r,o){return t.filter(l=>o||l.length===r.size).some(l=>l.every(a=>r.has(a)))}function Vh(t,r){return r.includes(t)?"code":"key"}const k_=()=>{const t=We();return F.useMemo(()=>({zoomIn:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1.2,r):!1},zoomOut:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1/1.2,r):!1},zoomTo:async(r,o)=>{const{panZoom:l}=t.getState();return l?l.scaleTo(r,o):!1},getZoom:()=>t.getState().transform[2],setViewport:async(r,o)=>{const{transform:[l,a,u],panZoom:d}=t.getState();return d?(await d.setViewport({x:r.x??l,y:r.y??a,zoom:r.zoom??u},o),!0):!1},getViewport:()=>{const[r,o,l]=t.getState().transform;return{x:r,y:o,zoom:l}},setCenter:async(r,o,l)=>t.getState().setCenter(r,o,l),fitBounds:async(r,o)=>{const{width:l,height:a,minZoom:u,maxZoom:d,panZoom:f}=t.getState(),g=cc(r,l,a,u,d,(o==null?void 0:o.padding)??.1);return f?(await f.setViewport(g,{duration:o==null?void 0:o.duration,ease:o==null?void 0:o.ease,interpolate:o==null?void 0:o.interpolate}),!0):!1},screenToFlowPosition:(r,o={})=>{const{transform:l,snapGrid:a,snapToGrid:u,domNode:d}=t.getState();if(!d)return r;const{x:f,y:g}=d.getBoundingClientRect(),y={x:r.x-f,y:r.y-g},m=o.snapGrid??a,x=o.snapToGrid??u;return Bo(y,l,x,m)},flowToScreenPosition:r=>{const{transform:o,domNode:l}=t.getState();if(!l)return r;const{x:a,y:u}=l.getBoundingClientRect(),d=Ri(r,o);return{x:d.x+a,y:d.y+u}}}),[])};function Lg(t,r){const o=[],l=new Map,a=[];for(const u of t)if(u.type==="add"){a.push(u);continue}else if(u.type==="remove"||u.type==="replace")l.set(u.id,[u]);else{const d=l.get(u.id);d?d.push(u):l.set(u.id,[u])}for(const u of r){const d=l.get(u.id);if(!d){o.push(u);continue}if(d[0].type==="remove")continue;if(d[0].type==="replace"){o.push({...d[0].item});continue}const f={...u};for(const g of d)E_(g,f);o.push(f)}return a.length&&a.forEach(u=>{u.index!==void 0?o.splice(u.index,0,{...u.item}):o.push({...u.item})}),o}function E_(t,r){switch(t.type){case"select":{r.selected=t.selected;break}case"position":{typeof t.position<"u"&&(r.position=t.position),typeof t.dragging<"u"&&(r.dragging=t.dragging);break}case"dimensions":{typeof t.dimensions<"u"&&(r.measured={...t.dimensions},t.setAttributes&&((t.setAttributes===!0||t.setAttributes==="width")&&(r.width=t.dimensions.width),(t.setAttributes===!0||t.setAttributes==="height")&&(r.height=t.dimensions.height))),typeof t.resizing=="boolean"&&(r.resizing=t.resizing);break}}}function N_(t,r){return Lg(t,r)}function j_(t,r){return Lg(t,r)}function Ar(t,r){return{id:t,type:"select",selected:r}}function ji(t,r=new Set,o=!1){const l=[];for(const[a,u]of t){const d=r.has(a);!(u.selected===void 0&&!d)&&u.selected!==d&&(o&&(u.selected=d),l.push(Ar(u.id,d)))}return l}function Wh({items:t=[],lookup:r}){var a;const o=[],l=new Map(t.map(u=>[u.id,u]));for(const[u,d]of t.entries()){const f=r.get(d.id),g=((a=f==null?void 0:f.internals)==null?void 0:a.userNode)??f;g!==void 0&&g!==d&&o.push({id:d.id,item:d,type:"replace"}),g===void 0&&o.push({item:d,type:"add",index:u})}for(const[u]of r)l.get(u)===void 0&&o.push({id:u,type:"remove"});return o}function Uh(t){return{id:t.id,type:"remove"}}const b_=ag();function C_(t,r,o={}){return d1(t,r,{...o,onError:o.onError??b_})}const Yh=t=>Qw(t),M_=t=>rg(t);function Ag(t){return F.forwardRef(t)}const zg=typeof window<"u"?F.useLayoutEffect:F.useEffect;function Gh(t){const[r,o]=F.useState(BigInt(0)),[l]=F.useState(()=>P_(()=>o(a=>a+BigInt(1))));return zg(()=>{const a=l.get();a.length&&(t(a),l.reset())},[r]),l}function P_(t){let r=[];return{get:()=>r,reset:()=>{r=[]},push:o=>{r.push(o),t()}}}const Dg=F.createContext(null);function I_({children:t}){const r=We(),o=F.useCallback(f=>{const{nodes:g=[],setNodes:y,hasDefaultNodes:m,onNodesChange:x,nodeLookup:v,fitViewQueued:_,onNodesChangeMiddlewareMap:S}=r.getState();let j=g;for(const k of f)j=typeof k=="function"?k(j):k;let N=Wh({items:j,lookup:v});for(const k of S.values())N=k(N);m&&y(j),N.length>0?x==null||x(N):_&&window.requestAnimationFrame(()=>{const{fitViewQueued:k,nodes:T,setNodes:E}=r.getState();k&&E(T)})},[]),l=Gh(o),a=F.useCallback(f=>{const{edges:g=[],setEdges:y,hasDefaultEdges:m,onEdgesChange:x,edgeLookup:v}=r.getState();let _=g;for(const S of f)_=typeof S=="function"?S(_):S;m?y(_):x&&x(Wh({items:_,lookup:v}))},[]),u=Gh(a),d=F.useMemo(()=>({nodeQueue:l,edgeQueue:u}),[]);return p.jsx(Dg.Provider,{value:d,children:t})}function T_(){const t=F.useContext(Dg);if(!t)throw new Error("useBatchContext must be used within a BatchProvider");return t}const R_=t=>!!t.panZoom;function yc(){const t=k_(),r=We(),o=T_(),l=Ae(R_),a=F.useMemo(()=>{const u=x=>r.getState().nodeLookup.get(x),d=x=>{o.nodeQueue.push(x)},f=x=>{o.edgeQueue.push(x)},g=x=>{var k,T;const{nodeLookup:v,nodeOrigin:_}=r.getState(),S=Yh(x)?x:v.get(x.id),j=S.parentId?cg(S.position,S.measured,S.parentId,v,_):S.position,N={...S,position:j,width:((k=S.measured)==null?void 0:k.width)??S.width,height:((T=S.measured)==null?void 0:T.height)??S.height};return Ro(N)},y=(x,v,_={replace:!1})=>{d(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&Yh(N)?N:{...j,...N}}return j}))},m=(x,v,_={replace:!1})=>{f(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&M_(N)?N:{...j,...N}}return j}))};return{getNodes:()=>r.getState().nodes.map(x=>({...x})),getNode:x=>{var v;return(v=u(x))==null?void 0:v.internals.userNode},getInternalNode:u,getEdges:()=>{const{edges:x=[]}=r.getState();return x.map(v=>({...v}))},getEdge:x=>r.getState().edgeLookup.get(x),setNodes:d,setEdges:f,addNodes:x=>{const v=Array.isArray(x)?x:[x];o.nodeQueue.push(_=>[..._,...v])},addEdges:x=>{const v=Array.isArray(x)?x:[x];o.edgeQueue.push(_=>[..._,...v])},toObject:()=>{const{nodes:x=[],edges:v=[],transform:_}=r.getState(),[S,j,N]=_;return{nodes:x.map(k=>({...k})),edges:v.map(k=>({...k})),viewport:{x:S,y:j,zoom:N}}},deleteElements:async({nodes:x=[],edges:v=[]})=>{const{nodes:_,edges:S,onNodesDelete:j,onEdgesDelete:N,triggerNodeChanges:k,triggerEdgeChanges:T,onDelete:E,onBeforeDelete:b}=r.getState(),{nodes:$,edges:O}=await t1({nodesToRemove:x,edgesToRemove:v,nodes:_,edges:S,onBeforeDelete:b}),H=O.length>0,I=$.length>0;if(H){const q=O.map(Uh);N==null||N(O),T(q)}if(I){const q=$.map(Uh);j==null||j($),k(q)}return(I||H)&&(E==null||E({nodes:$,edges:O})),{deletedNodes:$,deletedEdges:O}},getIntersectingNodes:(x,v=!0,_)=>{const S=yh(x),j=S?x:g(x),N=_!==void 0;return j?(_||r.getState().nodes).filter(k=>{const T=r.getState().nodeLookup.get(k.id);if(T&&!S&&(k.id===x.id||!T.internals.positionAbsolute))return!1;const E=Ro(N?k:T),b=vl(E,j);return v&&b>0||b>=E.width*E.height||b>=j.width*j.height}):[]},isNodeIntersecting:(x,v,_=!0)=>{const j=yh(x)?x:g(x);if(!j)return!1;const N=vl(j,v);return _&&N>0||N>=v.width*v.height||N>=j.width*j.height},updateNode:y,updateNodeData:(x,v,_={replace:!1})=>{y(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},updateEdge:m,updateEdgeData:(x,v,_={replace:!1})=>{m(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},getNodesBounds:x=>{const{nodeLookup:v,nodeOrigin:_}=r.getState();return Kw(x,{nodeLookup:v,nodeOrigin:_})},getHandleConnections:({type:x,id:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}-${x}${v?`-${v}`:""}`))==null?void 0:S.values())??[])},getNodeConnections:({type:x,handleId:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}${x?v?`-${x}-${v}`:`-${x}`:""}`))==null?void 0:S.values())??[])},fitView:async x=>{const v=r.getState().fitViewResolver??i1();return r.setState({fitViewQueued:!0,fitViewOptions:x,fitViewResolver:v}),o.nodeQueue.push(_=>[..._]),v.promise}}},[]);return F.useMemo(()=>({...a,...t,viewportInitialized:l}),[l])}const Xh=t=>t.selected,L_=typeof window<"u"?window:void 0;function A_({deleteKeyCode:t,multiSelectionKeyCode:r}){const o=We(),{deleteElements:l}=yc(),a=Ao(t,{actInsideInputWithModifier:!1}),u=Ao(r,{target:L_});F.useEffect(()=>{if(a){const{edges:d,nodes:f}=o.getState();l({nodes:f.filter(Xh),edges:d.filter(Xh)}),o.setState({nodesSelectionActive:!1})}},[a]),F.useEffect(()=>{o.setState({multiSelectionActive:u})},[u])}function z_(t){const r=We();F.useEffect(()=>{const o=()=>{var a,u,d,f;if(!t.current||!(((u=(a=t.current).checkVisibility)==null?void 0:u.call(a))??!0))return!1;const l=dc(t.current);(l.height===0||l.width===0)&&((f=(d=r.getState()).onError)==null||f.call(d,"004",sn.error004())),r.setState({width:l.width||500,height:l.height||500})};if(t.current){o(),window.addEventListener("resize",o);const l=new ResizeObserver(()=>o());return l.observe(t.current),()=>{window.removeEventListener("resize",o),l&&t.current&&l.unobserve(t.current)}}},[])}const Tl={position:"absolute",width:"100%",height:"100%",top:0,left:0},D_=t=>({userSelectionActive:t.userSelectionActive,lib:t.lib,connectionInProgress:t.connection.inProgress});function $_({onPaneContextMenu:t,zoomOnScroll:r=!0,zoomOnPinch:o=!0,panOnScroll:l=!1,panActivationKeyPressed:a,panOnScrollSpeed:u=.5,panOnScrollMode:d=$r.Free,zoomOnDoubleClick:f=!0,panOnDrag:g=!0,defaultViewport:y,translateExtent:m,minZoom:x,maxZoom:v,zoomActivationKeyCode:_,preventScrolling:S=!0,children:j,noWheelClassName:N,noPanClassName:k,onViewportChange:T,isControlledViewport:E,paneClickDistance:b,selectionOnDrag:$}){const O=We(),H=F.useRef(null),{userSelectionActive:I,lib:q,connectionInProgress:ne}=Ae(D_,qe),G=Ao(_),ee=F.useRef();z_(H);const J=F.useCallback(C=>{T==null||T({x:C[0],y:C[1],zoom:C[2]}),E||O.setState({transform:C})},[T,E]);return F.useEffect(()=>{if(H.current){ee.current=H1({domNode:H.current,minZoom:x,maxZoom:v,translateExtent:m,viewport:y,onDraggingChange:U=>O.setState(z=>z.paneDragging===U?z:{paneDragging:U}),onPanZoomStart:(U,z)=>{const{onViewportChangeStart:D,onMoveStart:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoom:(U,z)=>{const{onViewportChange:D,onMove:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoomEnd:(U,z)=>{const{onViewportChangeEnd:D,onMoveEnd:W}=O.getState();W==null||W(U,z),D==null||D(z)}});const{x:C,y:Y,zoom:V}=ee.current.getViewport();return O.setState({panZoom:ee.current,transform:[C,Y,V],domNode:H.current.closest(".react-flow")}),()=>{var U;(U=ee.current)==null||U.destroy()}}},[]),F.useEffect(()=>{var C;(C=ee.current)==null||C.update({onPaneContextMenu:t,zoomOnScroll:r,zoomOnPinch:o,panOnScroll:l,panActivationKeyPressed:a,panOnScrollSpeed:u,panOnScrollMode:d,zoomOnDoubleClick:f,panOnDrag:g,zoomActivationKeyPressed:G,preventScrolling:S,noPanClassName:k,userSelectionActive:I,noWheelClassName:N,lib:q,onTransformChange:J,connectionInProgress:ne,selectionOnDrag:$,paneClickDistance:b})},[t,r,o,l,a,u,d,f,g,G,S,k,I,N,q,J,ne,$,b]),p.jsx("div",{className:"react-flow__renderer",ref:H,style:Tl,children:j})}const O_=t=>({userSelectionActive:t.userSelectionActive,userSelectionRect:t.userSelectionRect});function F_(){const{userSelectionActive:t,userSelectionRect:r}=Ae(O_,qe);return t&&r?p.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:r.width,height:r.height,transform:`translate(${r.x}px, ${r.y}px)`}}):null}const zu=(t,r)=>o=>{o.target===r.current&&(t==null||t(o))},H_=t=>({userSelectionActive:t.userSelectionActive,elementsSelectable:t.elementsSelectable,dragging:t.paneDragging,panBy:t.panBy,autoPanSpeed:t.autoPanSpeed});function B_({isSelecting:t,selectionKeyPressed:r,selectionMode:o=Io.Full,panOnDrag:l,autoPanOnSelection:a,paneClickDistance:u,selectionOnDrag:d,onSelectionStart:f,onSelectionEnd:g,onPaneClick:y,onPaneContextMenu:m,onPaneScroll:x,onPaneMouseEnter:v,onPaneMouseMove:_,onPaneMouseLeave:S,children:j}){const N=F.useRef(0),k=We(),{userSelectionActive:T,elementsSelectable:E,dragging:b,panBy:$,autoPanSpeed:O}=Ae(H_,qe),H=E&&(t||T),I=F.useRef(null),q=F.useRef(),ne=F.useRef(new Set),G=F.useRef(new Set),ee=F.useRef(!1),J=F.useRef(!1),C=F.useRef({x:0,y:0}),Y=F.useRef(!1),V=K=>{if(J.current||ee.current||k.getState().connection.inProgress){J.current=!1,ee.current=!1;return}y==null||y(K),k.getState().resetSelectedElements(),k.setState({nodesSelectionActive:!1})},U=K=>{if(Array.isArray(l)&&(l!=null&&l.includes(2))){K.preventDefault();return}m==null||m(K)},z=x?K=>x(K):void 0,D=K=>{J.current&&(K.stopPropagation(),J.current=!1)},W=K=>{var Re,tt;if(K.pointerType==="touch"&&l!==!1&&!r)return;const{domNode:le,transform:pe}=k.getState();if(q.current=le==null?void 0:le.getBoundingClientRect(),!q.current)return;const _e=K.target===I.current;if(!_e&&!!K.target.closest(".nokey")||!t||!(d&&_e||r)||K.button!==0||!K.isPrimary)return;(tt=(Re=K.target)==null?void 0:Re.setPointerCapture)==null||tt.call(Re,K.pointerId),J.current=!1;const{x:je,y:Me}=on(K.nativeEvent,q.current),Pe=Bo({x:je,y:Me},pe);k.setState({userSelectionRect:{width:0,height:0,startX:Pe.x,startY:Pe.y,x:je,y:Me}}),_e||(K.stopPropagation(),K.preventDefault())};function M(K,le){const{userSelectionRect:pe}=k.getState();if(!pe)return;const{transform:_e,nodeLookup:xe,edgeLookup:ge,connectionLookup:je,triggerNodeChanges:Me,triggerEdgeChanges:Pe,defaultEdgeOptions:Re}=k.getState(),tt={x:pe.startX,y:pe.startY},{x:nt,y:Qe}=Ri(tt,_e),ot={startX:tt.x,startY:tt.y,x:Kze.id)),G.current=new Set;const Ke=(Re==null?void 0:Re.selectable)??!0;for(const ze of ne.current){const gt=je.get(ze);if(gt)for(const{edgeId:ft}of gt.values()){const Je=ge.get(ft);Je&&(Je.selectable??Ke)&&G.current.add(ft)}}if(!vh(at,ne.current)){const ze=ji(xe,ne.current,!0);Me(ze)}if(!vh(It,G.current)){const ze=ji(ge,G.current);Pe(ze)}k.setState({userSelectionRect:ot,userSelectionActive:!0,nodesSelectionActive:!1})}function R(){if(!a||!q.current)return;const[K,le]=uc(C.current,q.current,O);$({x:K,y:le}).then(pe=>{if(!J.current||!pe){N.current=requestAnimationFrame(R);return}const{x:_e,y:xe}=C.current;M(_e,xe),N.current=requestAnimationFrame(R)})}const re=()=>{cancelAnimationFrame(N.current),N.current=0,Y.current=!1};F.useEffect(()=>()=>re(),[]);const ie=K=>{const{userSelectionRect:le,transform:pe,resetSelectedElements:_e}=k.getState();if(!q.current||!le)return;const{x:xe,y:ge}=on(K.nativeEvent,q.current);C.current={x:xe,y:ge};const je=Ri({x:le.startX,y:le.startY},pe);if(!J.current){const Me=r?0:u;if(Math.hypot(xe-je.x,ge-je.y)<=Me)return;_e(),f==null||f(K)}J.current=!0,Y.current||(R(),Y.current=!0),M(xe,ge)},ce=K=>{var le,pe;if(!H){K.target===I.current&&k.getState().connection.inProgress&&(ee.current=!0);return}K.button===0&&((pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),!T&&K.target===I.current&&k.getState().userSelectionRect&&(V==null||V(K)),k.setState({userSelectionActive:!1,userSelectionRect:null}),J.current&&(g==null||g(K),k.setState({nodesSelectionActive:ne.current.size>0})),re())},fe=K=>{var le,pe;(pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),re()},de=l===!0||Array.isArray(l)&&l.includes(0);return p.jsxs("div",{className:it(["react-flow__pane",{draggable:de,dragging:b,selection:t}]),onClick:H?void 0:zu(V,I),onContextMenu:zu(U,I),onWheel:zu(z,I),onPointerEnter:H?void 0:v,onPointerMove:H?ie:_,onPointerUp:ce,onPointerCancel:H?fe:void 0,onPointerDownCapture:H?W:void 0,onClickCapture:H?D:void 0,onPointerLeave:S,ref:I,style:Tl,children:[j,p.jsx(F_,{})]})}function Ju({id:t,store:r,unselect:o=!1,nodeRef:l}){const{addSelectedNodes:a,unselectNodesAndEdges:u,multiSelectionActive:d,nodeLookup:f,onError:g}=r.getState(),y=f.get(t);if(!y){g==null||g("012",sn.error012(t));return}r.setState({nodesSelectionActive:!1}),y.selected?(o||y.selected&&d)&&(u({nodes:[y],edges:[]}),requestAnimationFrame(()=>{var m;return(m=l==null?void 0:l.current)==null?void 0:m.blur()})):a([t])}function $g({nodeRef:t,disabled:r=!1,noDragClassName:o,handleSelector:l,nodeId:a,isSelectable:u,nodeClickDistance:d}){const f=We(),[g,y]=F.useState(!1),m=F.useRef();return F.useEffect(()=>{if(!r)return m.current=b1({getStoreItems:()=>f.getState(),onNodeMouseDown:x=>{Ju({id:x,store:f,nodeRef:t})},onDragStart:()=>{y(!0)},onDragStop:()=>{y(!1)}}),()=>{var x;(x=m.current)==null||x.destroy(),m.current=void 0}},[r,f,t]),F.useEffect(()=>{r||!t.current||!m.current||m.current.update({noDragClassName:o,handleSelector:l,domNode:t.current,isSelectable:u,nodeId:a,nodeClickDistance:d})},[o,l,r,u,t,a,d]),g}const V_=t=>r=>r.selected&&(r.draggable||t&&typeof r.draggable>"u");function Og(){const t=We();return F.useCallback(o=>{const{nodeExtent:l,snapToGrid:a,snapGrid:u,nodesDraggable:d,onError:f,updateNodePositions:g,nodeLookup:y,nodeOrigin:m}=t.getState(),x=new Map,v=V_(d),_=a?u[0]:5,S=a?u[1]:5,j=o.direction.x*_*o.factor,N=o.direction.y*S*o.factor;for(const[,k]of y){if(!v(k))continue;let T={x:k.internals.positionAbsolute.x+j,y:k.internals.positionAbsolute.y+N};a&&(T=Ho(T,u));const{position:E,positionAbsolute:b}=ig({nodeId:k.id,nextPosition:T,nodeLookup:y,nodeExtent:l,nodeOrigin:m,onError:f});k.position=E,k.internals.positionAbsolute=b,x.set(k.id,k)}g(x)},[])}const vc=F.createContext(null),W_=vc.Provider;vc.Consumer;const Fg=()=>F.useContext(vc),U_=t=>({connectOnClick:t.connectOnClick,noPanClassName:t.noPanClassName,rfId:t.rfId}),Hg=F.createContext(null);function Y_({children:t}){const r=Ae(U_,qe);return p.jsx(Hg.Provider,{value:r,children:t})}function G_(){const t=F.useContext(Hg);if(!t)throw new Error("useHandleConfig must be used within a HandleConfigProvider");return t}const X_={connectingFrom:!1,connectingTo:!1,clickConnecting:!1,isPossibleEndHandle:!0,connectionInProcess:!1,clickConnectionInProcess:!1,valid:!1},q_=(t,r,o)=>l=>{const{connectionClickStartHandle:a,connectionMode:u,connection:d}=l,{fromHandle:f,toHandle:g,isValid:y}=d;if(!f&&!a)return X_;const m=(g==null?void 0:g.nodeId)===t&&(g==null?void 0:g.id)===r&&(g==null?void 0:g.type)===o;return{connectingFrom:(f==null?void 0:f.nodeId)===t&&(f==null?void 0:f.id)===r&&(f==null?void 0:f.type)===o,connectingTo:m,clickConnecting:(a==null?void 0:a.nodeId)===t&&(a==null?void 0:a.id)===r&&(a==null?void 0:a.type)===o,isPossibleEndHandle:u===Ii.Strict?(f==null?void 0:f.type)!==o:t!==(f==null?void 0:f.nodeId)||r!==(f==null?void 0:f.id),connectionInProcess:!!f,clickConnectionInProcess:!!a,valid:m&&y}};function Q_({type:t="source",position:r=Se.Top,isValidConnection:o,isConnectable:l=!0,isConnectableStart:a=!0,isConnectableEnd:u=!0,id:d,onConnect:f,children:g,className:y,onMouseDown:m,onTouchStart:x,...v},_){var Y,V;const S=d||null,j=t==="target",N=We(),k=Fg(),{connectOnClick:T,noPanClassName:E,rfId:b}=G_(),{connectingFrom:$,connectingTo:O,clickConnecting:H,isPossibleEndHandle:I,connectionInProcess:q,clickConnectionInProcess:ne,valid:G}=Ae(q_(k,S,t),qe);k||(V=(Y=N.getState()).onError)==null||V.call(Y,"010",sn.error010());const ee=U=>{const{defaultEdgeOptions:z,onConnect:D,hasDefaultEdges:W}=N.getState(),M={...z,...U};if(W){const{edges:R,setEdges:re,onError:ie}=N.getState();re(C_(M,R,{onError:ie}))}D==null||D(M),f==null||f(M)},J=U=>{if(!k)return;const z=hg(U.nativeEvent);if(a&&(z&&U.button===0||!z)){const D=N.getState();Zu.onPointerDown(U.nativeEvent,{handleDomNode:U.currentTarget,autoPanOnConnect:D.autoPanOnConnect,connectionMode:D.connectionMode,connectionRadius:D.connectionRadius,domNode:D.domNode,nodeLookup:D.nodeLookup,lib:D.lib,isTarget:j,handleId:S,nodeId:k,flowId:D.rfId,panBy:D.panBy,cancelConnection:D.cancelConnection,onConnectStart:D.onConnectStart,onConnectEnd:(...W)=>{var M,R;return(R=(M=N.getState()).onConnectEnd)==null?void 0:R.call(M,...W)},updateConnection:D.updateConnection,onConnect:ee,isValidConnection:o||((...W)=>{var M,R;return((R=(M=N.getState()).isValidConnection)==null?void 0:R.call(M,...W))??!0}),getTransform:()=>N.getState().transform,getFromHandle:()=>N.getState().connection.fromHandle,autoPanSpeed:D.autoPanSpeed,dragThreshold:D.connectionDragThreshold})}z?m==null||m(U):x==null||x(U)},C=U=>{const{onClickConnectStart:z,onClickConnectEnd:D,connectionClickStartHandle:W,connectionMode:M,isValidConnection:R,lib:re,rfId:ie,nodeLookup:ce,connection:fe}=N.getState();if(!k||!W&&!a)return;if(!W){z==null||z(U.nativeEvent,{nodeId:k,handleId:S,handleType:t}),N.setState({connectionClickStartHandle:{nodeId:k,type:t,id:S}});return}const de=dg(U.target),K=o||R,{connection:le,isValid:pe}=Zu.isValid(U.nativeEvent,{handle:{nodeId:k,id:S,type:t},connectionMode:M,fromNodeId:W.nodeId,fromHandleId:W.id||null,fromType:W.type,isValidConnection:K,flowId:ie,doc:de,lib:re,nodeLookup:ce});pe&&le&&ee(le);const _e=structuredClone(fe);delete _e.inProgress,_e.toPosition=_e.toHandle?_e.toHandle.position:null,D==null||D(U,_e),N.setState({connectionClickStartHandle:null})};return p.jsx("div",{"data-handleid":S,"data-nodeid":k,"data-handlepos":r,"data-id":`${b}-${k}-${S}-${t}`,className:it(["react-flow__handle",`react-flow__handle-${r}`,"nodrag",E,y,{source:!j,target:j,connectable:l,connectablestart:a,connectableend:u,clickconnecting:H,connectingfrom:$,connectingto:O,valid:G,connectionindicator:l&&(!q||I)&&(q||ne?u:a)}]),onMouseDown:J,onTouchStart:J,onClick:T?C:void 0,ref:_,...v,children:g})}const Ai=F.memo(Ag(Q_));function K_({data:t,isConnectable:r,sourcePosition:o=Se.Bottom}){return p.jsxs(p.Fragment,{children:[t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:o,isConnectable:r})]})}function Z_({data:t,isConnectable:r,targetPosition:o=Se.Top,sourcePosition:l=Se.Bottom}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:l,isConnectable:r})]})}function J_(){return null}function eS({data:t,isConnectable:r,targetPosition:o=Se.Top}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label]})}const xl={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},qh={input:K_,default:Z_,output:eS,group:J_};function tS(t){var r,o,l,a;return t.internals.handleBounds===void 0?{width:t.width??t.initialWidth??((r=t.style)==null?void 0:r.width),height:t.height??t.initialHeight??((o=t.style)==null?void 0:o.height)}:{width:t.width??((l=t.style)==null?void 0:l.width),height:t.height??((a=t.style)==null?void 0:a.height)}}const nS=t=>{const{width:r,height:o,x:l,y:a}=Fo(t.nodeLookup,{filter:u=>!!u.selected});return{width:rn(r)?r:null,height:rn(o)?o:null,userSelectionActive:t.userSelectionActive,transformString:`translate(${t.transform[0]}px,${t.transform[1]}px) scale(${t.transform[2]}) translate(${l}px,${a}px)`}};function rS({onSelectionContextMenu:t,noPanClassName:r,disableKeyboardA11y:o}){const l=We(),{width:a,height:u,transformString:d,userSelectionActive:f}=Ae(nS,qe),g=Og(),y=F.useRef(null);F.useEffect(()=>{var _;o||(_=y.current)==null||_.focus({preventScroll:!0})},[o]);const m=!f&&a!==null&&u!==null;if($g({nodeRef:y,disabled:!m}),!m)return null;const x=t?_=>{const S=l.getState().nodes.filter(j=>j.selected);t(_,S)}:void 0,v=_=>{Object.prototype.hasOwnProperty.call(xl,_.key)&&(_.preventDefault(),g({direction:xl[_.key],factor:_.shiftKey?4:1}))};return p.jsx("div",{className:it(["react-flow__nodesselection","react-flow__container",r]),style:{transform:d},children:p.jsx("div",{ref:y,className:"react-flow__nodesselection-rect",onContextMenu:x,tabIndex:o?void 0:-1,onKeyDown:o?void 0:v,style:{width:a,height:u}})})}const Qh=typeof window<"u"?window:void 0,iS=t=>({nodesSelectionActive:t.nodesSelectionActive,userSelectionActive:t.userSelectionActive});function Bg({children:t,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,paneClickDistance:f,deleteKeyCode:g,selectionKeyCode:y,selectionOnDrag:m,selectionMode:x,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:S,panActivationKeyCode:j,zoomActivationKeyCode:N,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:b,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:I,autoPanOnSelection:q,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,preventScrolling:C,onSelectionContextMenu:Y,noWheelClassName:V,noPanClassName:U,disableKeyboardA11y:z,onViewportChange:D,isControlledViewport:W}){const{nodesSelectionActive:M,userSelectionActive:R}=Ae(iS,qe),re=Ao(y,{target:Qh}),ie=Ao(j,{target:Qh}),ce=ie||I,fe=ie||b,de=m&&ce!==!0,K=re||R||de;return A_({deleteKeyCode:g,multiSelectionKeyCode:S}),p.jsx($_,{onPaneContextMenu:u,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:fe,panActivationKeyPressed:ie,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:!re&&ce,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,zoomActivationKeyCode:N,preventScrolling:C,noWheelClassName:V,noPanClassName:U,onViewportChange:D,isControlledViewport:W,paneClickDistance:f,selectionOnDrag:de,children:p.jsxs(B_,{onSelectionStart:v,onSelectionEnd:_,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,panOnDrag:ce,autoPanOnSelection:q,isSelecting:!!K,selectionMode:x,selectionKeyPressed:re,paneClickDistance:f,selectionOnDrag:de,children:[t,M&&p.jsx(rS,{onSelectionContextMenu:Y,noPanClassName:U,disableKeyboardA11y:z})]})})}Bg.displayName="FlowRenderer";const oS=F.memo(Bg),sS=t=>r=>t?ac(r.nodeLookup,{x:0,y:0,width:r.width,height:r.height},r.transform,!0).map(o=>o.id):Array.from(r.nodeLookup.keys());function lS(t){return Ae(F.useCallback(sS(t),[t]),qe)}const aS=t=>t.updateNodeInternals;function uS(){const t=Ae(aS),[r]=F.useState(()=>typeof ResizeObserver>"u"?null:new ResizeObserver(o=>{const l=new Map;o.forEach(a=>{const u=a.target.getAttribute("data-id");l.set(u,{id:u,nodeElement:a.target,force:!0})}),t(l)}));return F.useEffect(()=>()=>{r==null||r.disconnect()},[r]),r}function cS({node:t,nodeType:r,hasDimensions:o,resizeObserver:l}){const a=We(),u=F.useRef(null),d=F.useRef(null),f=F.useRef(t.sourcePosition),g=F.useRef(t.targetPosition),y=F.useRef(r),m=o&&!!t.internals.handleBounds;return F.useEffect(()=>{u.current&&!t.hidden&&(!m||d.current!==u.current)&&(d.current&&(l==null||l.unobserve(d.current)),l==null||l.observe(u.current),d.current=u.current)},[m,t.hidden]),F.useEffect(()=>()=>{d.current&&(l==null||l.unobserve(d.current),d.current=null)},[]),F.useEffect(()=>{if(u.current){const x=y.current!==r,v=f.current!==t.sourcePosition,_=g.current!==t.targetPosition;(x||v||_)&&(y.current=r,f.current=t.sourcePosition,g.current=t.targetPosition,a.getState().updateNodeInternals(new Map([[t.id,{id:t.id,nodeElement:u.current,force:!0}]])))}},[t.id,r,t.sourcePosition,t.targetPosition]),u}function dS({id:t,onClick:r,onMouseEnter:o,onMouseMove:l,onMouseLeave:a,onContextMenu:u,onDoubleClick:d,nodesDraggable:f,elementsSelectable:g,nodesConnectable:y,nodesFocusable:m,resizeObserver:x,noDragClassName:v,noPanClassName:_,disableKeyboardA11y:S,rfId:j,nodeTypes:N,nodeClickDistance:k,onError:T}){const{node:E,internals:b,isParent:$}=Ae(K=>{const le=K.nodeLookup.get(t),pe=K.parentLookup.has(t);return{node:le,internals:le.internals,isParent:pe}},qe);let O=E.type||"default",H=(N==null?void 0:N[O])||qh[O];H===void 0&&(T==null||T("003",sn.error003(O)),O="default",H=(N==null?void 0:N.default)||qh.default);const I=!!(E.draggable||f&&typeof E.draggable>"u"),q=!!(E.selectable||g&&typeof E.selectable>"u"),ne=!!(E.connectable||y&&typeof E.connectable>"u"),G=!!(E.focusable||m&&typeof E.focusable>"u"),ee=We(),J=ug(E),C=cS({node:E,nodeType:O,hasDimensions:J,resizeObserver:x}),Y=$g({nodeRef:C,disabled:E.hidden||!I,noDragClassName:v,handleSelector:E.dragHandle,nodeId:t,isSelectable:q,nodeClickDistance:k}),V=Og();if(E.hidden)return null;const U=an(E),z=tS(E),D=q||I||r||o||l||a,W=o?K=>o(K,{...b.userNode}):void 0,M=l?K=>l(K,{...b.userNode}):void 0,R=a?K=>a(K,{...b.userNode}):void 0,re=u?K=>u(K,{...b.userNode}):void 0,ie=d?K=>d(K,{...b.userNode}):void 0,ce=K=>{const{selectNodesOnDrag:le,nodeDragThreshold:pe}=ee.getState();q&&(!le||!I||pe>0)&&Ju({id:t,store:ee,nodeRef:C}),r&&r(K,{...b.userNode})},fe=K=>{if(!(fg(K.nativeEvent)||S)){if(Jp.includes(K.key)&&q){const le=K.key==="Escape";Ju({id:t,store:ee,unselect:le,nodeRef:C})}else if(I&&E.selected&&Object.prototype.hasOwnProperty.call(xl,K.key)){K.preventDefault();const{ariaLabelConfig:le}=ee.getState();ee.setState({ariaLiveMessage:le["node.a11yDescription.ariaLiveMessage"]({direction:K.key.replace("Arrow","").toLowerCase(),x:~~b.positionAbsolute.x,y:~~b.positionAbsolute.y})}),V({direction:xl[K.key],factor:K.shiftKey?4:1})}}},de=()=>{var je;if(S||!((je=C.current)!=null&&je.matches(":focus-visible")))return;const{transform:K,width:le,height:pe,autoPanOnNodeFocus:_e,setCenter:xe}=ee.getState();if(!_e)return;ac(new Map([[t,E]]),{x:0,y:0,width:le,height:pe},K,!0).length>0||xe(E.position.x+U.width/2,E.position.y+U.height/2,{zoom:K[2]})};return p.jsx("div",{className:it(["react-flow__node",`react-flow__node-${O}`,{[_]:I},E.className,{selected:E.selected,selectable:q,parent:$,draggable:I,dragging:Y}]),ref:C,style:{zIndex:b.z,transform:`translate(${b.positionAbsolute.x}px,${b.positionAbsolute.y}px)`,pointerEvents:D?"all":"none",visibility:J?"visible":"hidden",...E.style,...z},"data-id":t,"data-testid":`rf__node-${t}`,onMouseEnter:W,onMouseMove:M,onMouseLeave:R,onContextMenu:re,onClick:ce,onDoubleClick:ie,onKeyDown:G?fe:void 0,tabIndex:G?0:void 0,onFocus:G?de:void 0,role:E.ariaRole??(G?"group":void 0),"aria-roledescription":"node","aria-describedby":S?void 0:`${Ig}-${j}`,"aria-label":E.ariaLabel,...E.domAttributes,children:p.jsx(W_,{value:t,children:p.jsx(H,{id:t,data:E.data,type:O,positionAbsoluteX:b.positionAbsolute.x,positionAbsoluteY:b.positionAbsolute.y,selected:E.selected??!1,selectable:q,draggable:I,deletable:E.deletable??!0,isConnectable:ne,sourcePosition:E.sourcePosition,targetPosition:E.targetPosition,dragging:Y,dragHandle:E.dragHandle,zIndex:b.z,parentId:E.parentId,...U})})})}var fS=F.memo(dS);const hS=t=>({nodesConnectable:t.nodesConnectable,nodesFocusable:t.nodesFocusable,elementsSelectable:t.elementsSelectable,onError:t.onError});function Vg(t){const{nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,onError:a}=Ae(hS,qe),u=lS(t.onlyRenderVisibleElements),d=uS();return p.jsx("div",{className:"react-flow__nodes",style:Tl,children:u.map(f=>p.jsx(fS,{id:f,nodeTypes:t.nodeTypes,nodeExtent:t.nodeExtent,onClick:t.onNodeClick,onMouseEnter:t.onNodeMouseEnter,onMouseMove:t.onNodeMouseMove,onMouseLeave:t.onNodeMouseLeave,onContextMenu:t.onNodeContextMenu,onDoubleClick:t.onNodeDoubleClick,noDragClassName:t.noDragClassName,noPanClassName:t.noPanClassName,rfId:t.rfId,disableKeyboardA11y:t.disableKeyboardA11y,resizeObserver:d,nodesDraggable:t.nodesDraggable??!0,nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,nodeClickDistance:t.nodeClickDistance,onError:a},f))})}Vg.displayName="NodeRenderer";const pS=F.memo(Vg);function gS(t){return Ae(F.useCallback(o=>{if(!t)return o.edges.map(a=>a.id);const l=[];if(o.width&&o.height)for(const a of o.edges){const u=o.nodeLookup.get(a.source),d=o.nodeLookup.get(a.target);u&&d&&a1({sourceNode:u,targetNode:d,width:o.width,height:o.height,transform:o.transform})&&l.push(a.id)}return l},[t]),qe)}const mS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t}};return p.jsx("polyline",{className:"arrow",style:o,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},yS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t,fill:t}};return p.jsx("polyline",{className:"arrowclosed",style:o,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},Kh={[To.Arrow]:mS,[To.ArrowClosed]:yS};function vS(t){const r=We();return F.useMemo(()=>{var a,u;return Object.prototype.hasOwnProperty.call(Kh,t)?Kh[t]:((u=(a=r.getState()).onError)==null||u.call(a,"009",sn.error009(t)),null)},[t])}const xS=({id:t,type:r,color:o,width:l=12.5,height:a=12.5,markerUnits:u="strokeWidth",strokeWidth:d,orient:f="auto-start-reverse"})=>{const g=vS(r);return g?p.jsx("marker",{className:"react-flow__arrowhead",id:t,markerWidth:`${l}`,markerHeight:`${a}`,viewBox:"-10 -10 20 20",markerUnits:u,orient:f,refX:"0",refY:"0",children:p.jsx(g,{color:o,strokeWidth:d})}):null},Wg=({defaultColor:t,rfId:r})=>{const o=Ae(u=>u.edges),l=Ae(u=>u.defaultEdgeOptions),a=F.useMemo(()=>m1(o,{id:r,defaultColor:t,defaultMarkerStart:l==null?void 0:l.markerStart,defaultMarkerEnd:l==null?void 0:l.markerEnd}),[o,l,r,t]);return a.length?p.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:p.jsx("defs",{children:a.map(u=>p.jsx(xS,{id:u.id,type:u.type,color:u.color,width:u.width,height:u.height,markerUnits:u.markerUnits,strokeWidth:u.strokeWidth,orient:u.orient},u.id))})}):null};Wg.displayName="MarkerDefinitions";var wS=F.memo(Wg);function Ug({x:t,y:r,label:o,labelStyle:l,labelShowBg:a=!0,labelBgStyle:u,labelBgPadding:d=[2,4],labelBgBorderRadius:f=2,children:g,className:y,...m}){const[x,v]=F.useState({x:1,y:0,width:0,height:0}),_=it(["react-flow__edge-textwrapper",y]),S=F.useRef(null);return F.useEffect(()=>{if(S.current){const j=S.current.getBBox();v({x:j.x,y:j.y,width:j.width,height:j.height})}},[o]),o?p.jsxs("g",{transform:`translate(${t-x.width/2} ${r-x.height/2})`,className:_,visibility:x.width?"visible":"hidden",...m,children:[a&&p.jsx("rect",{width:x.width+2*d[0],x:-d[0],y:-d[1],height:x.height+2*d[1],className:"react-flow__edge-textbg",style:u,rx:f,ry:f}),p.jsx("text",{className:"react-flow__edge-text",y:x.height/2,dy:"0.3em",ref:S,style:l,children:o}),g]}):null}Ug.displayName="EdgeText";const _S=F.memo(Ug);function Rl({path:t,labelX:r,labelY:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g,interactionWidth:y=20,...m}){return p.jsxs(p.Fragment,{children:[p.jsx("path",{...m,d:t,fill:"none",className:it(["react-flow__edge-path",m.className])}),y?p.jsx("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:y,className:"react-flow__edge-interaction"}):null,l&&rn(r)&&rn(o)?p.jsx(_S,{x:r,y:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g}):null]})}function Zh({pos:t,x1:r,y1:o,x2:l,y2:a}){return t===Se.Left||t===Se.Right?[.5*(r+l),o]:[r,.5*(o+a)]}function Yg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top}){const[d,f]=Zh({pos:o,x1:t,y1:r,x2:l,y2:a}),[g,y]=Zh({pos:u,x1:l,y1:a,x2:t,y2:r}),[m,x,v,_]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:d,sourceControlY:f,targetControlX:g,targetControlY:y});return[`M${t},${r} C${d},${f} ${g},${y} ${l},${a}`,m,x,v,_]}function Gg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d,targetPosition:f,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})=>{const[T,E,b]=Yg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f}),$=t.isInternal?void 0:r;return p.jsx(Rl,{id:$,path:T,labelX:E,labelY:b,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})})}const SS=Gg({isInternal:!1}),Xg=Gg({isInternal:!0});SS.displayName="SimpleBezierEdge";Xg.displayName="SimpleBezierEdgeInternal";function qg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,sourcePosition:_=Se.Bottom,targetPosition:S=Se.Top,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=qu({sourceX:o,sourceY:l,sourcePosition:_,targetX:a,targetY:u,targetPosition:S,borderRadius:k==null?void 0:k.borderRadius,offset:k==null?void 0:k.offset,stepPosition:k==null?void 0:k.stepPosition}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:j,markerStart:N,interactionWidth:T})})}const Qg=qg({isInternal:!1}),Kg=qg({isInternal:!0});Qg.displayName="SmoothStepEdge";Kg.displayName="SmoothStepEdgeInternal";function Zg(t){return F.memo(({id:r,...o})=>{var a;const l=t.isInternal?void 0:r;return p.jsx(Qg,{...o,id:l,pathOptions:F.useMemo(()=>{var u;return{borderRadius:0,offset:(u=o.pathOptions)==null?void 0:u.offset}},[(a=o.pathOptions)==null?void 0:a.offset])})})}const kS=Zg({isInternal:!1}),Jg=Zg({isInternal:!0});kS.displayName="StepEdge";Jg.displayName="StepEdgeInternal";function em(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})=>{const[N,k,T]=yg({sourceX:o,sourceY:l,targetX:a,targetY:u}),E=t.isInternal?void 0:r;return p.jsx(Rl,{id:E,path:N,labelX:k,labelY:T,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})})}const ES=em({isInternal:!1}),tm=em({isInternal:!0});ES.displayName="StraightEdge";tm.displayName="StraightEdgeInternal";function nm(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d=Se.Bottom,targetPosition:f=Se.Top,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=gg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f,curvature:k==null?void 0:k.curvature}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:T})})}const NS=nm({isInternal:!1}),rm=nm({isInternal:!0});NS.displayName="BezierEdge";rm.displayName="BezierEdgeInternal";const Jh={default:rm,straight:tm,step:Jg,smoothstep:Kg,simplebezier:Xg},ep={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null,zIndex:void 0},jS=(t,r,o)=>o===Se.Left?t-r:o===Se.Right?t+r:t,bS=(t,r,o)=>o===Se.Top?t-r:o===Se.Bottom?t+r:t,tp="react-flow__edgeupdater";function np({position:t,centerX:r,centerY:o,radius:l=10,onMouseDown:a,onMouseEnter:u,onMouseOut:d,type:f}){return p.jsx("circle",{onMouseDown:a,onMouseEnter:u,onMouseOut:d,className:it([tp,`${tp}-${f}`]),cx:jS(r,l,t),cy:bS(o,l,t),r:l,stroke:"transparent",fill:"transparent"})}function CS({isReconnectable:t,reconnectRadius:r,edge:o,sourceX:l,sourceY:a,targetX:u,targetY:d,sourcePosition:f,targetPosition:g,onReconnect:y,onReconnectStart:m,onReconnectEnd:x,setReconnecting:v,setUpdateHover:_}){const S=We(),j=(b,$)=>{if(b.button!==0)return;const{autoPanOnConnect:O,domNode:H,connectionMode:I,connectionRadius:q,lib:ne,onConnectStart:G,cancelConnection:ee,nodeLookup:J,rfId:C,panBy:Y,updateConnection:V}=S.getState(),U=$.type==="target",z=(M,R)=>{v(!1),x==null||x(M,o,$.type,R)},D=M=>y==null?void 0:y(o,M),W=(M,R)=>{v(!0),m==null||m(b,o,$.type),G==null||G(M,R)};Zu.onPointerDown(b.nativeEvent,{autoPanOnConnect:O,connectionMode:I,connectionRadius:q,domNode:H,handleId:$.id,nodeId:$.nodeId,nodeLookup:J,isTarget:U,edgeUpdaterType:$.type,lib:ne,flowId:C,cancelConnection:ee,panBy:Y,isValidConnection:(...M)=>{var R,re;return((re=(R=S.getState()).isValidConnection)==null?void 0:re.call(R,...M))??!0},onConnect:D,onConnectStart:W,onConnectEnd:(...M)=>{var R,re;return(re=(R=S.getState()).onConnectEnd)==null?void 0:re.call(R,...M)},onReconnectEnd:z,updateConnection:V,getTransform:()=>S.getState().transform,getFromHandle:()=>S.getState().connection.fromHandle,dragThreshold:S.getState().connectionDragThreshold,handleDomNode:b.currentTarget})},N=b=>j(b,{nodeId:o.target,id:o.targetHandle??null,type:"target"}),k=b=>j(b,{nodeId:o.source,id:o.sourceHandle??null,type:"source"}),T=()=>_(!0),E=()=>_(!1);return p.jsxs(p.Fragment,{children:[(t===!0||t==="source")&&p.jsx(np,{position:f,centerX:l,centerY:a,radius:r,onMouseDown:N,onMouseEnter:T,onMouseOut:E,type:"source"}),(t===!0||t==="target")&&p.jsx(np,{position:g,centerX:u,centerY:d,radius:r,onMouseDown:k,onMouseEnter:T,onMouseOut:E,type:"target"})]})}function MS({id:t,edgesFocusable:r,edgesReconnectable:o,elementsSelectable:l,onClick:a,onDoubleClick:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,rfId:S,edgeTypes:j,noPanClassName:N,onError:k,disableKeyboardA11y:T}){let E=Ae(xe=>xe.edgeLookup.get(t));const b=Ae(xe=>xe.defaultEdgeOptions);E=b?{...b,...E}:E;let $=E.type||"default",O=(j==null?void 0:j[$])||Jh[$];O===void 0&&(k==null||k("011",sn.error011($)),$="default",O=(j==null?void 0:j.default)||Jh.default);const H=!!(E.focusable||r&&typeof E.focusable>"u"),I=typeof x<"u"&&(E.reconnectable||o&&typeof E.reconnectable>"u"),q=!!(E.selectable||l&&typeof E.selectable>"u"),ne=F.useRef(null),[G,ee]=F.useState(!1),[J,C]=F.useState(!1),Y=We(),{zIndex:V=E.zIndex,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R}=Ae(F.useCallback(xe=>{const ge=xe.nodeLookup.get(E.source),je=xe.nodeLookup.get(E.target);if(!ge||!je)return ep;const Me=g1({id:t,sourceNode:ge,targetNode:je,sourceHandle:E.sourceHandle||null,targetHandle:E.targetHandle||null,connectionMode:xe.connectionMode,onError:k}),Pe=l1({selected:E.selected,zIndex:E.zIndex,sourceNode:ge,targetNode:je,elevateOnSelect:xe.elevateEdgesOnSelect,zIndexMode:xe.zIndexMode});return{...Me||ep,zIndex:Pe}},[E.source,E.target,E.sourceHandle,E.targetHandle,E.selected,E.zIndex,k]),qe),re=F.useMemo(()=>E.markerStart?`url('#${Qu(E.markerStart,S)}')`:void 0,[E.markerStart,S]),ie=F.useMemo(()=>E.markerEnd?`url('#${Qu(E.markerEnd,S)}')`:void 0,[E.markerEnd,S]);if(E.hidden||U===null||z===null||D===null||W===null)return null;const ce=xe=>{var Pe;const{addSelectedEdges:ge,unselectNodesAndEdges:je,multiSelectionActive:Me}=Y.getState();q&&(Y.setState({nodesSelectionActive:!1}),E.selected&&Me?(je({nodes:[],edges:[E]}),(Pe=ne.current)==null||Pe.blur()):ge([t])),a&&a(xe,E)},fe=u?xe=>{u(xe,{...E})}:void 0,de=d?xe=>{d(xe,{...E})}:void 0,K=f?xe=>{f(xe,{...E})}:void 0,le=g?xe=>{g(xe,{...E})}:void 0,pe=y?xe=>{y(xe,{...E})}:void 0,_e=xe=>{var ge;if(!T&&Jp.includes(xe.key)&&q){const{unselectNodesAndEdges:je,addSelectedEdges:Me}=Y.getState();xe.key==="Escape"?((ge=ne.current)==null||ge.blur(),je({edges:[E]})):Me([t])}};return p.jsx("svg",{style:{zIndex:V},children:p.jsxs("g",{className:it(["react-flow__edge",`react-flow__edge-${$}`,E.className,N,{selected:E.selected,animated:E.animated,inactive:!q&&!a,updating:G,selectable:q}]),onClick:ce,onDoubleClick:fe,onContextMenu:de,onMouseEnter:K,onMouseMove:le,onMouseLeave:pe,onKeyDown:H?_e:void 0,tabIndex:H?0:void 0,role:E.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":t,"data-testid":`rf__edge-${t}`,"aria-label":E.ariaLabel===null?void 0:E.ariaLabel||`Edge from ${E.source} to ${E.target}`,"aria-describedby":H?`${Tg}-${S}`:void 0,ref:ne,...E.domAttributes,children:[!J&&p.jsx(O,{id:t,source:E.source,target:E.target,type:E.type,selected:E.selected,animated:E.animated,selectable:q,deletable:E.deletable??!0,label:E.label,labelStyle:E.labelStyle,labelShowBg:E.labelShowBg,labelBgStyle:E.labelBgStyle,labelBgPadding:E.labelBgPadding,labelBgBorderRadius:E.labelBgBorderRadius,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,data:E.data,style:E.style,sourceHandleId:E.sourceHandle,targetHandleId:E.targetHandle,markerStart:re,markerEnd:ie,pathOptions:"pathOptions"in E?E.pathOptions:void 0,interactionWidth:E.interactionWidth}),I&&p.jsx(CS,{edge:E,isReconnectable:I,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,setUpdateHover:ee,setReconnecting:C})]})})}var PS=F.memo(MS);const IS=t=>({edgesFocusable:t.edgesFocusable,edgesReconnectable:t.edgesReconnectable,elementsSelectable:t.elementsSelectable,connectionMode:t.connectionMode,onError:t.onError});function im({defaultMarkerColor:t,onlyRenderVisibleElements:r,rfId:o,edgeTypes:l,noPanClassName:a,onReconnect:u,onEdgeContextMenu:d,onEdgeMouseEnter:f,onEdgeMouseMove:g,onEdgeMouseLeave:y,onEdgeClick:m,reconnectRadius:x,onEdgeDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,disableKeyboardA11y:j}){const{edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,onError:E}=Ae(IS,qe),b=gS(r);return p.jsxs("div",{className:"react-flow__edges",children:[p.jsx(wS,{defaultColor:t,rfId:o}),b.map($=>p.jsx(PS,{id:$,edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,noPanClassName:a,onReconnect:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,onClick:m,reconnectRadius:x,onDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,rfId:o,onError:E,edgeTypes:l,disableKeyboardA11y:j},$))]})}im.displayName="EdgeRenderer";const TS=F.memo(im),rp=t=>`translate(${t[0]}px,${t[1]}px) scale(${t[2]})`;function RS({children:t}){const r=We(),o=F.useRef(null),[l]=F.useState(()=>r.getState().transform);return zg(()=>{let a=null;const u=()=>{const d=r.getState().transform;a&&d[0]===a[0]&&d[1]===a[1]&&d[2]===a[2]||(a=d,o.current&&(o.current.style.transform=rp(d)))};return u(),r.subscribe(u)},[r]),p.jsx("div",{ref:o,className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:rp(l)},children:t})}function LS(t){const r=yc(),o=F.useRef(!1);F.useEffect(()=>{!o.current&&r.viewportInitialized&&t&&(setTimeout(()=>t(r),1),o.current=!0)},[t,r.viewportInitialized])}const AS=t=>{var r;return(r=t.panZoom)==null?void 0:r.syncViewport};function zS(t){const r=Ae(AS),o=We();return F.useEffect(()=>{t&&(r==null||r(t),o.setState({transform:[t.x,t.y,t.zoom]}))},[t,r]),null}function DS(t){return t.connection.inProgress?{...t.connection,to:Bo(t.connection.to,t.transform)}:{...t.connection}}function $S(t){return DS}function OS(t){const r=$S();return Ae(r,qe)}const FS=t=>({nodesConnectable:t.nodesConnectable,isValid:t.connection.isValid,inProgress:t.connection.inProgress,width:t.width,height:t.height});function HS({containerStyle:t,style:r,type:o,component:l}){const{nodesConnectable:a,width:u,height:d,isValid:f,inProgress:g}=Ae(FS,qe);return!(u&&a&&g)?null:p.jsx("svg",{style:t,width:u,height:d,className:"react-flow__connectionline react-flow__container",children:p.jsx("g",{className:it(["react-flow__connection",ng(f)]),children:p.jsx(om,{style:r,type:o,CustomComponent:l,isValid:f})})})}const om=({style:t,type:r=dr.Bezier,CustomComponent:o,isValid:l})=>{const{inProgress:a,from:u,fromNode:d,fromHandle:f,fromPosition:g,to:y,toNode:m,toHandle:x,toPosition:v,pointer:_}=OS();if(!a)return;if(o)return p.jsx(o,{connectionLineType:r,connectionLineStyle:t,fromNode:d,fromHandle:f,fromX:u.x,fromY:u.y,toX:y.x,toY:y.y,fromPosition:g,toPosition:v,connectionStatus:ng(l),toNode:m,toHandle:x,pointer:_});let S="";const j={sourceX:u.x,sourceY:u.y,sourcePosition:g,targetX:y.x,targetY:y.y,targetPosition:v};switch(r){case dr.Bezier:[S]=gg(j);break;case dr.SimpleBezier:[S]=Yg(j);break;case dr.Step:[S]=qu({...j,borderRadius:0});break;case dr.SmoothStep:[S]=qu(j);break;default:[S]=yg(j)}return p.jsx("path",{d:S,fill:"none",className:"react-flow__connection-path",style:t})};om.displayName="ConnectionLine";const BS={};function ip(t=BS){F.useRef(t),We(),F.useEffect(()=>{},[t])}function VS(){We(),F.useRef(!1),F.useEffect(()=>{},[])}function sm({nodeTypes:t,edgeTypes:r,onInit:o,onNodeClick:l,onEdgeClick:a,onNodeDoubleClick:u,onEdgeDoubleClick:d,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,onSelectionContextMenu:x,onSelectionStart:v,onSelectionEnd:_,connectionLineType:S,connectionLineStyle:j,connectionLineComponent:N,connectionLineContainerStyle:k,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,deleteKeyCode:I,onlyRenderVisibleElements:q,elementsSelectable:ne,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,preventScrolling:Y,defaultMarkerColor:V,zoomOnScroll:U,zoomOnPinch:z,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,zoomOnDoubleClick:R,panOnDrag:re,autoPanOnSelection:ie,onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneScroll:le,onPaneContextMenu:pe,paneClickDistance:_e,nodeClickDistance:xe,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Me,onEdgeMouseLeave:Pe,reconnectRadius:Re,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,viewport:ft,onViewportChange:Je,nodesDraggable:vn}){return ip(t),ip(r),VS(),LS(o),zS(ft),p.jsx(oS,{onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneContextMenu:pe,onPaneScroll:le,paneClickDistance:_e,deleteKeyCode:I,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,elementsSelectable:ne,zoomOnScroll:U,zoomOnPinch:z,zoomOnDoubleClick:R,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,panOnDrag:re,autoPanOnSelection:ie,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,onSelectionContextMenu:x,preventScrolling:Y,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,onViewportChange:Je,isControlledViewport:!!ft,children:p.jsxs(RS,{children:[p.jsx(TS,{edgeTypes:r,onEdgeClick:a,onEdgeDoubleClick:d,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,onlyRenderVisibleElements:q,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Me,onEdgeMouseLeave:Pe,reconnectRadius:Re,defaultMarkerColor:V,noPanClassName:It,disableKeyboardA11y:Ke,rfId:gt}),p.jsx(HS,{style:j,type:S,component:N,containerStyle:k}),p.jsx("div",{className:"react-flow__edgelabel-renderer"}),p.jsx(pS,{nodeTypes:t,onNodeClick:l,onNodeDoubleClick:u,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,nodeClickDistance:xe,onlyRenderVisibleElements:q,noPanClassName:It,noDragClassName:ot,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,nodesDraggable:vn}),p.jsx("div",{className:"react-flow__viewport-portal"})]})})}sm.displayName="GraphView";const WS=F.memo(sm),US=ag(),op=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g=.5,maxZoom:y=2,nodeOrigin:m,nodeExtent:x,zIndexMode:v="basic"}={})=>{const _=new Map,S=new Map,j=new Map,N=new Map,k=l??r??[],T=o??t??[],E=m??[0,0],b=x??Po;wg(j,N,k);const{nodesInitialized:$}=Ku(T,_,S,{nodeOrigin:E,nodeExtent:b,zIndexMode:v});let O=[0,0,1];if(d&&a&&u){const H=Fo(_,{filter:G=>!!((G.width||G.initialWidth)&&(G.height||G.initialHeight))}),{x:I,y:q,zoom:ne}=cc(H,a,u,g,y,(f==null?void 0:f.padding)??.1);O=[I,q,ne]}return{rfId:"1",width:a??0,height:u??0,transform:O,nodes:T,nodesInitialized:$,nodeLookup:_,parentLookup:S,edges:k,edgeLookup:N,connectionLookup:j,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:o!==void 0,hasDefaultEdges:l!==void 0,panZoom:null,minZoom:g,maxZoom:y,translateExtent:Po,nodeExtent:b,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Ii.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:E,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:d??!1,fitViewOptions:f,fitViewResolver:null,connection:{...tg},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:US,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:eg,zIndexMode:v,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},YS=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v})=>i_((_,S)=>{async function j(){const{nodeLookup:N,panZoom:k,fitViewOptions:T,fitViewResolver:E,width:b,height:$,minZoom:O,maxZoom:H}=S();k&&(await e1({nodes:N,width:b,height:$,panZoom:k,minZoom:O,maxZoom:H},T),E==null||E.resolve(!0),_({fitViewResolver:null}))}return{...op({nodes:t,edges:r,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,defaultNodes:o,defaultEdges:l,zIndexMode:v}),setNodes:N=>{const{nodeLookup:k,parentLookup:T,nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,fitViewQueued:O,zIndexMode:H,nodesSelectionActive:I}=S(),{nodesInitialized:q,hasSelectedNodes:ne}=Ku(N,k,T,{nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,checkEquality:!0,zIndexMode:H}),G=I&≠O&&q?(j(),_({nodes:N,nodesInitialized:q,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:G})):_({nodes:N,nodesInitialized:q,nodesSelectionActive:G})},setEdges:N=>{const{connectionLookup:k,edgeLookup:T}=S();wg(k,T,N),_({edges:N})},setDefaultNodesAndEdges:(N,k)=>{if(N){const{setNodes:T}=S();T(N),_({hasDefaultNodes:!0})}if(k){const{setEdges:T}=S();T(k),_({hasDefaultEdges:!0})}},updateNodeInternals:N=>{const{triggerNodeChanges:k,nodeLookup:T,parentLookup:E,domNode:b,nodeOrigin:$,nodeExtent:O,debug:H,fitViewQueued:I,zIndexMode:q}=S(),{changes:ne,updatedInternals:G}=k1(N,T,E,b,$,O,q);G&&(x1(T,E,{nodeOrigin:$,nodeExtent:O,zIndexMode:q}),I?(j(),_({fitViewQueued:!1,fitViewOptions:void 0})):_({}),(ne==null?void 0:ne.length)>0&&(H&&console.log("React Flow: trigger node changes",ne),k==null||k(ne)))},updateNodePositions:(N,k=!1)=>{const T=[];let E=[];const{nodeLookup:b,triggerNodeChanges:$,connection:O,updateConnection:H,onNodesChangeMiddlewareMap:I}=S();for(const[q,ne]of N){const G=b.get(q),ee=!!(G!=null&&G.expandParent&&(G!=null&&G.parentId)&&(ne!=null&&ne.position)),J={id:q,type:"position",position:ee?{x:Math.max(0,ne.position.x),y:Math.max(0,ne.position.y)}:ne.position,dragging:k};if(G&&O.inProgress&&O.fromNode.id===G.id){const C=Vr(G,O.fromHandle,Se.Left,!0);H({...O,from:C})}ee&&G.parentId&&T.push({id:q,parentId:G.parentId,rect:{...ne.internals.positionAbsolute,width:ne.measured.width??0,height:ne.measured.height??0}}),E.push(J)}if(T.length>0){const{parentLookup:q,nodeOrigin:ne}=S(),G=mc(T,b,q,ne);E.push(...G)}for(const q of I.values())E=q(E);$(E)},triggerNodeChanges:N=>{const{onNodesChange:k,setNodes:T,nodes:E,hasDefaultNodes:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=N_(N,E);T(O)}$&&console.log("React Flow: trigger node changes",N),k==null||k(N)}},triggerEdgeChanges:N=>{const{onEdgesChange:k,setEdges:T,edges:E,hasDefaultEdges:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=j_(N,E);T(O)}$&&console.log("React Flow: trigger edge changes",N),k==null||k(N)}},addSelectedNodes:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));b(O);return}b(ji(E,new Set([...N]),!0)),$(ji(T))},addSelectedEdges:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));$(O);return}$(ji(T,new Set([...N]))),b(ji(E,new Set,!0))},unselectNodesAndEdges:({nodes:N,edges:k}={})=>{const{edges:T,nodes:E,nodeLookup:b,triggerNodeChanges:$,triggerEdgeChanges:O}=S(),H=N||E,I=k||T,q=[];for(const G of H){if(!G.selected)continue;const ee=b.get(G.id);ee&&(ee.selected=!1),q.push(Ar(G.id,!1))}const ne=[];for(const G of I)G.selected&&ne.push(Ar(G.id,!1));$(q),O(ne)},setMinZoom:N=>{const{panZoom:k,maxZoom:T}=S();k==null||k.setScaleExtent([N,T]),_({minZoom:N})},setMaxZoom:N=>{const{panZoom:k,minZoom:T}=S();k==null||k.setScaleExtent([T,N]),_({maxZoom:N})},setTranslateExtent:N=>{var k;(k=S().panZoom)==null||k.setTranslateExtent(N),_({translateExtent:N})},resetSelectedElements:()=>{const{edges:N,nodes:k,triggerNodeChanges:T,triggerEdgeChanges:E,elementsSelectable:b}=S();if(!b)return;const $=k.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]),O=N.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]);T($),E(O)},setNodeExtent:N=>{const{nodes:k,nodeLookup:T,parentLookup:E,nodeOrigin:b,elevateNodesOnSelect:$,nodeExtent:O,zIndexMode:H}=S();N[0][0]===O[0][0]&&N[0][1]===O[0][1]&&N[1][0]===O[1][0]&&N[1][1]===O[1][1]||(Ku(k,T,E,{nodeOrigin:b,nodeExtent:N,elevateNodesOnSelect:$,checkEquality:!1,zIndexMode:H}),_({nodeExtent:N}))},panBy:N=>{const{transform:k,width:T,height:E,panZoom:b,translateExtent:$}=S();return E1({delta:N,panZoom:b,transform:k,translateExtent:$,width:T,height:E})},setCenter:async(N,k,T)=>{const{width:E,height:b,maxZoom:$,panZoom:O}=S();if(!O)return!1;const H=typeof(T==null?void 0:T.zoom)<"u"?T.zoom:$;return await O.setViewport({x:E/2-N*H,y:b/2-k*H,zoom:H},{duration:T==null?void 0:T.duration,ease:T==null?void 0:T.ease,interpolate:T==null?void 0:T.interpolate}),!0},cancelConnection:()=>{_({connection:{...tg}})},updateConnection:N=>{_({connection:N})},reset:()=>_({...op()})}},Object.is);function lm({initialNodes:t,initialEdges:r,defaultNodes:o,defaultEdges:l,initialWidth:a,initialHeight:u,initialMinZoom:d,initialMaxZoom:f,initialFitViewOptions:g,fitView:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v,children:_}){const[S]=F.useState(()=>YS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:y,minZoom:d,maxZoom:f,fitViewOptions:g,nodeOrigin:m,nodeExtent:x,zIndexMode:v}));return p.jsx(o_,{value:S,children:p.jsx(I_,{children:p.jsx(Y_,{children:_})})})}function GS({children:t,nodes:r,edges:o,defaultNodes:l,defaultEdges:a,width:u,height:d,fitView:f,fitViewOptions:g,minZoom:y,maxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_}){return F.useContext(Pl)?p.jsx(p.Fragment,{children:t}):p.jsx(lm,{initialNodes:r,initialEdges:o,defaultNodes:l,defaultEdges:a,initialWidth:u,initialHeight:d,fitView:f,initialFitViewOptions:g,initialMinZoom:y,initialMaxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_,children:t})}const XS={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function qS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,className:a,nodeTypes:u,edgeTypes:d,onNodeClick:f,onEdgeClick:g,onInit:y,onMove:m,onMoveStart:x,onMoveEnd:v,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onSelectionChange:J,onSelectionDragStart:C,onSelectionDrag:Y,onSelectionDragStop:V,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onBeforeDelete:W,connectionMode:M,connectionLineType:R=dr.Bezier,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,deleteKeyCode:fe="Backspace",selectionKeyCode:de="Shift",selectionOnDrag:K=!1,selectionMode:le=Io.Full,panActivationKeyCode:pe="Space",multiSelectionKeyCode:_e=Lo()?"Meta":"Control",zoomActivationKeyCode:xe=Lo()?"Meta":"Control",snapToGrid:ge,snapGrid:je,onlyRenderVisibleElements:Me=!1,selectNodesOnDrag:Pe,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,nodeOrigin:ot=Rg,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke=!0,defaultViewport:ze=v_,minZoom:gt=.5,maxZoom:ft=2,translateExtent:Je=Po,preventScrolling:vn=!0,nodeExtent:wt,defaultMarkerColor:Gt="#b1b1b7",zoomOnScroll:zi=!0,zoomOnPinch:kt=!0,panOnScroll:hr=!1,panOnScrollSpeed:An=.5,panOnScrollMode:zn=$r.Free,zoomOnDoubleClick:pr=!0,panOnDrag:gr=!0,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr=1,nodeClickDistance:$n=0,children:Gr,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn=10,onNodesChange:Fn,onEdgesChange:Xr,noDragClassName:qr="nodrag",noWheelClassName:Qr="nowheel",noPanClassName:Tt="nopan",fitView:Hn,fitViewOptions:L,connectOnClick:te,attributionPosition:ke,proOptions:Te,defaultEdgeOptions:Ce,elevateNodesOnSelect:Bn=!0,elevateEdgesOnSelect:Al=!1,disableKeyboardA11y:Vo=!1,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanOnSelection:$i=!0,autoPanSpeed:Wo,connectionRadius:Kr,isValidConnection:Dl,onError:Uo,style:Zr,id:Rt,nodeDragThreshold:$l,connectionDragThreshold:Lt,viewport:Ol,onViewportChange:Fl,width:Hl,height:Jr,colorMode:ei="light",debug:wr,onScroll:kn,ariaLabelConfig:Bl,zIndexMode:Yo="basic",...Oi},Go){const _r=Rt||"1",Sr=S_(ei),Vl=F.useCallback(ti=>{ti.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),kn==null||kn(ti)},[kn]);return p.jsx("div",{"data-testid":"rf__wrapper",...Oi,onScroll:Vl,style:{...Zr,...XS},ref:Go,className:it(["react-flow",a,Sr]),id:Rt,role:"application",children:p.jsxs(GS,{nodes:t,edges:r,width:Hl,height:Jr,fitView:Hn,fitViewOptions:L,minZoom:gt,maxZoom:ft,nodeOrigin:ot,nodeExtent:wt,zIndexMode:Yo,children:[p.jsx(__,{nodes:t,edges:r,defaultNodes:o,defaultEdges:l,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke,elevateNodesOnSelect:Bn,elevateEdgesOnSelect:Al,minZoom:gt,maxZoom:ft,nodeExtent:wt,onNodesChange:Fn,onEdgesChange:Xr,snapToGrid:ge,snapGrid:je,connectionMode:M,translateExtent:Je,connectOnClick:te,defaultEdgeOptions:Ce,fitView:Hn,fitViewOptions:L,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onSelectionDrag:Y,onSelectionDragStart:C,onSelectionDragStop:V,onMove:m,onMoveStart:x,onMoveEnd:v,noPanClassName:Tt,nodeOrigin:ot,rfId:_r,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanSpeed:Wo,onError:Uo,connectionRadius:Kr,isValidConnection:Dl,selectNodesOnDrag:Pe,nodeDragThreshold:$l,connectionDragThreshold:Lt,onBeforeDelete:W,debug:wr,ariaLabelConfig:Bl,zIndexMode:Yo}),p.jsx(WS,{onInit:y,onNodeClick:f,onEdgeClick:g,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,nodeTypes:u,edgeTypes:d,connectionLineType:R,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,selectionKeyCode:de,selectionOnDrag:K,selectionMode:le,deleteKeyCode:fe,multiSelectionKeyCode:_e,panActivationKeyCode:pe,zoomActivationKeyCode:xe,onlyRenderVisibleElements:Me,defaultViewport:ze,translateExtent:Je,minZoom:gt,maxZoom:ft,preventScrolling:vn,zoomOnScroll:zi,zoomOnPinch:kt,zoomOnDoubleClick:pr,panOnScroll:hr,panOnScrollSpeed:An,panOnScrollMode:zn,panOnDrag:gr,autoPanOnSelection:$i,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr,nodeClickDistance:$n,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn,defaultMarkerColor:Gt,noDragClassName:qr,noWheelClassName:Qr,noPanClassName:Tt,rfId:_r,disableKeyboardA11y:Vo,nodeExtent:wt,viewport:Ol,onViewportChange:Fl,nodesDraggable:Re}),p.jsx(y_,{onSelectionChange:J}),Gr,p.jsx(f_,{proOptions:Te,position:ke}),p.jsx(d_,{rfId:_r,disableKeyboardA11y:Vo})]})})}var QS=Ag(qS);function KS({dimensions:t,lineWidth:r,variant:o,className:l}){return p.jsx("path",{strokeWidth:r,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`,className:it(["react-flow__background-pattern",o,l])})}function ZS({radius:t,className:r}){return p.jsx("circle",{cx:t,cy:t,r:t,className:it(["react-flow__background-pattern","dots",r])})}var fr;(function(t){t.Lines="lines",t.Dots="dots",t.Cross="cross"})(fr||(fr={}));const JS={[fr.Dots]:1,[fr.Lines]:1,[fr.Cross]:6},ek=t=>({transform:t.transform,patternId:`pattern-${t.rfId}`});function am({id:t,variant:r=fr.Dots,gap:o=20,size:l,lineWidth:a=1,offset:u=0,color:d,bgColor:f,style:g,className:y,patternClassName:m}){const x=F.useRef(null),{transform:v,patternId:_}=Ae(ek,qe),S=l||JS[r],j=r===fr.Dots,N=r===fr.Cross,k=Array.isArray(o)?o:[o,o],T=[k[0]*v[2]||1,k[1]*v[2]||1],E=S*v[2],b=Array.isArray(u)?u:[u,u],$=N?[E,E]:T,O=[b[0]*v[2]+$[0]/2,b[1]*v[2]+$[1]/2],H=`${_}${t||""}`;return p.jsxs("svg",{className:it(["react-flow__background",y]),style:{...g,...Tl,"--xy-background-color-props":f,"--xy-background-pattern-color-props":d},ref:x,"data-testid":"rf__background",children:[p.jsx("pattern",{id:H,x:v[0]%T[0],y:v[1]%T[1],width:T[0],height:T[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${O[0]},-${O[1]})`,children:j?p.jsx(ZS,{radius:E/2,className:m}):p.jsx(KS,{dimensions:$,lineWidth:a,variant:r,className:m})}),p.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}am.displayName="Background";const tk=F.memo(am);function nk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:p.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function rk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:p.jsx("path",{d:"M0 0h32v4.2H0z"})})}function ik(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:p.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function ok(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function sk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function rl({children:t,className:r,...o}){return p.jsx("button",{type:"button",className:it(["react-flow__controls-button",r]),...o,children:t})}const lk=t=>({isInteractive:t.nodesDraggable||t.nodesConnectable||t.elementsSelectable,minZoomReached:t.transform[2]<=t.minZoom,maxZoomReached:t.transform[2]>=t.maxZoom,ariaLabelConfig:t.ariaLabelConfig});function um({style:t,showZoom:r=!0,showFitView:o=!0,showInteractive:l=!0,fitViewOptions:a,onZoomIn:u,onZoomOut:d,onFitView:f,onInteractiveChange:g,className:y,children:m,position:x="bottom-left",orientation:v="vertical","aria-label":_}){const S=We(),{isInteractive:j,minZoomReached:N,maxZoomReached:k,ariaLabelConfig:T}=Ae(lk,qe),{zoomIn:E,zoomOut:b,fitView:$}=yc(),O=()=>{E(),u==null||u()},H=()=>{b(),d==null||d()},I=()=>{$(a),f==null||f()},q=()=>{S.setState({nodesDraggable:!j,nodesConnectable:!j,elementsSelectable:!j}),g==null||g(!j)},ne=v==="horizontal"?"horizontal":"vertical";return p.jsxs(Il,{className:it(["react-flow__controls",ne,y]),position:x,style:t,"data-testid":"rf__controls","aria-label":_??T["controls.ariaLabel"],children:[r&&p.jsxs(p.Fragment,{children:[p.jsx(rl,{onClick:O,className:"react-flow__controls-zoomin",title:T["controls.zoomIn.ariaLabel"],"aria-label":T["controls.zoomIn.ariaLabel"],disabled:k,children:p.jsx(nk,{})}),p.jsx(rl,{onClick:H,className:"react-flow__controls-zoomout",title:T["controls.zoomOut.ariaLabel"],"aria-label":T["controls.zoomOut.ariaLabel"],disabled:N,children:p.jsx(rk,{})})]}),o&&p.jsx(rl,{className:"react-flow__controls-fitview",onClick:I,title:T["controls.fitView.ariaLabel"],"aria-label":T["controls.fitView.ariaLabel"],children:p.jsx(ik,{})}),l&&p.jsx(rl,{className:"react-flow__controls-interactive",onClick:q,title:T["controls.interactive.ariaLabel"],"aria-label":T["controls.interactive.ariaLabel"],children:j?p.jsx(sk,{}):p.jsx(ok,{})}),m]})}um.displayName="Controls";const ak=F.memo(um);function uk({id:t,x:r,y:o,width:l,height:a,style:u,color:d,strokeColor:f,strokeWidth:g,className:y,borderRadius:m,shapeRendering:x,selected:v,onClick:_}){const{background:S,backgroundColor:j}=u||{},N=d||S||j;return p.jsx("rect",{className:it(["react-flow__minimap-node",{selected:v},y]),x:r,y:o,rx:m,ry:m,width:l,height:a,style:{fill:N,stroke:f,strokeWidth:g},shapeRendering:x,onClick:_?k=>_(k,t):void 0})}const ck=F.memo(uk),dk=t=>t.nodes.map(r=>r.id),Du=t=>t instanceof Function?t:()=>t;function fk({nodeStrokeColor:t,nodeColor:r,nodeClassName:o="",nodeBorderRadius:l=5,nodeStrokeWidth:a,nodeComponent:u=ck,onClick:d}){const f=Ae(dk,qe),g=Du(r),y=Du(t),m=Du(o),x=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return p.jsx(p.Fragment,{children:f.map(v=>p.jsx(pk,{id:v,nodeColorFunc:g,nodeStrokeColorFunc:y,nodeClassNameFunc:m,nodeBorderRadius:l,nodeStrokeWidth:a,NodeComponent:u,onClick:d,shapeRendering:x},v))})}function hk({id:t,nodeColorFunc:r,nodeStrokeColorFunc:o,nodeClassNameFunc:l,nodeBorderRadius:a,nodeStrokeWidth:u,shapeRendering:d,NodeComponent:f,onClick:g}){const{node:y,x:m,y:x,width:v,height:_}=Ae(S=>{const j=S.nodeLookup.get(t);if(!j)return{node:void 0,x:0,y:0,width:0,height:0};const N=j.internals.userNode,{x:k,y:T}=j.internals.positionAbsolute,{width:E,height:b}=an(N);return{node:N,x:k,y:T,width:E,height:b}},qe);return!y||y.hidden||!ug(y)?null:p.jsx(f,{x:m,y:x,width:v,height:_,style:y.style,selected:!!y.selected,className:l(y),color:r(y),borderRadius:a,strokeColor:o(y),strokeWidth:u,shapeRendering:d,onClick:g,id:y.id})}const pk=F.memo(hk);var gk=F.memo(fk);const mk=200,yk=150,vk=t=>!t.hidden,xk=t=>{const r={x:-t.transform[0]/t.transform[2],y:-t.transform[1]/t.transform[2],width:t.width/t.transform[2],height:t.height/t.transform[2]};return{viewBB:r,boundingRect:t.nodeLookup.size>0?sg(Fo(t.nodeLookup,{filter:vk}),r):r,rfId:t.rfId,panZoom:t.panZoom,translateExtent:t.translateExtent,flowWidth:t.width,flowHeight:t.height,ariaLabelConfig:t.ariaLabelConfig}},sp=(t,r)=>t.x===r.x&&t.y===r.y&&t.width===r.width&&t.height===r.height,wk=(t,r)=>sp(t.viewBB,r.viewBB)&&sp(t.boundingRect,r.boundingRect)&&t.rfId===r.rfId&&t.panZoom===r.panZoom&&t.translateExtent===r.translateExtent&&t.flowWidth===r.flowWidth&&t.flowHeight===r.flowHeight&&t.ariaLabelConfig===r.ariaLabelConfig,_k="react-flow__minimap-desc";function cm({style:t,className:r,nodeStrokeColor:o,nodeColor:l,nodeClassName:a="",nodeBorderRadius:u=5,nodeStrokeWidth:d,nodeComponent:f,bgColor:g,maskColor:y,maskStrokeColor:m,maskStrokeWidth:x,position:v="bottom-right",onClick:_,onNodeClick:S,pannable:j=!1,zoomable:N=!1,ariaLabel:k,inversePan:T,zoomStep:E=1,offsetScale:b=5}){const $=We(),O=F.useRef(null),{boundingRect:H,viewBB:I,rfId:q,panZoom:ne,translateExtent:G,flowWidth:ee,flowHeight:J,ariaLabelConfig:C}=Ae(xk,wk),Y=(t==null?void 0:t.width)??mk,V=(t==null?void 0:t.height)??yk,U=H.width/Y,z=H.height/V,D=Math.max(U,z),W=D*Y,M=D*V,R=b*D,re=H.x-(W-H.width)/2-R,ie=H.y-(M-H.height)/2-R,ce=W+R*2,fe=M+R*2,de=`${_k}-${q}`,K=F.useRef(0),le=F.useRef();K.current=D,F.useEffect(()=>{if(O.current&&ne)return le.current=R1({domNode:O.current,panZoom:ne,getTransform:()=>$.getState().transform,getViewScale:()=>K.current}),()=>{var ge;(ge=le.current)==null||ge.destroy()}},[ne]),F.useEffect(()=>{var ge;(ge=le.current)==null||ge.update({translateExtent:G,width:ee,height:J,inversePan:T,pannable:j,zoomStep:E,zoomable:N})},[j,N,T,E,G,ee,J]);const pe=_?ge=>{var Pe;const[je,Me]=((Pe=le.current)==null?void 0:Pe.pointer(ge))||[0,0];_(ge,{x:je,y:Me})}:void 0,_e=S?F.useCallback((ge,je)=>{const Me=$.getState().nodeLookup.get(je).internals.userNode;S(ge,Me)},[]):void 0,xe=k??C["minimap.ariaLabel"];return p.jsx(Il,{position:v,style:{...t,"--xy-minimap-background-color-props":typeof g=="string"?g:void 0,"--xy-minimap-mask-background-color-props":typeof y=="string"?y:void 0,"--xy-minimap-mask-stroke-color-props":typeof m=="string"?m:void 0,"--xy-minimap-mask-stroke-width-props":typeof x=="number"?x*D:void 0,"--xy-minimap-node-background-color-props":typeof l=="string"?l:void 0,"--xy-minimap-node-stroke-color-props":typeof o=="string"?o:void 0,"--xy-minimap-node-stroke-width-props":typeof d=="number"?d:void 0},className:it(["react-flow__minimap",r]),"data-testid":"rf__minimap",children:p.jsxs("svg",{width:Y,height:V,viewBox:`${re} ${ie} ${ce} ${fe}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":de,ref:O,onClick:pe,children:[xe&&p.jsx("title",{id:de,children:xe}),p.jsx(gk,{onClick:_e,nodeColor:l,nodeStrokeColor:o,nodeBorderRadius:u,nodeClassName:a,nodeStrokeWidth:d,nodeComponent:f}),p.jsx("path",{className:"react-flow__minimap-mask",d:`M${re-R},${ie-R}h${ce+R*2}v${fe+R*2}h${-ce-R*2}z - M${I.x},${I.y}h${I.width}v${I.height}h${-I.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}cm.displayName="MiniMap";const Sk=F.memo(cm),kk=t=>r=>t?`${Math.max(1/r.transform[2],1)}`:void 0,Ek={[Li.Line]:"right",[Li.Handle]:"bottom-right"};function Nk({nodeId:t,position:r,variant:o=Li.Handle,className:l,style:a=void 0,children:u,color:d,minWidth:f=10,minHeight:g=10,maxWidth:y=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:x=!1,resizeDirection:v,autoScale:_=!0,shouldResize:S,onResizeStart:j,onResize:N,onResizeEnd:k}){const T=Fg(),E=typeof t=="string"?t:T,b=We(),$=F.useRef(null),O=o===Li.Handle,H=Ae(F.useCallback(kk(O&&_),[O,_]),qe),I=F.useRef(null),q=r??Ek[o];F.useEffect(()=>{if(!(!$.current||!E))return I.current||(I.current=Y1({domNode:$.current,nodeId:E,getStoreItems:()=>{const{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,domNode:V}=b.getState();return{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,paneDomNode:V}},onChange:(G,ee)=>{const{triggerNodeChanges:J,nodeLookup:C,parentLookup:Y,nodeOrigin:V}=b.getState(),U=[],z={x:G.x,y:G.y},D=C.get(E);if(D&&D.expandParent&&D.parentId){const W=D.origin??V,M=G.width??D.measured.width??0,R=G.height??D.measured.height??0,re={id:D.id,parentId:D.parentId,rect:{width:M,height:R,...cg({x:G.x??D.position.x,y:G.y??D.position.y},{width:M,height:R},D.parentId,C,W)}},ie=mc([re],C,Y,V);U.push(...ie),z.x=G.x?Math.max(W[0]*M,G.x):void 0,z.y=G.y?Math.max(W[1]*R,G.y):void 0}if(z.x!==void 0&&z.y!==void 0){const W={id:E,type:"position",position:{...z}};U.push(W)}if(G.width!==void 0&&G.height!==void 0){const M={id:E,type:"dimensions",resizing:!0,setAttributes:v?v==="horizontal"?"width":"height":!0,dimensions:{width:G.width,height:G.height}};U.push(M)}for(const W of ee){const M={...W,type:"position"};U.push(M)}J(U)},onEnd:({width:G,height:ee})=>{const J={id:E,type:"dimensions",resizing:!1,dimensions:{width:G,height:ee}};b.getState().triggerNodeChanges([J])}})),I.current.update({controlPosition:q,boundaries:{minWidth:f,minHeight:g,maxWidth:y,maxHeight:m},keepAspectRatio:x,resizeDirection:v,onResizeStart:j,onResize:N,onResizeEnd:k,shouldResize:S}),()=>{var G;(G=I.current)==null||G.destroy()}},[q,f,g,y,m,x,j,N,k,S]);const ne=q.split("-");return p.jsx("div",{className:it(["react-flow__resize-control","nodrag",...ne,o,l]),ref:$,style:{...a,scale:H,...d&&{[O?"backgroundColor":"borderColor"]:d}},children:u})}F.memo(Nk);const jk={"arch.context":0,"django.app":0,"django.route":1,"django.url_name":1,"django.view":2,"django.viewset_action":2,"django.permission":2,"django.serializer":3,"django.form":3,"django.serializer_field":4,"django.service":4,"django.model":5,"django.field":6,"django.relation":6,"django.task":7,"django.receiver":7,"django.signal":7,"django.test":7,"django.migration_op":7,"django.admin":7,"django.management_command":7,"django.consumer":7,"django.websocket_route":1,"django.template":11,"django.htmx":9,"django.cache_key":7,"django.feature_flag":7,"django.side_effect":7,"graphql.type":3,"graphql.field":4,"graphql.operation":8,"fastapi.route":1,"fastapi.model":3,"openapi.path":8,"react.api_client":9,"react.query_key":10,"react.hook":10,"react.feature":10,"react.route":11,"react.page":11,"react.component":12,"react.form_schema":13,"react.test":13,"react.context":12};function Ll(t){return jk[t]??8}function bk(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r)a.sort((u,d)=>u.name.localeCompare(d.name)),a.forEach((u,d)=>{o.set(u.id,{x:l*260,y:d*108})});return o}const dm=90,Ck=new Set(["django.field","django.serializer_field","django.relation","django.test","react.test","graphql.field","django.url_name","django.throttle"]),lp={"arch.context":"#edf2f4","django.app":"#8d99ae","django.route":"#4cc9f0","django.view":"#4895ef","django.viewset_action":"#4361ee","django.permission":"#7b8cde","django.serializer":"#f4a261","django.form":"#e9c46a","django.serializer_field":"#e9c46a","django.service":"#90be6d","django.model":"#2a9d8f","django.field":"#8ac926","django.task":"#e76f51","django.receiver":"#e85d04","django.signal":"#f4a261","django.test":"#6c757d","django.admin":"#adb5bd","django.migration_op":"#9d4edd","django.consumer":"#e76f51","django.websocket_route":"#4cc9f0","django.template":"#c77dff","django.htmx":"#ff6b6b","django.cache_key":"#6c757d","django.feature_flag":"#f4a261","django.side_effect":"#e85d04","graphql.type":"#00bbf9","graphql.operation":"#00bbf9","fastapi.route":"#4cc9f0","fastapi.model":"#f4a261","openapi.path":"#00bbf9","react.api_client":"#ff6b6b","react.query_key":"#adb5bd","react.hook":"#7b2cbf","react.feature":"#9d4edd","react.route":"#c77dff","react.page":"#c77dff","react.component":"#9d4edd","react.form_schema":"#ffd166","react.test":"#6c757d"},Mk=Math.PI*(3-Math.sqrt(5)),fm=220,Pk=26,Ik={0:"context",1:"routes",2:"views",3:"serializers",4:"services",5:"models",6:"fields",7:"jobs / signals",8:"openapi",9:"api client",10:"hooks",11:"pages",12:"components",13:"forms / tests"};function hm(t){return t.startsWith("react.")?"react":t.startsWith("openapi.")||t.startsWith("graphql.")||t.startsWith("fastapi.")?"stitch":t.startsWith("arch.")?"arch":"django"}function dE(t){return lp[t]?lp[t]:t.startsWith("react.")?"#9d4edd":t.startsWith("openapi.")?"#00bbf9":"#4a5568"}function Tk(t){return t>=dm?"3d":"2d"}function Rk(t){return t>=dm?"overview":"full"}function Lk(t,r,o=1){const l=new Set([t]);let a=new Set([t]);for(let u=0;uo.families.has(hm(f.type)));o.detail==="overview"&&(l=l.filter(f=>!Ck.has(f.type)));const a=new Set(l.map(f=>f.id)),u=r.filter(f=>a.has(f.src)&&a.has(f.dst)),d=o.focusId?Lk(o.focusId,u,1):new Set;if(o.neighborhoodOnly&&o.focusId&&d.size){l=l.filter(g=>d.has(g.id));const f=new Set(l.map(g=>g.id));return{nodes:l,edges:u.filter(g=>f.has(g.src)&&f.has(g.dst)),neighborIds:d}}return{nodes:l,edges:u,neighborIds:d}}function fE(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r){a.sort((d,f)=>d.name.localeCompare(f.name));const u=l*fm;a.forEach((d,f)=>{if(a.length===1){o.set(d.id,{x:u,y:0,z:0});return}const g=Pk*Math.sqrt(f+1),y=f*Mk;o.set(d.id,{x:u,y:g*Math.cos(y),z:g*Math.sin(y)})})}return o}function hE(t){const r=new Map;for(const o of t){const l=Ll(o.type);r.set(l,(r.get(l)||0)+1)}return[...r.entries()].sort((o,l)=>o[0]-l[0]).map(([o,l])=>({layer:o,x:o*fm,count:l}))}const il=16,zk=12,Dk=new Set(["django.route","react.route","react.page","django.task","django.migration_op","django.permission","django.throttle","django.admin","django.management_command","openapi.path","django.consumer","django.websocket_route","django.template","django.cache_key","django.feature_flag","django.side_effect","graphql.operation","fastapi.route"]),$k=new Set(["django.serializer","django.serializer_field","django.form","openapi.path","react.form_schema","django.route","graphql.type","graphql.field","graphql.operation","fastapi.model","fastapi.route"]),ap={"arch.context":"Ownership boundary from loadpath.yml — the context this code belongs to.","django.app":"Django app package that owns models, views, and jobs.","django.route":"HTTP URL that publishes a view. A sink: this is where a change becomes a public request.","django.url_name":"Named URL used by reverse() / {% url %} lookups.","django.view":"Request handler (class-based view, function view, or ViewSet).","django.viewset_action":"One ViewSet action (list, create, retrieve, update, destroy).","django.permission":"Auth gate on a view — who is allowed to hit this path.","django.throttle":"Rate-limit class attached to a view.","django.serializer":"Request/response contract: which fields go in and come out.","django.form":"Django form that validates submitted input.","django.serializer_field":"One field on a serializer or form — the typed slot on the contract.","django.service":"Internal service or use-case. Work that is not itself an HTTP sink.","django.model":"ORM model. Schema and relations live here.","django.field":"Model column. Type, indexes, and relations are the contract of the table.","django.relation":"Model-to-model relation (FK / M2M / O2O).","django.task":"Celery or Dramatiq job. Once enqueued, this is a sink.","django.receiver":"Signal handler that runs after a model event.","django.signal":"Django signal that receivers subscribe to.","django.test":"Backend test that mentions symbols on this path.","django.admin":"Django admin class for a model.","django.migration_op":"Schema migration operation (CreateModel, AlterField, …).","django.management_command":"manage.py command — an operational sink.","django.consumer":"Django Channels WebSocket/HTTP consumer. A sink once a client connects.","django.websocket_route":"ASGI WebSocket URL. A sink: this is where a change becomes a live connection.","django.template":"Django template. HTML (and HTMX) the server renders.","django.htmx":"HTMX call from a template to a URL — another published seam.","django.cache_key":"Cache get/set key. Invalidation is part of the load path.","django.feature_flag":"Feature flag checked on this path. The change may be dark-launched.","django.side_effect":"transaction.on_commit (or similar) side effect that runs after the request commits.","graphql.type":"GraphQL object/input type — a published contract.","graphql.field":"One field on a GraphQL type.","graphql.operation":"GraphQL query, mutation, or subscription. A published contract and a sink.","fastapi.route":"FastAPI path operation sitting next to Django in this repo.","fastapi.model":"Pydantic response/request model — the FastAPI contract.","openapi.path":"Generated OpenAPI operation. The typed HTTP contract between stacks.","react.api_client":"Frontend fetch or generated client call to an API path.","react.query_key":"React Query cache key. Invalidation and reads share this name.","react.hook":"Data hook wrapping query or mutation calls.","react.feature":"Frontend feature module (folder).","react.route":"Client-side route. A sink: this is a URL the user can open.","react.page":"Page or screen component rendered by a route.","react.component":"UI component.","react.form_schema":"Zod (or similar) schema — typed form inputs on the client.","react.test":"Frontend test covering a page, hook, or component.","react.context":"React context provider."},Ok={field_type:"Type",fields:"Fields",form_fields:"Form fields",permissions:"Permissions",throttles:"Throttles",authentication:"Authentication",pagination:"Pagination",filterset:"Filterset",bases:"Extends",on_delete:"on_delete",related_name:"related_name",unique:"Unique",db_index:"Indexed",relation:"Relation field",looks_idempotent_on_pk:"Idempotent on pk",broker:"Broker",route:"Route",url_name:"URL name",view:"View",include:"Includes",mounted_at:"Mounted at",full_path:"Full path",method:"Method",path:"Path",operation_id:"Operation",raw:"URL",kind:"Schema",exclude:"Excludes",queryset_in_serializer:"Queryset in serializer",get_queryset:"Custom get_queryset",get_serializer_class:"Dynamic serializer",dynamic:"Dynamic",fbv:"Function view",ninja:"Django Ninja",django_form:"Django form",mutation:"Mutation",has_error_boundary:"Error boundary",invalidation:"Cache invalidation",inferred:"Inferred stitch",generated:"Generated",shared:"Shared module",element:"Renders",model_name:"Model",field_name:"Field",op:"Operation",app:"App",feature:"Feature",from_view:"From view",mentions:"Mentions",nodeid:"Test id",task:"Task",to:"Related to"},up=["field_type","method","path","operation_id","raw","route","mounted_at","full_path","url_name","view","element","fields","form_fields","exclude","kind","bases","permissions","authentication","throttles","pagination","filterset","on_delete","related_name","to","unique","db_index","relation","looks_idempotent_on_pk","broker","task","model_name","field_name","op","app","feature","from_view","include","fbv","ninja","django_form","mutation","has_error_boundary","invalidation","inferred","generated","shared","queryset_in_serializer","get_queryset","get_serializer_class","dynamic","mentions","nodeid"],cp=new Set(["referenced","placeholder","booted","line","call","from","import","local","source","file","plain_handler","string_ref","pagination_sink","match","via","generated_client","django","react","superseded_by_generated","foreign_app","imported"]),Fk=new Set(["looks_idempotent_on_pk"]),Hk=new Set(["inferred","generated","mutation","fbv","ninja"]);function Bk(t){return ap[t]?ap[t]:t.startsWith("react.")?"A React node on the load path.":t.startsWith("django.")?"A Django node on the load path.":t.startsWith("openapi.")?"A stitch node between Django and React.":"A node on the architecture graph."}function Vk(t,r,o){const l=new Map(r.map(x=>[x.id,x])),a=[];Dk.has(t.type)&&a.push("sink"),$k.has(t.type)&&a.push("contract");const u=t.extra??{};u.inferred&&a.push("inferred"),u.generated&&a.push("generated"),u.mutation&&a.push("mutation"),u.fbv&&a.push("function view"),u.ninja&&a.push("ninja");const d=o.filter(x=>x.dst===t.id),f=o.filter(x=>x.src===t.id),g=d.slice(0,il).map(x=>dp(x,l,x.src)),y=f.slice(0,il).map(x=>dp(x,l,x.dst)),m=t.file_path?`${t.file_path}${t.start_line?`:${t.start_line}`:""}`:void 0;return{type:t.type,typeLabel:No(_l(t.type)),layer:Ik[Ll(t.type)]??"other",purpose:Bk(t.type),name:t.name,qualifiedName:t.qualified_name,file:m,context:t.context,roles:a,facts:Wk(u).filter(x=>!(x.key==="app"&&x.value===t.context)),inputs:g,outputs:y,extraInputs:Math.max(0,d.length-il),extraOutputs:Math.max(0,f.length-il)}}function dp(t,r,o){const l=r.get(o),a=o.includes(":")?o.slice(o.indexOf(":")+1):o;return{id:o,name:(l==null?void 0:l.name)||a,type:(l==null?void 0:l.type)||"",typeLabel:l?No(_l(l.type)):"",edgeType:t.type,edgeLabel:No(t.type),inferred:t.confidence<.8}}function Wk(t){const r=[...up.filter(a=>a in t),...Object.keys(t).filter(a=>!up.includes(a)&&!cp.has(a))],o=[],l=new Set;for(const a of r){if(l.has(a)||cp.has(a)||Hk.has(a))continue;l.add(a);const u=Uk(a,t[a]);u!=null&&o.push({key:a,label:Ok[a]??No(a),value:u})}return o}function Uk(t,r){if(r==null)return null;if(typeof r=="boolean")return!r&&!Fk.has(t)?null:r?"yes":"no";if(typeof r=="number")return String(r);if(typeof r=="string")return r.trim()||null;if(Array.isArray(r)){const o=r.map(u=>typeof u=="string"||typeof u=="number"?String(u):"").filter(Boolean);if(!o.length)return null;const l=o.slice(0,zk),a=o.length-l.length;return a>0?`${l.join(", ")} +${a} more`:l.join(", ")}return null}const Yk=F.lazy(()=>m0(()=>import("./LayeredGraph3D-CNVAazxv.js"),[],import.meta.url).then(t=>({default:t.LayeredGraph3D}))),Gk={cheap:"var(--edge-cheap)",expensive:"var(--edge-expensive)",critical:"var(--edge-critical)"};function Xk({data:t,selected:r}){return p.jsxs("div",{className:r?"lp-node selected":"lp-node",children:[p.jsx(Ai,{type:"target",position:Se.Left,isConnectable:!1}),p.jsx("div",{className:"t",children:_l(t.type)}),p.jsx("div",{className:"n",title:t.name,children:t.name}),p.jsx(Ai,{type:"source",position:Se.Right,isConnectable:!1})]})}const qk={load:Xk},fp=180,hp=56,Qk=new Set(["django","react","stitch","arch"]);function Kk(t,r,o=null){const l=new Map(t.map(f=>[f.id,f])),a=bk(t),u=t.map(f=>({id:f.id,type:"load",position:a.get(f.id)??{x:0,y:0},data:{name:f.name,type:f.type,file:f.file_path},selected:o===f.id,sourcePosition:Se.Right,targetPosition:Se.Left,width:fp,height:hp,style:{width:fp,height:hp}})),d=r.filter(f=>l.has(f.src)&&l.has(f.dst)).map(f=>{const g=Gk[f.weight]||"var(--edge-cheap)";return{id:f.id,source:f.src,target:f.dst,type:"smoothstep",animated:f.weight==="critical",style:{stroke:g,strokeWidth:f.weight==="critical"?2.4:1.2,strokeDasharray:f.confidence<.8?"6 4":void 0},markerEnd:{type:To.ArrowClosed,width:14,height:14,color:g},label:f.type.replaceAll("_"," "),labelStyle:{fill:"var(--muted)",fontSize:10}}});return{rfNodes:u,rfEdges:d}}function pp({node:t,nodes:r,edges:o,onClose:l,onWhatIf:a}){const u=Vk(t,r,o);return F.useEffect(()=>{const d=f=>{f.key==="Escape"&&l()};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[l]),p.jsxs("aside",{className:"inspector","data-testid":"graph-inspector",children:[p.jsxs("div",{className:"inspector-head",children:[p.jsx("div",{className:"t",children:u.typeLabel}),p.jsx("div",{className:"inspector-roles",children:u.roles.map(d=>p.jsx("span",{className:"inspector-chip",children:d},d))}),p.jsx("button",{type:"button",className:"inspector-close","data-testid":"graph-inspector-close","aria-label":"Close inspector",onClick:l,children:"×"})]}),p.jsx("div",{className:"n",children:Ni(u.name)}),p.jsx("p",{className:"inspector-purpose","data-testid":"graph-inspector-purpose",children:u.purpose}),u.context?p.jsx("div",{className:"muted",children:Ni(u.context)}):null,u.file?p.jsx("div",{className:"file",children:Ni(u.file)}):null,p.jsx("div",{className:"muted",children:Ni(u.qualifiedName)}),p.jsxs("div",{className:"muted inspector-layer",children:["layer · ",u.layer]}),u.facts.length?p.jsx("dl",{className:"inspector-facts","data-testid":"graph-inspector-facts",children:u.facts.map(d=>p.jsxs("div",{className:"inspector-fact",children:[p.jsx("dt",{children:d.label}),p.jsx("dd",{children:Ni(d.value)})]},d.key))}):null,p.jsx(gp,{title:"Inputs",testId:"graph-inspector-inputs",links:u.inputs,extra:u.extraInputs,empty:"Nothing in this graph points here."}),p.jsx(gp,{title:"Outputs",testId:"graph-inspector-outputs",links:u.outputs,extra:u.extraOutputs,empty:"This node does not point at anything in this graph."}),a?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-whatif",onClick:()=>a(t.id),children:"What if this changes"}):null]})}function gp({title:t,testId:r,links:o,extra:l,empty:a}){return p.jsxs("section",{className:"inspector-section","data-testid":r,children:[p.jsxs("h3",{children:[t,p.jsx("span",{className:"count",children:o.length+l})]}),o.length?p.jsx("ul",{children:o.map((u,d)=>p.jsxs("li",{children:[p.jsx("span",{className:"inspector-link-name",title:u.name,children:Ni(u.name)}),p.jsxs("span",{className:"inspector-link-meta",children:[u.typeLabel?`${u.typeLabel} · `:"",u.edgeLabel,u.inferred?" · inferred":""]})]},`${u.edgeType}:${u.id}:${d}`))}):p.jsx("p",{className:"muted",children:a}),l?p.jsxs("p",{className:"muted",children:["+",l," more"]}):null]})}function $u({nodes:t,edges:r,onWhatIf:o,focusPath:l}){const[a,u]=F.useState(null),[d,f]=F.useState(null),[g,y]=F.useState(null),[m,x]=F.useState(new Set(Qk)),[v,_]=F.useState(!1),S=typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,j=d??Tk(t.length),N=g??Rk(t.length),k=F.useMemo(()=>Ak(t,r,{detail:N,families:m,focusId:a,neighborhoodOnly:v&&j==="3d"}),[t,r,N,m,a,v,j]),T=F.useMemo(()=>new Map(k.nodes.map(G=>[G.id,G])),[k.nodes]),E=a?T.get(a)??null:null,{rfNodes:b,rfEdges:$}=F.useMemo(()=>{const G=Kk(k.nodes,k.edges,a);return S&&(G.rfEdges=G.rfEdges.map(ee=>({...ee,animated:!1}))),G},[k.nodes,k.edges,a,S]);F.useEffect(()=>{a&&!T.has(a)&&u(null)},[T,a]),F.useEffect(()=>{if(!l)return;const G=t.find(ee=>ee.file_path===l);G&&u(G.id)},[l,t]);const O=(G,ee)=>{u(ee.id)},H=()=>{u(null),_(!1)},I=G=>{x(ee=>{const J=new Set(ee);if(J.has(G)){if(J.size===1)return ee;J.delete(G)}else J.add(G);return J})},q=F.useMemo(()=>{const G=new Set;for(const ee of t)G.add(hm(ee.type));return G},[t]),ne=t.length-k.nodes.length;return p.jsxs("div",{className:"impact-graph",style:{flex:1,minHeight:0,position:"relative",display:"flex",flexDirection:"column"},children:[p.jsxs("div",{className:"graph-toolbar","data-testid":"graph-toolbar",children:[p.jsxs("div",{className:"seg","aria-label":"Graph projection",children:[p.jsx("button",{type:"button","data-testid":"graph-view-2d",className:j==="2d"?"active":"","aria-pressed":j==="2d",onClick:()=>f("2d"),children:"2D map"}),p.jsx("button",{type:"button","data-testid":"graph-view-3d",className:j==="3d"?"active":"","aria-pressed":j==="3d",onClick:()=>f("3d"),children:"3D layers"})]}),p.jsxs("div",{className:"seg","aria-label":"Graph detail",children:[p.jsx("button",{type:"button","data-testid":"graph-detail-overview",className:N==="overview"?"active":"","aria-pressed":N==="overview",onClick:()=>y("overview"),children:"Overview"}),p.jsx("button",{type:"button","data-testid":"graph-detail-full",className:N==="full"?"active":"","aria-pressed":N==="full",onClick:()=>y("full"),children:"Full"})]}),p.jsx("div",{className:"seg","aria-label":"Graph families",children:["django","stitch","react"].filter(G=>q.has(G)).map(G=>p.jsx("button",{type:"button","data-testid":`graph-family-${G}`,className:m.has(G)?"active":"","aria-pressed":m.has(G),onClick:()=>I(G),children:G},G))}),j==="3d"?p.jsx("button",{type:"button",className:v?"chip-btn active":"chip-btn","data-testid":"graph-neighborhood",disabled:!a,onClick:()=>_(G=>!G),children:v?"Neighborhood":"Focus neighbors"}):null,p.jsxs("span",{className:"muted graph-count",children:[k.nodes.length," nodes · ",k.edges.length," edges",ne?` · ${ne} hidden`:""]})]}),p.jsx("div",{className:"graph-stage",children:j==="3d"?p.jsxs("div",{className:"graph-3d","data-testid":"graph-3d",children:[p.jsx("p",{className:"graph-3d-hint",children:"Architecture layers are stacked in depth (Django → stitch → React). Drag to orbit, scroll to zoom, click a node to inspect it."}),p.jsx(F.Suspense,{fallback:p.jsx("p",{className:"muted graph-3d-hint",children:"Loading 3D layers…"}),children:p.jsx(Yk,{nodes:k.nodes,edges:k.edges,selectedId:a,neighborIds:k.neighborIds,onSelect:G=>{u(G),G||_(!1)}})}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]}):p.jsxs(lm,{children:[p.jsxs(QS,{nodes:b,edges:$,nodeTypes:qk,fitView:!0,fitViewOptions:{padding:.2,maxZoom:1.15},minZoom:.25,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,deleteKeyCode:null,onNodeClick:O,onPaneClick:H,proOptions:{hideAttribution:!1},"data-testid":"impact-graph",children:[p.jsx(tk,{}),p.jsx(Sk,{pannable:!0,zoomable:!0,ariaLabel:"Impact graph overview",nodeColor:"var(--muted)",nodeStrokeColor:"transparent",nodeStrokeWidth:0,maskColor:"rgba(0, 0, 0, 0.45)",maskStrokeColor:"var(--accent)",maskStrokeWidth:1.4,bgColor:"var(--graph-bg)",style:{width:184,height:128}}),p.jsx(ak,{})]}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]})})]})}const mp=[{value:"HEAD",label:"HEAD",group:"preset"},{value:"HEAD~1",label:"HEAD~1",group:"preset"}],Zk=["preset","branch","tag","commit"];function Jk(t){var a;if(!(t!=null&&t.git))return[...mp];const r=((a=t.presets)!=null&&a.length?t.presets:mp.map(u=>u.value)).map(u=>({value:u,label:u,group:"preset"})),o=new Set(r.map(u=>u.value)),l=[...r];for(const u of t.branches||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.current?`${u.name} (current)`:u.name,detail:u.subject,group:"branch"}));for(const u of t.tags||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.name,detail:u.subject,group:"tag"}));for(const u of t.commits||[])o.has(u.sha)||(o.add(u.sha),l.push({value:u.sha,label:u.short,detail:u.subject,group:"commit"}));return l}function eE(t,r){const o=r.trim().toLowerCase();return o?t.filter(l=>l.value.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)||(l.detail||"").toLowerCase().includes(o)):t}function tE(t){return Zk.map(r=>({group:r,items:t.filter(o=>o.group===r)})).filter(r=>r.items.length>0)}function nE(t){return t==="preset"?"Common":t==="branch"?"Branches":t==="tag"?"Tags":"Recent commits"}function yp({value:t,onChange:r,placeholder:o,testId:l,menuTestId:a,refs:u,onNeedRefs:d}){const f=F.useId(),g=F.useRef(null),[y,m]=F.useState(!1),[x,v]=F.useState(null),[_,S]=F.useState(0),j=F.useMemo(()=>{const b=Jk(u);return x===null?b:eE(b,x)},[u,x]),N=F.useMemo(()=>tE(j),[j]);F.useEffect(()=>{y&&d()},[y,d]),F.useEffect(()=>{S(0)},[x,y]);const k=()=>{m(!1),v(null)},T=b=>{r(b.value),k()},E=b=>{if(b.key==="ArrowDown"){if(b.preventDefault(),!y){m(!0);return}S($=>Math.min($+1,Math.max(j.length-1,0)))}else if(b.key==="ArrowUp"){if(b.preventDefault(),!y)return;S($=>Math.max($-1,0))}else if(b.key==="Enter"&&y){b.preventDefault();const $=j[_];$&&T($)}else b.key==="Escape"&&y&&(b.preventDefault(),k())};return p.jsxs("div",{className:"combo",ref:g,onBlur:b=>{b.currentTarget.contains(b.relatedTarget)||k()},children:[p.jsxs("div",{className:"combo-row",children:[p.jsx("input",{"data-testid":l,value:t,placeholder:o,spellCheck:!1,role:"combobox","aria-expanded":y,"aria-controls":f,"aria-autocomplete":"list",onChange:b=>{r(b.target.value),y&&v(b.target.value)},onKeyDown:E}),p.jsx("button",{type:"button",className:"icon-btn combo-toggle","data-testid":`${l}-toggle`,"aria-label":"Show recent refs","aria-expanded":y,onMouseDown:b=>b.preventDefault(),onClick:()=>y?k():m(!0),children:p.jsx(h0,{})})]}),y?p.jsx("div",{className:"combo-menu",id:f,role:"listbox","data-testid":a,children:N.length===0?p.jsx("div",{className:"combo-empty muted",children:"No matching refs — the typed value is kept"}):N.map(b=>p.jsxs("div",{className:"combo-group",children:[p.jsx("div",{className:"combo-heading",children:nE(b.group)}),b.items.map($=>{const O=j.indexOf($);return p.jsxs("button",{type:"button",role:"option","aria-selected":O===_,className:O===_?"combo-option active":"combo-option","data-testid":`ref-option-${$.group}`,onMouseDown:H=>H.preventDefault(),onMouseEnter:()=>S(O),onClick:()=>T($),children:[p.jsx("span",{className:"combo-label",children:$.label}),$.detail?p.jsx("span",{className:"combo-detail",children:$.detail}):null]},`${$.group}:${$.value}`)})]},b.group))}):null]})}function rE({initialPath:t,onSelect:r,onClose:o}){const[l,a]=F.useState(null),[u,d]=F.useState(t),[f,g]=F.useState(null),[y,m]=F.useState(""),[x,v]=F.useState(!1),_=F.useRef(null),S=F.useRef(0),j=async E=>{const b=S.current+1;S.current=b,v(!0);try{const $=await $e.browse(E);if(S.current!==b)return;a($),d($.path),g($.is_git?$.path:null),m("")}catch($){if(S.current!==b)return;m($ instanceof Error?$.message:String($))}finally{S.current===b&&v(!1)}};F.useEffect(()=>{var E,b;j(t),(E=_.current)==null||E.focus(),(b=_.current)==null||b.select()},[t]);const N=f||(l==null?void 0:l.path)||u,k=f&&f!==(l==null?void 0:l.path)?f.split(/[\\/]/).filter(Boolean).pop():l!=null&&l.is_git?"this repository":"this folder",T=E=>{E.key==="Escape"&&(E.preventDefault(),o())};return p.jsx("div",{className:"modal-backdrop","data-testid":"repo-explorer","data-overlay":"true",onClick:o,onKeyDown:T,children:p.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"explorer-title",onClick:E=>E.stopPropagation(),children:[p.jsxs("div",{className:"modal-head",children:[p.jsxs("div",{children:[p.jsx("h2",{id:"explorer-title",children:"Select repository"}),p.jsx("p",{className:"muted",children:"Browse to a git root, or paste the full path."})]}),p.jsx("button",{type:"button",className:"btn ghost","data-testid":"explorer-cancel",onClick:o,children:"Cancel"})]}),p.jsxs("form",{className:"explorer-path",onSubmit:E=>{E.preventDefault(),j(u)},children:[p.jsx("input",{ref:_,"data-testid":"explorer-path",value:u,onChange:E=>d(E.target.value),spellCheck:!1,"aria-label":"Directory path"}),p.jsx("button",{type:"button",className:"btn",disabled:!(l!=null&&l.parent),onClick:()=>(l==null?void 0:l.parent)&&void j(l.parent),children:"Up"}),p.jsx("button",{type:"button",className:"btn",onClick:()=>l&&void j(l.home),children:"Home"}),p.jsx("button",{type:"submit",className:"btn",children:"Go"})]}),y?p.jsx("div",{className:"error",role:"alert",children:y}):null,p.jsx("div",{className:"explorer-list",role:"listbox","aria-label":"Folders","aria-busy":x,children:l!=null&&l.entries.length?l.entries.map(E=>{const b=f===E.path;return p.jsxs("button",{type:"button",role:"option","aria-selected":b,className:b?"explorer-row active":"explorer-row","data-testid":"explorer-entry","data-path":E.path,onClick:()=>g(E.path),onDoubleClick:()=>void j(E.path),children:[p.jsx(Sp,{}),p.jsx("span",{className:"explorer-name",children:E.name}),E.is_git?p.jsx("span",{className:"chip git-badge",children:"git"}):null]},E.path)}):p.jsx("div",{className:"muted explorer-empty",children:x?"Loading…":"No folders here"})}),p.jsxs("div",{className:"modal-foot",children:[p.jsx("span",{className:"muted explorer-current",title:N,children:N}),p.jsxs("button",{type:"button",className:"btn primary","data-testid":"explorer-use",disabled:!N,onClick:()=>N&&r(N),children:["Use ",k]})]})]})})}const wl=[{id:"obsidian",label:"Obsidian",group:"dark"},{id:"nord",label:"Nord",group:"dark"},{id:"solarized-dark",label:"Solarized Dark",group:"dark"},{id:"forest",label:"Forest",group:"dark"},{id:"rose",label:"Rose Pine",group:"dark"},{id:"amber",label:"Midnight Amber",group:"dark"},{id:"volcano",label:"Volcano",group:"dark"},{id:"lavender",label:"Lavender",group:"dark"},{id:"neon-noir",label:"Neon Noir",group:"dark"},{id:"synthwave",label:"Synthwave",group:"dark"},{id:"phosphor",label:"Phosphor",group:"dark"},{id:"aurora",label:"Aurora",group:"dark"},{id:"biolume",label:"Biolume",group:"dark"},{id:"carbon",label:"Carbon",group:"dark"},{id:"paper",label:"Paper",group:"light"},{id:"solarized-light",label:"Solarized Light",group:"light"},{id:"seafoam",label:"Seafoam",group:"light"},{id:"high-contrast",label:"High Contrast",group:"light"},{id:"sakura",label:"Sakura",group:"light"},{id:"citrus",label:"Citrus",group:"light"},{id:"peach",label:"Peach Fuzz",group:"light"},{id:"candy",label:"Cotton Candy",group:"light"},{id:"sky",label:"Clear Sky",group:"light"},{id:"coral",label:"Coral Reef",group:"light"}],iE="obsidian",pm="loadpath.theme";function oE(t){return wl.some(r=>r.id===t)}function gm(){try{const t=localStorage.getItem(pm)||"";if(oE(t))return t}catch{}return iE}function sE(t){var r;return((r=wl.find(o=>o.id===t))==null?void 0:r.group)==="light"?"light":"dark"}function mm(t){document.documentElement.dataset.theme=t,document.documentElement.style.colorScheme=sE(t);try{localStorage.setItem(pm,t)}catch{}}const vp=[{id:"review",label:"Review",testId:"tab-review",shortcut:"1",icon:a0},{id:"architecture",label:"Architecture",testId:"tab-architecture",shortcut:"2",icon:u0},{id:"graph",label:"Impact graph",testId:"tab-graph",shortcut:"3",icon:c0},{id:"prs",label:"Pull requests",testId:"tab-prs",shortcut:"4",icon:d0},{id:"settings",label:"Settings",testId:"tab-settings",shortcut:"5",icon:f0}];function lE(t){const r=t.total||0;return r<=0?null:Math.min(100,Math.round(100*(t.done||0)/r))}function Ou(t,r,o){let l;try{l=new URL(t)}catch{return}if(l.protocol!=="https:"||l.username||l.password)return;const a=l.hostname.toLowerCase();a!==r&&!a.endsWith(`.${r}`)||l.pathname.startsWith(o)&&window.open(l.toString(),"_blank","noopener,noreferrer")}function aE(){var _n,Sn,Fn,Xr,qr,Qr,Tt,Hn;const[t,r]=F.useState("review"),[o,l]=F.useState(localStorage.getItem("loadpath.repo")||""),[a,u]=F.useState(localStorage.getItem("loadpath.base")||"HEAD~1"),[d,f]=F.useState(localStorage.getItem("loadpath.head")||"HEAD"),[g,y]=F.useState(null),[m,x]=F.useState(null),[v,_]=F.useState([]),[S,j]=F.useState("review"),[N,k]=F.useState(""),[T,E]=F.useState(""),[b,$]=F.useState(null),[O,H]=F.useState(""),[I,q]=F.useState({}),[ne,G]=F.useState([]),[ee,J]=F.useState([]),[C,Y]=F.useState(localStorage.getItem("loadpath.scmRepo")||""),[V,U]=F.useState(localStorage.getItem("loadpath.provider")||"github"),[z,D]=F.useState(localStorage.getItem("loadpath.prNumber")||""),[W,M]=F.useState(localStorage.getItem("loadpath.dirty")==="1"),[R,re]=F.useState(0),[ie,ce]=F.useState(""),[fe,de]=F.useState(gm),[K,le]=F.useState(!1),[pe,_e]=F.useState(!1),[xe,ge]=F.useState(null),[je,Me]=F.useState(null),[Pe,Re]=F.useState(!1),[tt,nt]=F.useState(!1),Qe=F.useRef(o);Qe.current=o;const ot=F.useRef(!1);ot.current=pe;const at=F.useRef(""),It=L=>{de(L),mm(L)},Ke=F.useRef(""),ze=L=>{Ke.current=L,E(L)},gt=L=>{const te=()=>{$e.indexProgress(L).then(Te=>{Ke.current&&(Te.message&&ze(Te.message),$(lE(Te)))}).catch(()=>{})};te();const ke=window.setInterval(te,250);return()=>{window.clearInterval(ke),$(null)}};F.useEffect(()=>{$e.settings().then(q).catch(()=>{}).finally(()=>le(!0)),$e.repos().then(L=>_(L.repos)).catch(()=>{})},[]);const ft=()=>o.trim()?!0:(k("Point at a local repository path first."),!1);F.useEffect(()=>{if(t!=="architecture"||!o.trim())return;const L=o;let te=!1;return $e.architecture(L).then(ke=>{!te&&Qe.current===L&&x(ke)}).catch(()=>{}),()=>{te=!0}},[t,o]);const Je=L=>{l(L),localStorage.setItem("loadpath.repo",L),L.trim()!==at.current&&(at.current="",ge(null))},vn=F.useCallback(()=>{const L=Qe.current.trim();!L||at.current===L||(at.current=L,$e.gitRefs(L).then(te=>{Qe.current.trim()===L&&ge(te)}).catch(()=>{at.current===L&&(at.current="",ge(null))}))},[]),wt=(L,te)=>{u(L),f(te),localStorage.setItem("loadpath.base",L),localStorage.setItem("loadpath.head",te)},Gt=(L,te,ke)=>{U(L),Y(te),localStorage.setItem("loadpath.provider",L),localStorage.setItem("loadpath.scmRepo",te),ke!==void 0&&(D(ke),localStorage.setItem("loadpath.prNumber",ke))},zi=L=>L==="github"?!!I.github_token_set:L==="gitlab"?!!I.gitlab_token_set:!!I.bitbucket_token_set,kt=F.useCallback(async(L=V)=>{var te;try{const ke=await $e.scmRepos(L);J(ke.repos),(te=ke.user)!=null&&te.login&&q(Te=>({...Te,...L==="github"?{github_user:ke.user.login}:L==="gitlab"?{gitlab_user:ke.user.login}:{bitbucket_user:ke.user.login}}))}catch{J([])}},[V]);F.useEffect(()=>{if(t!=="prs")return;let L=!1;return kt(V).catch(()=>{L||J([])}),()=>{L=!0}},[t,V,kt]),F.useEffect(()=>{if(!je)return;let L=!1,te=0;const ke=async()=>{try{const Te=await $e.githubOAuthPoll(je.flow_id);if(L)return;if(Te.status==="complete"){Me(null);const Ce=await $e.settings();q(Ce),H(Te.user?`Signed in to GitHub as ${Te.user}`:"Signed in to GitHub"),kt("github");return}if(Te.status==="pending"||Te.status==="slow_down"){te=window.setTimeout(ke,Math.max(Te.interval||je.interval,5)*1e3);return}Me(null),k(Te.status==="denied"?"GitHub sign-in was denied.":"GitHub sign-in expired. Try again.")}catch(Te){if(L)return;Me(null),k(Te instanceof Error?Te.message:String(Te))}};return te=window.setTimeout(ke,Math.max(je.interval,5)*1e3),()=>{L=!0,window.clearTimeout(te)}},[je,kt]),F.useEffect(()=>{if(!Pe)return;let L=!1,te=0;const ke=Date.now(),Te=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.bitbucket.connected){Re(!1);const Bn=await $e.settings();q(Bn),H(Ce.bitbucket.user?`Signed in to Bitbucket as ${Ce.bitbucket.user}`:"Signed in to Bitbucket"),kt("bitbucket");return}if(Date.now()-ke>18e4){Re(!1),k("Bitbucket sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Te,1500)}catch(Ce){if(L)return;Re(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Te,1500),()=>{L=!0,window.clearTimeout(te)}},[Pe,kt]),F.useEffect(()=>{if(!tt)return;let L=!1,te=0;const ke=Date.now(),Te=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.gitlab.connected){nt(!1);const Bn=await $e.settings();q(Bn),H(Ce.gitlab.user?`Signed in to GitLab as ${Ce.gitlab.user}`:"Signed in to GitLab"),kt("gitlab");return}if(Date.now()-ke>18e4){nt(!1),k("GitLab sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Te,1500)}catch(Ce){if(L)return;nt(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Te,1500),()=>{L=!0,window.clearTimeout(te)}},[tt,kt]);const hr=async(L=o)=>{if(!L.trim())return null;const te=await $e.architecture(L);return Qe.current===L&&x(te),te},An=async()=>{if(Ke.current||!ft())return;k(""),H(""),ze("Tracing load path…"),Je(o),wt(a,d);const L=gt(o);try{const te=await $e.review(o,a,d,!0,W);y(te),re(0),j("review"),r("review"),await $e.repos().then(ke=>_(ke.repos)).catch(()=>{}),await hr(o)}catch(te){k(te instanceof Error?te.message:String(te))}finally{L(),ze("")}},zn=async(L=!0)=>{if(Ke.current||!ft())return;k(""),H(""),ze(L?"Indexing…":"Full reindex…"),Je(o);const te=gt(o);try{await $e.index(o,L);const ke=await hr(o);await $e.repos().then(Te=>_(Te.repos)).catch(()=>{}),ke!=null&&ke.indexed&&(j("architecture"),r("architecture"))}catch(ke){k(ke instanceof Error?ke.message:String(ke))}finally{te(),ze("")}},pr=async()=>{if(!Ke.current&&ft()){k(""),H(""),ze("Detecting layout…"),Je(o);try{const L=await $e.init(o);H(L.message),await $e.repos().then(te=>_(te.repos)).catch(()=>{})}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},gr=async()=>{if(g!=null&&g.markdown)try{await navigator.clipboard.writeText(g.markdown),H("Copied markdown brief")}catch(L){k(L instanceof Error?L.message:String(L))}},mr=async()=>{if(!Ke.current){if(!(g!=null&&g.markdown)||!C||!z){k("Pick a pull request first (Pull requests tab), then post the brief.");return}ze("Posting Loadpath brief…");try{const L=await $e.postComment(V,C,Number(z),g.markdown);H(L.updated?"Updated the Loadpath PR comment":"Posted the Loadpath PR comment")}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},yr=async()=>{if(!Ke.current){k(""),ze("Fetching pull requests…");try{const L=await $e.prs(V,C);G(L.pull_requests);const te=ee.find(ke=>ke.slug.toLowerCase()===C.trim().toLowerCase());te!=null&&te.local_path&&Je(te.local_path)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},un=async()=>{k("");try{const L=await $e.githubOAuthStart();Me(L),Ou(L.verification_uri_complete,"github.com","/login/device")}catch(L){k(L instanceof Error?L.message:String(L))}},cn=async()=>{k("");try{const L=await $e.bitbucketOAuthStart();Re(!0),Ou(L.authorize_url,"bitbucket.org","/site/oauth2/authorize")}catch(L){Re(!1),k(L instanceof Error?L.message:String(L))}},Ur=async()=>{k("");try{const L=await $e.gitlabOAuthStart();nt(!0),Ou(L.authorize_url,new URL(L.authorize_url).hostname,"/oauth/authorize")}catch(L){nt(!1),k(L instanceof Error?L.message:String(L))}},Dn=async L=>{if(!(Ke.current||!o.trim())){k(""),ze("Walking what-if path…");try{const te=await $e.whatIf(o,L);H(`${te.title} — ${te.confidence.level} · ${(te.sinks||[]).length} sinks`),y({...te,markdown:te.markdown||"",index:te.index||(g==null?void 0:g.index),workspace:te.workspace||(g==null?void 0:g.workspace)}),re(0),j("review"),r("review")}catch(te){k(te instanceof Error?te.message:String(te))}finally{ze("")}}},Yr=async L=>{if(Ke.current)return;Gt(L.provider,L.repo,String(L.number));const te=ee.find(Ce=>Ce.slug.toLowerCase()===L.repo.toLowerCase());te!=null&&te.local_path&&Je(te.local_path),k(""),ze(`Fetching ${L.provider} #${L.number}…`);const ke=(te==null?void 0:te.local_path)||o,Te=ke?gt(ke):()=>{};try{const Ce=await $e.reviewPr(L.provider,L.repo,L.number,(te==null?void 0:te.local_path)||o||void 0);y(Ce),re(0),Ce.pull_request&&typeof Ce.pull_request.repo_path=="string"&&Je(Ce.pull_request.repo_path),wt(String(Ce.base||L.target_branch),String(Ce.head||L.source_branch)),j("review"),r("review")}catch(Ce){wt(L.base_sha||L.target_branch,L.head_sha||L.source_branch),r("review"),k(Ce instanceof Error?Ce.message:String(Ce))}finally{Te(),ze("")}},$n=async L=>{k("");try{q(await $e.oauthDisconnect(L)),V===L&&J([]),H(`Disconnected ${L}`)}catch(te){k(te instanceof Error?te.message:String(te))}},Gr=async L=>{L.preventDefault();const te=new FormData(L.currentTarget),ke={github_token:String(te.get("github_token")||""),github_oauth_client_id:String(te.get("github_oauth_client_id")||""),github_host:String(te.get("github_host")||""),gitlab_token:String(te.get("gitlab_token")||""),gitlab_host:String(te.get("gitlab_host")||""),gitlab_oauth_client_id:String(te.get("gitlab_oauth_client_id")||""),gitlab_oauth_client_secret:String(te.get("gitlab_oauth_client_secret")||""),bitbucket_token:String(te.get("bitbucket_token")||""),bitbucket_username:String(te.get("bitbucket_username")||""),bitbucket_oauth_client_id:String(te.get("bitbucket_oauth_client_id")||""),bitbucket_oauth_client_secret:String(te.get("bitbucket_oauth_client_secret")||""),ai_provider:String(te.get("ai_provider")||"none"),ai_api_key:String(te.get("ai_api_key")||""),ai_model:String(te.get("ai_model")||""),ai_base_url:String(te.get("ai_base_url")||"")},Te=v.length?{...ke,workspaces:v.map(Ce=>({path:Ce.path,name:Ce.name}))}:ke;try{q(await $e.saveSettings(Te)),H("Settings saved on this machine")}catch(Ce){k(Ce instanceof Error?Ce.message:String(Ce))}},vr=async()=>{if(!(!g||Ke.current)){ze("Residual analysis…");try{const L=await $e.residual(g);ce(L.note)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},xr=F.useRef(An);xr.current=An;const Xt=F.useRef(t);Xt.current=t,F.useEffect(()=>{const L=te=>{if(ot.current){te.key==="Escape"&&(te.preventDefault(),_e(!1));return}const ke=te.target;if(ke&&(ke.tagName==="INPUT"||ke.tagName==="TEXTAREA"||ke.tagName==="SELECT"||ke.isContentEditable)){te.key==="Escape"&&ke.blur();return}if(te.key==="Escape"){k(""),H("");return}const Te=vp.find(Ce=>Ce.shortcut===te.key);if(Te&&!te.metaKey&&!te.ctrlKey&&!te.altKey&&r(Te.id),(te.metaKey||te.ctrlKey)&&te.key==="Enter"){if(Xt.current==="settings"||Xt.current==="prs"||Ke.current)return;te.preventDefault(),xr.current()}};return window.addEventListener("keydown",L),()=>window.removeEventListener("keydown",L)},[]);const On=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.nodes)??[]:(g==null?void 0:g.nodes)??[],[S,m,g]),xn=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.edges)??[]:(g==null?void 0:g.edges)??[],[S,m,g]),Di=g!=null&&g.index?`${g.index.counts.nodes} nodes · ${g.index.counts.edges} edges`:m!=null&&m.indexed?`${m.counts.nodes} nodes · ${m.counts.edges} edges`:"Not indexed",wn=((g==null?void 0:g.findings)||[]).filter(L=>!L.waived);return p.jsxs("div",{className:"app",children:[p.jsx("a",{className:"skip",href:"#main",children:"Skip to content"}),p.jsxs("nav",{className:"rail","data-testid":"rail","aria-label":"Primary",children:[p.jsxs("div",{className:"brand",children:[p.jsx("div",{className:"brand-mark",children:"Loadpath"}),p.jsx("div",{className:"brand-sub",children:"Load-path review"})]}),vp.map(L=>{const te=L.icon,ke=t===L.id;return p.jsxs("button",{type:"button","data-testid":L.testId,className:ke?"nav-item active":"nav-item","aria-current":ke?"page":void 0,"aria-label":L.label,onClick:()=>r(L.id),children:[p.jsx(te,{}),p.jsx("span",{children:L.label})]},L.id)}),p.jsxs("div",{className:"theme-pick",children:[p.jsx("label",{htmlFor:"theme-select",children:"Theme"}),p.jsx("select",{id:"theme-select","data-testid":"theme-select",value:fe,onChange:L=>It(L.target.value),children:["dark","light"].map(L=>p.jsx("optgroup",{label:L==="dark"?"Dark":"Light",children:wl.filter(te=>te.group===L).map(te=>p.jsx("option",{value:te.id,children:te.label},te.id))},L))})]}),p.jsxs("div",{className:"rail-foot",children:[p.jsx("div",{className:"muted",role:"status",children:T||Di}),p.jsxs("div",{className:"kbd-hint",children:[p.jsx("kbd",{children:"1"}),"–",p.jsx("kbd",{children:"5"})," tabs · ",p.jsx("kbd",{children:"Ctrl"}),"+",p.jsx("kbd",{children:"Enter"})," review"]})]})]}),p.jsxs("div",{className:"main",id:"main",children:[T?p.jsxs("div",{className:b!=null?"progress determinate":"progress",role:"status","aria-live":"polite","aria-busy":"true","data-testid":"index-progress",children:[p.jsx("i",{style:b!=null?{width:`${b}%`}:void 0}),p.jsx("span",{className:"sr-only",children:T})]}):null,p.jsxs("header",{className:"topbar","data-testid":"topbar",children:[v.length>0?p.jsxs("label",{className:"field workspace",children:[p.jsx("span",{children:"Workspace"}),p.jsxs("select",{"data-testid":"workspace-select",value:v.some(L=>L.path===o)?o:"",onChange:L=>{L.target.value&&Je(L.target.value)},children:[p.jsx("option",{value:"",children:"Indexed repos…"}),v.map(L=>p.jsxs("option",{value:L.path,children:[L.name,L.indexed?` (${L.counts.nodes})`:""]},L.path))]})]}):null,p.jsxs("label",{className:"field path",children:[p.jsx("span",{children:"Repository"}),p.jsxs("div",{className:"path-row",children:[p.jsx("input",{"data-testid":"repo-path",placeholder:"Local monorepo path",value:o,onChange:L=>{const te=L.target.value;l(te),te.trim()!==at.current&&(at.current="",ge(null))},spellCheck:!1}),p.jsx("button",{type:"button",className:"icon-btn","data-testid":"btn-browse-repo","aria-label":"Browse for a local repository",onClick:()=>_e(!0),children:p.jsx(Sp,{})})]})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Base"}),p.jsx(yp,{testId:"base-ref",menuTestId:"base-ref-menu",value:a,onChange:L=>wt(L,d),placeholder:"base",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Head"}),p.jsx(yp,{testId:"head-ref",menuTestId:"head-ref-menu",value:d,onChange:L=>wt(a,L),placeholder:"head",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field dirty",children:[p.jsx("span",{children:"Working tree"}),p.jsx("button",{type:"button",className:W?"chip-btn active":"chip-btn","data-testid":"btn-dirty","aria-pressed":W,onClick:()=>{const L=!W;M(L),localStorage.setItem("loadpath.dirty",L?"1":"0")},children:W?"Include uncommitted":"Committed range"})]}),p.jsxs("div",{className:"topbar-actions",children:[p.jsx("button",{type:"button","data-testid":"btn-init",disabled:!!T,onClick:pr,children:"Draft config"}),p.jsx("button",{type:"button","data-testid":"btn-index",disabled:!!T,onClick:()=>zn(!0),children:"Index"}),p.jsx("button",{type:"button","data-testid":"btn-review",className:"btn primary",disabled:!!T,onClick:An,children:"Review"})]})]}),p.jsxs("div",{className:"alerts",children:[N?p.jsxs("div",{className:"error","data-testid":"error",role:"alert",children:[p.jsx("span",{children:N}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>k(""),"aria-label":"Dismiss error",children:"×"})]}):null,O?p.jsxs("div",{className:"banner","data-testid":"status-note",children:[p.jsx("span",{children:O}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>H(""),"aria-label":"Dismiss",children:"×"})]}):null,((_n=g==null?void 0:g.index)!=null&&_n.stale||m!=null&&m.stale)&&(t==="review"||t==="architecture")?p.jsx("div",{className:"banner stale","data-testid":"index-stale",children:"Index is stale — files changed since the last extract. Index again before trusting this walk."}):null,((Sn=g==null?void 0:g.index)==null?void 0:Sn.django_boot)==="failed"||(m==null?void 0:m.django_boot)==="failed"?p.jsx("div",{className:"banner warn","data-testid":"django-boot-failed",children:((Fn=g==null?void 0:g.index)==null?void 0:Fn.django_boot_detail)||(m==null?void 0:m.django_boot_detail)||"django.setup() failed"}):null,(Xr=g==null?void 0:g.workspace)!=null&&Xr.dirty_overlaps_review&&t==="review"?p.jsxs("div",{className:"banner warn","data-testid":"dirty-tree",children:["Uncommitted files overlap this review: ",(g.workspace.dirty_overlap||[]).slice(0,6).join(", ")]}):null]}),p.jsxs("div",{className:"stage",children:[t==="review"&&p.jsxs("div",{className:"content","data-testid":"review-layout",children:[p.jsx("aside",{className:"brief","data-testid":"brief",children:g?p.jsx(uE,{review:g,findings:wn,aiNote:ie,busy:!!T,tourIndex:R,onTour:re,onAskAi:vr,onCopy:gr,onPost:mr}):p.jsxs("div",{className:"empty","data-testid":"review-empty",children:[p.jsx("h2",{children:"Trace the force of this diff"}),p.jsx("p",{children:"The graph is the architecture. The brief is where this change travels — not a hunk list."}),p.jsxs("ol",{children:[p.jsx("li",{children:"Point at a Django + React monorepo, or pick an indexed workspace."}),p.jsxs("li",{children:["Index it. Missing ",p.jsx("code",{children:"loadpath.yml"})," is drafted from ",p.jsx("code",{children:"manage.py"})," and"," ",p.jsx("code",{children:"src/features"}),"."]}),p.jsx("li",{children:"Review a git range, or open a pull request so base/head become a three-dot merge-base."})]})]})}),p.jsx("div",{className:"graph-wrap","data-testid":"review-graph",children:g?p.jsx($u,{nodes:g.nodes,edges:g.edges,onWhatIf:Dn,focusPath:(qr=g.read_order[R])==null?void 0:qr.path}):null})]}),t==="architecture"&&p.jsxs("div",{className:"content","data-testid":"architecture-panel",children:[p.jsx("aside",{className:"brief","data-testid":"architecture-brief",children:m!=null&&m.indexed?p.jsx(cE,{architecture:m,busy:!!T,onReindex:()=>zn(!1),onReview:An}):p.jsx("p",{className:"muted","data-testid":"architecture-empty",children:"Index this repo to build the architecture graph. Review then walks that same graph for a git range — it does not start from a hunk list."})}),p.jsx("div",{className:"graph-wrap","data-testid":"architecture-graph",children:m!=null&&m.indexed?p.jsx($u,{nodes:m.nodes,edges:m.edges,onWhatIf:Dn}):null})]}),t==="graph"&&p.jsxs("div",{className:"graph-wrap","data-testid":"graph-full",style:{height:"100%"},children:[p.jsxs("div",{className:"graph-modes",children:[p.jsxs("div",{className:"seg","aria-label":"Graph scope",children:[p.jsx("button",{type:"button","aria-pressed":S==="review","data-testid":"graph-mode-review",className:S==="review"?"active":"",onClick:()=>j("review"),children:"This review"}),p.jsx("button",{type:"button","aria-pressed":S==="architecture","data-testid":"graph-mode-architecture",className:S==="architecture"?"active":"",onClick:()=>j("architecture"),children:"Indexed architecture"})]}),p.jsxs("div",{className:"legend","aria-hidden":"true",children:[p.jsxs("span",{children:[p.jsx("i",{})," cheap"]}),p.jsxs("span",{children:[p.jsx("i",{className:"exp"})," expensive"]}),p.jsxs("span",{children:[p.jsx("i",{className:"crit"})," critical"]}),p.jsxs("span",{children:[p.jsx("i",{className:"dash"})," inferred"]})]})]}),On.length?p.jsx($u,{nodes:On,edges:xn,onWhatIf:Dn}):p.jsx("p",{className:"empty","data-testid":"graph-empty",children:"Index the repo or run a review first. Click a node to inspect it."})]}),t==="prs"&&p.jsxs("div",{className:"pr-list","data-testid":"pr-list",children:[p.jsxs("div",{className:"pr-toolbar",children:[p.jsxs("label",{className:"field provider",children:[p.jsx("span",{children:"Provider"}),p.jsxs("select",{"data-testid":"pr-provider",value:V,onChange:L=>Gt(L.target.value,C,z),children:[p.jsx("option",{value:"github",children:"GitHub"}),p.jsx("option",{value:"gitlab",children:"GitLab"}),p.jsx("option",{value:"bitbucket",children:"Bitbucket"})]})]}),p.jsxs("label",{className:"field",children:[p.jsx("span",{children:"Repository"}),p.jsx("input",{"data-testid":"pr-repo",placeholder:ee.length?"Search your repos":"owner/repo",value:C,onChange:L=>Gt(V,L.target.value,z),list:"scm-repos",spellCheck:!1}),p.jsx("datalist",{id:"scm-repos",children:ee.map(L=>p.jsxs("option",{value:L.slug,children:[L.private?"private":"public",L.local_path?" · local":""]},L.slug))})]}),p.jsx("button",{type:"button","data-testid":"btn-refresh-repos",className:"btn",disabled:!!T||!zi(V),onClick:()=>{kt(V)},children:"My repos"}),p.jsx("button",{type:"button","data-testid":"btn-list-prs",className:"btn",disabled:!!T,onClick:yr,children:"List PRs"})]}),ee.length>0?p.jsxs("p",{className:"muted scm-count","data-testid":"scm-repo-count",children:[ee.length," ",V," repositor",ee.length===1?"y":"ies",V==="github"&&I.github_user?` · @${String(I.github_user)}`:"",V==="gitlab"&&I.gitlab_user?` · @${String(I.gitlab_user)}`:"",V==="bitbucket"&&I.bitbucket_user?` · ${String(I.bitbucket_user)}`:""]}):null,ne.length===0?p.jsxs("div",{className:"empty","data-testid":"pr-empty",children:[p.jsx("h2",{children:"No pull requests loaded"}),p.jsx("p",{children:"Sign in under Settings (or paste a token), load your repositories, then list open PRs. Reviewing a PR fills base and head from its SHAs."})]}):ne.map(L=>p.jsxs("article",{className:"pr","data-testid":`pr-${L.number}`,children:[p.jsxs("h3",{children:["#",L.number," ",L.title]}),p.jsxs("div",{className:"pr-meta muted",children:[p.jsx("span",{className:`chip ${L.draft?"":"open"}`,children:L.draft?"draft":L.state}),p.jsx("span",{children:L.author}),p.jsxs("span",{children:[L.source_branch," → ",L.target_branch]})]}),p.jsxs("div",{className:"pr-actions",children:[p.jsxs("a",{href:L.url,target:"_blank",rel:"noreferrer",children:["Open on ",L.provider]}),p.jsx("button",{type:"button",className:"btn primary","data-testid":`pr-review-${L.number}`,onClick:()=>void Yr(L),children:"Review this PR"})]})]},`${L.provider}-${L.number}`))]}),t==="settings"&&K&&p.jsxs("form",{className:"settings","data-testid":"settings-form",onSubmit:Gr,children:[p.jsxs("div",{children:[p.jsx("h1",{children:"Settings"}),p.jsx("p",{className:"muted",children:"Tokens stay on this machine in ~/.loadpath/settings.json. AI runs only on residual uncertainty the graph could not close."})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Appearance"}),p.jsx("p",{className:"muted",children:"Local to this browser. High contrast is a first-class theme, not an afterthought."}),p.jsx("div",{className:"theme-grid","data-testid":"theme-grid",children:wl.map(L=>p.jsxs("button",{type:"button","data-theme":L.id,className:fe===L.id?"theme-swatch active":"theme-swatch","data-testid":`theme-${L.id}`,onClick:()=>It(L.id),children:[p.jsx("div",{className:"swatch-bar","aria-hidden":"true"}),p.jsx("div",{className:"name",children:L.label}),p.jsx("div",{className:"group",children:L.group})]},L.id))})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Source control"}),p.jsx("p",{className:"muted",children:"Sign in with OAuth to list every repository the account can access. Tokens stay in ~/.loadpath/settings.json. A classic PAT still works if you prefer not to register an OAuth app."}),p.jsxs("div",{className:"scm-login","data-testid":"scm-github",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitHub"}),p.jsx("p",{className:"muted",children:I.github_token_set?I.github_user?`Signed in as @${String(I.github_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.github_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-github-disconnect",onClick:()=>void $n("github"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-github-login",disabled:!!je||!I.github_oauth_ready,onClick:()=>void un(),children:je?"Waiting for GitHub…":"Sign in with GitHub"})})]}),je?p.jsxs("p",{className:"oauth-code","data-testid":"github-user-code",children:["Enter ",p.jsx("code",{children:je.user_code})," at GitHub if the browser did not fill it in."]}):null,I.github_oauth_ready?null:p.jsx("p",{className:"muted",children:"Sign-in needs a GitHub OAuth App with Device Flow enabled. Set LOADPATH_GITHUB_CLIENT_ID or paste the client ID below."}),p.jsx("label",{htmlFor:"github_oauth_client_id",children:"GitHub OAuth client ID"}),p.jsx("input",{id:"github_oauth_client_id",name:"github_oauth_client_id","data-testid":"github-oauth-client-id",placeholder:"Ov23…",defaultValue:String(I.github_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"github_token",children:"GitHub token (optional PAT)"}),p.jsx("input",{id:"github_token",name:"github_token",type:"password",placeholder:"ghp_…",autoComplete:"off"}),p.jsx("label",{htmlFor:"github_host",children:"GitHub host (Enterprise)"}),p.jsx("input",{id:"github_host",name:"github_host","data-testid":"github-host",placeholder:"github.com",defaultValue:String(I.github_host||""),autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-gitlab",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitLab"}),p.jsx("p",{className:"muted",children:I.gitlab_token_set?I.gitlab_user?`Signed in as @${String(I.gitlab_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.gitlab_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-gitlab-disconnect",onClick:()=>void $n("gitlab"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-gitlab-login",disabled:tt||!I.gitlab_oauth_ready,onClick:()=>void Ur(),children:tt?"Waiting for GitLab…":"Sign in with GitLab"})})]}),p.jsx("label",{htmlFor:"gitlab_host",children:"GitLab host"}),p.jsx("input",{id:"gitlab_host",name:"gitlab_host","data-testid":"gitlab-host",placeholder:"gitlab.com",defaultValue:String(I.gitlab_host||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_id",children:"GitLab OAuth application ID"}),p.jsx("input",{id:"gitlab_oauth_client_id",name:"gitlab_oauth_client_id","data-testid":"gitlab-oauth-client-id",defaultValue:String(I.gitlab_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_secret",children:"GitLab OAuth secret"}),p.jsx("input",{id:"gitlab_oauth_client_secret",name:"gitlab_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_token",children:"GitLab token (optional PAT)"}),p.jsx("input",{id:"gitlab_token",name:"gitlab_token",type:"password",placeholder:"glpat-…",autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-bitbucket",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"Bitbucket"}),p.jsx("p",{className:"muted",children:I.bitbucket_token_set?I.bitbucket_user?`Signed in as ${String(I.bitbucket_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.bitbucket_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-bitbucket-disconnect",onClick:()=>void $n("bitbucket"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-bitbucket-login",disabled:Pe||!I.bitbucket_oauth_ready,onClick:()=>void cn(),children:Pe?"Waiting for Bitbucket…":"Sign in with Bitbucket"})})]}),I.bitbucket_oauth_ready?null:p.jsxs("p",{className:"muted",children:["Sign-in needs a Bitbucket OAuth consumer (key + secret). Callback URL:"," ",p.jsx("code",{children:"/api/oauth/bitbucket/callback"})," on this app origin."]}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_id",children:"Bitbucket OAuth key"}),p.jsx("input",{id:"bitbucket_oauth_client_id",name:"bitbucket_oauth_client_id","data-testid":"bitbucket-oauth-client-id",defaultValue:String(I.bitbucket_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_secret",children:"Bitbucket OAuth secret"}),p.jsx("input",{id:"bitbucket_oauth_client_secret",name:"bitbucket_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_token",children:"Bitbucket token (optional app password)"}),p.jsx("input",{id:"bitbucket_token",name:"bitbucket_token",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_username",children:"Bitbucket username (app passwords)"}),p.jsx("input",{id:"bitbucket_username",name:"bitbucket_username",defaultValue:String(I.bitbucket_username||"")})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Residual AI"}),p.jsx("label",{htmlFor:"ai_provider",children:"Provider"}),p.jsxs("select",{id:"ai_provider",name:"ai_provider",defaultValue:String(((Qr=I.ai)==null?void 0:Qr.provider)||"none"),children:[p.jsx("option",{value:"none",children:"none (graph only)"}),p.jsx("option",{value:"anthropic",children:"Anthropic"}),p.jsx("option",{value:"openai",children:"OpenAI"}),p.jsx("option",{value:"grok",children:"Grok / xAI"}),p.jsx("option",{value:"deepseek",children:"DeepSeek"}),p.jsx("option",{value:"cursor",children:"Cursor-compatible (OpenAI protocol)"}),p.jsx("option",{value:"ollama",children:"Ollama local"})]}),p.jsx("label",{htmlFor:"ai_api_key",children:"API key"}),p.jsx("input",{id:"ai_api_key",name:"ai_api_key",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"ai_model",children:"Model"}),p.jsx("input",{id:"ai_model",name:"ai_model","data-testid":"ai-model",placeholder:"optional override",defaultValue:String(((Tt=I.ai)==null?void 0:Tt.model)||"")}),p.jsx("label",{htmlFor:"ai_base_url",children:"Base URL"}),p.jsx("input",{id:"ai_base_url",name:"ai_base_url","data-testid":"ai-base-url",placeholder:"optional, OpenAI-compatible",defaultValue:String(((Hn=I.ai)==null?void 0:Hn.base_url)||"")}),p.jsx("button",{className:"btn primary",type:"submit","data-testid":"btn-save-settings",children:"Save"})]})]})]})]}),pe?p.jsx(rE,{initialPath:o,onClose:()=>_e(!1),onSelect:L=>{Je(L),_e(!1)}}):null]})}function uE({review:t,findings:r,aiNote:o,busy:l,tourIndex:a,onTour:u,onAskAi:d,onCopy:f,onPost:g}){var m,x,v,_,S,j,N,k,T,E,b,$,O,H;const y=[...new Set(t.confidence.reasons||[])];return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:`merge-box ${t.confidence.level}`,children:[p.jsxs("div",{className:`level ${t.confidence.level}`,children:[t.confidence.level.toUpperCase()," — ",t.title]}),y.length?p.jsx("ul",{className:"reasons",children:y.map(I=>p.jsx("li",{children:I},I))}):null,t.low_risk?p.jsx("span",{className:"chip",children:"low-risk"}):null,t.change_kinds.map(I=>p.jsx("span",{className:"chip",children:No(I)},I)),(m=t.contract_break)!=null&&m.kind&&t.contract_break.kind!=="none"?p.jsxs("span",{className:`chip ${t.contract_break.kind==="breaking"?"blocker":""}`,"data-testid":"contract-kind",children:["contract ",t.contract_break.kind]}):null]}),p.jsxs("div",{className:"metrics",children:[p.jsxs("div",{className:"metric",children:[p.jsxs("div",{className:"n",children:[t.confidence.covered_sinks,"/",t.confidence.sinks]}),p.jsx("div",{className:"l",children:"Sinks tested"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:r.length}),p.jsx("div",{className:"l",children:"Findings"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:t.residuals.length}),p.jsx("div",{className:"l",children:"Residuals"})]})]}),p.jsx("pre",{className:"headline",children:t.headline}),t.index?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Index ",p.jsx("span",{className:"count",children:t.index.counts.nodes})]}),p.jsxs("div",{className:"muted",children:["Walked ",t.index.counts.nodes," nodes / ",t.index.counts.edges," edges",t.index.reindex_skipped?" from an unchanged index":t.index.reindexed?" after an incremental refresh":" from the existing index",t.index.django_boot&&t.index.django_boot!=="off"?` · Django boot ${t.index.django_boot}`:"",(x=t.workspace)!=null&&x.three_dot?" · three-dot range":""]})]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Read this ",p.jsx("span",{className:"count",children:t.read_order.length})]}),t.read_order.map((I,q)=>p.jsxs("div",{className:q===a?"read-item tour-current":"read-item",children:[p.jsxs("span",{className:"file",children:[q+1,". ",I.path]}),p.jsx("div",{className:"why",children:I.why})]},I.path)),t.read_order.length>0?p.jsxs("div",{className:"btn-row tour-row",children:[p.jsx("button",{type:"button",className:"btn","data-testid":"btn-tour-prev",disabled:a<=0,onClick:()=>u(Math.max(0,a-1)),children:"Previous"}),p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-tour-next",disabled:a>=t.read_order.length-1,onClick:()=>u(Math.min(t.read_order.length-1,a+1)),children:"Next in read order"}),p.jsxs("span",{className:"muted",children:[a+1,"/",t.read_order.length]})]}):null]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Clusters ",p.jsx("span",{className:"count",children:t.clusters.length})]}),t.clusters.map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:I.title})," — ",I.files.join(", ")]},I.id))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Architecture ",p.jsx("span",{className:"count",children:r.length})]}),r.length===0?p.jsx("div",{className:"muted",children:t.architecture_note}):r.map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${I.severity}`,children:I.severity}),I.message]},I.rule+I.message))]}),p.jsx(ym,{cards:t.deepening}),(_=(v=t.contract_break)==null?void 0:v.reasons)!=null&&_.length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Contract ",p.jsx("span",{className:"count",children:t.contract_break.kind})]}),t.contract_break.reasons.map(I=>p.jsx("div",{className:"muted",children:I},I))]}):null,(S=t.auth)!=null&&S.note?p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Auth"}),p.jsx("div",{className:"muted",children:t.auth.note}),(t.auth.missing_permissions||[]).map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:"chip warning",children:"missing"}),I.name]},I.id))]}):null,(t.suggested_tests||[]).length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Suggested tests ",p.jsx("span",{className:"count",children:(j=t.suggested_tests)==null?void 0:j.length})]}),(t.suggested_tests||[]).map(I=>p.jsxs("div",{className:"residual",children:[p.jsx("strong",{children:I.title}),p.jsx("pre",{className:"headline",children:I.body})]},I.title))]}):null,(N=t.trend)!=null&&N.note?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Confidence trend"}),p.jsx("div",{className:"muted",children:t.trend.note}),(t.trend.points||[]).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[I.level," · ",_p(I.created_at),I.sinks!=null?` · ${I.sinks} sinks`:""]},I.id))]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Residual ",p.jsx("span",{className:"count",children:t.residuals.length})]}),p.jsx("p",{className:"muted",children:"AI is only used here, on what the graph could not close."}),t.residuals.map(I=>p.jsx("div",{className:"residual muted",children:I},I))]}),(T=(k=t.evolution)==null?void 0:k.notes)!=null&&T.length||(b=(E=t.evolution)==null?void 0:E.hotspots)!=null&&b.some(I=>I.commits)?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Churn & coupling"}),((($=t.evolution)==null?void 0:$.notes)||[]).map(I=>p.jsx("div",{className:"muted",children:I},I)),(((O=t.evolution)==null?void 0:O.hotspots)||[]).filter(I=>I.commits).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("span",{className:"file",children:I.path})," — ",I.commits," commits, bus factor ",I.bus_factor]},I.path))]}):null,p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:l,onClick:d,children:"Ask configured model"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-copy-markdown",onClick:f,children:"Copy markdown"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-post-comment",onClick:g,children:"Post to PR"})]}),o?p.jsx("pre",{className:"headline",children:o}):null,p.jsx("div",{className:"kicker",children:"Reviewers"}),p.jsx("div",{className:"muted",children:t.suggested_reviewers.join(", ")||"—"}),(H=t.knowledge_owners)!=null&&H.length?p.jsxs("div",{className:"muted",children:["Knowledge: ",t.knowledge_owners.join(", ")]}):null]})}function cE({architecture:t,busy:r,onReindex:o,onReview:l}){const a=t.findings.filter(u=>!u.waived);return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"merge-box high",children:[p.jsxs("div",{className:"level high",children:["INDEXED — ",t.counts.nodes," nodes"]}),p.jsxs("div",{className:"muted",style:{marginTop:8},children:[t.indexed_at?`Last index ${_p(t.indexed_at)}`:"Indexed",t.incremental?" · incremental":" · full",t.stale?" · stale":"",t.django_boot&&t.django_boot!=="off"?` · Django boot ${t.django_boot}`:""]}),p.jsxs("span",{className:"chip",children:[t.counts.edges," edges"]}),t.has_config?p.jsx("span",{className:"chip",children:"loadpath.yml"}):null]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Bounded contexts"}),Object.values(t.contexts).map(u=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:u.name})," — ",(u.django_apps||[]).join(", ")||"no apps"," ·"," ",(u.owners||[]).join(", ")||"unowned"]},u.name))]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Rules ",p.jsx("span",{className:"count",children:(t.rules||[]).length})]}),(t.rules||[]).map(u=>p.jsx("div",{className:"muted",children:u},u))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Findings ",p.jsx("span",{className:"count",children:a.length})]}),a.length===0?p.jsx("div",{className:"muted",children:"No architecture rule hits on the full graph."}):a.map(u=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${u.severity}`,children:u.severity}),u.message]},u.rule+u.message))]}),p.jsx(ym,{cards:t.deepening}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Types"}),p.jsx("table",{className:"type-table",children:p.jsx("tbody",{children:Object.entries(t.type_counts||{}).sort((u,d)=>d[1]-u[1]).slice(0,12).map(([u,d])=>p.jsxs("tr",{children:[p.jsx("td",{children:_l(u)}),p.jsx("td",{children:d})]},u))})})]}),p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:r,onClick:o,"data-testid":"btn-full-reindex",children:"Full reindex"}),p.jsx("button",{type:"button",className:"btn primary",disabled:r,onClick:l,children:"Review against this index"})]})]})}function ym({cards:t}){const r=t||[];return r.length?p.jsxs("details",{className:"section",open:!0,"data-testid":"deepening-list",children:[p.jsxs("summary",{children:["Depth ",p.jsx("span",{className:"count",children:r.length})]}),p.jsx("p",{className:"muted",children:"Deepening opportunities: more behaviour behind a smaller interface, at a real seam."}),r.map(o=>p.jsxs("div",{className:"finding","data-testid":"deepening-card",children:[p.jsx("span",{className:`chip ${o.strength}`,children:l0(o.strength)}),o.top?p.jsx("span",{className:"chip",children:"top"}):null,p.jsx("strong",{children:o.title}),p.jsx("div",{className:"why",children:o.message}),o.deletion_test?p.jsxs("div",{className:"muted",children:["Deletion test: ",o.deletion_test]}):null,o.before&&o.after?p.jsxs("div",{className:"muted",children:[o.before," → ",o.after]}):null]},o.rule+o.title))]}):null}mm(gm());i0.createRoot(document.getElementById("root")).render(p.jsx(F.StrictMode,{children:p.jsx(aE,{})}));export{Ik as L,hE as a,dE as c,p as j,fE as l,F as r,_l as t}; +`)),m=y.reduce((x,v)=>x.concat(...v),[]);return[y,m]}return[[],[]]},[t]);return F.useEffect(()=>{const g=(r==null?void 0:r.target)??Hh,y=(r==null?void 0:r.actInsideInputWithModifier)??!0;if(t!==null){const m=_=>{var N,k;if(a.current=_.ctrlKey||_.metaKey||_.shiftKey||_.altKey,(!a.current||a.current&&!y)&&fg(_))return!1;const j=Vh(_.code,f);if(u.current.add(_[j]),Bh(d,u.current,!1)){const T=((k=(N=_.composedPath)==null?void 0:N.call(_))==null?void 0:k[0])||_.target,E=(T==null?void 0:T.nodeName)==="BUTTON"||(T==null?void 0:T.nodeName)==="A";r.preventDefault!==!1&&(a.current||!E)&&_.preventDefault(),l(!0)}},x=_=>{const S=Vh(_.code,f);Bh(d,u.current,!0)?(l(!1),u.current.clear()):u.current.delete(_[S]),_.key==="Meta"&&u.current.clear(),a.current=!1},v=()=>{u.current.clear(),l(!1)};return g==null||g.addEventListener("keydown",m),g==null||g.addEventListener("keyup",x),window.addEventListener("blur",v),window.addEventListener("contextmenu",v),()=>{g==null||g.removeEventListener("keydown",m),g==null||g.removeEventListener("keyup",x),window.removeEventListener("blur",v),window.removeEventListener("contextmenu",v)}}},[t,l]),o}function Bh(t,r,o){return t.filter(l=>o||l.length===r.size).some(l=>l.every(a=>r.has(a)))}function Vh(t,r){return r.includes(t)?"code":"key"}const k_=()=>{const t=We();return F.useMemo(()=>({zoomIn:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1.2,r):!1},zoomOut:async r=>{const{panZoom:o}=t.getState();return o?o.scaleBy(1/1.2,r):!1},zoomTo:async(r,o)=>{const{panZoom:l}=t.getState();return l?l.scaleTo(r,o):!1},getZoom:()=>t.getState().transform[2],setViewport:async(r,o)=>{const{transform:[l,a,u],panZoom:d}=t.getState();return d?(await d.setViewport({x:r.x??l,y:r.y??a,zoom:r.zoom??u},o),!0):!1},getViewport:()=>{const[r,o,l]=t.getState().transform;return{x:r,y:o,zoom:l}},setCenter:async(r,o,l)=>t.getState().setCenter(r,o,l),fitBounds:async(r,o)=>{const{width:l,height:a,minZoom:u,maxZoom:d,panZoom:f}=t.getState(),g=cc(r,l,a,u,d,(o==null?void 0:o.padding)??.1);return f?(await f.setViewport(g,{duration:o==null?void 0:o.duration,ease:o==null?void 0:o.ease,interpolate:o==null?void 0:o.interpolate}),!0):!1},screenToFlowPosition:(r,o={})=>{const{transform:l,snapGrid:a,snapToGrid:u,domNode:d}=t.getState();if(!d)return r;const{x:f,y:g}=d.getBoundingClientRect(),y={x:r.x-f,y:r.y-g},m=o.snapGrid??a,x=o.snapToGrid??u;return Bo(y,l,x,m)},flowToScreenPosition:r=>{const{transform:o,domNode:l}=t.getState();if(!l)return r;const{x:a,y:u}=l.getBoundingClientRect(),d=Ri(r,o);return{x:d.x+a,y:d.y+u}}}),[])};function Lg(t,r){const o=[],l=new Map,a=[];for(const u of t)if(u.type==="add"){a.push(u);continue}else if(u.type==="remove"||u.type==="replace")l.set(u.id,[u]);else{const d=l.get(u.id);d?d.push(u):l.set(u.id,[u])}for(const u of r){const d=l.get(u.id);if(!d){o.push(u);continue}if(d[0].type==="remove")continue;if(d[0].type==="replace"){o.push({...d[0].item});continue}const f={...u};for(const g of d)E_(g,f);o.push(f)}return a.length&&a.forEach(u=>{u.index!==void 0?o.splice(u.index,0,{...u.item}):o.push({...u.item})}),o}function E_(t,r){switch(t.type){case"select":{r.selected=t.selected;break}case"position":{typeof t.position<"u"&&(r.position=t.position),typeof t.dragging<"u"&&(r.dragging=t.dragging);break}case"dimensions":{typeof t.dimensions<"u"&&(r.measured={...t.dimensions},t.setAttributes&&((t.setAttributes===!0||t.setAttributes==="width")&&(r.width=t.dimensions.width),(t.setAttributes===!0||t.setAttributes==="height")&&(r.height=t.dimensions.height))),typeof t.resizing=="boolean"&&(r.resizing=t.resizing);break}}}function N_(t,r){return Lg(t,r)}function j_(t,r){return Lg(t,r)}function Ar(t,r){return{id:t,type:"select",selected:r}}function ji(t,r=new Set,o=!1){const l=[];for(const[a,u]of t){const d=r.has(a);!(u.selected===void 0&&!d)&&u.selected!==d&&(o&&(u.selected=d),l.push(Ar(u.id,d)))}return l}function Wh({items:t=[],lookup:r}){var a;const o=[],l=new Map(t.map(u=>[u.id,u]));for(const[u,d]of t.entries()){const f=r.get(d.id),g=((a=f==null?void 0:f.internals)==null?void 0:a.userNode)??f;g!==void 0&&g!==d&&o.push({id:d.id,item:d,type:"replace"}),g===void 0&&o.push({item:d,type:"add",index:u})}for(const[u]of r)l.get(u)===void 0&&o.push({id:u,type:"remove"});return o}function Uh(t){return{id:t.id,type:"remove"}}const b_=ag();function C_(t,r,o={}){return d1(t,r,{...o,onError:o.onError??b_})}const Yh=t=>Qw(t),M_=t=>rg(t);function Ag(t){return F.forwardRef(t)}const zg=typeof window<"u"?F.useLayoutEffect:F.useEffect;function Gh(t){const[r,o]=F.useState(BigInt(0)),[l]=F.useState(()=>P_(()=>o(a=>a+BigInt(1))));return zg(()=>{const a=l.get();a.length&&(t(a),l.reset())},[r]),l}function P_(t){let r=[];return{get:()=>r,reset:()=>{r=[]},push:o=>{r.push(o),t()}}}const Dg=F.createContext(null);function I_({children:t}){const r=We(),o=F.useCallback(f=>{const{nodes:g=[],setNodes:y,hasDefaultNodes:m,onNodesChange:x,nodeLookup:v,fitViewQueued:_,onNodesChangeMiddlewareMap:S}=r.getState();let j=g;for(const k of f)j=typeof k=="function"?k(j):k;let N=Wh({items:j,lookup:v});for(const k of S.values())N=k(N);m&&y(j),N.length>0?x==null||x(N):_&&window.requestAnimationFrame(()=>{const{fitViewQueued:k,nodes:T,setNodes:E}=r.getState();k&&E(T)})},[]),l=Gh(o),a=F.useCallback(f=>{const{edges:g=[],setEdges:y,hasDefaultEdges:m,onEdgesChange:x,edgeLookup:v}=r.getState();let _=g;for(const S of f)_=typeof S=="function"?S(_):S;m?y(_):x&&x(Wh({items:_,lookup:v}))},[]),u=Gh(a),d=F.useMemo(()=>({nodeQueue:l,edgeQueue:u}),[]);return p.jsx(Dg.Provider,{value:d,children:t})}function T_(){const t=F.useContext(Dg);if(!t)throw new Error("useBatchContext must be used within a BatchProvider");return t}const R_=t=>!!t.panZoom;function yc(){const t=k_(),r=We(),o=T_(),l=Ae(R_),a=F.useMemo(()=>{const u=x=>r.getState().nodeLookup.get(x),d=x=>{o.nodeQueue.push(x)},f=x=>{o.edgeQueue.push(x)},g=x=>{var k,T;const{nodeLookup:v,nodeOrigin:_}=r.getState(),S=Yh(x)?x:v.get(x.id),j=S.parentId?cg(S.position,S.measured,S.parentId,v,_):S.position,N={...S,position:j,width:((k=S.measured)==null?void 0:k.width)??S.width,height:((T=S.measured)==null?void 0:T.height)??S.height};return Ro(N)},y=(x,v,_={replace:!1})=>{d(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&Yh(N)?N:{...j,...N}}return j}))},m=(x,v,_={replace:!1})=>{f(S=>S.map(j=>{if(j.id===x){const N=typeof v=="function"?v(j):v;return _.replace&&M_(N)?N:{...j,...N}}return j}))};return{getNodes:()=>r.getState().nodes.map(x=>({...x})),getNode:x=>{var v;return(v=u(x))==null?void 0:v.internals.userNode},getInternalNode:u,getEdges:()=>{const{edges:x=[]}=r.getState();return x.map(v=>({...v}))},getEdge:x=>r.getState().edgeLookup.get(x),setNodes:d,setEdges:f,addNodes:x=>{const v=Array.isArray(x)?x:[x];o.nodeQueue.push(_=>[..._,...v])},addEdges:x=>{const v=Array.isArray(x)?x:[x];o.edgeQueue.push(_=>[..._,...v])},toObject:()=>{const{nodes:x=[],edges:v=[],transform:_}=r.getState(),[S,j,N]=_;return{nodes:x.map(k=>({...k})),edges:v.map(k=>({...k})),viewport:{x:S,y:j,zoom:N}}},deleteElements:async({nodes:x=[],edges:v=[]})=>{const{nodes:_,edges:S,onNodesDelete:j,onEdgesDelete:N,triggerNodeChanges:k,triggerEdgeChanges:T,onDelete:E,onBeforeDelete:b}=r.getState(),{nodes:$,edges:O}=await t1({nodesToRemove:x,edgesToRemove:v,nodes:_,edges:S,onBeforeDelete:b}),H=O.length>0,I=$.length>0;if(H){const q=O.map(Uh);N==null||N(O),T(q)}if(I){const q=$.map(Uh);j==null||j($),k(q)}return(I||H)&&(E==null||E({nodes:$,edges:O})),{deletedNodes:$,deletedEdges:O}},getIntersectingNodes:(x,v=!0,_)=>{const S=yh(x),j=S?x:g(x),N=_!==void 0;return j?(_||r.getState().nodes).filter(k=>{const T=r.getState().nodeLookup.get(k.id);if(T&&!S&&(k.id===x.id||!T.internals.positionAbsolute))return!1;const E=Ro(N?k:T),b=vl(E,j);return v&&b>0||b>=E.width*E.height||b>=j.width*j.height}):[]},isNodeIntersecting:(x,v,_=!0)=>{const j=yh(x)?x:g(x);if(!j)return!1;const N=vl(j,v);return _&&N>0||N>=v.width*v.height||N>=j.width*j.height},updateNode:y,updateNodeData:(x,v,_={replace:!1})=>{y(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},updateEdge:m,updateEdgeData:(x,v,_={replace:!1})=>{m(x,S=>{const j=typeof v=="function"?v(S):v;return _.replace?{...S,data:j}:{...S,data:{...S.data,...j}}},_)},getNodesBounds:x=>{const{nodeLookup:v,nodeOrigin:_}=r.getState();return Kw(x,{nodeLookup:v,nodeOrigin:_})},getHandleConnections:({type:x,id:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}-${x}${v?`-${v}`:""}`))==null?void 0:S.values())??[])},getNodeConnections:({type:x,handleId:v,nodeId:_})=>{var S;return Array.from(((S=r.getState().connectionLookup.get(`${_}${x?v?`-${x}-${v}`:`-${x}`:""}`))==null?void 0:S.values())??[])},fitView:async x=>{const v=r.getState().fitViewResolver??i1();return r.setState({fitViewQueued:!0,fitViewOptions:x,fitViewResolver:v}),o.nodeQueue.push(_=>[..._]),v.promise}}},[]);return F.useMemo(()=>({...a,...t,viewportInitialized:l}),[l])}const Xh=t=>t.selected,L_=typeof window<"u"?window:void 0;function A_({deleteKeyCode:t,multiSelectionKeyCode:r}){const o=We(),{deleteElements:l}=yc(),a=Ao(t,{actInsideInputWithModifier:!1}),u=Ao(r,{target:L_});F.useEffect(()=>{if(a){const{edges:d,nodes:f}=o.getState();l({nodes:f.filter(Xh),edges:d.filter(Xh)}),o.setState({nodesSelectionActive:!1})}},[a]),F.useEffect(()=>{o.setState({multiSelectionActive:u})},[u])}function z_(t){const r=We();F.useEffect(()=>{const o=()=>{var a,u,d,f;if(!t.current||!(((u=(a=t.current).checkVisibility)==null?void 0:u.call(a))??!0))return!1;const l=dc(t.current);(l.height===0||l.width===0)&&((f=(d=r.getState()).onError)==null||f.call(d,"004",sn.error004())),r.setState({width:l.width||500,height:l.height||500})};if(t.current){o(),window.addEventListener("resize",o);const l=new ResizeObserver(()=>o());return l.observe(t.current),()=>{window.removeEventListener("resize",o),l&&t.current&&l.unobserve(t.current)}}},[])}const Tl={position:"absolute",width:"100%",height:"100%",top:0,left:0},D_=t=>({userSelectionActive:t.userSelectionActive,lib:t.lib,connectionInProgress:t.connection.inProgress});function $_({onPaneContextMenu:t,zoomOnScroll:r=!0,zoomOnPinch:o=!0,panOnScroll:l=!1,panActivationKeyPressed:a,panOnScrollSpeed:u=.5,panOnScrollMode:d=$r.Free,zoomOnDoubleClick:f=!0,panOnDrag:g=!0,defaultViewport:y,translateExtent:m,minZoom:x,maxZoom:v,zoomActivationKeyCode:_,preventScrolling:S=!0,children:j,noWheelClassName:N,noPanClassName:k,onViewportChange:T,isControlledViewport:E,paneClickDistance:b,selectionOnDrag:$}){const O=We(),H=F.useRef(null),{userSelectionActive:I,lib:q,connectionInProgress:ne}=Ae(D_,qe),G=Ao(_),ee=F.useRef();z_(H);const J=F.useCallback(C=>{T==null||T({x:C[0],y:C[1],zoom:C[2]}),E||O.setState({transform:C})},[T,E]);return F.useEffect(()=>{if(H.current){ee.current=H1({domNode:H.current,minZoom:x,maxZoom:v,translateExtent:m,viewport:y,onDraggingChange:U=>O.setState(z=>z.paneDragging===U?z:{paneDragging:U}),onPanZoomStart:(U,z)=>{const{onViewportChangeStart:D,onMoveStart:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoom:(U,z)=>{const{onViewportChange:D,onMove:W}=O.getState();W==null||W(U,z),D==null||D(z)},onPanZoomEnd:(U,z)=>{const{onViewportChangeEnd:D,onMoveEnd:W}=O.getState();W==null||W(U,z),D==null||D(z)}});const{x:C,y:Y,zoom:V}=ee.current.getViewport();return O.setState({panZoom:ee.current,transform:[C,Y,V],domNode:H.current.closest(".react-flow")}),()=>{var U;(U=ee.current)==null||U.destroy()}}},[]),F.useEffect(()=>{var C;(C=ee.current)==null||C.update({onPaneContextMenu:t,zoomOnScroll:r,zoomOnPinch:o,panOnScroll:l,panActivationKeyPressed:a,panOnScrollSpeed:u,panOnScrollMode:d,zoomOnDoubleClick:f,panOnDrag:g,zoomActivationKeyPressed:G,preventScrolling:S,noPanClassName:k,userSelectionActive:I,noWheelClassName:N,lib:q,onTransformChange:J,connectionInProgress:ne,selectionOnDrag:$,paneClickDistance:b})},[t,r,o,l,a,u,d,f,g,G,S,k,I,N,q,J,ne,$,b]),p.jsx("div",{className:"react-flow__renderer",ref:H,style:Tl,children:j})}const O_=t=>({userSelectionActive:t.userSelectionActive,userSelectionRect:t.userSelectionRect});function F_(){const{userSelectionActive:t,userSelectionRect:r}=Ae(O_,qe);return t&&r?p.jsx("div",{className:"react-flow__selection react-flow__container",style:{width:r.width,height:r.height,transform:`translate(${r.x}px, ${r.y}px)`}}):null}const zu=(t,r)=>o=>{o.target===r.current&&(t==null||t(o))},H_=t=>({userSelectionActive:t.userSelectionActive,elementsSelectable:t.elementsSelectable,dragging:t.paneDragging,panBy:t.panBy,autoPanSpeed:t.autoPanSpeed});function B_({isSelecting:t,selectionKeyPressed:r,selectionMode:o=Io.Full,panOnDrag:l,autoPanOnSelection:a,paneClickDistance:u,selectionOnDrag:d,onSelectionStart:f,onSelectionEnd:g,onPaneClick:y,onPaneContextMenu:m,onPaneScroll:x,onPaneMouseEnter:v,onPaneMouseMove:_,onPaneMouseLeave:S,children:j}){const N=F.useRef(0),k=We(),{userSelectionActive:T,elementsSelectable:E,dragging:b,panBy:$,autoPanSpeed:O}=Ae(H_,qe),H=E&&(t||T),I=F.useRef(null),q=F.useRef(),ne=F.useRef(new Set),G=F.useRef(new Set),ee=F.useRef(!1),J=F.useRef(!1),C=F.useRef({x:0,y:0}),Y=F.useRef(!1),V=K=>{if(J.current||ee.current||k.getState().connection.inProgress){J.current=!1,ee.current=!1;return}y==null||y(K),k.getState().resetSelectedElements(),k.setState({nodesSelectionActive:!1})},U=K=>{if(Array.isArray(l)&&(l!=null&&l.includes(2))){K.preventDefault();return}m==null||m(K)},z=x?K=>x(K):void 0,D=K=>{J.current&&(K.stopPropagation(),J.current=!1)},W=K=>{var Re,tt;if(K.pointerType==="touch"&&l!==!1&&!r)return;const{domNode:le,transform:pe}=k.getState();if(q.current=le==null?void 0:le.getBoundingClientRect(),!q.current)return;const _e=K.target===I.current;if(!_e&&!!K.target.closest(".nokey")||!t||!(d&&_e||r)||K.button!==0||!K.isPrimary)return;(tt=(Re=K.target)==null?void 0:Re.setPointerCapture)==null||tt.call(Re,K.pointerId),J.current=!1;const{x:je,y:Pe}=on(K.nativeEvent,q.current),Ie=Bo({x:je,y:Pe},pe);k.setState({userSelectionRect:{width:0,height:0,startX:Ie.x,startY:Ie.y,x:je,y:Pe}}),_e||(K.stopPropagation(),K.preventDefault())};function M(K,le){const{userSelectionRect:pe}=k.getState();if(!pe)return;const{transform:_e,nodeLookup:xe,edgeLookup:ge,connectionLookup:je,triggerNodeChanges:Pe,triggerEdgeChanges:Ie,defaultEdgeOptions:Re}=k.getState(),tt={x:pe.startX,y:pe.startY},{x:nt,y:Qe}=Ri(tt,_e),ot={startX:tt.x,startY:tt.y,x:Kze.id)),G.current=new Set;const Ke=(Re==null?void 0:Re.selectable)??!0;for(const ze of ne.current){const gt=je.get(ze);if(gt)for(const{edgeId:ft}of gt.values()){const Je=ge.get(ft);Je&&(Je.selectable??Ke)&&G.current.add(ft)}}if(!vh(at,ne.current)){const ze=ji(xe,ne.current,!0);Pe(ze)}if(!vh(It,G.current)){const ze=ji(ge,G.current);Ie(ze)}k.setState({userSelectionRect:ot,userSelectionActive:!0,nodesSelectionActive:!1})}function R(){if(!a||!q.current)return;const[K,le]=uc(C.current,q.current,O);$({x:K,y:le}).then(pe=>{if(!J.current||!pe){N.current=requestAnimationFrame(R);return}const{x:_e,y:xe}=C.current;M(_e,xe),N.current=requestAnimationFrame(R)})}const re=()=>{cancelAnimationFrame(N.current),N.current=0,Y.current=!1};F.useEffect(()=>()=>re(),[]);const ie=K=>{const{userSelectionRect:le,transform:pe,resetSelectedElements:_e}=k.getState();if(!q.current||!le)return;const{x:xe,y:ge}=on(K.nativeEvent,q.current);C.current={x:xe,y:ge};const je=Ri({x:le.startX,y:le.startY},pe);if(!J.current){const Pe=r?0:u;if(Math.hypot(xe-je.x,ge-je.y)<=Pe)return;_e(),f==null||f(K)}J.current=!0,Y.current||(R(),Y.current=!0),M(xe,ge)},ce=K=>{var le,pe;if(!H){K.target===I.current&&k.getState().connection.inProgress&&(ee.current=!0);return}K.button===0&&((pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),!T&&K.target===I.current&&k.getState().userSelectionRect&&(V==null||V(K)),k.setState({userSelectionActive:!1,userSelectionRect:null}),J.current&&(g==null||g(K),k.setState({nodesSelectionActive:ne.current.size>0})),re())},fe=K=>{var le,pe;(pe=(le=K.target)==null?void 0:le.releasePointerCapture)==null||pe.call(le,K.pointerId),re()},de=l===!0||Array.isArray(l)&&l.includes(0);return p.jsxs("div",{className:it(["react-flow__pane",{draggable:de,dragging:b,selection:t}]),onClick:H?void 0:zu(V,I),onContextMenu:zu(U,I),onWheel:zu(z,I),onPointerEnter:H?void 0:v,onPointerMove:H?ie:_,onPointerUp:ce,onPointerCancel:H?fe:void 0,onPointerDownCapture:H?W:void 0,onClickCapture:H?D:void 0,onPointerLeave:S,ref:I,style:Tl,children:[j,p.jsx(F_,{})]})}function Ju({id:t,store:r,unselect:o=!1,nodeRef:l}){const{addSelectedNodes:a,unselectNodesAndEdges:u,multiSelectionActive:d,nodeLookup:f,onError:g}=r.getState(),y=f.get(t);if(!y){g==null||g("012",sn.error012(t));return}r.setState({nodesSelectionActive:!1}),y.selected?(o||y.selected&&d)&&(u({nodes:[y],edges:[]}),requestAnimationFrame(()=>{var m;return(m=l==null?void 0:l.current)==null?void 0:m.blur()})):a([t])}function $g({nodeRef:t,disabled:r=!1,noDragClassName:o,handleSelector:l,nodeId:a,isSelectable:u,nodeClickDistance:d}){const f=We(),[g,y]=F.useState(!1),m=F.useRef();return F.useEffect(()=>{if(!r)return m.current=b1({getStoreItems:()=>f.getState(),onNodeMouseDown:x=>{Ju({id:x,store:f,nodeRef:t})},onDragStart:()=>{y(!0)},onDragStop:()=>{y(!1)}}),()=>{var x;(x=m.current)==null||x.destroy(),m.current=void 0}},[r,f,t]),F.useEffect(()=>{r||!t.current||!m.current||m.current.update({noDragClassName:o,handleSelector:l,domNode:t.current,isSelectable:u,nodeId:a,nodeClickDistance:d})},[o,l,r,u,t,a,d]),g}const V_=t=>r=>r.selected&&(r.draggable||t&&typeof r.draggable>"u");function Og(){const t=We();return F.useCallback(o=>{const{nodeExtent:l,snapToGrid:a,snapGrid:u,nodesDraggable:d,onError:f,updateNodePositions:g,nodeLookup:y,nodeOrigin:m}=t.getState(),x=new Map,v=V_(d),_=a?u[0]:5,S=a?u[1]:5,j=o.direction.x*_*o.factor,N=o.direction.y*S*o.factor;for(const[,k]of y){if(!v(k))continue;let T={x:k.internals.positionAbsolute.x+j,y:k.internals.positionAbsolute.y+N};a&&(T=Ho(T,u));const{position:E,positionAbsolute:b}=ig({nodeId:k.id,nextPosition:T,nodeLookup:y,nodeExtent:l,nodeOrigin:m,onError:f});k.position=E,k.internals.positionAbsolute=b,x.set(k.id,k)}g(x)},[])}const vc=F.createContext(null),W_=vc.Provider;vc.Consumer;const Fg=()=>F.useContext(vc),U_=t=>({connectOnClick:t.connectOnClick,noPanClassName:t.noPanClassName,rfId:t.rfId}),Hg=F.createContext(null);function Y_({children:t}){const r=Ae(U_,qe);return p.jsx(Hg.Provider,{value:r,children:t})}function G_(){const t=F.useContext(Hg);if(!t)throw new Error("useHandleConfig must be used within a HandleConfigProvider");return t}const X_={connectingFrom:!1,connectingTo:!1,clickConnecting:!1,isPossibleEndHandle:!0,connectionInProcess:!1,clickConnectionInProcess:!1,valid:!1},q_=(t,r,o)=>l=>{const{connectionClickStartHandle:a,connectionMode:u,connection:d}=l,{fromHandle:f,toHandle:g,isValid:y}=d;if(!f&&!a)return X_;const m=(g==null?void 0:g.nodeId)===t&&(g==null?void 0:g.id)===r&&(g==null?void 0:g.type)===o;return{connectingFrom:(f==null?void 0:f.nodeId)===t&&(f==null?void 0:f.id)===r&&(f==null?void 0:f.type)===o,connectingTo:m,clickConnecting:(a==null?void 0:a.nodeId)===t&&(a==null?void 0:a.id)===r&&(a==null?void 0:a.type)===o,isPossibleEndHandle:u===Ii.Strict?(f==null?void 0:f.type)!==o:t!==(f==null?void 0:f.nodeId)||r!==(f==null?void 0:f.id),connectionInProcess:!!f,clickConnectionInProcess:!!a,valid:m&&y}};function Q_({type:t="source",position:r=Se.Top,isValidConnection:o,isConnectable:l=!0,isConnectableStart:a=!0,isConnectableEnd:u=!0,id:d,onConnect:f,children:g,className:y,onMouseDown:m,onTouchStart:x,...v},_){var Y,V;const S=d||null,j=t==="target",N=We(),k=Fg(),{connectOnClick:T,noPanClassName:E,rfId:b}=G_(),{connectingFrom:$,connectingTo:O,clickConnecting:H,isPossibleEndHandle:I,connectionInProcess:q,clickConnectionInProcess:ne,valid:G}=Ae(q_(k,S,t),qe);k||(V=(Y=N.getState()).onError)==null||V.call(Y,"010",sn.error010());const ee=U=>{const{defaultEdgeOptions:z,onConnect:D,hasDefaultEdges:W}=N.getState(),M={...z,...U};if(W){const{edges:R,setEdges:re,onError:ie}=N.getState();re(C_(M,R,{onError:ie}))}D==null||D(M),f==null||f(M)},J=U=>{if(!k)return;const z=hg(U.nativeEvent);if(a&&(z&&U.button===0||!z)){const D=N.getState();Zu.onPointerDown(U.nativeEvent,{handleDomNode:U.currentTarget,autoPanOnConnect:D.autoPanOnConnect,connectionMode:D.connectionMode,connectionRadius:D.connectionRadius,domNode:D.domNode,nodeLookup:D.nodeLookup,lib:D.lib,isTarget:j,handleId:S,nodeId:k,flowId:D.rfId,panBy:D.panBy,cancelConnection:D.cancelConnection,onConnectStart:D.onConnectStart,onConnectEnd:(...W)=>{var M,R;return(R=(M=N.getState()).onConnectEnd)==null?void 0:R.call(M,...W)},updateConnection:D.updateConnection,onConnect:ee,isValidConnection:o||((...W)=>{var M,R;return((R=(M=N.getState()).isValidConnection)==null?void 0:R.call(M,...W))??!0}),getTransform:()=>N.getState().transform,getFromHandle:()=>N.getState().connection.fromHandle,autoPanSpeed:D.autoPanSpeed,dragThreshold:D.connectionDragThreshold})}z?m==null||m(U):x==null||x(U)},C=U=>{const{onClickConnectStart:z,onClickConnectEnd:D,connectionClickStartHandle:W,connectionMode:M,isValidConnection:R,lib:re,rfId:ie,nodeLookup:ce,connection:fe}=N.getState();if(!k||!W&&!a)return;if(!W){z==null||z(U.nativeEvent,{nodeId:k,handleId:S,handleType:t}),N.setState({connectionClickStartHandle:{nodeId:k,type:t,id:S}});return}const de=dg(U.target),K=o||R,{connection:le,isValid:pe}=Zu.isValid(U.nativeEvent,{handle:{nodeId:k,id:S,type:t},connectionMode:M,fromNodeId:W.nodeId,fromHandleId:W.id||null,fromType:W.type,isValidConnection:K,flowId:ie,doc:de,lib:re,nodeLookup:ce});pe&&le&&ee(le);const _e=structuredClone(fe);delete _e.inProgress,_e.toPosition=_e.toHandle?_e.toHandle.position:null,D==null||D(U,_e),N.setState({connectionClickStartHandle:null})};return p.jsx("div",{"data-handleid":S,"data-nodeid":k,"data-handlepos":r,"data-id":`${b}-${k}-${S}-${t}`,className:it(["react-flow__handle",`react-flow__handle-${r}`,"nodrag",E,y,{source:!j,target:j,connectable:l,connectablestart:a,connectableend:u,clickconnecting:H,connectingfrom:$,connectingto:O,valid:G,connectionindicator:l&&(!q||I)&&(q||ne?u:a)}]),onMouseDown:J,onTouchStart:J,onClick:T?C:void 0,ref:_,...v,children:g})}const Ai=F.memo(Ag(Q_));function K_({data:t,isConnectable:r,sourcePosition:o=Se.Bottom}){return p.jsxs(p.Fragment,{children:[t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:o,isConnectable:r})]})}function Z_({data:t,isConnectable:r,targetPosition:o=Se.Top,sourcePosition:l=Se.Bottom}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label,p.jsx(Ai,{type:"source",position:l,isConnectable:r})]})}function J_(){return null}function eS({data:t,isConnectable:r,targetPosition:o=Se.Top}){return p.jsxs(p.Fragment,{children:[p.jsx(Ai,{type:"target",position:o,isConnectable:r}),t==null?void 0:t.label]})}const xl={ArrowUp:{x:0,y:-1},ArrowDown:{x:0,y:1},ArrowLeft:{x:-1,y:0},ArrowRight:{x:1,y:0}},qh={input:K_,default:Z_,output:eS,group:J_};function tS(t){var r,o,l,a;return t.internals.handleBounds===void 0?{width:t.width??t.initialWidth??((r=t.style)==null?void 0:r.width),height:t.height??t.initialHeight??((o=t.style)==null?void 0:o.height)}:{width:t.width??((l=t.style)==null?void 0:l.width),height:t.height??((a=t.style)==null?void 0:a.height)}}const nS=t=>{const{width:r,height:o,x:l,y:a}=Fo(t.nodeLookup,{filter:u=>!!u.selected});return{width:rn(r)?r:null,height:rn(o)?o:null,userSelectionActive:t.userSelectionActive,transformString:`translate(${t.transform[0]}px,${t.transform[1]}px) scale(${t.transform[2]}) translate(${l}px,${a}px)`}};function rS({onSelectionContextMenu:t,noPanClassName:r,disableKeyboardA11y:o}){const l=We(),{width:a,height:u,transformString:d,userSelectionActive:f}=Ae(nS,qe),g=Og(),y=F.useRef(null);F.useEffect(()=>{var _;o||(_=y.current)==null||_.focus({preventScroll:!0})},[o]);const m=!f&&a!==null&&u!==null;if($g({nodeRef:y,disabled:!m}),!m)return null;const x=t?_=>{const S=l.getState().nodes.filter(j=>j.selected);t(_,S)}:void 0,v=_=>{Object.prototype.hasOwnProperty.call(xl,_.key)&&(_.preventDefault(),g({direction:xl[_.key],factor:_.shiftKey?4:1}))};return p.jsx("div",{className:it(["react-flow__nodesselection","react-flow__container",r]),style:{transform:d},children:p.jsx("div",{ref:y,className:"react-flow__nodesselection-rect",onContextMenu:x,tabIndex:o?void 0:-1,onKeyDown:o?void 0:v,style:{width:a,height:u}})})}const Qh=typeof window<"u"?window:void 0,iS=t=>({nodesSelectionActive:t.nodesSelectionActive,userSelectionActive:t.userSelectionActive});function Bg({children:t,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,paneClickDistance:f,deleteKeyCode:g,selectionKeyCode:y,selectionOnDrag:m,selectionMode:x,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:S,panActivationKeyCode:j,zoomActivationKeyCode:N,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:b,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:I,autoPanOnSelection:q,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,preventScrolling:C,onSelectionContextMenu:Y,noWheelClassName:V,noPanClassName:U,disableKeyboardA11y:z,onViewportChange:D,isControlledViewport:W}){const{nodesSelectionActive:M,userSelectionActive:R}=Ae(iS,qe),re=Ao(y,{target:Qh}),ie=Ao(j,{target:Qh}),ce=ie||I,fe=ie||b,de=m&&ce!==!0,K=re||R||de;return A_({deleteKeyCode:g,multiSelectionKeyCode:S}),p.jsx($_,{onPaneContextMenu:u,elementsSelectable:k,zoomOnScroll:T,zoomOnPinch:E,panOnScroll:fe,panActivationKeyPressed:ie,panOnScrollSpeed:$,panOnScrollMode:O,zoomOnDoubleClick:H,panOnDrag:!re&&ce,defaultViewport:ne,translateExtent:G,minZoom:ee,maxZoom:J,zoomActivationKeyCode:N,preventScrolling:C,noWheelClassName:V,noPanClassName:U,onViewportChange:D,isControlledViewport:W,paneClickDistance:f,selectionOnDrag:de,children:p.jsxs(B_,{onSelectionStart:v,onSelectionEnd:_,onPaneClick:r,onPaneMouseEnter:o,onPaneMouseMove:l,onPaneMouseLeave:a,onPaneContextMenu:u,onPaneScroll:d,panOnDrag:ce,autoPanOnSelection:q,isSelecting:!!K,selectionMode:x,selectionKeyPressed:re,paneClickDistance:f,selectionOnDrag:de,children:[t,M&&p.jsx(rS,{onSelectionContextMenu:Y,noPanClassName:U,disableKeyboardA11y:z})]})})}Bg.displayName="FlowRenderer";const oS=F.memo(Bg),sS=t=>r=>t?ac(r.nodeLookup,{x:0,y:0,width:r.width,height:r.height},r.transform,!0).map(o=>o.id):Array.from(r.nodeLookup.keys());function lS(t){return Ae(F.useCallback(sS(t),[t]),qe)}const aS=t=>t.updateNodeInternals;function uS(){const t=Ae(aS),[r]=F.useState(()=>typeof ResizeObserver>"u"?null:new ResizeObserver(o=>{const l=new Map;o.forEach(a=>{const u=a.target.getAttribute("data-id");l.set(u,{id:u,nodeElement:a.target,force:!0})}),t(l)}));return F.useEffect(()=>()=>{r==null||r.disconnect()},[r]),r}function cS({node:t,nodeType:r,hasDimensions:o,resizeObserver:l}){const a=We(),u=F.useRef(null),d=F.useRef(null),f=F.useRef(t.sourcePosition),g=F.useRef(t.targetPosition),y=F.useRef(r),m=o&&!!t.internals.handleBounds;return F.useEffect(()=>{u.current&&!t.hidden&&(!m||d.current!==u.current)&&(d.current&&(l==null||l.unobserve(d.current)),l==null||l.observe(u.current),d.current=u.current)},[m,t.hidden]),F.useEffect(()=>()=>{d.current&&(l==null||l.unobserve(d.current),d.current=null)},[]),F.useEffect(()=>{if(u.current){const x=y.current!==r,v=f.current!==t.sourcePosition,_=g.current!==t.targetPosition;(x||v||_)&&(y.current=r,f.current=t.sourcePosition,g.current=t.targetPosition,a.getState().updateNodeInternals(new Map([[t.id,{id:t.id,nodeElement:u.current,force:!0}]])))}},[t.id,r,t.sourcePosition,t.targetPosition]),u}function dS({id:t,onClick:r,onMouseEnter:o,onMouseMove:l,onMouseLeave:a,onContextMenu:u,onDoubleClick:d,nodesDraggable:f,elementsSelectable:g,nodesConnectable:y,nodesFocusable:m,resizeObserver:x,noDragClassName:v,noPanClassName:_,disableKeyboardA11y:S,rfId:j,nodeTypes:N,nodeClickDistance:k,onError:T}){const{node:E,internals:b,isParent:$}=Ae(K=>{const le=K.nodeLookup.get(t),pe=K.parentLookup.has(t);return{node:le,internals:le.internals,isParent:pe}},qe);let O=E.type||"default",H=(N==null?void 0:N[O])||qh[O];H===void 0&&(T==null||T("003",sn.error003(O)),O="default",H=(N==null?void 0:N.default)||qh.default);const I=!!(E.draggable||f&&typeof E.draggable>"u"),q=!!(E.selectable||g&&typeof E.selectable>"u"),ne=!!(E.connectable||y&&typeof E.connectable>"u"),G=!!(E.focusable||m&&typeof E.focusable>"u"),ee=We(),J=ug(E),C=cS({node:E,nodeType:O,hasDimensions:J,resizeObserver:x}),Y=$g({nodeRef:C,disabled:E.hidden||!I,noDragClassName:v,handleSelector:E.dragHandle,nodeId:t,isSelectable:q,nodeClickDistance:k}),V=Og();if(E.hidden)return null;const U=an(E),z=tS(E),D=q||I||r||o||l||a,W=o?K=>o(K,{...b.userNode}):void 0,M=l?K=>l(K,{...b.userNode}):void 0,R=a?K=>a(K,{...b.userNode}):void 0,re=u?K=>u(K,{...b.userNode}):void 0,ie=d?K=>d(K,{...b.userNode}):void 0,ce=K=>{const{selectNodesOnDrag:le,nodeDragThreshold:pe}=ee.getState();q&&(!le||!I||pe>0)&&Ju({id:t,store:ee,nodeRef:C}),r&&r(K,{...b.userNode})},fe=K=>{if(!(fg(K.nativeEvent)||S)){if(Jp.includes(K.key)&&q){const le=K.key==="Escape";Ju({id:t,store:ee,unselect:le,nodeRef:C})}else if(I&&E.selected&&Object.prototype.hasOwnProperty.call(xl,K.key)){K.preventDefault();const{ariaLabelConfig:le}=ee.getState();ee.setState({ariaLiveMessage:le["node.a11yDescription.ariaLiveMessage"]({direction:K.key.replace("Arrow","").toLowerCase(),x:~~b.positionAbsolute.x,y:~~b.positionAbsolute.y})}),V({direction:xl[K.key],factor:K.shiftKey?4:1})}}},de=()=>{var je;if(S||!((je=C.current)!=null&&je.matches(":focus-visible")))return;const{transform:K,width:le,height:pe,autoPanOnNodeFocus:_e,setCenter:xe}=ee.getState();if(!_e)return;ac(new Map([[t,E]]),{x:0,y:0,width:le,height:pe},K,!0).length>0||xe(E.position.x+U.width/2,E.position.y+U.height/2,{zoom:K[2]})};return p.jsx("div",{className:it(["react-flow__node",`react-flow__node-${O}`,{[_]:I},E.className,{selected:E.selected,selectable:q,parent:$,draggable:I,dragging:Y}]),ref:C,style:{zIndex:b.z,transform:`translate(${b.positionAbsolute.x}px,${b.positionAbsolute.y}px)`,pointerEvents:D?"all":"none",visibility:J?"visible":"hidden",...E.style,...z},"data-id":t,"data-testid":`rf__node-${t}`,onMouseEnter:W,onMouseMove:M,onMouseLeave:R,onContextMenu:re,onClick:ce,onDoubleClick:ie,onKeyDown:G?fe:void 0,tabIndex:G?0:void 0,onFocus:G?de:void 0,role:E.ariaRole??(G?"group":void 0),"aria-roledescription":"node","aria-describedby":S?void 0:`${Ig}-${j}`,"aria-label":E.ariaLabel,...E.domAttributes,children:p.jsx(W_,{value:t,children:p.jsx(H,{id:t,data:E.data,type:O,positionAbsoluteX:b.positionAbsolute.x,positionAbsoluteY:b.positionAbsolute.y,selected:E.selected??!1,selectable:q,draggable:I,deletable:E.deletable??!0,isConnectable:ne,sourcePosition:E.sourcePosition,targetPosition:E.targetPosition,dragging:Y,dragHandle:E.dragHandle,zIndex:b.z,parentId:E.parentId,...U})})})}var fS=F.memo(dS);const hS=t=>({nodesConnectable:t.nodesConnectable,nodesFocusable:t.nodesFocusable,elementsSelectable:t.elementsSelectable,onError:t.onError});function Vg(t){const{nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,onError:a}=Ae(hS,qe),u=lS(t.onlyRenderVisibleElements),d=uS();return p.jsx("div",{className:"react-flow__nodes",style:Tl,children:u.map(f=>p.jsx(fS,{id:f,nodeTypes:t.nodeTypes,nodeExtent:t.nodeExtent,onClick:t.onNodeClick,onMouseEnter:t.onNodeMouseEnter,onMouseMove:t.onNodeMouseMove,onMouseLeave:t.onNodeMouseLeave,onContextMenu:t.onNodeContextMenu,onDoubleClick:t.onNodeDoubleClick,noDragClassName:t.noDragClassName,noPanClassName:t.noPanClassName,rfId:t.rfId,disableKeyboardA11y:t.disableKeyboardA11y,resizeObserver:d,nodesDraggable:t.nodesDraggable??!0,nodesConnectable:r,nodesFocusable:o,elementsSelectable:l,nodeClickDistance:t.nodeClickDistance,onError:a},f))})}Vg.displayName="NodeRenderer";const pS=F.memo(Vg);function gS(t){return Ae(F.useCallback(o=>{if(!t)return o.edges.map(a=>a.id);const l=[];if(o.width&&o.height)for(const a of o.edges){const u=o.nodeLookup.get(a.source),d=o.nodeLookup.get(a.target);u&&d&&a1({sourceNode:u,targetNode:d,width:o.width,height:o.height,transform:o.transform})&&l.push(a.id)}return l},[t]),qe)}const mS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t}};return p.jsx("polyline",{className:"arrow",style:o,strokeLinecap:"round",fill:"none",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4"})},yS=({color:t="none",strokeWidth:r=1})=>{const o={strokeWidth:r,...t&&{stroke:t,fill:t}};return p.jsx("polyline",{className:"arrowclosed",style:o,strokeLinecap:"round",strokeLinejoin:"round",points:"-5,-4 0,0 -5,4 -5,-4"})},Kh={[To.Arrow]:mS,[To.ArrowClosed]:yS};function vS(t){const r=We();return F.useMemo(()=>{var a,u;return Object.prototype.hasOwnProperty.call(Kh,t)?Kh[t]:((u=(a=r.getState()).onError)==null||u.call(a,"009",sn.error009(t)),null)},[t])}const xS=({id:t,type:r,color:o,width:l=12.5,height:a=12.5,markerUnits:u="strokeWidth",strokeWidth:d,orient:f="auto-start-reverse"})=>{const g=vS(r);return g?p.jsx("marker",{className:"react-flow__arrowhead",id:t,markerWidth:`${l}`,markerHeight:`${a}`,viewBox:"-10 -10 20 20",markerUnits:u,orient:f,refX:"0",refY:"0",children:p.jsx(g,{color:o,strokeWidth:d})}):null},Wg=({defaultColor:t,rfId:r})=>{const o=Ae(u=>u.edges),l=Ae(u=>u.defaultEdgeOptions),a=F.useMemo(()=>m1(o,{id:r,defaultColor:t,defaultMarkerStart:l==null?void 0:l.markerStart,defaultMarkerEnd:l==null?void 0:l.markerEnd}),[o,l,r,t]);return a.length?p.jsx("svg",{className:"react-flow__marker","aria-hidden":"true",children:p.jsx("defs",{children:a.map(u=>p.jsx(xS,{id:u.id,type:u.type,color:u.color,width:u.width,height:u.height,markerUnits:u.markerUnits,strokeWidth:u.strokeWidth,orient:u.orient},u.id))})}):null};Wg.displayName="MarkerDefinitions";var wS=F.memo(Wg);function Ug({x:t,y:r,label:o,labelStyle:l,labelShowBg:a=!0,labelBgStyle:u,labelBgPadding:d=[2,4],labelBgBorderRadius:f=2,children:g,className:y,...m}){const[x,v]=F.useState({x:1,y:0,width:0,height:0}),_=it(["react-flow__edge-textwrapper",y]),S=F.useRef(null);return F.useEffect(()=>{if(S.current){const j=S.current.getBBox();v({x:j.x,y:j.y,width:j.width,height:j.height})}},[o]),o?p.jsxs("g",{transform:`translate(${t-x.width/2} ${r-x.height/2})`,className:_,visibility:x.width?"visible":"hidden",...m,children:[a&&p.jsx("rect",{width:x.width+2*d[0],x:-d[0],y:-d[1],height:x.height+2*d[1],className:"react-flow__edge-textbg",style:u,rx:f,ry:f}),p.jsx("text",{className:"react-flow__edge-text",y:x.height/2,dy:"0.3em",ref:S,style:l,children:o}),g]}):null}Ug.displayName="EdgeText";const _S=F.memo(Ug);function Rl({path:t,labelX:r,labelY:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g,interactionWidth:y=20,...m}){return p.jsxs(p.Fragment,{children:[p.jsx("path",{...m,d:t,fill:"none",className:it(["react-flow__edge-path",m.className])}),y?p.jsx("path",{d:t,fill:"none",strokeOpacity:0,strokeWidth:y,className:"react-flow__edge-interaction"}):null,l&&rn(r)&&rn(o)?p.jsx(_S,{x:r,y:o,label:l,labelStyle:a,labelShowBg:u,labelBgStyle:d,labelBgPadding:f,labelBgBorderRadius:g}):null]})}function Zh({pos:t,x1:r,y1:o,x2:l,y2:a}){return t===Se.Left||t===Se.Right?[.5*(r+l),o]:[r,.5*(o+a)]}function Yg({sourceX:t,sourceY:r,sourcePosition:o=Se.Bottom,targetX:l,targetY:a,targetPosition:u=Se.Top}){const[d,f]=Zh({pos:o,x1:t,y1:r,x2:l,y2:a}),[g,y]=Zh({pos:u,x1:l,y1:a,x2:t,y2:r}),[m,x,v,_]=pg({sourceX:t,sourceY:r,targetX:l,targetY:a,sourceControlX:d,sourceControlY:f,targetControlX:g,targetControlY:y});return[`M${t},${r} C${d},${f} ${g},${y} ${l},${a}`,m,x,v,_]}function Gg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d,targetPosition:f,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})=>{const[T,E,b]=Yg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f}),$=t.isInternal?void 0:r;return p.jsx(Rl,{id:$,path:T,labelX:E,labelY:b,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:k})})}const SS=Gg({isInternal:!1}),Xg=Gg({isInternal:!0});SS.displayName="SimpleBezierEdge";Xg.displayName="SimpleBezierEdgeInternal";function qg(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,sourcePosition:_=Se.Bottom,targetPosition:S=Se.Top,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=qu({sourceX:o,sourceY:l,sourcePosition:_,targetX:a,targetY:u,targetPosition:S,borderRadius:k==null?void 0:k.borderRadius,offset:k==null?void 0:k.offset,stepPosition:k==null?void 0:k.stepPosition}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:j,markerStart:N,interactionWidth:T})})}const Qg=qg({isInternal:!1}),Kg=qg({isInternal:!0});Qg.displayName="SmoothStepEdge";Kg.displayName="SmoothStepEdgeInternal";function Zg(t){return F.memo(({id:r,...o})=>{var a;const l=t.isInternal?void 0:r;return p.jsx(Qg,{...o,id:l,pathOptions:F.useMemo(()=>{var u;return{borderRadius:0,offset:(u=o.pathOptions)==null?void 0:u.offset}},[(a=o.pathOptions)==null?void 0:a.offset])})})}const kS=Zg({isInternal:!1}),Jg=Zg({isInternal:!0});kS.displayName="StepEdge";Jg.displayName="StepEdgeInternal";function em(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})=>{const[N,k,T]=yg({sourceX:o,sourceY:l,targetX:a,targetY:u}),E=t.isInternal?void 0:r;return p.jsx(Rl,{id:E,path:N,labelX:k,labelY:T,label:d,labelStyle:f,labelShowBg:g,labelBgStyle:y,labelBgPadding:m,labelBgBorderRadius:x,style:v,markerEnd:_,markerStart:S,interactionWidth:j})})}const ES=em({isInternal:!1}),tm=em({isInternal:!0});ES.displayName="StraightEdge";tm.displayName="StraightEdgeInternal";function nm(t){return F.memo(({id:r,sourceX:o,sourceY:l,targetX:a,targetY:u,sourcePosition:d=Se.Bottom,targetPosition:f=Se.Top,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,pathOptions:k,interactionWidth:T})=>{const[E,b,$]=gg({sourceX:o,sourceY:l,sourcePosition:d,targetX:a,targetY:u,targetPosition:f,curvature:k==null?void 0:k.curvature}),O=t.isInternal?void 0:r;return p.jsx(Rl,{id:O,path:E,labelX:b,labelY:$,label:g,labelStyle:y,labelShowBg:m,labelBgStyle:x,labelBgPadding:v,labelBgBorderRadius:_,style:S,markerEnd:j,markerStart:N,interactionWidth:T})})}const NS=nm({isInternal:!1}),rm=nm({isInternal:!0});NS.displayName="BezierEdge";rm.displayName="BezierEdgeInternal";const Jh={default:rm,straight:tm,step:Jg,smoothstep:Kg,simplebezier:Xg},ep={sourceX:null,sourceY:null,targetX:null,targetY:null,sourcePosition:null,targetPosition:null,zIndex:void 0},jS=(t,r,o)=>o===Se.Left?t-r:o===Se.Right?t+r:t,bS=(t,r,o)=>o===Se.Top?t-r:o===Se.Bottom?t+r:t,tp="react-flow__edgeupdater";function np({position:t,centerX:r,centerY:o,radius:l=10,onMouseDown:a,onMouseEnter:u,onMouseOut:d,type:f}){return p.jsx("circle",{onMouseDown:a,onMouseEnter:u,onMouseOut:d,className:it([tp,`${tp}-${f}`]),cx:jS(r,l,t),cy:bS(o,l,t),r:l,stroke:"transparent",fill:"transparent"})}function CS({isReconnectable:t,reconnectRadius:r,edge:o,sourceX:l,sourceY:a,targetX:u,targetY:d,sourcePosition:f,targetPosition:g,onReconnect:y,onReconnectStart:m,onReconnectEnd:x,setReconnecting:v,setUpdateHover:_}){const S=We(),j=(b,$)=>{if(b.button!==0)return;const{autoPanOnConnect:O,domNode:H,connectionMode:I,connectionRadius:q,lib:ne,onConnectStart:G,cancelConnection:ee,nodeLookup:J,rfId:C,panBy:Y,updateConnection:V}=S.getState(),U=$.type==="target",z=(M,R)=>{v(!1),x==null||x(M,o,$.type,R)},D=M=>y==null?void 0:y(o,M),W=(M,R)=>{v(!0),m==null||m(b,o,$.type),G==null||G(M,R)};Zu.onPointerDown(b.nativeEvent,{autoPanOnConnect:O,connectionMode:I,connectionRadius:q,domNode:H,handleId:$.id,nodeId:$.nodeId,nodeLookup:J,isTarget:U,edgeUpdaterType:$.type,lib:ne,flowId:C,cancelConnection:ee,panBy:Y,isValidConnection:(...M)=>{var R,re;return((re=(R=S.getState()).isValidConnection)==null?void 0:re.call(R,...M))??!0},onConnect:D,onConnectStart:W,onConnectEnd:(...M)=>{var R,re;return(re=(R=S.getState()).onConnectEnd)==null?void 0:re.call(R,...M)},onReconnectEnd:z,updateConnection:V,getTransform:()=>S.getState().transform,getFromHandle:()=>S.getState().connection.fromHandle,dragThreshold:S.getState().connectionDragThreshold,handleDomNode:b.currentTarget})},N=b=>j(b,{nodeId:o.target,id:o.targetHandle??null,type:"target"}),k=b=>j(b,{nodeId:o.source,id:o.sourceHandle??null,type:"source"}),T=()=>_(!0),E=()=>_(!1);return p.jsxs(p.Fragment,{children:[(t===!0||t==="source")&&p.jsx(np,{position:f,centerX:l,centerY:a,radius:r,onMouseDown:N,onMouseEnter:T,onMouseOut:E,type:"source"}),(t===!0||t==="target")&&p.jsx(np,{position:g,centerX:u,centerY:d,radius:r,onMouseDown:k,onMouseEnter:T,onMouseOut:E,type:"target"})]})}function MS({id:t,edgesFocusable:r,edgesReconnectable:o,elementsSelectable:l,onClick:a,onDoubleClick:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,rfId:S,edgeTypes:j,noPanClassName:N,onError:k,disableKeyboardA11y:T}){let E=Ae(xe=>xe.edgeLookup.get(t));const b=Ae(xe=>xe.defaultEdgeOptions);E=b?{...b,...E}:E;let $=E.type||"default",O=(j==null?void 0:j[$])||Jh[$];O===void 0&&(k==null||k("011",sn.error011($)),$="default",O=(j==null?void 0:j.default)||Jh.default);const H=!!(E.focusable||r&&typeof E.focusable>"u"),I=typeof x<"u"&&(E.reconnectable||o&&typeof E.reconnectable>"u"),q=!!(E.selectable||l&&typeof E.selectable>"u"),ne=F.useRef(null),[G,ee]=F.useState(!1),[J,C]=F.useState(!1),Y=We(),{zIndex:V=E.zIndex,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R}=Ae(F.useCallback(xe=>{const ge=xe.nodeLookup.get(E.source),je=xe.nodeLookup.get(E.target);if(!ge||!je)return ep;const Pe=g1({id:t,sourceNode:ge,targetNode:je,sourceHandle:E.sourceHandle||null,targetHandle:E.targetHandle||null,connectionMode:xe.connectionMode,onError:k}),Ie=l1({selected:E.selected,zIndex:E.zIndex,sourceNode:ge,targetNode:je,elevateOnSelect:xe.elevateEdgesOnSelect,zIndexMode:xe.zIndexMode});return{...Pe||ep,zIndex:Ie}},[E.source,E.target,E.sourceHandle,E.targetHandle,E.selected,E.zIndex,k]),qe),re=F.useMemo(()=>E.markerStart?`url('#${Qu(E.markerStart,S)}')`:void 0,[E.markerStart,S]),ie=F.useMemo(()=>E.markerEnd?`url('#${Qu(E.markerEnd,S)}')`:void 0,[E.markerEnd,S]);if(E.hidden||U===null||z===null||D===null||W===null)return null;const ce=xe=>{var Ie;const{addSelectedEdges:ge,unselectNodesAndEdges:je,multiSelectionActive:Pe}=Y.getState();q&&(Y.setState({nodesSelectionActive:!1}),E.selected&&Pe?(je({nodes:[],edges:[E]}),(Ie=ne.current)==null||Ie.blur()):ge([t])),a&&a(xe,E)},fe=u?xe=>{u(xe,{...E})}:void 0,de=d?xe=>{d(xe,{...E})}:void 0,K=f?xe=>{f(xe,{...E})}:void 0,le=g?xe=>{g(xe,{...E})}:void 0,pe=y?xe=>{y(xe,{...E})}:void 0,_e=xe=>{var ge;if(!T&&Jp.includes(xe.key)&&q){const{unselectNodesAndEdges:je,addSelectedEdges:Pe}=Y.getState();xe.key==="Escape"?((ge=ne.current)==null||ge.blur(),je({edges:[E]})):Pe([t])}};return p.jsx("svg",{style:{zIndex:V},children:p.jsxs("g",{className:it(["react-flow__edge",`react-flow__edge-${$}`,E.className,N,{selected:E.selected,animated:E.animated,inactive:!q&&!a,updating:G,selectable:q}]),onClick:ce,onDoubleClick:fe,onContextMenu:de,onMouseEnter:K,onMouseMove:le,onMouseLeave:pe,onKeyDown:H?_e:void 0,tabIndex:H?0:void 0,role:E.ariaRole??(H?"group":"img"),"aria-roledescription":"edge","data-id":t,"data-testid":`rf__edge-${t}`,"aria-label":E.ariaLabel===null?void 0:E.ariaLabel||`Edge from ${E.source} to ${E.target}`,"aria-describedby":H?`${Tg}-${S}`:void 0,ref:ne,...E.domAttributes,children:[!J&&p.jsx(O,{id:t,source:E.source,target:E.target,type:E.type,selected:E.selected,animated:E.animated,selectable:q,deletable:E.deletable??!0,label:E.label,labelStyle:E.labelStyle,labelShowBg:E.labelShowBg,labelBgStyle:E.labelBgStyle,labelBgPadding:E.labelBgPadding,labelBgBorderRadius:E.labelBgBorderRadius,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,data:E.data,style:E.style,sourceHandleId:E.sourceHandle,targetHandleId:E.targetHandle,markerStart:re,markerEnd:ie,pathOptions:"pathOptions"in E?E.pathOptions:void 0,interactionWidth:E.interactionWidth}),I&&p.jsx(CS,{edge:E,isReconnectable:I,reconnectRadius:m,onReconnect:x,onReconnectStart:v,onReconnectEnd:_,sourceX:U,sourceY:z,targetX:D,targetY:W,sourcePosition:M,targetPosition:R,setUpdateHover:ee,setReconnecting:C})]})})}var PS=F.memo(MS);const IS=t=>({edgesFocusable:t.edgesFocusable,edgesReconnectable:t.edgesReconnectable,elementsSelectable:t.elementsSelectable,connectionMode:t.connectionMode,onError:t.onError});function im({defaultMarkerColor:t,onlyRenderVisibleElements:r,rfId:o,edgeTypes:l,noPanClassName:a,onReconnect:u,onEdgeContextMenu:d,onEdgeMouseEnter:f,onEdgeMouseMove:g,onEdgeMouseLeave:y,onEdgeClick:m,reconnectRadius:x,onEdgeDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,disableKeyboardA11y:j}){const{edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,onError:E}=Ae(IS,qe),b=gS(r);return p.jsxs("div",{className:"react-flow__edges",children:[p.jsx(wS,{defaultColor:t,rfId:o}),b.map($=>p.jsx(PS,{id:$,edgesFocusable:N,edgesReconnectable:k,elementsSelectable:T,noPanClassName:a,onReconnect:u,onContextMenu:d,onMouseEnter:f,onMouseMove:g,onMouseLeave:y,onClick:m,reconnectRadius:x,onDoubleClick:v,onReconnectStart:_,onReconnectEnd:S,rfId:o,onError:E,edgeTypes:l,disableKeyboardA11y:j},$))]})}im.displayName="EdgeRenderer";const TS=F.memo(im),rp=t=>`translate(${t[0]}px,${t[1]}px) scale(${t[2]})`;function RS({children:t}){const r=We(),o=F.useRef(null),[l]=F.useState(()=>r.getState().transform);return zg(()=>{let a=null;const u=()=>{const d=r.getState().transform;a&&d[0]===a[0]&&d[1]===a[1]&&d[2]===a[2]||(a=d,o.current&&(o.current.style.transform=rp(d)))};return u(),r.subscribe(u)},[r]),p.jsx("div",{ref:o,className:"react-flow__viewport xyflow__viewport react-flow__container",style:{transform:rp(l)},children:t})}function LS(t){const r=yc(),o=F.useRef(!1);F.useEffect(()=>{!o.current&&r.viewportInitialized&&t&&(setTimeout(()=>t(r),1),o.current=!0)},[t,r.viewportInitialized])}const AS=t=>{var r;return(r=t.panZoom)==null?void 0:r.syncViewport};function zS(t){const r=Ae(AS),o=We();return F.useEffect(()=>{t&&(r==null||r(t),o.setState({transform:[t.x,t.y,t.zoom]}))},[t,r]),null}function DS(t){return t.connection.inProgress?{...t.connection,to:Bo(t.connection.to,t.transform)}:{...t.connection}}function $S(t){return DS}function OS(t){const r=$S();return Ae(r,qe)}const FS=t=>({nodesConnectable:t.nodesConnectable,isValid:t.connection.isValid,inProgress:t.connection.inProgress,width:t.width,height:t.height});function HS({containerStyle:t,style:r,type:o,component:l}){const{nodesConnectable:a,width:u,height:d,isValid:f,inProgress:g}=Ae(FS,qe);return!(u&&a&&g)?null:p.jsx("svg",{style:t,width:u,height:d,className:"react-flow__connectionline react-flow__container",children:p.jsx("g",{className:it(["react-flow__connection",ng(f)]),children:p.jsx(om,{style:r,type:o,CustomComponent:l,isValid:f})})})}const om=({style:t,type:r=dr.Bezier,CustomComponent:o,isValid:l})=>{const{inProgress:a,from:u,fromNode:d,fromHandle:f,fromPosition:g,to:y,toNode:m,toHandle:x,toPosition:v,pointer:_}=OS();if(!a)return;if(o)return p.jsx(o,{connectionLineType:r,connectionLineStyle:t,fromNode:d,fromHandle:f,fromX:u.x,fromY:u.y,toX:y.x,toY:y.y,fromPosition:g,toPosition:v,connectionStatus:ng(l),toNode:m,toHandle:x,pointer:_});let S="";const j={sourceX:u.x,sourceY:u.y,sourcePosition:g,targetX:y.x,targetY:y.y,targetPosition:v};switch(r){case dr.Bezier:[S]=gg(j);break;case dr.SimpleBezier:[S]=Yg(j);break;case dr.Step:[S]=qu({...j,borderRadius:0});break;case dr.SmoothStep:[S]=qu(j);break;default:[S]=yg(j)}return p.jsx("path",{d:S,fill:"none",className:"react-flow__connection-path",style:t})};om.displayName="ConnectionLine";const BS={};function ip(t=BS){F.useRef(t),We(),F.useEffect(()=>{},[t])}function VS(){We(),F.useRef(!1),F.useEffect(()=>{},[])}function sm({nodeTypes:t,edgeTypes:r,onInit:o,onNodeClick:l,onEdgeClick:a,onNodeDoubleClick:u,onEdgeDoubleClick:d,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,onSelectionContextMenu:x,onSelectionStart:v,onSelectionEnd:_,connectionLineType:S,connectionLineStyle:j,connectionLineComponent:N,connectionLineContainerStyle:k,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,deleteKeyCode:I,onlyRenderVisibleElements:q,elementsSelectable:ne,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,preventScrolling:Y,defaultMarkerColor:V,zoomOnScroll:U,zoomOnPinch:z,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,zoomOnDoubleClick:R,panOnDrag:re,autoPanOnSelection:ie,onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneScroll:le,onPaneContextMenu:pe,paneClickDistance:_e,nodeClickDistance:xe,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Pe,onEdgeMouseLeave:Ie,reconnectRadius:Re,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,viewport:ft,onViewportChange:Je,nodesDraggable:vn}){return ip(t),ip(r),VS(),LS(o),zS(ft),p.jsx(oS,{onPaneClick:ce,onPaneMouseEnter:fe,onPaneMouseMove:de,onPaneMouseLeave:K,onPaneContextMenu:pe,onPaneScroll:le,paneClickDistance:_e,deleteKeyCode:I,selectionKeyCode:T,selectionOnDrag:E,selectionMode:b,onSelectionStart:v,onSelectionEnd:_,multiSelectionKeyCode:$,panActivationKeyCode:O,zoomActivationKeyCode:H,elementsSelectable:ne,zoomOnScroll:U,zoomOnPinch:z,zoomOnDoubleClick:R,panOnScroll:D,panOnScrollSpeed:W,panOnScrollMode:M,panOnDrag:re,autoPanOnSelection:ie,defaultViewport:G,translateExtent:ee,minZoom:J,maxZoom:C,onSelectionContextMenu:x,preventScrolling:Y,noDragClassName:ot,noWheelClassName:at,noPanClassName:It,disableKeyboardA11y:Ke,onViewportChange:Je,isControlledViewport:!!ft,children:p.jsxs(RS,{children:[p.jsx(TS,{edgeTypes:r,onEdgeClick:a,onEdgeDoubleClick:d,onReconnect:tt,onReconnectStart:nt,onReconnectEnd:Qe,onlyRenderVisibleElements:q,onEdgeContextMenu:ge,onEdgeMouseEnter:je,onEdgeMouseMove:Pe,onEdgeMouseLeave:Ie,reconnectRadius:Re,defaultMarkerColor:V,noPanClassName:It,disableKeyboardA11y:Ke,rfId:gt}),p.jsx(HS,{style:j,type:S,component:N,containerStyle:k}),p.jsx("div",{className:"react-flow__edgelabel-renderer"}),p.jsx(pS,{nodeTypes:t,onNodeClick:l,onNodeDoubleClick:u,onNodeMouseEnter:f,onNodeMouseMove:g,onNodeMouseLeave:y,onNodeContextMenu:m,nodeClickDistance:xe,onlyRenderVisibleElements:q,noPanClassName:It,noDragClassName:ot,disableKeyboardA11y:Ke,nodeExtent:ze,rfId:gt,nodesDraggable:vn}),p.jsx("div",{className:"react-flow__viewport-portal"})]})})}sm.displayName="GraphView";const WS=F.memo(sm),US=ag(),op=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g=.5,maxZoom:y=2,nodeOrigin:m,nodeExtent:x,zIndexMode:v="basic"}={})=>{const _=new Map,S=new Map,j=new Map,N=new Map,k=l??r??[],T=o??t??[],E=m??[0,0],b=x??Po;wg(j,N,k);const{nodesInitialized:$}=Ku(T,_,S,{nodeOrigin:E,nodeExtent:b,zIndexMode:v});let O=[0,0,1];if(d&&a&&u){const H=Fo(_,{filter:G=>!!((G.width||G.initialWidth)&&(G.height||G.initialHeight))}),{x:I,y:q,zoom:ne}=cc(H,a,u,g,y,(f==null?void 0:f.padding)??.1);O=[I,q,ne]}return{rfId:"1",width:a??0,height:u??0,transform:O,nodes:T,nodesInitialized:$,nodeLookup:_,parentLookup:S,edges:k,edgeLookup:N,connectionLookup:j,onNodesChange:null,onEdgesChange:null,hasDefaultNodes:o!==void 0,hasDefaultEdges:l!==void 0,panZoom:null,minZoom:g,maxZoom:y,translateExtent:Po,nodeExtent:b,nodesSelectionActive:!1,userSelectionActive:!1,userSelectionRect:null,connectionMode:Ii.Strict,domNode:null,paneDragging:!1,noPanClassName:"nopan",nodeOrigin:E,nodeDragThreshold:1,connectionDragThreshold:1,snapGrid:[15,15],snapToGrid:!1,nodesDraggable:!0,nodesConnectable:!0,nodesFocusable:!0,edgesFocusable:!0,edgesReconnectable:!0,elementsSelectable:!0,elevateNodesOnSelect:!0,elevateEdgesOnSelect:!0,selectNodesOnDrag:!0,multiSelectionActive:!1,fitViewQueued:d??!1,fitViewOptions:f,fitViewResolver:null,connection:{...tg},connectionClickStartHandle:null,connectOnClick:!0,ariaLiveMessage:"",autoPanOnConnect:!0,autoPanOnNodeDrag:!0,autoPanOnNodeFocus:!0,autoPanSpeed:15,connectionRadius:20,onError:US,isValidConnection:void 0,onSelectionChangeHandlers:[],lib:"react",debug:!1,ariaLabelConfig:eg,zIndexMode:v,onNodesChangeMiddlewareMap:new Map,onEdgesChangeMiddlewareMap:new Map}},YS=({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v})=>i_((_,S)=>{async function j(){const{nodeLookup:N,panZoom:k,fitViewOptions:T,fitViewResolver:E,width:b,height:$,minZoom:O,maxZoom:H}=S();k&&(await e1({nodes:N,width:b,height:$,panZoom:k,minZoom:O,maxZoom:H},T),E==null||E.resolve(!0),_({fitViewResolver:null}))}return{...op({nodes:t,edges:r,width:a,height:u,fitView:d,fitViewOptions:f,minZoom:g,maxZoom:y,nodeOrigin:m,nodeExtent:x,defaultNodes:o,defaultEdges:l,zIndexMode:v}),setNodes:N=>{const{nodeLookup:k,parentLookup:T,nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,fitViewQueued:O,zIndexMode:H,nodesSelectionActive:I}=S(),{nodesInitialized:q,hasSelectedNodes:ne}=Ku(N,k,T,{nodeOrigin:E,nodeExtent:b,elevateNodesOnSelect:$,checkEquality:!0,zIndexMode:H}),G=I&≠O&&q?(j(),_({nodes:N,nodesInitialized:q,fitViewQueued:!1,fitViewOptions:void 0,nodesSelectionActive:G})):_({nodes:N,nodesInitialized:q,nodesSelectionActive:G})},setEdges:N=>{const{connectionLookup:k,edgeLookup:T}=S();wg(k,T,N),_({edges:N})},setDefaultNodesAndEdges:(N,k)=>{if(N){const{setNodes:T}=S();T(N),_({hasDefaultNodes:!0})}if(k){const{setEdges:T}=S();T(k),_({hasDefaultEdges:!0})}},updateNodeInternals:N=>{const{triggerNodeChanges:k,nodeLookup:T,parentLookup:E,domNode:b,nodeOrigin:$,nodeExtent:O,debug:H,fitViewQueued:I,zIndexMode:q}=S(),{changes:ne,updatedInternals:G}=k1(N,T,E,b,$,O,q);G&&(x1(T,E,{nodeOrigin:$,nodeExtent:O,zIndexMode:q}),I?(j(),_({fitViewQueued:!1,fitViewOptions:void 0})):_({}),(ne==null?void 0:ne.length)>0&&(H&&console.log("React Flow: trigger node changes",ne),k==null||k(ne)))},updateNodePositions:(N,k=!1)=>{const T=[];let E=[];const{nodeLookup:b,triggerNodeChanges:$,connection:O,updateConnection:H,onNodesChangeMiddlewareMap:I}=S();for(const[q,ne]of N){const G=b.get(q),ee=!!(G!=null&&G.expandParent&&(G!=null&&G.parentId)&&(ne!=null&&ne.position)),J={id:q,type:"position",position:ee?{x:Math.max(0,ne.position.x),y:Math.max(0,ne.position.y)}:ne.position,dragging:k};if(G&&O.inProgress&&O.fromNode.id===G.id){const C=Vr(G,O.fromHandle,Se.Left,!0);H({...O,from:C})}ee&&G.parentId&&T.push({id:q,parentId:G.parentId,rect:{...ne.internals.positionAbsolute,width:ne.measured.width??0,height:ne.measured.height??0}}),E.push(J)}if(T.length>0){const{parentLookup:q,nodeOrigin:ne}=S(),G=mc(T,b,q,ne);E.push(...G)}for(const q of I.values())E=q(E);$(E)},triggerNodeChanges:N=>{const{onNodesChange:k,setNodes:T,nodes:E,hasDefaultNodes:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=N_(N,E);T(O)}$&&console.log("React Flow: trigger node changes",N),k==null||k(N)}},triggerEdgeChanges:N=>{const{onEdgesChange:k,setEdges:T,edges:E,hasDefaultEdges:b,debug:$}=S();if(N!=null&&N.length){if(b){const O=j_(N,E);T(O)}$&&console.log("React Flow: trigger edge changes",N),k==null||k(N)}},addSelectedNodes:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));b(O);return}b(ji(E,new Set([...N]),!0)),$(ji(T))},addSelectedEdges:N=>{const{multiSelectionActive:k,edgeLookup:T,nodeLookup:E,triggerNodeChanges:b,triggerEdgeChanges:$}=S();if(k){const O=N.map(H=>Ar(H,!0));$(O);return}$(ji(T,new Set([...N]))),b(ji(E,new Set,!0))},unselectNodesAndEdges:({nodes:N,edges:k}={})=>{const{edges:T,nodes:E,nodeLookup:b,triggerNodeChanges:$,triggerEdgeChanges:O}=S(),H=N||E,I=k||T,q=[];for(const G of H){if(!G.selected)continue;const ee=b.get(G.id);ee&&(ee.selected=!1),q.push(Ar(G.id,!1))}const ne=[];for(const G of I)G.selected&&ne.push(Ar(G.id,!1));$(q),O(ne)},setMinZoom:N=>{const{panZoom:k,maxZoom:T}=S();k==null||k.setScaleExtent([N,T]),_({minZoom:N})},setMaxZoom:N=>{const{panZoom:k,minZoom:T}=S();k==null||k.setScaleExtent([T,N]),_({maxZoom:N})},setTranslateExtent:N=>{var k;(k=S().panZoom)==null||k.setTranslateExtent(N),_({translateExtent:N})},resetSelectedElements:()=>{const{edges:N,nodes:k,triggerNodeChanges:T,triggerEdgeChanges:E,elementsSelectable:b}=S();if(!b)return;const $=k.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]),O=N.reduce((H,I)=>I.selected?[...H,Ar(I.id,!1)]:H,[]);T($),E(O)},setNodeExtent:N=>{const{nodes:k,nodeLookup:T,parentLookup:E,nodeOrigin:b,elevateNodesOnSelect:$,nodeExtent:O,zIndexMode:H}=S();N[0][0]===O[0][0]&&N[0][1]===O[0][1]&&N[1][0]===O[1][0]&&N[1][1]===O[1][1]||(Ku(k,T,E,{nodeOrigin:b,nodeExtent:N,elevateNodesOnSelect:$,checkEquality:!1,zIndexMode:H}),_({nodeExtent:N}))},panBy:N=>{const{transform:k,width:T,height:E,panZoom:b,translateExtent:$}=S();return E1({delta:N,panZoom:b,transform:k,translateExtent:$,width:T,height:E})},setCenter:async(N,k,T)=>{const{width:E,height:b,maxZoom:$,panZoom:O}=S();if(!O)return!1;const H=typeof(T==null?void 0:T.zoom)<"u"?T.zoom:$;return await O.setViewport({x:E/2-N*H,y:b/2-k*H,zoom:H},{duration:T==null?void 0:T.duration,ease:T==null?void 0:T.ease,interpolate:T==null?void 0:T.interpolate}),!0},cancelConnection:()=>{_({connection:{...tg}})},updateConnection:N=>{_({connection:N})},reset:()=>_({...op()})}},Object.is);function lm({initialNodes:t,initialEdges:r,defaultNodes:o,defaultEdges:l,initialWidth:a,initialHeight:u,initialMinZoom:d,initialMaxZoom:f,initialFitViewOptions:g,fitView:y,nodeOrigin:m,nodeExtent:x,zIndexMode:v,children:_}){const[S]=F.useState(()=>YS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,width:a,height:u,fitView:y,minZoom:d,maxZoom:f,fitViewOptions:g,nodeOrigin:m,nodeExtent:x,zIndexMode:v}));return p.jsx(o_,{value:S,children:p.jsx(I_,{children:p.jsx(Y_,{children:_})})})}function GS({children:t,nodes:r,edges:o,defaultNodes:l,defaultEdges:a,width:u,height:d,fitView:f,fitViewOptions:g,minZoom:y,maxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_}){return F.useContext(Pl)?p.jsx(p.Fragment,{children:t}):p.jsx(lm,{initialNodes:r,initialEdges:o,defaultNodes:l,defaultEdges:a,initialWidth:u,initialHeight:d,fitView:f,initialFitViewOptions:g,initialMinZoom:y,initialMaxZoom:m,nodeOrigin:x,nodeExtent:v,zIndexMode:_,children:t})}const XS={width:"100%",height:"100%",overflow:"hidden",position:"relative",zIndex:0};function qS({nodes:t,edges:r,defaultNodes:o,defaultEdges:l,className:a,nodeTypes:u,edgeTypes:d,onNodeClick:f,onEdgeClick:g,onInit:y,onMove:m,onMoveStart:x,onMoveEnd:v,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onSelectionChange:J,onSelectionDragStart:C,onSelectionDrag:Y,onSelectionDragStop:V,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onBeforeDelete:W,connectionMode:M,connectionLineType:R=dr.Bezier,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,deleteKeyCode:fe="Backspace",selectionKeyCode:de="Shift",selectionOnDrag:K=!1,selectionMode:le=Io.Full,panActivationKeyCode:pe="Space",multiSelectionKeyCode:_e=Lo()?"Meta":"Control",zoomActivationKeyCode:xe=Lo()?"Meta":"Control",snapToGrid:ge,snapGrid:je,onlyRenderVisibleElements:Pe=!1,selectNodesOnDrag:Ie,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,nodeOrigin:ot=Rg,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke=!0,defaultViewport:ze=v_,minZoom:gt=.5,maxZoom:ft=2,translateExtent:Je=Po,preventScrolling:vn=!0,nodeExtent:wt,defaultMarkerColor:Gt="#b1b1b7",zoomOnScroll:zi=!0,zoomOnPinch:kt=!0,panOnScroll:hr=!1,panOnScrollSpeed:An=.5,panOnScrollMode:zn=$r.Free,zoomOnDoubleClick:pr=!0,panOnDrag:gr=!0,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr=1,nodeClickDistance:$n=0,children:Gr,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn=10,onNodesChange:Fn,onEdgesChange:Xr,noDragClassName:qr="nodrag",noWheelClassName:Qr="nowheel",noPanClassName:Tt="nopan",fitView:Hn,fitViewOptions:L,connectOnClick:te,attributionPosition:ke,proOptions:Me,defaultEdgeOptions:Ce,elevateNodesOnSelect:Bn=!0,elevateEdgesOnSelect:Al=!1,disableKeyboardA11y:Vo=!1,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanOnSelection:$i=!0,autoPanSpeed:Wo,connectionRadius:Kr,isValidConnection:Dl,onError:Uo,style:Zr,id:Rt,nodeDragThreshold:$l,connectionDragThreshold:Lt,viewport:Ol,onViewportChange:Fl,width:Hl,height:Jr,colorMode:ei="light",debug:wr,onScroll:kn,ariaLabelConfig:Bl,zIndexMode:Yo="basic",...Oi},Go){const _r=Rt||"1",Sr=S_(ei),Vl=F.useCallback(ti=>{ti.currentTarget.scrollTo({top:0,left:0,behavior:"instant"}),kn==null||kn(ti)},[kn]);return p.jsx("div",{"data-testid":"rf__wrapper",...Oi,onScroll:Vl,style:{...Zr,...XS},ref:Go,className:it(["react-flow",a,Sr]),id:Rt,role:"application",children:p.jsxs(GS,{nodes:t,edges:r,width:Hl,height:Jr,fitView:Hn,fitViewOptions:L,minZoom:gt,maxZoom:ft,nodeOrigin:ot,nodeExtent:wt,zIndexMode:Yo,children:[p.jsx(__,{nodes:t,edges:r,defaultNodes:o,defaultEdges:l,onConnect:_,onConnectStart:S,onConnectEnd:j,onClickConnectStart:N,onClickConnectEnd:k,nodesDraggable:Re,autoPanOnNodeFocus:tt,nodesConnectable:nt,nodesFocusable:Qe,edgesFocusable:at,edgesReconnectable:It,elementsSelectable:Ke,elevateNodesOnSelect:Bn,elevateEdgesOnSelect:Al,minZoom:gt,maxZoom:ft,nodeExtent:wt,onNodesChange:Fn,onEdgesChange:Xr,snapToGrid:ge,snapGrid:je,connectionMode:M,translateExtent:Je,connectOnClick:te,defaultEdgeOptions:Ce,fitView:Hn,fitViewOptions:L,onNodesDelete:ne,onEdgesDelete:G,onDelete:ee,onNodeDragStart:H,onNodeDrag:I,onNodeDragStop:q,onSelectionDrag:Y,onSelectionDragStart:C,onSelectionDragStop:V,onMove:m,onMoveStart:x,onMoveEnd:v,noPanClassName:Tt,nodeOrigin:ot,rfId:_r,autoPanOnConnect:Ye,autoPanOnNodeDrag:zl,autoPanSpeed:Wo,onError:Uo,connectionRadius:Kr,isValidConnection:Dl,selectNodesOnDrag:Ie,nodeDragThreshold:$l,connectionDragThreshold:Lt,onBeforeDelete:W,debug:wr,ariaLabelConfig:Bl,zIndexMode:Yo}),p.jsx(WS,{onInit:y,onNodeClick:f,onEdgeClick:g,onNodeMouseEnter:T,onNodeMouseMove:E,onNodeMouseLeave:b,onNodeContextMenu:$,onNodeDoubleClick:O,nodeTypes:u,edgeTypes:d,connectionLineType:R,connectionLineStyle:re,connectionLineComponent:ie,connectionLineContainerStyle:ce,selectionKeyCode:de,selectionOnDrag:K,selectionMode:le,deleteKeyCode:fe,multiSelectionKeyCode:_e,panActivationKeyCode:pe,zoomActivationKeyCode:xe,onlyRenderVisibleElements:Pe,defaultViewport:ze,translateExtent:Je,minZoom:gt,maxZoom:ft,preventScrolling:vn,zoomOnScroll:zi,zoomOnPinch:kt,zoomOnDoubleClick:pr,panOnScroll:hr,panOnScrollSpeed:An,panOnScrollMode:zn,panOnDrag:gr,autoPanOnSelection:$i,onPaneClick:mr,onPaneMouseEnter:yr,onPaneMouseMove:un,onPaneMouseLeave:cn,onPaneScroll:Ur,onPaneContextMenu:Dn,paneClickDistance:Yr,nodeClickDistance:$n,onSelectionContextMenu:U,onSelectionStart:z,onSelectionEnd:D,onReconnect:vr,onReconnectStart:xr,onReconnectEnd:Xt,onEdgeContextMenu:On,onEdgeDoubleClick:xn,onEdgeMouseEnter:Di,onEdgeMouseMove:wn,onEdgeMouseLeave:_n,reconnectRadius:Sn,defaultMarkerColor:Gt,noDragClassName:qr,noWheelClassName:Qr,noPanClassName:Tt,rfId:_r,disableKeyboardA11y:Vo,nodeExtent:wt,viewport:Ol,onViewportChange:Fl,nodesDraggable:Re}),p.jsx(y_,{onSelectionChange:J}),Gr,p.jsx(f_,{proOptions:Me,position:ke}),p.jsx(d_,{rfId:_r,disableKeyboardA11y:Vo})]})})}var QS=Ag(qS);function KS({dimensions:t,lineWidth:r,variant:o,className:l}){return p.jsx("path",{strokeWidth:r,d:`M${t[0]/2} 0 V${t[1]} M0 ${t[1]/2} H${t[0]}`,className:it(["react-flow__background-pattern",o,l])})}function ZS({radius:t,className:r}){return p.jsx("circle",{cx:t,cy:t,r:t,className:it(["react-flow__background-pattern","dots",r])})}var fr;(function(t){t.Lines="lines",t.Dots="dots",t.Cross="cross"})(fr||(fr={}));const JS={[fr.Dots]:1,[fr.Lines]:1,[fr.Cross]:6},ek=t=>({transform:t.transform,patternId:`pattern-${t.rfId}`});function am({id:t,variant:r=fr.Dots,gap:o=20,size:l,lineWidth:a=1,offset:u=0,color:d,bgColor:f,style:g,className:y,patternClassName:m}){const x=F.useRef(null),{transform:v,patternId:_}=Ae(ek,qe),S=l||JS[r],j=r===fr.Dots,N=r===fr.Cross,k=Array.isArray(o)?o:[o,o],T=[k[0]*v[2]||1,k[1]*v[2]||1],E=S*v[2],b=Array.isArray(u)?u:[u,u],$=N?[E,E]:T,O=[b[0]*v[2]+$[0]/2,b[1]*v[2]+$[1]/2],H=`${_}${t||""}`;return p.jsxs("svg",{className:it(["react-flow__background",y]),style:{...g,...Tl,"--xy-background-color-props":f,"--xy-background-pattern-color-props":d},ref:x,"data-testid":"rf__background",children:[p.jsx("pattern",{id:H,x:v[0]%T[0],y:v[1]%T[1],width:T[0],height:T[1],patternUnits:"userSpaceOnUse",patternTransform:`translate(-${O[0]},-${O[1]})`,children:j?p.jsx(ZS,{radius:E/2,className:m}):p.jsx(KS,{dimensions:$,lineWidth:a,variant:r,className:m})}),p.jsx("rect",{x:"0",y:"0",width:"100%",height:"100%",fill:`url(#${H})`})]})}am.displayName="Background";const tk=F.memo(am);function nk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 32",children:p.jsx("path",{d:"M32 18.133H18.133V32h-4.266V18.133H0v-4.266h13.867V0h4.266v13.867H32z"})})}function rk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 5",children:p.jsx("path",{d:"M0 0h32v4.2H0z"})})}function ik(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 32 30",children:p.jsx("path",{d:"M3.692 4.63c0-.53.4-.938.939-.938h5.215V0H4.708C2.13 0 0 2.054 0 4.63v5.216h3.692V4.631zM27.354 0h-5.2v3.692h5.17c.53 0 .984.4.984.939v5.215H32V4.631A4.624 4.624 0 0027.354 0zm.954 24.83c0 .532-.4.94-.939.94h-5.215v3.768h5.215c2.577 0 4.631-2.13 4.631-4.707v-5.139h-3.692v5.139zm-23.677.94c-.531 0-.939-.4-.939-.94v-5.138H0v5.139c0 2.577 2.13 4.707 4.708 4.707h5.138V25.77H4.631z"})})}function ok(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0 8 0 4.571 3.429 4.571 7.619v3.048H3.048A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047zm4.724-13.866H7.467V7.619c0-2.59 2.133-4.724 4.723-4.724 2.591 0 4.724 2.133 4.724 4.724v3.048z"})})}function sk(){return p.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 25 32",children:p.jsx("path",{d:"M21.333 10.667H19.81V7.619C19.81 3.429 16.38 0 12.19 0c-4.114 1.828-1.37 2.133.305 2.438 1.676.305 4.42 2.59 4.42 5.181v3.048H3.047A3.056 3.056 0 000 13.714v15.238A3.056 3.056 0 003.048 32h18.285a3.056 3.056 0 003.048-3.048V13.714a3.056 3.056 0 00-3.048-3.047zM12.19 24.533a3.056 3.056 0 01-3.047-3.047 3.056 3.056 0 013.047-3.048 3.056 3.056 0 013.048 3.048 3.056 3.056 0 01-3.048 3.047z"})})}function rl({children:t,className:r,...o}){return p.jsx("button",{type:"button",className:it(["react-flow__controls-button",r]),...o,children:t})}const lk=t=>({isInteractive:t.nodesDraggable||t.nodesConnectable||t.elementsSelectable,minZoomReached:t.transform[2]<=t.minZoom,maxZoomReached:t.transform[2]>=t.maxZoom,ariaLabelConfig:t.ariaLabelConfig});function um({style:t,showZoom:r=!0,showFitView:o=!0,showInteractive:l=!0,fitViewOptions:a,onZoomIn:u,onZoomOut:d,onFitView:f,onInteractiveChange:g,className:y,children:m,position:x="bottom-left",orientation:v="vertical","aria-label":_}){const S=We(),{isInteractive:j,minZoomReached:N,maxZoomReached:k,ariaLabelConfig:T}=Ae(lk,qe),{zoomIn:E,zoomOut:b,fitView:$}=yc(),O=()=>{E(),u==null||u()},H=()=>{b(),d==null||d()},I=()=>{$(a),f==null||f()},q=()=>{S.setState({nodesDraggable:!j,nodesConnectable:!j,elementsSelectable:!j}),g==null||g(!j)},ne=v==="horizontal"?"horizontal":"vertical";return p.jsxs(Il,{className:it(["react-flow__controls",ne,y]),position:x,style:t,"data-testid":"rf__controls","aria-label":_??T["controls.ariaLabel"],children:[r&&p.jsxs(p.Fragment,{children:[p.jsx(rl,{onClick:O,className:"react-flow__controls-zoomin",title:T["controls.zoomIn.ariaLabel"],"aria-label":T["controls.zoomIn.ariaLabel"],disabled:k,children:p.jsx(nk,{})}),p.jsx(rl,{onClick:H,className:"react-flow__controls-zoomout",title:T["controls.zoomOut.ariaLabel"],"aria-label":T["controls.zoomOut.ariaLabel"],disabled:N,children:p.jsx(rk,{})})]}),o&&p.jsx(rl,{className:"react-flow__controls-fitview",onClick:I,title:T["controls.fitView.ariaLabel"],"aria-label":T["controls.fitView.ariaLabel"],children:p.jsx(ik,{})}),l&&p.jsx(rl,{className:"react-flow__controls-interactive",onClick:q,title:T["controls.interactive.ariaLabel"],"aria-label":T["controls.interactive.ariaLabel"],children:j?p.jsx(sk,{}):p.jsx(ok,{})}),m]})}um.displayName="Controls";const ak=F.memo(um);function uk({id:t,x:r,y:o,width:l,height:a,style:u,color:d,strokeColor:f,strokeWidth:g,className:y,borderRadius:m,shapeRendering:x,selected:v,onClick:_}){const{background:S,backgroundColor:j}=u||{},N=d||S||j;return p.jsx("rect",{className:it(["react-flow__minimap-node",{selected:v},y]),x:r,y:o,rx:m,ry:m,width:l,height:a,style:{fill:N,stroke:f,strokeWidth:g},shapeRendering:x,onClick:_?k=>_(k,t):void 0})}const ck=F.memo(uk),dk=t=>t.nodes.map(r=>r.id),Du=t=>t instanceof Function?t:()=>t;function fk({nodeStrokeColor:t,nodeColor:r,nodeClassName:o="",nodeBorderRadius:l=5,nodeStrokeWidth:a,nodeComponent:u=ck,onClick:d}){const f=Ae(dk,qe),g=Du(r),y=Du(t),m=Du(o),x=typeof window>"u"||window.chrome?"crispEdges":"geometricPrecision";return p.jsx(p.Fragment,{children:f.map(v=>p.jsx(pk,{id:v,nodeColorFunc:g,nodeStrokeColorFunc:y,nodeClassNameFunc:m,nodeBorderRadius:l,nodeStrokeWidth:a,NodeComponent:u,onClick:d,shapeRendering:x},v))})}function hk({id:t,nodeColorFunc:r,nodeStrokeColorFunc:o,nodeClassNameFunc:l,nodeBorderRadius:a,nodeStrokeWidth:u,shapeRendering:d,NodeComponent:f,onClick:g}){const{node:y,x:m,y:x,width:v,height:_}=Ae(S=>{const j=S.nodeLookup.get(t);if(!j)return{node:void 0,x:0,y:0,width:0,height:0};const N=j.internals.userNode,{x:k,y:T}=j.internals.positionAbsolute,{width:E,height:b}=an(N);return{node:N,x:k,y:T,width:E,height:b}},qe);return!y||y.hidden||!ug(y)?null:p.jsx(f,{x:m,y:x,width:v,height:_,style:y.style,selected:!!y.selected,className:l(y),color:r(y),borderRadius:a,strokeColor:o(y),strokeWidth:u,shapeRendering:d,onClick:g,id:y.id})}const pk=F.memo(hk);var gk=F.memo(fk);const mk=200,yk=150,vk=t=>!t.hidden,xk=t=>{const r={x:-t.transform[0]/t.transform[2],y:-t.transform[1]/t.transform[2],width:t.width/t.transform[2],height:t.height/t.transform[2]};return{viewBB:r,boundingRect:t.nodeLookup.size>0?sg(Fo(t.nodeLookup,{filter:vk}),r):r,rfId:t.rfId,panZoom:t.panZoom,translateExtent:t.translateExtent,flowWidth:t.width,flowHeight:t.height,ariaLabelConfig:t.ariaLabelConfig}},sp=(t,r)=>t.x===r.x&&t.y===r.y&&t.width===r.width&&t.height===r.height,wk=(t,r)=>sp(t.viewBB,r.viewBB)&&sp(t.boundingRect,r.boundingRect)&&t.rfId===r.rfId&&t.panZoom===r.panZoom&&t.translateExtent===r.translateExtent&&t.flowWidth===r.flowWidth&&t.flowHeight===r.flowHeight&&t.ariaLabelConfig===r.ariaLabelConfig,_k="react-flow__minimap-desc";function cm({style:t,className:r,nodeStrokeColor:o,nodeColor:l,nodeClassName:a="",nodeBorderRadius:u=5,nodeStrokeWidth:d,nodeComponent:f,bgColor:g,maskColor:y,maskStrokeColor:m,maskStrokeWidth:x,position:v="bottom-right",onClick:_,onNodeClick:S,pannable:j=!1,zoomable:N=!1,ariaLabel:k,inversePan:T,zoomStep:E=1,offsetScale:b=5}){const $=We(),O=F.useRef(null),{boundingRect:H,viewBB:I,rfId:q,panZoom:ne,translateExtent:G,flowWidth:ee,flowHeight:J,ariaLabelConfig:C}=Ae(xk,wk),Y=(t==null?void 0:t.width)??mk,V=(t==null?void 0:t.height)??yk,U=H.width/Y,z=H.height/V,D=Math.max(U,z),W=D*Y,M=D*V,R=b*D,re=H.x-(W-H.width)/2-R,ie=H.y-(M-H.height)/2-R,ce=W+R*2,fe=M+R*2,de=`${_k}-${q}`,K=F.useRef(0),le=F.useRef();K.current=D,F.useEffect(()=>{if(O.current&&ne)return le.current=R1({domNode:O.current,panZoom:ne,getTransform:()=>$.getState().transform,getViewScale:()=>K.current}),()=>{var ge;(ge=le.current)==null||ge.destroy()}},[ne]),F.useEffect(()=>{var ge;(ge=le.current)==null||ge.update({translateExtent:G,width:ee,height:J,inversePan:T,pannable:j,zoomStep:E,zoomable:N})},[j,N,T,E,G,ee,J]);const pe=_?ge=>{var Ie;const[je,Pe]=((Ie=le.current)==null?void 0:Ie.pointer(ge))||[0,0];_(ge,{x:je,y:Pe})}:void 0,_e=S?F.useCallback((ge,je)=>{const Pe=$.getState().nodeLookup.get(je).internals.userNode;S(ge,Pe)},[]):void 0,xe=k??C["minimap.ariaLabel"];return p.jsx(Il,{position:v,style:{...t,"--xy-minimap-background-color-props":typeof g=="string"?g:void 0,"--xy-minimap-mask-background-color-props":typeof y=="string"?y:void 0,"--xy-minimap-mask-stroke-color-props":typeof m=="string"?m:void 0,"--xy-minimap-mask-stroke-width-props":typeof x=="number"?x*D:void 0,"--xy-minimap-node-background-color-props":typeof l=="string"?l:void 0,"--xy-minimap-node-stroke-color-props":typeof o=="string"?o:void 0,"--xy-minimap-node-stroke-width-props":typeof d=="number"?d:void 0},className:it(["react-flow__minimap",r]),"data-testid":"rf__minimap",children:p.jsxs("svg",{width:Y,height:V,viewBox:`${re} ${ie} ${ce} ${fe}`,className:"react-flow__minimap-svg",role:"img","aria-labelledby":de,ref:O,onClick:pe,children:[xe&&p.jsx("title",{id:de,children:xe}),p.jsx(gk,{onClick:_e,nodeColor:l,nodeStrokeColor:o,nodeBorderRadius:u,nodeClassName:a,nodeStrokeWidth:d,nodeComponent:f}),p.jsx("path",{className:"react-flow__minimap-mask",d:`M${re-R},${ie-R}h${ce+R*2}v${fe+R*2}h${-ce-R*2}z + M${I.x},${I.y}h${I.width}v${I.height}h${-I.width}z`,fillRule:"evenodd",pointerEvents:"none"})]})})}cm.displayName="MiniMap";const Sk=F.memo(cm),kk=t=>r=>t?`${Math.max(1/r.transform[2],1)}`:void 0,Ek={[Li.Line]:"right",[Li.Handle]:"bottom-right"};function Nk({nodeId:t,position:r,variant:o=Li.Handle,className:l,style:a=void 0,children:u,color:d,minWidth:f=10,minHeight:g=10,maxWidth:y=Number.MAX_VALUE,maxHeight:m=Number.MAX_VALUE,keepAspectRatio:x=!1,resizeDirection:v,autoScale:_=!0,shouldResize:S,onResizeStart:j,onResize:N,onResizeEnd:k}){const T=Fg(),E=typeof t=="string"?t:T,b=We(),$=F.useRef(null),O=o===Li.Handle,H=Ae(F.useCallback(kk(O&&_),[O,_]),qe),I=F.useRef(null),q=r??Ek[o];F.useEffect(()=>{if(!(!$.current||!E))return I.current||(I.current=Y1({domNode:$.current,nodeId:E,getStoreItems:()=>{const{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,domNode:V}=b.getState();return{nodeLookup:G,transform:ee,snapGrid:J,snapToGrid:C,nodeOrigin:Y,paneDomNode:V}},onChange:(G,ee)=>{const{triggerNodeChanges:J,nodeLookup:C,parentLookup:Y,nodeOrigin:V}=b.getState(),U=[],z={x:G.x,y:G.y},D=C.get(E);if(D&&D.expandParent&&D.parentId){const W=D.origin??V,M=G.width??D.measured.width??0,R=G.height??D.measured.height??0,re={id:D.id,parentId:D.parentId,rect:{width:M,height:R,...cg({x:G.x??D.position.x,y:G.y??D.position.y},{width:M,height:R},D.parentId,C,W)}},ie=mc([re],C,Y,V);U.push(...ie),z.x=G.x?Math.max(W[0]*M,G.x):void 0,z.y=G.y?Math.max(W[1]*R,G.y):void 0}if(z.x!==void 0&&z.y!==void 0){const W={id:E,type:"position",position:{...z}};U.push(W)}if(G.width!==void 0&&G.height!==void 0){const M={id:E,type:"dimensions",resizing:!0,setAttributes:v?v==="horizontal"?"width":"height":!0,dimensions:{width:G.width,height:G.height}};U.push(M)}for(const W of ee){const M={...W,type:"position"};U.push(M)}J(U)},onEnd:({width:G,height:ee})=>{const J={id:E,type:"dimensions",resizing:!1,dimensions:{width:G,height:ee}};b.getState().triggerNodeChanges([J])}})),I.current.update({controlPosition:q,boundaries:{minWidth:f,minHeight:g,maxWidth:y,maxHeight:m},keepAspectRatio:x,resizeDirection:v,onResizeStart:j,onResize:N,onResizeEnd:k,shouldResize:S}),()=>{var G;(G=I.current)==null||G.destroy()}},[q,f,g,y,m,x,j,N,k,S]);const ne=q.split("-");return p.jsx("div",{className:it(["react-flow__resize-control","nodrag",...ne,o,l]),ref:$,style:{...a,scale:H,...d&&{[O?"backgroundColor":"borderColor"]:d}},children:u})}F.memo(Nk);const jk={"arch.context":0,"django.app":0,"django.route":1,"django.url_name":1,"django.view":2,"django.viewset_action":2,"django.permission":2,"django.serializer":3,"django.form":3,"django.serializer_field":4,"django.service":4,"django.model":5,"django.field":6,"django.relation":6,"django.task":7,"django.receiver":7,"django.signal":7,"django.test":7,"django.migration_op":7,"django.admin":7,"django.management_command":7,"django.consumer":7,"django.websocket_route":1,"django.template":11,"django.htmx":9,"django.cache_key":7,"django.feature_flag":7,"django.side_effect":7,"graphql.type":3,"graphql.field":4,"graphql.operation":8,"fastapi.route":1,"fastapi.model":3,"openapi.path":8,"react.api_client":9,"react.query_key":10,"react.hook":10,"react.feature":10,"react.route":11,"react.page":11,"react.component":12,"react.form_schema":13,"react.test":13,"react.context":12};function Ll(t){return jk[t]??8}function bk(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r)a.sort((u,d)=>u.name.localeCompare(d.name)),a.forEach((u,d)=>{o.set(u.id,{x:l*260,y:d*108})});return o}const dm=90,Ck=new Set(["django.field","django.serializer_field","django.relation","django.test","react.test","graphql.field","django.url_name","django.throttle"]),lp={"arch.context":"#edf2f4","django.app":"#8d99ae","django.route":"#4cc9f0","django.view":"#4895ef","django.viewset_action":"#4361ee","django.permission":"#7b8cde","django.serializer":"#f4a261","django.form":"#e9c46a","django.serializer_field":"#e9c46a","django.service":"#90be6d","django.model":"#2a9d8f","django.field":"#8ac926","django.task":"#e76f51","django.receiver":"#e85d04","django.signal":"#f4a261","django.test":"#6c757d","django.admin":"#adb5bd","django.migration_op":"#9d4edd","django.consumer":"#e76f51","django.websocket_route":"#4cc9f0","django.template":"#c77dff","django.htmx":"#ff6b6b","django.cache_key":"#6c757d","django.feature_flag":"#f4a261","django.side_effect":"#e85d04","graphql.type":"#00bbf9","graphql.operation":"#00bbf9","fastapi.route":"#4cc9f0","fastapi.model":"#f4a261","openapi.path":"#00bbf9","react.api_client":"#ff6b6b","react.query_key":"#adb5bd","react.hook":"#7b2cbf","react.feature":"#9d4edd","react.route":"#c77dff","react.page":"#c77dff","react.component":"#9d4edd","react.form_schema":"#ffd166","react.test":"#6c757d"},Mk=Math.PI*(3-Math.sqrt(5)),fm=220,Pk=26,Ik={0:"context",1:"routes",2:"views",3:"serializers",4:"services",5:"models",6:"fields",7:"jobs / signals",8:"openapi",9:"api client",10:"hooks",11:"pages",12:"components",13:"forms / tests"};function hm(t){return t.startsWith("react.")?"react":t.startsWith("openapi.")||t.startsWith("graphql.")||t.startsWith("fastapi.")?"stitch":t.startsWith("arch.")?"arch":"django"}function dE(t){return lp[t]?lp[t]:t.startsWith("react.")?"#9d4edd":t.startsWith("openapi.")?"#00bbf9":"#4a5568"}function Tk(t){return t>=dm?"3d":"2d"}function Rk(t){return t>=dm?"overview":"full"}function Lk(t,r,o=1){const l=new Set([t]);let a=new Set([t]);for(let u=0;uo.families.has(hm(f.type)));o.detail==="overview"&&(l=l.filter(f=>!Ck.has(f.type)));const a=new Set(l.map(f=>f.id)),u=r.filter(f=>a.has(f.src)&&a.has(f.dst)),d=o.focusId?Lk(o.focusId,u,1):new Set;if(o.neighborhoodOnly&&o.focusId&&d.size){l=l.filter(g=>d.has(g.id));const f=new Set(l.map(g=>g.id));return{nodes:l,edges:u.filter(g=>f.has(g.src)&&f.has(g.dst)),neighborIds:d}}return{nodes:l,edges:u,neighborIds:d}}function fE(t){const r=new Map;for(const l of t){const a=Ll(l.type),u=r.get(a)??[];u.push(l),r.set(a,u)}const o=new Map;for(const[l,a]of r){a.sort((d,f)=>d.name.localeCompare(f.name));const u=l*fm;a.forEach((d,f)=>{if(a.length===1){o.set(d.id,{x:u,y:0,z:0});return}const g=Pk*Math.sqrt(f+1),y=f*Mk;o.set(d.id,{x:u,y:g*Math.cos(y),z:g*Math.sin(y)})})}return o}function hE(t){const r=new Map;for(const o of t){const l=Ll(o.type);r.set(l,(r.get(l)||0)+1)}return[...r.entries()].sort((o,l)=>o[0]-l[0]).map(([o,l])=>({layer:o,x:o*fm,count:l}))}const il=16,zk=12,Dk=new Set(["django.route","react.route","react.page","django.task","django.migration_op","django.permission","django.throttle","django.admin","django.management_command","openapi.path","django.consumer","django.websocket_route","django.template","django.cache_key","django.feature_flag","django.side_effect","graphql.operation","fastapi.route"]),$k=new Set(["django.serializer","django.serializer_field","django.form","openapi.path","react.form_schema","django.route","graphql.type","graphql.field","graphql.operation","fastapi.model","fastapi.route"]),ap={"arch.context":"Ownership boundary from loadpath.yml — the context this code belongs to.","django.app":"Django app package that owns models, views, and jobs.","django.route":"HTTP URL that publishes a view. A sink: this is where a change becomes a public request.","django.url_name":"Named URL used by reverse() / {% url %} lookups.","django.view":"Request handler (class-based view, function view, or ViewSet).","django.viewset_action":"One ViewSet action (list, create, retrieve, update, destroy).","django.permission":"Auth gate on a view — who is allowed to hit this path.","django.throttle":"Rate-limit class attached to a view.","django.serializer":"Request/response contract: which fields go in and come out.","django.form":"Django form that validates submitted input.","django.serializer_field":"One field on a serializer or form — the typed slot on the contract.","django.service":"Internal service or use-case. Work that is not itself an HTTP sink.","django.model":"ORM model. Schema and relations live here.","django.field":"Model column. Type, indexes, and relations are the contract of the table.","django.relation":"Model-to-model relation (FK / M2M / O2O).","django.task":"Celery or Dramatiq job. Once enqueued, this is a sink.","django.receiver":"Signal handler that runs after a model event.","django.signal":"Django signal that receivers subscribe to.","django.test":"Backend test that mentions symbols on this path.","django.admin":"Django admin class for a model.","django.migration_op":"Schema migration operation (CreateModel, AlterField, …).","django.management_command":"manage.py command — an operational sink.","django.consumer":"Django Channels WebSocket/HTTP consumer. A sink once a client connects.","django.websocket_route":"ASGI WebSocket URL. A sink: this is where a change becomes a live connection.","django.template":"Django template. HTML (and HTMX) the server renders.","django.htmx":"HTMX call from a template to a URL — another published seam.","django.cache_key":"Cache get/set key. Invalidation is part of the load path.","django.feature_flag":"Feature flag checked on this path. The change may be dark-launched.","django.side_effect":"transaction.on_commit (or similar) side effect that runs after the request commits.","graphql.type":"GraphQL object/input type — a published contract.","graphql.field":"One field on a GraphQL type.","graphql.operation":"GraphQL query, mutation, or subscription. A published contract and a sink.","fastapi.route":"FastAPI path operation sitting next to Django in this repo.","fastapi.model":"Pydantic response/request model — the FastAPI contract.","openapi.path":"Generated OpenAPI operation. The typed HTTP contract between stacks.","react.api_client":"Frontend fetch or generated client call to an API path.","react.query_key":"React Query cache key. Invalidation and reads share this name.","react.hook":"Data hook wrapping query or mutation calls.","react.feature":"Frontend feature module (folder).","react.route":"Client-side route. A sink: this is a URL the user can open.","react.page":"Page or screen component rendered by a route.","react.component":"UI component.","react.form_schema":"Zod (or similar) schema — typed form inputs on the client.","react.test":"Frontend test covering a page, hook, or component.","react.context":"React context provider."},Ok={field_type:"Type",fields:"Fields",form_fields:"Form fields",permissions:"Permissions",throttles:"Throttles",authentication:"Authentication",pagination:"Pagination",filterset:"Filterset",bases:"Extends",on_delete:"on_delete",related_name:"related_name",unique:"Unique",db_index:"Indexed",relation:"Relation field",looks_idempotent_on_pk:"Idempotent on pk",broker:"Broker",route:"Route",url_name:"URL name",view:"View",include:"Includes",mounted_at:"Mounted at",full_path:"Full path",method:"Method",path:"Path",operation_id:"Operation",raw:"URL",kind:"Schema",exclude:"Excludes",queryset_in_serializer:"Queryset in serializer",get_queryset:"Custom get_queryset",get_serializer_class:"Dynamic serializer",dynamic:"Dynamic",fbv:"Function view",ninja:"Django Ninja",django_form:"Django form",mutation:"Mutation",has_error_boundary:"Error boundary",invalidation:"Cache invalidation",inferred:"Inferred stitch",generated:"Generated",shared:"Shared module",element:"Renders",model_name:"Model",field_name:"Field",op:"Operation",app:"App",feature:"Feature",from_view:"From view",mentions:"Mentions",nodeid:"Test id",task:"Task",to:"Related to"},up=["field_type","method","path","operation_id","raw","route","mounted_at","full_path","url_name","view","element","fields","form_fields","exclude","kind","bases","permissions","authentication","throttles","pagination","filterset","on_delete","related_name","to","unique","db_index","relation","looks_idempotent_on_pk","broker","task","model_name","field_name","op","app","feature","from_view","include","fbv","ninja","django_form","mutation","has_error_boundary","invalidation","inferred","generated","shared","queryset_in_serializer","get_queryset","get_serializer_class","dynamic","mentions","nodeid"],cp=new Set(["referenced","placeholder","booted","line","call","from","import","local","source","file","plain_handler","string_ref","pagination_sink","match","via","generated_client","django","react","superseded_by_generated","foreign_app","imported"]),Fk=new Set(["looks_idempotent_on_pk"]),Hk=new Set(["inferred","generated","mutation","fbv","ninja"]);function Bk(t){return ap[t]?ap[t]:t.startsWith("react.")?"A React node on the load path.":t.startsWith("django.")?"A Django node on the load path.":t.startsWith("openapi.")?"A stitch node between Django and React.":"A node on the architecture graph."}function Vk(t,r,o){const l=new Map(r.map(x=>[x.id,x])),a=[];Dk.has(t.type)&&a.push("sink"),$k.has(t.type)&&a.push("contract");const u=t.extra??{};u.inferred&&a.push("inferred"),u.generated&&a.push("generated"),u.mutation&&a.push("mutation"),u.fbv&&a.push("function view"),u.ninja&&a.push("ninja");const d=o.filter(x=>x.dst===t.id),f=o.filter(x=>x.src===t.id),g=d.slice(0,il).map(x=>dp(x,l,x.src)),y=f.slice(0,il).map(x=>dp(x,l,x.dst)),m=t.file_path?`${t.file_path}${t.start_line?`:${t.start_line}`:""}`:void 0;return{type:t.type,typeLabel:No(_l(t.type)),layer:Ik[Ll(t.type)]??"other",purpose:Bk(t.type),name:t.name,qualifiedName:t.qualified_name,file:m,context:t.context,roles:a,facts:Wk(u).filter(x=>!(x.key==="app"&&x.value===t.context)),inputs:g,outputs:y,extraInputs:Math.max(0,d.length-il),extraOutputs:Math.max(0,f.length-il)}}function dp(t,r,o){const l=r.get(o),a=o.includes(":")?o.slice(o.indexOf(":")+1):o;return{id:o,name:(l==null?void 0:l.name)||a,type:(l==null?void 0:l.type)||"",typeLabel:l?No(_l(l.type)):"",edgeType:t.type,edgeLabel:No(t.type),inferred:t.confidence<.8}}function Wk(t){const r=[...up.filter(a=>a in t),...Object.keys(t).filter(a=>!up.includes(a)&&!cp.has(a))],o=[],l=new Set;for(const a of r){if(l.has(a)||cp.has(a)||Hk.has(a))continue;l.add(a);const u=Uk(a,t[a]);u!=null&&o.push({key:a,label:Ok[a]??No(a),value:u})}return o}function Uk(t,r){if(r==null)return null;if(typeof r=="boolean")return!r&&!Fk.has(t)?null:r?"yes":"no";if(typeof r=="number")return String(r);if(typeof r=="string")return r.trim()||null;if(Array.isArray(r)){const o=r.map(u=>typeof u=="string"||typeof u=="number"?String(u):"").filter(Boolean);if(!o.length)return null;const l=o.slice(0,zk),a=o.length-l.length;return a>0?`${l.join(", ")} +${a} more`:l.join(", ")}return null}const Yk=F.lazy(()=>m0(()=>import("./LayeredGraph3D-bMz3wlDF.js"),[],import.meta.url).then(t=>({default:t.LayeredGraph3D}))),Gk={cheap:"var(--edge-cheap)",expensive:"var(--edge-expensive)",critical:"var(--edge-critical)"};function Xk({data:t,selected:r}){return p.jsxs("div",{className:r?"lp-node selected":"lp-node",children:[p.jsx(Ai,{type:"target",position:Se.Left,isConnectable:!1}),p.jsx("div",{className:"t",children:_l(t.type)}),p.jsx("div",{className:"n",title:t.name,children:t.name}),p.jsx(Ai,{type:"source",position:Se.Right,isConnectable:!1})]})}const qk={load:Xk},fp=180,hp=56,Qk=new Set(["django","react","stitch","arch"]);function Kk(t,r,o=null){const l=new Map(t.map(f=>[f.id,f])),a=bk(t),u=t.map(f=>({id:f.id,type:"load",position:a.get(f.id)??{x:0,y:0},data:{name:f.name,type:f.type,file:f.file_path},selected:o===f.id,sourcePosition:Se.Right,targetPosition:Se.Left,width:fp,height:hp,style:{width:fp,height:hp}})),d=r.filter(f=>l.has(f.src)&&l.has(f.dst)).map(f=>{const g=Gk[f.weight]||"var(--edge-cheap)";return{id:f.id,source:f.src,target:f.dst,type:"smoothstep",animated:f.weight==="critical",style:{stroke:g,strokeWidth:f.weight==="critical"?2.4:1.2,strokeDasharray:f.confidence<.8?"6 4":void 0},markerEnd:{type:To.ArrowClosed,width:14,height:14,color:g},label:f.type.replaceAll("_"," "),labelStyle:{fill:"var(--muted)",fontSize:10}}});return{rfNodes:u,rfEdges:d}}function pp({node:t,nodes:r,edges:o,onClose:l,onWhatIf:a}){const u=Vk(t,r,o);return F.useEffect(()=>{const d=f=>{f.key==="Escape"&&l()};return window.addEventListener("keydown",d),()=>window.removeEventListener("keydown",d)},[l]),p.jsxs("aside",{className:"inspector","data-testid":"graph-inspector",children:[p.jsxs("div",{className:"inspector-head",children:[p.jsx("div",{className:"t",children:u.typeLabel}),p.jsx("div",{className:"inspector-roles",children:u.roles.map(d=>p.jsx("span",{className:"inspector-chip",children:d},d))}),p.jsx("button",{type:"button",className:"inspector-close","data-testid":"graph-inspector-close","aria-label":"Close inspector",onClick:l,children:"×"})]}),p.jsx("div",{className:"n",children:Ni(u.name)}),p.jsx("p",{className:"inspector-purpose","data-testid":"graph-inspector-purpose",children:u.purpose}),u.context?p.jsx("div",{className:"muted",children:Ni(u.context)}):null,u.file?p.jsx("div",{className:"file",children:Ni(u.file)}):null,p.jsx("div",{className:"muted",children:Ni(u.qualifiedName)}),p.jsxs("div",{className:"muted inspector-layer",children:["layer · ",u.layer]}),u.facts.length?p.jsx("dl",{className:"inspector-facts","data-testid":"graph-inspector-facts",children:u.facts.map(d=>p.jsxs("div",{className:"inspector-fact",children:[p.jsx("dt",{children:d.label}),p.jsx("dd",{children:Ni(d.value)})]},d.key))}):null,p.jsx(gp,{title:"Inputs",testId:"graph-inspector-inputs",links:u.inputs,extra:u.extraInputs,empty:"Nothing in this graph points here."}),p.jsx(gp,{title:"Outputs",testId:"graph-inspector-outputs",links:u.outputs,extra:u.extraOutputs,empty:"This node does not point at anything in this graph."}),a?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-whatif",onClick:()=>a(t.id),children:"What if this changes"}):null]})}function gp({title:t,testId:r,links:o,extra:l,empty:a}){return p.jsxs("section",{className:"inspector-section","data-testid":r,children:[p.jsxs("h3",{children:[t,p.jsx("span",{className:"count",children:o.length+l})]}),o.length?p.jsx("ul",{children:o.map((u,d)=>p.jsxs("li",{children:[p.jsx("span",{className:"inspector-link-name",title:u.name,children:Ni(u.name)}),p.jsxs("span",{className:"inspector-link-meta",children:[u.typeLabel?`${u.typeLabel} · `:"",u.edgeLabel,u.inferred?" · inferred":""]})]},`${u.edgeType}:${u.id}:${d}`))}):p.jsx("p",{className:"muted",children:a}),l?p.jsxs("p",{className:"muted",children:["+",l," more"]}):null]})}function $u({nodes:t,edges:r,onWhatIf:o,focusPath:l}){const[a,u]=F.useState(null),[d,f]=F.useState(null),[g,y]=F.useState(null),[m,x]=F.useState(new Set(Qk)),[v,_]=F.useState(!1),S=typeof window<"u"&&window.matchMedia("(prefers-reduced-motion: reduce)").matches,j=d??Tk(t.length),N=g??Rk(t.length),k=F.useMemo(()=>Ak(t,r,{detail:N,families:m,focusId:a,neighborhoodOnly:v&&j==="3d"}),[t,r,N,m,a,v,j]),T=F.useMemo(()=>new Map(k.nodes.map(G=>[G.id,G])),[k.nodes]),E=a?T.get(a)??null:null,{rfNodes:b,rfEdges:$}=F.useMemo(()=>{const G=Kk(k.nodes,k.edges,a);return S&&(G.rfEdges=G.rfEdges.map(ee=>({...ee,animated:!1}))),G},[k.nodes,k.edges,a,S]);F.useEffect(()=>{a&&!T.has(a)&&u(null)},[T,a]),F.useEffect(()=>{if(!l)return;const G=t.find(ee=>ee.file_path===l);G&&u(G.id)},[l,t]);const O=(G,ee)=>{u(ee.id)},H=()=>{u(null),_(!1)},I=G=>{x(ee=>{const J=new Set(ee);if(J.has(G)){if(J.size===1)return ee;J.delete(G)}else J.add(G);return J})},q=F.useMemo(()=>{const G=new Set;for(const ee of t)G.add(hm(ee.type));return G},[t]),ne=t.length-k.nodes.length;return p.jsxs("div",{className:"impact-graph",style:{flex:1,minHeight:0,position:"relative",display:"flex",flexDirection:"column"},children:[p.jsxs("div",{className:"graph-toolbar","data-testid":"graph-toolbar",children:[p.jsxs("div",{className:"seg","aria-label":"Graph projection",children:[p.jsx("button",{type:"button","data-testid":"graph-view-2d",className:j==="2d"?"active":"","aria-pressed":j==="2d",onClick:()=>f("2d"),children:"2D map"}),p.jsx("button",{type:"button","data-testid":"graph-view-3d",className:j==="3d"?"active":"","aria-pressed":j==="3d",onClick:()=>f("3d"),children:"3D layers"})]}),p.jsxs("div",{className:"seg","aria-label":"Graph detail",children:[p.jsx("button",{type:"button","data-testid":"graph-detail-overview",className:N==="overview"?"active":"","aria-pressed":N==="overview",onClick:()=>y("overview"),children:"Overview"}),p.jsx("button",{type:"button","data-testid":"graph-detail-full",className:N==="full"?"active":"","aria-pressed":N==="full",onClick:()=>y("full"),children:"Full"})]}),p.jsx("div",{className:"seg","aria-label":"Graph families",children:["django","stitch","react"].filter(G=>q.has(G)).map(G=>p.jsx("button",{type:"button","data-testid":`graph-family-${G}`,className:m.has(G)?"active":"","aria-pressed":m.has(G),onClick:()=>I(G),children:G},G))}),j==="3d"?p.jsx("button",{type:"button",className:v?"chip-btn active":"chip-btn","data-testid":"graph-neighborhood",disabled:!a,onClick:()=>_(G=>!G),children:v?"Neighborhood":"Focus neighbors"}):null,p.jsxs("span",{className:"muted graph-count",children:[k.nodes.length," nodes · ",k.edges.length," edges",ne?` · ${ne} hidden`:""]})]}),p.jsx("div",{className:"graph-stage",children:j==="3d"?p.jsxs("div",{className:"graph-3d","data-testid":"graph-3d",children:[p.jsx("p",{className:"graph-3d-hint",children:"Architecture layers are stacked in depth (Django → stitch → React). Drag to orbit, scroll to zoom, click a node to inspect it."}),p.jsx(F.Suspense,{fallback:p.jsx("p",{className:"muted graph-3d-hint",children:"Loading 3D layers…"}),children:p.jsx(Yk,{nodes:k.nodes,edges:k.edges,selectedId:a,neighborIds:k.neighborIds,onSelect:G=>{u(G),G||_(!1)}})}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]}):p.jsxs(lm,{children:[p.jsxs(QS,{nodes:b,edges:$,nodeTypes:qk,fitView:!0,fitViewOptions:{padding:.2,maxZoom:1.15},minZoom:.25,nodesDraggable:!1,nodesConnectable:!1,elementsSelectable:!0,deleteKeyCode:null,onNodeClick:O,onPaneClick:H,proOptions:{hideAttribution:!1},"data-testid":"impact-graph",children:[p.jsx(tk,{}),p.jsx(Sk,{pannable:!0,zoomable:!0,ariaLabel:"Impact graph overview",nodeColor:"var(--muted)",nodeStrokeColor:"transparent",nodeStrokeWidth:0,maskColor:"rgba(0, 0, 0, 0.45)",maskStrokeColor:"var(--accent)",maskStrokeWidth:1.4,bgColor:"var(--graph-bg)",style:{width:184,height:128}}),p.jsx(ak,{})]}),E?p.jsx(pp,{node:E,nodes:t,edges:r,onClose:H,onWhatIf:o}):null]})})]})}const mp=[{value:"HEAD",label:"HEAD",group:"preset"},{value:"HEAD~1",label:"HEAD~1",group:"preset"}],Zk=["preset","branch","tag","commit"];function Jk(t){var a;if(!(t!=null&&t.git))return[...mp];const r=((a=t.presets)!=null&&a.length?t.presets:mp.map(u=>u.value)).map(u=>({value:u,label:u,group:"preset"})),o=new Set(r.map(u=>u.value)),l=[...r];for(const u of t.branches||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.current?`${u.name} (current)`:u.name,detail:u.subject,group:"branch"}));for(const u of t.tags||[])o.has(u.name)||(o.add(u.name),l.push({value:u.name,label:u.name,detail:u.subject,group:"tag"}));for(const u of t.commits||[])o.has(u.sha)||(o.add(u.sha),l.push({value:u.sha,label:u.short,detail:u.subject,group:"commit"}));return l}function eE(t,r){const o=r.trim().toLowerCase();return o?t.filter(l=>l.value.toLowerCase().includes(o)||l.label.toLowerCase().includes(o)||(l.detail||"").toLowerCase().includes(o)):t}function tE(t){return Zk.map(r=>({group:r,items:t.filter(o=>o.group===r)})).filter(r=>r.items.length>0)}function nE(t){return t==="preset"?"Common":t==="branch"?"Branches":t==="tag"?"Tags":"Recent commits"}function yp({value:t,onChange:r,placeholder:o,testId:l,menuTestId:a,refs:u,onNeedRefs:d}){const f=F.useId(),g=F.useRef(null),[y,m]=F.useState(!1),[x,v]=F.useState(null),[_,S]=F.useState(0),j=F.useMemo(()=>{const b=Jk(u);return x===null?b:eE(b,x)},[u,x]),N=F.useMemo(()=>tE(j),[j]);F.useEffect(()=>{y&&d()},[y,d]),F.useEffect(()=>{S(0)},[x,y]);const k=()=>{m(!1),v(null)},T=b=>{r(b.value),k()},E=b=>{if(b.key==="ArrowDown"){if(b.preventDefault(),!y){m(!0);return}S($=>Math.min($+1,Math.max(j.length-1,0)))}else if(b.key==="ArrowUp"){if(b.preventDefault(),!y)return;S($=>Math.max($-1,0))}else if(b.key==="Enter"&&y){b.preventDefault();const $=j[_];$&&T($)}else b.key==="Escape"&&y&&(b.preventDefault(),k())};return p.jsxs("div",{className:"combo",ref:g,onBlur:b=>{b.currentTarget.contains(b.relatedTarget)||k()},children:[p.jsxs("div",{className:"combo-row",children:[p.jsx("input",{"data-testid":l,value:t,placeholder:o,spellCheck:!1,role:"combobox","aria-expanded":y,"aria-controls":f,"aria-autocomplete":"list",onChange:b=>{r(b.target.value),y&&v(b.target.value)},onKeyDown:E}),p.jsx("button",{type:"button",className:"icon-btn combo-toggle","data-testid":`${l}-toggle`,"aria-label":"Show recent refs","aria-expanded":y,onMouseDown:b=>b.preventDefault(),onClick:()=>y?k():m(!0),children:p.jsx(h0,{})})]}),y?p.jsx("div",{className:"combo-menu",id:f,role:"listbox","data-testid":a,children:N.length===0?p.jsx("div",{className:"combo-empty muted",children:"No matching refs — the typed value is kept"}):N.map(b=>p.jsxs("div",{className:"combo-group",children:[p.jsx("div",{className:"combo-heading",children:nE(b.group)}),b.items.map($=>{const O=j.indexOf($);return p.jsxs("button",{type:"button",role:"option","aria-selected":O===_,className:O===_?"combo-option active":"combo-option","data-testid":`ref-option-${$.group}`,onMouseDown:H=>H.preventDefault(),onMouseEnter:()=>S(O),onClick:()=>T($),children:[p.jsx("span",{className:"combo-label",children:$.label}),$.detail?p.jsx("span",{className:"combo-detail",children:$.detail}):null]},`${$.group}:${$.value}`)})]},b.group))}):null]})}function rE({initialPath:t,onSelect:r,onClose:o}){const[l,a]=F.useState(null),[u,d]=F.useState(t),[f,g]=F.useState(null),[y,m]=F.useState(""),[x,v]=F.useState(!1),_=F.useRef(null),S=F.useRef(0),j=async E=>{const b=S.current+1;S.current=b,v(!0);try{const $=await $e.browse(E);if(S.current!==b)return;a($),d($.path),g($.is_git?$.path:null),m("")}catch($){if(S.current!==b)return;m($ instanceof Error?$.message:String($))}finally{S.current===b&&v(!1)}};F.useEffect(()=>{var E,b;j(t),(E=_.current)==null||E.focus(),(b=_.current)==null||b.select()},[t]);const N=f||(l==null?void 0:l.path)||u,k=f&&f!==(l==null?void 0:l.path)?f.split(/[\\/]/).filter(Boolean).pop():l!=null&&l.is_git?"this repository":"this folder",T=E=>{E.key==="Escape"&&(E.preventDefault(),o())};return p.jsx("div",{className:"modal-backdrop","data-testid":"repo-explorer","data-overlay":"true",onClick:o,onKeyDown:T,children:p.jsxs("div",{className:"modal",role:"dialog","aria-modal":"true","aria-labelledby":"explorer-title",onClick:E=>E.stopPropagation(),children:[p.jsxs("div",{className:"modal-head",children:[p.jsxs("div",{children:[p.jsx("h2",{id:"explorer-title",children:"Select repository"}),p.jsx("p",{className:"muted",children:"Browse to a git root, or paste the full path."})]}),p.jsx("button",{type:"button",className:"btn ghost","data-testid":"explorer-cancel",onClick:o,children:"Cancel"})]}),p.jsxs("form",{className:"explorer-path",onSubmit:E=>{E.preventDefault(),j(u)},children:[p.jsx("input",{ref:_,"data-testid":"explorer-path",value:u,onChange:E=>d(E.target.value),spellCheck:!1,"aria-label":"Directory path"}),p.jsx("button",{type:"button",className:"btn",disabled:!(l!=null&&l.parent),onClick:()=>(l==null?void 0:l.parent)&&void j(l.parent),children:"Up"}),p.jsx("button",{type:"button",className:"btn",onClick:()=>l&&void j(l.home),children:"Home"}),p.jsx("button",{type:"submit",className:"btn",children:"Go"})]}),y?p.jsx("div",{className:"error",role:"alert",children:y}):null,p.jsx("div",{className:"explorer-list",role:"listbox","aria-label":"Folders","aria-busy":x,children:l!=null&&l.entries.length?l.entries.map(E=>{const b=f===E.path;return p.jsxs("button",{type:"button",role:"option","aria-selected":b,className:b?"explorer-row active":"explorer-row","data-testid":"explorer-entry","data-path":E.path,onClick:()=>g(E.path),onDoubleClick:()=>void j(E.path),children:[p.jsx(Sp,{}),p.jsx("span",{className:"explorer-name",children:E.name}),E.is_git?p.jsx("span",{className:"chip git-badge",children:"git"}):null]},E.path)}):p.jsx("div",{className:"muted explorer-empty",children:x?"Loading…":"No folders here"})}),p.jsxs("div",{className:"modal-foot",children:[p.jsx("span",{className:"muted explorer-current",title:N,children:N}),p.jsxs("button",{type:"button",className:"btn primary","data-testid":"explorer-use",disabled:!N,onClick:()=>N&&r(N),children:["Use ",k]})]})]})})}const wl=[{id:"obsidian",label:"Obsidian",group:"dark"},{id:"nord",label:"Nord",group:"dark"},{id:"solarized-dark",label:"Solarized Dark",group:"dark"},{id:"forest",label:"Forest",group:"dark"},{id:"rose",label:"Rose Pine",group:"dark"},{id:"amber",label:"Midnight Amber",group:"dark"},{id:"volcano",label:"Volcano",group:"dark"},{id:"lavender",label:"Lavender",group:"dark"},{id:"neon-noir",label:"Neon Noir",group:"dark"},{id:"synthwave",label:"Synthwave",group:"dark"},{id:"phosphor",label:"Phosphor",group:"dark"},{id:"aurora",label:"Aurora",group:"dark"},{id:"biolume",label:"Biolume",group:"dark"},{id:"carbon",label:"Carbon",group:"dark"},{id:"paper",label:"Paper",group:"light"},{id:"solarized-light",label:"Solarized Light",group:"light"},{id:"seafoam",label:"Seafoam",group:"light"},{id:"high-contrast",label:"High Contrast",group:"light"},{id:"sakura",label:"Sakura",group:"light"},{id:"citrus",label:"Citrus",group:"light"},{id:"peach",label:"Peach Fuzz",group:"light"},{id:"candy",label:"Cotton Candy",group:"light"},{id:"sky",label:"Clear Sky",group:"light"},{id:"coral",label:"Coral Reef",group:"light"}],iE="obsidian",pm="loadpath.theme";function oE(t){return wl.some(r=>r.id===t)}function gm(){try{const t=localStorage.getItem(pm)||"";if(oE(t))return t}catch{}return iE}function sE(t){var r;return((r=wl.find(o=>o.id===t))==null?void 0:r.group)==="light"?"light":"dark"}function mm(t){document.documentElement.dataset.theme=t,document.documentElement.style.colorScheme=sE(t);try{localStorage.setItem(pm,t)}catch{}}const vp=[{id:"review",label:"Review",testId:"tab-review",shortcut:"1",icon:a0},{id:"architecture",label:"Architecture",testId:"tab-architecture",shortcut:"2",icon:u0},{id:"graph",label:"Impact graph",testId:"tab-graph",shortcut:"3",icon:c0},{id:"prs",label:"Pull requests",testId:"tab-prs",shortcut:"4",icon:d0},{id:"settings",label:"Settings",testId:"tab-settings",shortcut:"5",icon:f0}];function lE(t){const r=t.total||0;return r<=0?null:Math.min(100,Math.round(100*(t.done||0)/r))}function Ou(t,r,o){let l;try{l=new URL(t)}catch{return}if(l.protocol!=="https:"||l.username||l.password)return;const a=l.hostname.toLowerCase();a!==r&&!a.endsWith(`.${r}`)||l.pathname.startsWith(o)&&window.open(l.toString(),"_blank","noopener,noreferrer")}function aE(){var _n,Sn,Fn,Xr,qr,Qr,Tt,Hn;const[t,r]=F.useState("review"),[o,l]=F.useState(localStorage.getItem("loadpath.repo")||""),[a,u]=F.useState(localStorage.getItem("loadpath.base")||"HEAD~1"),[d,f]=F.useState(localStorage.getItem("loadpath.head")||"HEAD"),[g,y]=F.useState(null),[m,x]=F.useState(null),[v,_]=F.useState([]),[S,j]=F.useState("review"),[N,k]=F.useState(""),[T,E]=F.useState(""),[b,$]=F.useState(null),[O,H]=F.useState(""),[I,q]=F.useState({}),[ne,G]=F.useState([]),[ee,J]=F.useState([]),[C,Y]=F.useState(localStorage.getItem("loadpath.scmRepo")||""),[V,U]=F.useState(localStorage.getItem("loadpath.provider")||"github"),[z,D]=F.useState(localStorage.getItem("loadpath.prNumber")||""),[W,M]=F.useState(localStorage.getItem("loadpath.dirty")==="1"),[R,re]=F.useState(0),[ie,ce]=F.useState(""),[fe,de]=F.useState(gm),[K,le]=F.useState(!1),[pe,_e]=F.useState(!1),[xe,ge]=F.useState(null),[je,Pe]=F.useState(null),[Ie,Re]=F.useState(!1),[tt,nt]=F.useState(!1),Qe=F.useRef(o);Qe.current=o;const ot=F.useRef(!1);ot.current=pe;const at=F.useRef(""),It=L=>{de(L),mm(L)},Ke=F.useRef(""),ze=L=>{Ke.current=L,E(L)},gt=L=>{const te=()=>{$e.indexProgress(L).then(Me=>{Ke.current&&(Me.phase&&Me.phase!=="idle"&&Me.message&&ze(Me.message),$(Me.phase&&Me.phase!=="idle"?lE(Me):null))}).catch(()=>{})};te();const ke=window.setInterval(te,250);return()=>{window.clearInterval(ke),$(null)}};F.useEffect(()=>{$e.settings().then(q).catch(()=>{}).finally(()=>le(!0)),$e.repos().then(L=>_(L.repos)).catch(()=>{})},[]);const ft=()=>o.trim()?!0:(k("Point at a local repository path first."),!1);F.useEffect(()=>{if(t!=="architecture"||!o.trim())return;const L=o;let te=!1;return $e.architecture(L).then(ke=>{!te&&Qe.current===L&&x(ke)}).catch(()=>{}),()=>{te=!0}},[t,o]);const Je=L=>{l(L),localStorage.setItem("loadpath.repo",L),L.trim()!==at.current&&(at.current="",ge(null))},vn=F.useCallback(()=>{const L=Qe.current.trim();!L||at.current===L||(at.current=L,$e.gitRefs(L).then(te=>{Qe.current.trim()===L&&ge(te)}).catch(()=>{at.current===L&&(at.current="",ge(null))}))},[]),wt=(L,te)=>{u(L),f(te),localStorage.setItem("loadpath.base",L),localStorage.setItem("loadpath.head",te)},Gt=(L,te,ke)=>{U(L),Y(te),localStorage.setItem("loadpath.provider",L),localStorage.setItem("loadpath.scmRepo",te),ke!==void 0&&(D(ke),localStorage.setItem("loadpath.prNumber",ke))},zi=L=>L==="github"?!!I.github_token_set:L==="gitlab"?!!I.gitlab_token_set:!!I.bitbucket_token_set,kt=F.useCallback(async(L=V)=>{var te;try{const ke=await $e.scmRepos(L);J(ke.repos),(te=ke.user)!=null&&te.login&&q(Me=>({...Me,...L==="github"?{github_user:ke.user.login}:L==="gitlab"?{gitlab_user:ke.user.login}:{bitbucket_user:ke.user.login}}))}catch{J([])}},[V]);F.useEffect(()=>{if(t!=="prs")return;let L=!1;return kt(V).catch(()=>{L||J([])}),()=>{L=!0}},[t,V,kt]),F.useEffect(()=>{if(!je)return;let L=!1,te=0;const ke=async()=>{try{const Me=await $e.githubOAuthPoll(je.flow_id);if(L)return;if(Me.status==="complete"){Pe(null);const Ce=await $e.settings();q(Ce),H(Me.user?`Signed in to GitHub as ${Me.user}`:"Signed in to GitHub"),kt("github");return}if(Me.status==="pending"||Me.status==="slow_down"){te=window.setTimeout(ke,Math.max(Me.interval||je.interval,5)*1e3);return}Pe(null),k(Me.status==="denied"?"GitHub sign-in was denied.":"GitHub sign-in expired. Try again.")}catch(Me){if(L)return;Pe(null),k(Me instanceof Error?Me.message:String(Me))}};return te=window.setTimeout(ke,Math.max(je.interval,5)*1e3),()=>{L=!0,window.clearTimeout(te)}},[je,kt]),F.useEffect(()=>{if(!Ie)return;let L=!1,te=0;const ke=Date.now(),Me=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.bitbucket.connected){Re(!1);const Bn=await $e.settings();q(Bn),H(Ce.bitbucket.user?`Signed in to Bitbucket as ${Ce.bitbucket.user}`:"Signed in to Bitbucket"),kt("bitbucket");return}if(Date.now()-ke>18e4){Re(!1),k("Bitbucket sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Me,1500)}catch(Ce){if(L)return;Re(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Me,1500),()=>{L=!0,window.clearTimeout(te)}},[Ie,kt]),F.useEffect(()=>{if(!tt)return;let L=!1,te=0;const ke=Date.now(),Me=async()=>{try{const Ce=await $e.oauthStatus();if(L)return;if(Ce.gitlab.connected){nt(!1);const Bn=await $e.settings();q(Bn),H(Ce.gitlab.user?`Signed in to GitLab as ${Ce.gitlab.user}`:"Signed in to GitLab"),kt("gitlab");return}if(Date.now()-ke>18e4){nt(!1),k("GitLab sign-in timed out. Finish in the browser, or try again.");return}te=window.setTimeout(Me,1500)}catch(Ce){if(L)return;nt(!1),k(Ce instanceof Error?Ce.message:String(Ce))}};return te=window.setTimeout(Me,1500),()=>{L=!0,window.clearTimeout(te)}},[tt,kt]);const hr=async(L=o)=>{if(!L.trim())return null;const te=await $e.architecture(L);return Qe.current===L&&x(te),te},An=async()=>{if(Ke.current||!ft())return;k(""),H(""),ze("Tracing load path…"),Je(o),wt(a,d);const L=gt(o);try{const te=await $e.review(o,a,d,!0,W);y(te),re(0),j("review"),r("review"),await $e.repos().then(ke=>_(ke.repos)).catch(()=>{}),await hr(o)}catch(te){k(te instanceof Error?te.message:String(te))}finally{L(),ze("")}},zn=async(L=!0)=>{if(Ke.current||!ft())return;k(""),H(""),ze(L?"Indexing…":"Full reindex…"),Je(o);const te=gt(o);try{await $e.index(o,L);const ke=await hr(o);await $e.repos().then(Me=>_(Me.repos)).catch(()=>{}),ke!=null&&ke.indexed&&(j("architecture"),r("architecture"))}catch(ke){k(ke instanceof Error?ke.message:String(ke))}finally{te(),ze("")}},pr=async()=>{if(!Ke.current&&ft()){k(""),H(""),ze("Detecting layout…"),Je(o);try{const L=await $e.init(o);H(L.message),await $e.repos().then(te=>_(te.repos)).catch(()=>{})}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},gr=async()=>{if(g!=null&&g.markdown)try{await navigator.clipboard.writeText(g.markdown),H("Copied markdown brief")}catch(L){k(L instanceof Error?L.message:String(L))}},mr=async()=>{if(!Ke.current){if(!(g!=null&&g.markdown)||!C||!z){k("Pick a pull request first (Pull requests tab), then post the brief.");return}ze("Posting Loadpath brief…");try{const L=await $e.postComment(V,C,Number(z),g.markdown);H(L.updated?"Updated the Loadpath PR comment":"Posted the Loadpath PR comment")}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},yr=async()=>{if(!Ke.current){k(""),ze("Fetching pull requests…");try{const L=await $e.prs(V,C);G(L.pull_requests);const te=ee.find(ke=>ke.slug.toLowerCase()===C.trim().toLowerCase());te!=null&&te.local_path&&Je(te.local_path)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},un=async()=>{k("");try{const L=await $e.githubOAuthStart();Pe(L),Ou(L.verification_uri_complete,"github.com","/login/device")}catch(L){k(L instanceof Error?L.message:String(L))}},cn=async()=>{k("");try{const L=await $e.bitbucketOAuthStart();Re(!0),Ou(L.authorize_url,"bitbucket.org","/site/oauth2/authorize")}catch(L){Re(!1),k(L instanceof Error?L.message:String(L))}},Ur=async()=>{k("");try{const L=await $e.gitlabOAuthStart();nt(!0),Ou(L.authorize_url,new URL(L.authorize_url).hostname,"/oauth/authorize")}catch(L){nt(!1),k(L instanceof Error?L.message:String(L))}},Dn=async L=>{if(!(Ke.current||!o.trim())){k(""),ze("Walking what-if path…");try{const te=await $e.whatIf(o,L);H(`${te.title} — ${te.confidence.level} · ${(te.sinks||[]).length} sinks`),y({...te,markdown:te.markdown||"",index:te.index||(g==null?void 0:g.index),workspace:te.workspace||(g==null?void 0:g.workspace)}),re(0),j("review"),r("review")}catch(te){k(te instanceof Error?te.message:String(te))}finally{ze("")}}},Yr=async L=>{if(Ke.current)return;Gt(L.provider,L.repo,String(L.number));const te=ee.find(Ce=>Ce.slug.toLowerCase()===L.repo.toLowerCase());te!=null&&te.local_path&&Je(te.local_path),k(""),ze(`Fetching ${L.provider} #${L.number}…`);const ke=(te==null?void 0:te.local_path)||o,Me=ke?gt(ke):()=>{};try{const Ce=await $e.reviewPr(L.provider,L.repo,L.number,(te==null?void 0:te.local_path)||o||void 0);y(Ce),re(0),Ce.pull_request&&typeof Ce.pull_request.repo_path=="string"&&Je(Ce.pull_request.repo_path),wt(String(Ce.base||L.target_branch),String(Ce.head||L.source_branch)),j("review"),r("review")}catch(Ce){wt(L.base_sha||L.target_branch,L.head_sha||L.source_branch),r("review"),k(Ce instanceof Error?Ce.message:String(Ce))}finally{Me(),ze("")}},$n=async L=>{k("");try{q(await $e.oauthDisconnect(L)),V===L&&J([]),H(`Disconnected ${L}`)}catch(te){k(te instanceof Error?te.message:String(te))}},Gr=async L=>{L.preventDefault();const te=new FormData(L.currentTarget),ke={github_token:String(te.get("github_token")||""),github_oauth_client_id:String(te.get("github_oauth_client_id")||""),github_host:String(te.get("github_host")||""),gitlab_token:String(te.get("gitlab_token")||""),gitlab_host:String(te.get("gitlab_host")||""),gitlab_oauth_client_id:String(te.get("gitlab_oauth_client_id")||""),gitlab_oauth_client_secret:String(te.get("gitlab_oauth_client_secret")||""),bitbucket_token:String(te.get("bitbucket_token")||""),bitbucket_username:String(te.get("bitbucket_username")||""),bitbucket_oauth_client_id:String(te.get("bitbucket_oauth_client_id")||""),bitbucket_oauth_client_secret:String(te.get("bitbucket_oauth_client_secret")||""),ai_provider:String(te.get("ai_provider")||"none"),ai_api_key:String(te.get("ai_api_key")||""),ai_model:String(te.get("ai_model")||""),ai_base_url:String(te.get("ai_base_url")||"")},Me=v.length?{...ke,workspaces:v.map(Ce=>({path:Ce.path,name:Ce.name}))}:ke;try{q(await $e.saveSettings(Me)),H("Settings saved on this machine")}catch(Ce){k(Ce instanceof Error?Ce.message:String(Ce))}},vr=async()=>{if(!(!g||Ke.current)){ze("Residual analysis…");try{const L=await $e.residual(g);ce(L.note)}catch(L){k(L instanceof Error?L.message:String(L))}finally{ze("")}}},xr=F.useRef(An);xr.current=An;const Xt=F.useRef(t);Xt.current=t,F.useEffect(()=>{const L=te=>{if(ot.current){te.key==="Escape"&&(te.preventDefault(),_e(!1));return}const ke=te.target;if(ke&&(ke.tagName==="INPUT"||ke.tagName==="TEXTAREA"||ke.tagName==="SELECT"||ke.isContentEditable)){te.key==="Escape"&&ke.blur();return}if(te.key==="Escape"){k(""),H("");return}const Me=vp.find(Ce=>Ce.shortcut===te.key);if(Me&&!te.metaKey&&!te.ctrlKey&&!te.altKey&&r(Me.id),(te.metaKey||te.ctrlKey)&&te.key==="Enter"){if(Xt.current==="settings"||Xt.current==="prs"||Ke.current)return;te.preventDefault(),xr.current()}};return window.addEventListener("keydown",L),()=>window.removeEventListener("keydown",L)},[]);const On=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.nodes)??[]:(g==null?void 0:g.nodes)??[],[S,m,g]),xn=F.useMemo(()=>S==="architecture"?(m==null?void 0:m.edges)??[]:(g==null?void 0:g.edges)??[],[S,m,g]),Di=g!=null&&g.index?`${g.index.counts.nodes} nodes · ${g.index.counts.edges} edges`:m!=null&&m.indexed?`${m.counts.nodes} nodes · ${m.counts.edges} edges`:"Not indexed",wn=((g==null?void 0:g.findings)||[]).filter(L=>!L.waived);return p.jsxs("div",{className:"app",children:[p.jsx("a",{className:"skip",href:"#main",children:"Skip to content"}),p.jsxs("nav",{className:"rail","data-testid":"rail","aria-label":"Primary",children:[p.jsxs("div",{className:"brand",children:[p.jsx("div",{className:"brand-mark",children:"Loadpath"}),p.jsx("div",{className:"brand-sub",children:"Load-path review"})]}),vp.map(L=>{const te=L.icon,ke=t===L.id;return p.jsxs("button",{type:"button","data-testid":L.testId,className:ke?"nav-item active":"nav-item","aria-current":ke?"page":void 0,"aria-label":L.label,onClick:()=>r(L.id),children:[p.jsx(te,{}),p.jsx("span",{children:L.label})]},L.id)}),p.jsxs("div",{className:"theme-pick",children:[p.jsx("label",{htmlFor:"theme-select",children:"Theme"}),p.jsx("select",{id:"theme-select","data-testid":"theme-select",value:fe,onChange:L=>It(L.target.value),children:["dark","light"].map(L=>p.jsx("optgroup",{label:L==="dark"?"Dark":"Light",children:wl.filter(te=>te.group===L).map(te=>p.jsx("option",{value:te.id,children:te.label},te.id))},L))})]}),p.jsxs("div",{className:"rail-foot",children:[p.jsx("div",{className:"muted",role:"status",children:T||Di}),p.jsxs("div",{className:"kbd-hint",children:[p.jsx("kbd",{children:"1"}),"–",p.jsx("kbd",{children:"5"})," tabs · ",p.jsx("kbd",{children:"Ctrl"}),"+",p.jsx("kbd",{children:"Enter"})," review"]})]})]}),p.jsxs("div",{className:"main",id:"main",children:[T?p.jsxs("div",{className:b!=null?"progress determinate":"progress",role:"status","aria-live":"polite","aria-busy":"true","data-testid":"index-progress",children:[p.jsx("i",{style:b!=null?{width:`${b}%`}:void 0}),p.jsx("span",{className:"sr-only",children:T})]}):null,p.jsxs("header",{className:"topbar","data-testid":"topbar",children:[v.length>0?p.jsxs("label",{className:"field workspace",children:[p.jsx("span",{children:"Workspace"}),p.jsxs("select",{"data-testid":"workspace-select",value:v.some(L=>L.path===o)?o:"",onChange:L=>{L.target.value&&Je(L.target.value)},children:[p.jsx("option",{value:"",children:"Indexed repos…"}),v.map(L=>p.jsxs("option",{value:L.path,children:[L.name,L.indexed?` (${L.counts.nodes})`:""]},L.path))]})]}):null,p.jsxs("label",{className:"field path",children:[p.jsx("span",{children:"Repository"}),p.jsxs("div",{className:"path-row",children:[p.jsx("input",{"data-testid":"repo-path",placeholder:"Local monorepo path",value:o,onChange:L=>{const te=L.target.value;l(te),te.trim()!==at.current&&(at.current="",ge(null))},spellCheck:!1}),p.jsx("button",{type:"button",className:"icon-btn","data-testid":"btn-browse-repo","aria-label":"Browse for a local repository",onClick:()=>_e(!0),children:p.jsx(Sp,{})})]})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Base"}),p.jsx(yp,{testId:"base-ref",menuTestId:"base-ref-menu",value:a,onChange:L=>wt(L,d),placeholder:"base",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field ref",children:[p.jsx("span",{children:"Head"}),p.jsx(yp,{testId:"head-ref",menuTestId:"head-ref-menu",value:d,onChange:L=>wt(a,L),placeholder:"head",refs:xe,onNeedRefs:vn})]}),p.jsxs("label",{className:"field dirty",children:[p.jsx("span",{children:"Working tree"}),p.jsx("button",{type:"button",className:W?"chip-btn active":"chip-btn","data-testid":"btn-dirty","aria-pressed":W,onClick:()=>{const L=!W;M(L),localStorage.setItem("loadpath.dirty",L?"1":"0")},children:W?"Include uncommitted":"Committed range"})]}),p.jsxs("div",{className:"topbar-actions",children:[p.jsx("button",{type:"button","data-testid":"btn-init",disabled:!!T,onClick:pr,children:"Draft config"}),p.jsx("button",{type:"button","data-testid":"btn-index",disabled:!!T,onClick:()=>zn(!0),children:"Index"}),p.jsx("button",{type:"button","data-testid":"btn-review",className:"btn primary",disabled:!!T,onClick:An,children:"Review"})]})]}),p.jsxs("div",{className:"alerts",children:[N?p.jsxs("div",{className:"error","data-testid":"error",role:"alert",children:[p.jsx("span",{children:N}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>k(""),"aria-label":"Dismiss error",children:"×"})]}):null,O?p.jsxs("div",{className:"banner","data-testid":"status-note",children:[p.jsx("span",{children:O}),p.jsx("button",{type:"button",className:"dismiss",onClick:()=>H(""),"aria-label":"Dismiss",children:"×"})]}):null,((_n=g==null?void 0:g.index)!=null&&_n.stale||m!=null&&m.stale)&&(t==="review"||t==="architecture")?p.jsx("div",{className:"banner stale","data-testid":"index-stale",children:"Index is stale — files changed since the last extract. Index again before trusting this walk."}):null,((Sn=g==null?void 0:g.index)==null?void 0:Sn.django_boot)==="failed"||(m==null?void 0:m.django_boot)==="failed"?p.jsx("div",{className:"banner warn","data-testid":"django-boot-failed",children:((Fn=g==null?void 0:g.index)==null?void 0:Fn.django_boot_detail)||(m==null?void 0:m.django_boot_detail)||"django.setup() failed"}):null,(Xr=g==null?void 0:g.workspace)!=null&&Xr.dirty_overlaps_review&&t==="review"?p.jsxs("div",{className:"banner warn","data-testid":"dirty-tree",children:["Uncommitted files overlap this review: ",(g.workspace.dirty_overlap||[]).slice(0,6).join(", ")]}):null]}),p.jsxs("div",{className:"stage",children:[t==="review"&&p.jsxs("div",{className:"content","data-testid":"review-layout",children:[p.jsx("aside",{className:"brief","data-testid":"brief",children:g?p.jsx(uE,{review:g,findings:wn,aiNote:ie,busy:!!T,tourIndex:R,onTour:re,onAskAi:vr,onCopy:gr,onPost:mr}):p.jsxs("div",{className:"empty","data-testid":"review-empty",children:[p.jsx("h2",{children:"Trace the force of this diff"}),p.jsx("p",{children:"The graph is the architecture. The brief is where this change travels — not a hunk list."}),p.jsxs("ol",{children:[p.jsx("li",{children:"Point at a Django + React monorepo, or pick an indexed workspace."}),p.jsxs("li",{children:["Index it. Missing ",p.jsx("code",{children:"loadpath.yml"})," is drafted from ",p.jsx("code",{children:"manage.py"})," and"," ",p.jsx("code",{children:"src/features"}),"."]}),p.jsx("li",{children:"Review a git range, or open a pull request so base/head become a three-dot merge-base."})]})]})}),p.jsx("div",{className:"graph-wrap","data-testid":"review-graph",children:g?p.jsx($u,{nodes:g.nodes,edges:g.edges,onWhatIf:Dn,focusPath:(qr=g.read_order[R])==null?void 0:qr.path}):null})]}),t==="architecture"&&p.jsxs("div",{className:"content","data-testid":"architecture-panel",children:[p.jsx("aside",{className:"brief","data-testid":"architecture-brief",children:m!=null&&m.indexed?p.jsx(cE,{architecture:m,busy:!!T,onReindex:()=>zn(!1),onReview:An}):p.jsx("p",{className:"muted","data-testid":"architecture-empty",children:"Index this repo to build the architecture graph. Review then walks that same graph for a git range — it does not start from a hunk list."})}),p.jsx("div",{className:"graph-wrap","data-testid":"architecture-graph",children:m!=null&&m.indexed?p.jsx($u,{nodes:m.nodes,edges:m.edges,onWhatIf:Dn}):null})]}),t==="graph"&&p.jsxs("div",{className:"graph-wrap","data-testid":"graph-full",style:{height:"100%"},children:[p.jsxs("div",{className:"graph-modes",children:[p.jsxs("div",{className:"seg","aria-label":"Graph scope",children:[p.jsx("button",{type:"button","aria-pressed":S==="review","data-testid":"graph-mode-review",className:S==="review"?"active":"",onClick:()=>j("review"),children:"This review"}),p.jsx("button",{type:"button","aria-pressed":S==="architecture","data-testid":"graph-mode-architecture",className:S==="architecture"?"active":"",onClick:()=>j("architecture"),children:"Indexed architecture"})]}),p.jsxs("div",{className:"legend","aria-hidden":"true",children:[p.jsxs("span",{children:[p.jsx("i",{})," cheap"]}),p.jsxs("span",{children:[p.jsx("i",{className:"exp"})," expensive"]}),p.jsxs("span",{children:[p.jsx("i",{className:"crit"})," critical"]}),p.jsxs("span",{children:[p.jsx("i",{className:"dash"})," inferred"]})]})]}),On.length?p.jsx($u,{nodes:On,edges:xn,onWhatIf:Dn}):p.jsx("p",{className:"empty","data-testid":"graph-empty",children:"Index the repo or run a review first. Click a node to inspect it."})]}),t==="prs"&&p.jsxs("div",{className:"pr-list","data-testid":"pr-list",children:[p.jsxs("div",{className:"pr-toolbar",children:[p.jsxs("label",{className:"field provider",children:[p.jsx("span",{children:"Provider"}),p.jsxs("select",{"data-testid":"pr-provider",value:V,onChange:L=>Gt(L.target.value,C,z),children:[p.jsx("option",{value:"github",children:"GitHub"}),p.jsx("option",{value:"gitlab",children:"GitLab"}),p.jsx("option",{value:"bitbucket",children:"Bitbucket"})]})]}),p.jsxs("label",{className:"field",children:[p.jsx("span",{children:"Repository"}),p.jsx("input",{"data-testid":"pr-repo",placeholder:ee.length?"Search your repos":"owner/repo",value:C,onChange:L=>Gt(V,L.target.value,z),list:"scm-repos",spellCheck:!1}),p.jsx("datalist",{id:"scm-repos",children:ee.map(L=>p.jsxs("option",{value:L.slug,children:[L.private?"private":"public",L.local_path?" · local":""]},L.slug))})]}),p.jsx("button",{type:"button","data-testid":"btn-refresh-repos",className:"btn",disabled:!!T||!zi(V),onClick:()=>{kt(V)},children:"My repos"}),p.jsx("button",{type:"button","data-testid":"btn-list-prs",className:"btn",disabled:!!T,onClick:yr,children:"List PRs"})]}),ee.length>0?p.jsxs("p",{className:"muted scm-count","data-testid":"scm-repo-count",children:[ee.length," ",V," repositor",ee.length===1?"y":"ies",V==="github"&&I.github_user?` · @${String(I.github_user)}`:"",V==="gitlab"&&I.gitlab_user?` · @${String(I.gitlab_user)}`:"",V==="bitbucket"&&I.bitbucket_user?` · ${String(I.bitbucket_user)}`:""]}):null,ne.length===0?p.jsxs("div",{className:"empty","data-testid":"pr-empty",children:[p.jsx("h2",{children:"No pull requests loaded"}),p.jsx("p",{children:"Sign in under Settings (or paste a token), load your repositories, then list open PRs. Reviewing a PR fills base and head from its SHAs."})]}):ne.map(L=>p.jsxs("article",{className:"pr","data-testid":`pr-${L.number}`,children:[p.jsxs("h3",{children:["#",L.number," ",L.title]}),p.jsxs("div",{className:"pr-meta muted",children:[p.jsx("span",{className:`chip ${L.draft?"":"open"}`,children:L.draft?"draft":L.state}),p.jsx("span",{children:L.author}),p.jsxs("span",{children:[L.source_branch," → ",L.target_branch]})]}),p.jsxs("div",{className:"pr-actions",children:[p.jsxs("a",{href:L.url,target:"_blank",rel:"noreferrer",children:["Open on ",L.provider]}),p.jsx("button",{type:"button",className:"btn primary","data-testid":`pr-review-${L.number}`,onClick:()=>void Yr(L),children:"Review this PR"})]})]},`${L.provider}-${L.number}`))]}),t==="settings"&&K&&p.jsxs("form",{className:"settings","data-testid":"settings-form",onSubmit:Gr,children:[p.jsxs("div",{children:[p.jsx("h1",{children:"Settings"}),p.jsx("p",{className:"muted",children:"Tokens stay on this machine in ~/.loadpath/settings.json. AI runs only on residual uncertainty the graph could not close."})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Appearance"}),p.jsx("p",{className:"muted",children:"Local to this browser. High contrast is a first-class theme, not an afterthought."}),p.jsx("div",{className:"theme-grid","data-testid":"theme-grid",children:wl.map(L=>p.jsxs("button",{type:"button","data-theme":L.id,className:fe===L.id?"theme-swatch active":"theme-swatch","data-testid":`theme-${L.id}`,onClick:()=>It(L.id),children:[p.jsx("div",{className:"swatch-bar","aria-hidden":"true"}),p.jsx("div",{className:"name",children:L.label}),p.jsx("div",{className:"group",children:L.group})]},L.id))})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Source control"}),p.jsx("p",{className:"muted",children:"Sign in with OAuth to list every repository the account can access. Tokens stay in ~/.loadpath/settings.json. A classic PAT still works if you prefer not to register an OAuth app."}),p.jsxs("div",{className:"scm-login","data-testid":"scm-github",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitHub"}),p.jsx("p",{className:"muted",children:I.github_token_set?I.github_user?`Signed in as @${String(I.github_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.github_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-github-disconnect",onClick:()=>void $n("github"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-github-login",disabled:!!je||!I.github_oauth_ready,onClick:()=>void un(),children:je?"Waiting for GitHub…":"Sign in with GitHub"})})]}),je?p.jsxs("p",{className:"oauth-code","data-testid":"github-user-code",children:["Enter ",p.jsx("code",{children:je.user_code})," at GitHub if the browser did not fill it in."]}):null,I.github_oauth_ready?null:p.jsx("p",{className:"muted",children:"Sign-in needs a GitHub OAuth App with Device Flow enabled. Set LOADPATH_GITHUB_CLIENT_ID or paste the client ID below."}),p.jsx("label",{htmlFor:"github_oauth_client_id",children:"GitHub OAuth client ID"}),p.jsx("input",{id:"github_oauth_client_id",name:"github_oauth_client_id","data-testid":"github-oauth-client-id",placeholder:"Ov23…",defaultValue:String(I.github_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"github_token",children:"GitHub token (optional PAT)"}),p.jsx("input",{id:"github_token",name:"github_token",type:"password",placeholder:"ghp_…",autoComplete:"off"}),p.jsx("label",{htmlFor:"github_host",children:"GitHub host (Enterprise)"}),p.jsx("input",{id:"github_host",name:"github_host","data-testid":"github-host",placeholder:"github.com",defaultValue:String(I.github_host||""),autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-gitlab",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"GitLab"}),p.jsx("p",{className:"muted",children:I.gitlab_token_set?I.gitlab_user?`Signed in as @${String(I.gitlab_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.gitlab_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-gitlab-disconnect",onClick:()=>void $n("gitlab"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-gitlab-login",disabled:tt||!I.gitlab_oauth_ready,onClick:()=>void Ur(),children:tt?"Waiting for GitLab…":"Sign in with GitLab"})})]}),p.jsx("label",{htmlFor:"gitlab_host",children:"GitLab host"}),p.jsx("input",{id:"gitlab_host",name:"gitlab_host","data-testid":"gitlab-host",placeholder:"gitlab.com",defaultValue:String(I.gitlab_host||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_id",children:"GitLab OAuth application ID"}),p.jsx("input",{id:"gitlab_oauth_client_id",name:"gitlab_oauth_client_id","data-testid":"gitlab-oauth-client-id",defaultValue:String(I.gitlab_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_oauth_client_secret",children:"GitLab OAuth secret"}),p.jsx("input",{id:"gitlab_oauth_client_secret",name:"gitlab_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"gitlab_token",children:"GitLab token (optional PAT)"}),p.jsx("input",{id:"gitlab_token",name:"gitlab_token",type:"password",placeholder:"glpat-…",autoComplete:"off"}),p.jsxs("div",{className:"scm-login","data-testid":"scm-bitbucket",children:[p.jsxs("div",{children:[p.jsx("strong",{children:"Bitbucket"}),p.jsx("p",{className:"muted",children:I.bitbucket_token_set?I.bitbucket_user?`Signed in as ${String(I.bitbucket_user)}`:"Token saved on this machine":"Not connected"})]}),p.jsx("div",{className:"btn-row",children:I.bitbucket_token_set?p.jsx("button",{type:"button",className:"btn","data-testid":"btn-bitbucket-disconnect",onClick:()=>void $n("bitbucket"),children:"Disconnect"}):p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-bitbucket-login",disabled:Ie||!I.bitbucket_oauth_ready,onClick:()=>void cn(),children:Ie?"Waiting for Bitbucket…":"Sign in with Bitbucket"})})]}),I.bitbucket_oauth_ready?null:p.jsxs("p",{className:"muted",children:["Sign-in needs a Bitbucket OAuth consumer (key + secret). Callback URL:"," ",p.jsx("code",{children:"/api/oauth/bitbucket/callback"})," on this app origin."]}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_id",children:"Bitbucket OAuth key"}),p.jsx("input",{id:"bitbucket_oauth_client_id",name:"bitbucket_oauth_client_id","data-testid":"bitbucket-oauth-client-id",defaultValue:String(I.bitbucket_oauth_client_id||""),autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_oauth_client_secret",children:"Bitbucket OAuth secret"}),p.jsx("input",{id:"bitbucket_oauth_client_secret",name:"bitbucket_oauth_client_secret",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_token",children:"Bitbucket token (optional app password)"}),p.jsx("input",{id:"bitbucket_token",name:"bitbucket_token",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"bitbucket_username",children:"Bitbucket username (app passwords)"}),p.jsx("input",{id:"bitbucket_username",name:"bitbucket_username",defaultValue:String(I.bitbucket_username||"")})]}),p.jsxs("section",{className:"settings-card",children:[p.jsx("h2",{children:"Residual AI"}),p.jsx("label",{htmlFor:"ai_provider",children:"Provider"}),p.jsxs("select",{id:"ai_provider",name:"ai_provider",defaultValue:String(((Qr=I.ai)==null?void 0:Qr.provider)||"none"),children:[p.jsx("option",{value:"none",children:"none (graph only)"}),p.jsx("option",{value:"anthropic",children:"Anthropic"}),p.jsx("option",{value:"openai",children:"OpenAI"}),p.jsx("option",{value:"grok",children:"Grok / xAI"}),p.jsx("option",{value:"deepseek",children:"DeepSeek"}),p.jsx("option",{value:"cursor",children:"Cursor-compatible (OpenAI protocol)"}),p.jsx("option",{value:"ollama",children:"Ollama local"})]}),p.jsx("label",{htmlFor:"ai_api_key",children:"API key"}),p.jsx("input",{id:"ai_api_key",name:"ai_api_key",type:"password",autoComplete:"off"}),p.jsx("label",{htmlFor:"ai_model",children:"Model"}),p.jsx("input",{id:"ai_model",name:"ai_model","data-testid":"ai-model",placeholder:"optional override",defaultValue:String(((Tt=I.ai)==null?void 0:Tt.model)||"")}),p.jsx("label",{htmlFor:"ai_base_url",children:"Base URL"}),p.jsx("input",{id:"ai_base_url",name:"ai_base_url","data-testid":"ai-base-url",placeholder:"optional, OpenAI-compatible",defaultValue:String(((Hn=I.ai)==null?void 0:Hn.base_url)||"")}),p.jsx("button",{className:"btn primary",type:"submit","data-testid":"btn-save-settings",children:"Save"})]})]})]})]}),pe?p.jsx(rE,{initialPath:o,onClose:()=>_e(!1),onSelect:L=>{Je(L),_e(!1)}}):null]})}function uE({review:t,findings:r,aiNote:o,busy:l,tourIndex:a,onTour:u,onAskAi:d,onCopy:f,onPost:g}){var m,x,v,_,S,j,N,k,T,E,b,$,O,H;const y=[...new Set(t.confidence.reasons||[])];return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:`merge-box ${t.confidence.level}`,children:[p.jsxs("div",{className:`level ${t.confidence.level}`,children:[t.confidence.level.toUpperCase()," — ",t.title]}),y.length?p.jsx("ul",{className:"reasons",children:y.map(I=>p.jsx("li",{children:I},I))}):null,t.low_risk?p.jsx("span",{className:"chip",children:"low-risk"}):null,t.change_kinds.map(I=>p.jsx("span",{className:"chip",children:No(I)},I)),(m=t.contract_break)!=null&&m.kind&&t.contract_break.kind!=="none"?p.jsxs("span",{className:`chip ${t.contract_break.kind==="breaking"?"blocker":""}`,"data-testid":"contract-kind",children:["contract ",t.contract_break.kind]}):null]}),p.jsxs("div",{className:"metrics",children:[p.jsxs("div",{className:"metric",children:[p.jsxs("div",{className:"n",children:[t.confidence.covered_sinks,"/",t.confidence.sinks]}),p.jsx("div",{className:"l",children:"Sinks tested"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:r.length}),p.jsx("div",{className:"l",children:"Findings"})]}),p.jsxs("div",{className:"metric",children:[p.jsx("div",{className:"n",children:t.residuals.length}),p.jsx("div",{className:"l",children:"Residuals"})]})]}),p.jsx("pre",{className:"headline",children:t.headline}),t.index?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Index ",p.jsx("span",{className:"count",children:t.index.counts.nodes})]}),p.jsxs("div",{className:"muted",children:["Walked ",t.index.counts.nodes," nodes / ",t.index.counts.edges," edges",t.index.reindex_skipped?" from an unchanged index":t.index.reindexed?" after an incremental refresh":" from the existing index",t.index.django_boot&&t.index.django_boot!=="off"?` · Django boot ${t.index.django_boot}`:"",(x=t.workspace)!=null&&x.three_dot?" · three-dot range":""]})]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Read this ",p.jsx("span",{className:"count",children:t.read_order.length})]}),t.read_order.map((I,q)=>p.jsxs("div",{className:q===a?"read-item tour-current":"read-item",children:[p.jsxs("span",{className:"file",children:[q+1,". ",I.path]}),p.jsx("div",{className:"why",children:I.why})]},I.path)),t.read_order.length>0?p.jsxs("div",{className:"btn-row tour-row",children:[p.jsx("button",{type:"button",className:"btn","data-testid":"btn-tour-prev",disabled:a<=0,onClick:()=>u(Math.max(0,a-1)),children:"Previous"}),p.jsx("button",{type:"button",className:"btn primary","data-testid":"btn-tour-next",disabled:a>=t.read_order.length-1,onClick:()=>u(Math.min(t.read_order.length-1,a+1)),children:"Next in read order"}),p.jsxs("span",{className:"muted",children:[a+1,"/",t.read_order.length]})]}):null]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Clusters ",p.jsx("span",{className:"count",children:t.clusters.length})]}),t.clusters.map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:I.title})," — ",I.files.join(", ")]},I.id))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Architecture ",p.jsx("span",{className:"count",children:r.length})]}),r.length===0?p.jsx("div",{className:"muted",children:t.architecture_note}):r.map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${I.severity}`,children:I.severity}),I.message]},I.rule+I.message))]}),p.jsx(ym,{cards:t.deepening}),(_=(v=t.contract_break)==null?void 0:v.reasons)!=null&&_.length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Contract ",p.jsx("span",{className:"count",children:t.contract_break.kind})]}),t.contract_break.reasons.map(I=>p.jsx("div",{className:"muted",children:I},I))]}):null,(S=t.auth)!=null&&S.note?p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Auth"}),p.jsx("div",{className:"muted",children:t.auth.note}),(t.auth.missing_permissions||[]).map(I=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:"chip warning",children:"missing"}),I.name]},I.id))]}):null,(t.suggested_tests||[]).length?p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Suggested tests ",p.jsx("span",{className:"count",children:(j=t.suggested_tests)==null?void 0:j.length})]}),(t.suggested_tests||[]).map(I=>p.jsxs("div",{className:"residual",children:[p.jsx("strong",{children:I.title}),p.jsx("pre",{className:"headline",children:I.body})]},I.title))]}):null,(N=t.trend)!=null&&N.note?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Confidence trend"}),p.jsx("div",{className:"muted",children:t.trend.note}),(t.trend.points||[]).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[I.level," · ",_p(I.created_at),I.sinks!=null?` · ${I.sinks} sinks`:""]},I.id))]}):null,p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Residual ",p.jsx("span",{className:"count",children:t.residuals.length})]}),p.jsx("p",{className:"muted",children:"AI is only used here, on what the graph could not close."}),t.residuals.map(I=>p.jsx("div",{className:"residual muted",children:I},I))]}),(T=(k=t.evolution)==null?void 0:k.notes)!=null&&T.length||(b=(E=t.evolution)==null?void 0:E.hotspots)!=null&&b.some(I=>I.commits)?p.jsxs("details",{className:"section",children:[p.jsx("summary",{children:"Churn & coupling"}),((($=t.evolution)==null?void 0:$.notes)||[]).map(I=>p.jsx("div",{className:"muted",children:I},I)),(((O=t.evolution)==null?void 0:O.hotspots)||[]).filter(I=>I.commits).slice(0,6).map(I=>p.jsxs("div",{className:"muted",children:[p.jsx("span",{className:"file",children:I.path})," — ",I.commits," commits, bus factor ",I.bus_factor]},I.path))]}):null,p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:l,onClick:d,children:"Ask configured model"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-copy-markdown",onClick:f,children:"Copy markdown"}),p.jsx("button",{type:"button",className:"btn","data-testid":"btn-post-comment",onClick:g,children:"Post to PR"})]}),o?p.jsx("pre",{className:"headline",children:o}):null,p.jsx("div",{className:"kicker",children:"Reviewers"}),p.jsx("div",{className:"muted",children:t.suggested_reviewers.join(", ")||"—"}),(H=t.knowledge_owners)!=null&&H.length?p.jsxs("div",{className:"muted",children:["Knowledge: ",t.knowledge_owners.join(", ")]}):null]})}function cE({architecture:t,busy:r,onReindex:o,onReview:l}){const a=t.findings.filter(u=>!u.waived);return p.jsxs(p.Fragment,{children:[p.jsxs("div",{className:"merge-box high",children:[p.jsxs("div",{className:"level high",children:["INDEXED — ",t.counts.nodes," nodes"]}),p.jsxs("div",{className:"muted",style:{marginTop:8},children:[t.indexed_at?`Last index ${_p(t.indexed_at)}`:"Indexed",t.incremental?" · incremental":" · full",t.stale?" · stale":"",t.django_boot&&t.django_boot!=="off"?` · Django boot ${t.django_boot}`:""]}),p.jsxs("span",{className:"chip",children:[t.counts.edges," edges"]}),t.has_config?p.jsx("span",{className:"chip",children:"loadpath.yml"}):null]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Bounded contexts"}),Object.values(t.contexts).map(u=>p.jsxs("div",{className:"muted",children:[p.jsx("strong",{children:u.name})," — ",(u.django_apps||[]).join(", ")||"no apps"," ·"," ",(u.owners||[]).join(", ")||"unowned"]},u.name))]}),p.jsxs("details",{className:"section",children:[p.jsxs("summary",{children:["Rules ",p.jsx("span",{className:"count",children:(t.rules||[]).length})]}),(t.rules||[]).map(u=>p.jsx("div",{className:"muted",children:u},u))]}),p.jsxs("details",{className:"section",open:!0,children:[p.jsxs("summary",{children:["Findings ",p.jsx("span",{className:"count",children:a.length})]}),a.length===0?p.jsx("div",{className:"muted",children:"No architecture rule hits on the full graph."}):a.map(u=>p.jsxs("div",{className:"finding",children:[p.jsx("span",{className:`chip ${u.severity}`,children:u.severity}),u.message]},u.rule+u.message))]}),p.jsx(ym,{cards:t.deepening}),p.jsxs("details",{className:"section",open:!0,children:[p.jsx("summary",{children:"Types"}),p.jsx("table",{className:"type-table",children:p.jsx("tbody",{children:Object.entries(t.type_counts||{}).sort((u,d)=>d[1]-u[1]).slice(0,12).map(([u,d])=>p.jsxs("tr",{children:[p.jsx("td",{children:_l(u)}),p.jsx("td",{children:d})]},u))})})]}),p.jsxs("div",{className:"btn-row",children:[p.jsx("button",{type:"button",className:"btn",disabled:r,onClick:o,"data-testid":"btn-full-reindex",children:"Full reindex"}),p.jsx("button",{type:"button",className:"btn primary",disabled:r,onClick:l,children:"Review against this index"})]})]})}function ym({cards:t}){const r=t||[];return r.length?p.jsxs("details",{className:"section",open:!0,"data-testid":"deepening-list",children:[p.jsxs("summary",{children:["Depth ",p.jsx("span",{className:"count",children:r.length})]}),p.jsx("p",{className:"muted",children:"Deepening opportunities: more behaviour behind a smaller interface, at a real seam."}),r.map(o=>p.jsxs("div",{className:"finding","data-testid":"deepening-card",children:[p.jsx("span",{className:`chip ${o.strength}`,children:l0(o.strength)}),o.top?p.jsx("span",{className:"chip",children:"top"}):null,p.jsx("strong",{children:o.title}),p.jsx("div",{className:"why",children:o.message}),o.deletion_test?p.jsxs("div",{className:"muted",children:["Deletion test: ",o.deletion_test]}):null,o.before&&o.after?p.jsxs("div",{className:"muted",children:[o.before," → ",o.after]}):null]},o.rule+o.title))]}):null}mm(gm());i0.createRoot(document.getElementById("root")).render(p.jsx(F.StrictMode,{children:p.jsx(aE,{})}));export{Ik as L,hE as a,dE as c,p as j,fE as l,F as r,_l as t}; diff --git a/src/loadpath/static/index.html b/src/loadpath/static/index.html index 18dfb64..d8ebada 100644 --- a/src/loadpath/static/index.html +++ b/src/loadpath/static/index.html @@ -17,7 +17,7 @@ - + diff --git a/tests/e2e/test_ui_flows.py b/tests/e2e/test_ui_flows.py index b78fa60..24d76bd 100644 --- a/tests/e2e/test_ui_flows.py +++ b/tests/e2e/test_ui_flows.py @@ -157,6 +157,51 @@ def test_ui_index_review_graph_copy_and_workspace(live_app, browser_page): assert "pull request" in post_err.lower() +@pytest.mark.playwright +def test_ui_index_polls_progress_endpoint(live_app, browser_page): + import time + + base_url, repo = live_app + page = browser_page + page.goto(base_url, wait_until="networkidle") + _wait_fonts(page) + page.get_by_test_id("repo-path").fill(str(repo)) + + progress_hits: list[str] = [] + + def on_route(route): + req = route.request + url = req.url + if "/api/index/progress" in url: + progress_hits.append(url) + route.continue_() + return + if req.method == "POST" and url.rstrip("/").endswith("/api/index"): + time.sleep(1.2) + route.continue_() + return + route.continue_() + + page.route("**/api/**", on_route) + with page.expect_response( + lambda r: r.url.rstrip("/").endswith("/api/index") and r.request.method == "POST", + timeout=60_000, + ): + page.get_by_test_id("btn-index").click() + page.locator(".progress").wait_for(timeout=5_000) + page.wait_for_function( + """() => { + const t = document.querySelector('.rail-foot .muted')?.textContent || ''; + return /Extract|Scan|Stitch|Indexed|Boot|Hashed/.test(t); + }""", + timeout=10_000, + ) + page.screenshot(path="/opt/cursor/artifacts/index_progress_bar.png") + page.get_by_test_id("architecture-brief").locator(".level").wait_for(timeout=15_000) + assert progress_hits, "UI should poll GET /api/index/progress while indexing" + page.screenshot(path="/opt/cursor/artifacts/index_complete_architecture.png") + + @pytest.mark.playwright def test_ui_settings_preserve_model_and_theme(live_app, browser_page): base_url, _repo = live_app diff --git a/tests/unit/test_index_progress.py b/tests/unit/test_index_progress.py index e799d98..3071483 100644 --- a/tests/unit/test_index_progress.py +++ b/tests/unit/test_index_progress.py @@ -89,3 +89,12 @@ def test_api_index_progress_idle_then_done(tmp_path, monkeypatch): assert body["phase"] == "done" assert body["message"] assert "elapsed_ms" in body + + +def test_default_workers_stays_sequential_on_small_trees(monkeypatch): + from loadpath.index import default_workers + + monkeypatch.delenv("LOADPATH_INDEX_JOBS", raising=False) + assert default_workers(42) == 1 + monkeypatch.setenv("LOADPATH_INDEX_JOBS", "3") + assert default_workers(42) == 3 diff --git a/ui/src/App.tsx b/ui/src/App.tsx index d15eb5b..fa019d9 100644 --- a/ui/src/App.tsx +++ b/ui/src/App.tsx @@ -95,8 +95,8 @@ export function App() { .indexProgress(repoPath) .then((p) => { if (!busyRef.current) return; - if (p.message) markBusy(p.message); - setIndexPct(progressPercent(p)); + if (p.phase && p.phase !== "idle" && p.message) markBusy(p.message); + setIndexPct(p.phase && p.phase !== "idle" ? progressPercent(p) : null); }) .catch(() => undefined); };